|
Object » BitBlt
BitBlt represents a block transfer (BLT) of pixels into a rectangle (destX, destY, width, height) of the destinationForm. The source of pixels may be a similar rectangle (at sourceX, sourceY) in the sourceForm, or a constant color, currently called halftoneForm. If both are specified, their pixel values are combined with a logical AND function prior to transfer. In any case, the pixels from the source are combined with those of the destination as specified by the combinationRule.
Hint: BitBlt works slightly different for monochrome display media. For a monochrome destination form, the fill color is translated into a halftone form, a form with black and white pixels in a regular sequence. Such forms were used in Smalltalk-80 to create the impression of various gray levels. (See examples below)
destForm - DisplayMedium
The Destination form, a display medium onto which the BitBlt
draws.
sourceForm - DisplayMedium or nil
halftoneForm - Color or Bitmap
or nil
The color that is used to fill a rectangular area of the
destination form. Use instance method fillColor: to set
this variable and fillColor to access its current value.
A Bitmap must be the bitmap of a Form with extent 32@32 and depth 1.
combinationRule - Integer
clipX - SmallInteger
clipY - SmallInteger
clipWidth - SmallInteger
clipHeight - SmallInteger
These four values define the clipping rectangle in coordinates of the destForm.
The clipping rectangle is
clipX @ clipY extent: clipWidth @ clipHeight
destX - SmallInteger
destY - SmallInteger
width - SmallInteger
height - SmallInteger
These four values define the destination rectangle in coordinates of
the destForm.
The destination rectangle is
destX @ destY extent: width @ height
sourceX - SmallInteger
sourceY - SmallInteger
width - SmallInteger
height - SmallInteger
These four values define the source rectangle in coordinates of the destForm.
The source rectangle is
sourceX @ sourceY extent: width @ height
Note that the destination rectangle and the source rectangle have the same extent.
colorMap -
ColorMap or
BitMap
A color map is needed when an instance of
ColorForm is copied onto a DisplayMedium
without a color map.
destForm: df sourceForm: sf halftoneForm: hf
combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin
extent: extent clipRect: clipRect
Creates a fully initialized new instance. This is the traditional
message to create an instance of BitBlt.
destForm: df sourceForm: sf fillColor: hf
combinationRule: cr destOrigin: destOrigin sourceOrigin: sourceOrigin
extent: extent clipRect: clipRect
Creates a fully initialized new instance. This is a newer message to
create an instance of BitBlt. It is in fact
equivalent to the more traditional message, but the change of the
message reflects the fact
that with the introduction of color support the halftone form of early
Smalltalks was
replaced with the fillColor.
Ensure that you always provide a
Rectangle
as the actual value following the name clipRect:. The virtual machine
may crash immediately when the value provided is not a rectangle.
When you want to use the entire display area of your display device, you can
use Display boundingBox to obtain a suitable clipping rectangle.
BitBlt is the most basic interface to display operations. BitBlt operations are heavily used, but explicit use of BitBlt is infrequently needed. Most of the following examples look quite artificial.
Filling a rectangular area of the screen:
| bitBlt | bitBlt := BitBlt destForm: Display sourceForm: nil fillColor: Color red combinationRule: Form over destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 200@200 clipRect: Display fullBoundingBox. bitBlt copyBits.
The instance creation method that is used here answers a fully initialized instance of BitBlt. It is therefore possible to immediately send it the message copyBits which performs the bitBlt operation on all bits in the rectangle 0 @ 0 extent: 200 @ 200.
When you change the combination rule, the background is not erased and the colored region looks as if a colored transparent sheet was placed in front of the display screen:
| bitBlt | bitBlt := BitBlt destForm: Display sourceForm: nil fillColor: Color red combinationRule: Form and destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 200@200 clipRect: Display fullBoundingBox. bitBlt copyBits.
Try also the combination rule Form under:
| bitBlt | bitBlt := BitBlt destForm: Display sourceForm: nil fillColor: Color red combinationRule: Form under destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 200@200 clipRect: Display fullBoundingBox. bitBlt copyBits.
The combination rule Form reverse has a special property: It is an operation that can be fully reversed by repetition. To demonstrate this, the bitBlt copyBity is performed twice in the following example.
| bitBlt | bitBlt := BitBlt destForm: Display sourceForm: nil fillColor: Color red combinationRule: Form reverse destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 200@200 clipRect: Display fullBoundingBox. bitBlt copyBits. (Delay forMilliseconds: 500) wait. bitBlt copyBits.
To get a better impression from the power of BitBlt, you should try all the preceding examples with different fill colors.
The following example is a nice demo without practical value. It copies the right half of the display screen into the left half:
| bitBlt | bitBlt := BitBlt destForm: Display sourceForm: Display fillColor: nil combinationRule: Form over destOrigin: 0 @ 0 sourceOrigin: Display fullBoundingBox width // 2 @ 0 extent: Display fullBoundingBox width // 2 @ Display fullBoundingBox height clipRect: Display fullBoundingBox. bitBlt copyBits.
Just for fun, you should also try this example:
| bitBlt |
bitBlt := BitBlt destForm: Display sourceForm: Display fillColor: Color red combinationRule: Form and destOrigin: 0 @ 0 sourceOrigin: Display fullBoundingBox width // 2 @ 0 extent: Display fullBoundingBox width // 2 @ Display fullBoundingBox height clipRect: Display fullBoundingBox. bitBlt copyBits.
For a monochrome destination form, the fill color is converted into a halftone form:
| bitBlt form | form := Form extent: 100 @ 100 depth: 1. bitBlt := BitBlt destForm: form sourceForm: nil fillColor: Color lightGray combinationRule: Form over destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 100 @ 100 clipRect: form boundingBox. bitBlt copyBits. form displayAt: 10 @ 10
Here, we provide a halftone form:
| bitBlt form halftone | form := Form extent: 100 @ 100 depth: 1. halftone := Bitmap withAll: #( 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224 286331153 572662306 1145324612 2290649224). bitBlt := BitBlt destForm: form sourceForm: nil fillColor: halftone combinationRule: Form over destOrigin: 0 @ 0 sourceOrigin: 0 @ 0 extent: 100 @ 100 clipRect: form boundingBox. bitBlt copyBits. form displayAt: 10 @ 10
Here is a more practical example. It draws a grid. Drawing a grid with BitBlt operations is very fast and this piece of code can be used in diagram painting software.
| painter mf | mf := 10. Display fill: (0 @ 0 extent: 110 @ 110) fillColor: Color white. painter := BitBlt destForm: Display sourceForm: nil halftoneForm: Color black combinationRule: Form over destOrigin: 5 @ 5 sourceOrigin: 0 @ 0 extent: 1 @ 101 clipRect: Display fullBoundingBox. " now, draw the vertical lines. In fact, we fill rectangles of width 1 and height 101 " 0 to: 10 do: [:idx | painter destOrigin: idx * mf @ 0 + 4; copyBits. ]. " draw the horizontal lines. " " first, change the settings in painter to fill rectangles of width 101 and height 1: " painter width: 101; height: 1. " now draw the 11 grid lines: " 0 to: 10 do: [:idx | painter destOrigin: 0 @ (idx * mf) + 4; copyBits. ].
The combination rule whose value is 0 through 15 programs the transfer to produce 1 or 0 according to its 4-bit representation as follows:
At each pixel the corresponding bits of the source and destination pixel values determine one of these conditions; if the combination rule has a 1 in the corresponding bit position, then the new destination value will be 1, otherwise it will be zero. Forms may be of different depths, see the comment in class Form.
In addition to the original 16 combination rules, this BitBlt supports
The color specified by halftoneForm may be either a Color or a Pattern. A Color is converted to a pixelValue for the depth of the destinationForm. If a Pattern, BitBlt will simply interpret its bitmap as an array of Color pixelValues. BitBlt aligns the first element of this array with the top scanline of the destinationForm, the second with the second, and so on, cycling through the color array as necessary. Within each scan line the 32-bit value is repeated from left to right across the form. If the value repeats on pixels boundaries, the effect will be a constant color; if not, it will produce a halftone that repeats on 32-bit boundaries.
Any transfer specified is further clipped by the specified rectangle (clipX, clipY, clipWidth, clipHeight), and also by the bounds of the source and destination forms. To make a small Form repeat and fill a big form, use an InfiniteForm as the source. To write on a form and leave with both transparent and opaque areas, use a MaskedForm as the source.Pixels from a source to a destination whose pixels have a different depth are converted based on the optional colorMap. If colorMap is nil, then conversion to more bits is done by filling the new high-order bits with zero, and conversion to fewer bits is done by truncating the lost high-order bits.
The colorMap, if specified, must be a either word array (ie Bitmap) with 2^n elements, where n is the pixel depth of the source, or a fully specified ColorMap which may contain a lookup table (ie Bitmap) and/or four separate masks and shifts which are applied to the pixels. For every source pixel, BitBlt will first perform masking and shifting and then index the lookup table, and select the corresponding pixelValue and mask it to the destination pixel size before storing.
When blitting from a 32 or 16 bit deep Form to one 8 bits or less, the default is truncation. This will produce very strange colors, since truncation of the high bits does not produce the nearest encoded color. Supply a 512 long colorMap, and red, green, and blue will be shifted down to 3 bits each, and mapped. The message copybits...stdColors will use the best map to the standard colors for destinations of depths 8, 4, 2 and 1. Two other sized of colorMaps are allowed, 4096 (4 bits per color) and 32786 (five bits per color).
Normal blits between 16 and 32 bit forms truncates or pads the colors automatically to provide the best preservation of colors.
Colors can be remapped at the same depth. Sometimes a Form is in terms of colors that are not the standard colors for this depth, for example in a GIF file. Convert the Form to a MaskedForm and send colorMap: the list of colors that the picture is in terms of. MaskedForm will use the colorMap when copying to the display or another Form. (Note also that a Form can be copied to itself, and transformed in the process, if a non-nil colorMap is supplied.)
|