Understanding ImageData, MaskData and AlphaData |
|
imageData.
|
The Tip on this page is based on the MetaCard 2.4.2 engine and earlier. If you have a version of MetaCard/Revolution that uses the MetaCard 2.4.3 engine or higher, you can view the revised Tip for assistance. |
After some trial and error, there is a rhyme and a reason to MetaCard/Revolution’s
imageData, maskData and alphaData properties. Keep in mind that
it appears that BOTH MetaCard’s AND Revolution’s documentation on this is a bit off, so
hopefully either (a) I will be proven wrong, or (b) their documentation will be fixed. — Editor.
The Basics
| Type | Calculation | Total |
| Pixels | 40 x 20 = |
800 |
| Bytes | 40 x 20 x 4 = |
3,200 |
| Bits | 40 x 20 x 4 x 8 = |
25,600 |
IMPORTANT! This is the key to working with imageData in
MetaCard/Revolution. If you don’t get the byte order correctly as BGRO
(in Windows) and ORGB (Macintosh), you will not get anywhere with your
image manipulation code.
Also note that this is an acknowledged bug in MetaCard/Revolution, and has been fixed in the MetaCard 2.4.3 engine (used by MetaCard 2.4.3 and Revolution 1.5). |
Example So Far
| Red Pixel | Green Pixel | Blue Pixel | ||||||||||
| Pixel | 1 | 2 | 3 | |||||||||
| Byte | 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
| Bit | Blue |
Green |
Red |
Other |
Blue |
Green |
Red |
Other |
Blue |
Green |
Red |
Other |
| Bit Value | 00000000 |
00000000 |
11111111 |
00000000 |
00000000 |
11111111 |
00000000 |
00000000 |
11111111 |
00000000 |
00000000 |
00000000 |
| Byte Value | 0 |
0 |
255 |
0 |
0 |
255 |
0 |
0 |
255 |
0 |
0 |
0 |
Retreiving Image Data
imageData property: The 32-bit binary values are retrieved
from an image by asking for the imageData of an image (and can be stored in a variable or
custom property for later use). You can retrieve the bytes of imageData (remember there are 4 of
them for each pixel) as an ASCII value by asking for the charToNum(char X of the imageData of
imageDescriptor), where X is the byte number to retrieve.
Why does this work? Well, if you notice that the byte values in the table above are
able to contain a value from 0 to 255, and you consider that the ASCII value of a
character is also from 0 to 255, it makes sense to be able to retrieve
the numeric value of a byte by thinking of the bytes of an image as
characters, and then using charToNum to get the value.
|
So in our 3-pixel image example above (which we’ll call "ThreePixel"), if you executed...
answer charToNum(char 6 of the imageData of image "ThreePixel")
... you would get 255 displayed in the Answer dialog, which would correspond
to the Green bit of the second pixel of our image.Note also that if you...
answer length(the imageData of image "ThreePixel")
... you would get 12 displayed in the Answer dialog (because it shows the number of
characters, or bytes in the imageData, and since there are 4 bytes of imageData for
every pixel, you get 12 in the result).
maskData property: This is a property of an image where it is an
all-or-nothing mask of a given pixel of an image. Note that this is dealing with pixels, not
bits. The maskData contains 8-bit (1 byte or character) binary values
that have a value that is either zero
or non-zero. If the value is 0, that pixel is transparent. If the
value is non-zero, the pixel is opaque. You can retrieve the ASCII value of a pixel’s
maskData in the same way you do with imageData above. So in our 3-pixel image example, if you executed...
answer charToNum(char 1 of the maskData of image "ThreePixel")
... you would get 255 displayed in the Answer dialog, which would correspond
to the default non-zero value for the mask of the Red pixel in our image. Since it is 255, the pixel is
opaque.
Note also that if you...
answer length(the maskData of image "ThreePixel")
... you would get 3 displayed in the Answer dialog because it shows the number of
characters, or bytes in the maskData, and since there is 1 byte of maskData
for every pixel, you get 3 in the result).
alphaData property: This is a property of an image where you can
impose a variable level of transparency for a given pixel of an image. Note that like
maskData, this is dealing with pixels, not bits.
The alphaData contains 8-bit (1 byte or character) binary values
that have a value from 0 to 255. If the value is 0, the pixel is transparent. If
the value is 255, the value is fully opaque. Any other value inbetween sets a level
of transparency (i.e. 128 would make the pixel 50% transparent). You can retrieve
the ASCII value of a pixel’s alphaData in the same way you do with imageData above. So in our 3-pixel image example, if you executed...
answer charToNum(char 1 of the alphaData of image "ThreePixel")
... you would get 255 displayed in the Answer dialog, which would correspond
to the fully opaque value for the alpha level of the Red pixel in our image.
You probably noticed that it is similar to the maskData property, and can effectively do
everything maskData can do and more. So why not just use alphaData all the time?
The reason is that alphaData takes a lot longer to execute than maskData, so if
you just want to turn pixels on and off, you’re better off using maskData.
|
Note also that if you...
answer length(the alphaData of image "ThreePixel")
... you would get 3 displayed in the Answer dialog because it shows the number of
characters, or bytes in the alphaData, and since there is 1 byte of alphaData
for every pixel, you get 3 in the result).
Setting Image Data
Keep in mind that you don’t set specific parts of imageData,
maskData or alphaData, you set these properties as a whole. That is, let’s
say you want to make the second row of pixels in an image to be transparent. You choose to set the
maskData of these pixels to 0, and you’ll need to use the binaryEncode
function in order to set the binary data (remember that all of this image information is stored in binary).
Here’s a simple example that will do that:
on mouseUp
put the imageData of img 1 into iData
put empty into mData
put the height of img 1 into tH
put the width of img 1 into tW
put binaryEncode("C",0) into transparentPixel
put binaryEncode("C",255) into opaquePixel
repeat with i = 1 to tH -- iterate through each row
repeat with j = 1 to tW -- iterate through each column
if i = 2 then
put transparentPixel after mData
else
put opaquePixel after mData
end if
end repeat
end repeat
set the maskData of img 1 to mData
set the imageData of img 1 to iData
end mouseUp
You can see that the maskData was set as a whole.
IMPORTANT! You need to set the
imageData of the image after you have applied a mask or an alpha change.
It doesn’t seem to work if you do it the other way around.
|
There are two basic uses of binaryEncode when setting imageData,
maskData, or alphaData. In both of these instances, you are setting the equivalent
of one pixel of the image.
The first is used to set imageData:
binaryEncode("CCCC",0,redByte,greenByte,blueByte)
The second is used to set maskData or alphaData:
binaryEncode("C",{maskOrAlphaByte})
In the cases above, redByte, greenByte, blueByte, and maskOrAlphaByte
each contain a value from 0 to 255. To show you how this works, below is a script that creates a 20 x 20 pure blue image, that is set to 50% transparency:
on mouseUp
create image
put it into tID
set the width of tID to 20
set the height of tID to 20
put empty into iData
put empty into aData
put binaryEncode("CCCC",0,0,0,255) into bluePixel
put binaryEncode("C",128) into halfTransPixel
repeat with i = 1 to 400
put bluePixel after iData
put halfTransPixel after aData
end repeat
set the alphaData of tID to aData
set the imageData of tID to iData
end mouseUp
Conclusions and a Note of Caution
One note of caution, however, is that any changes you make to the image data of an image is permanent;
if you screw up, you will have to reimport the original image to get it back to the way it was. One way around this is to
store in a custom property of the image a copy of the original imageData prior to manipulating it;
something like:
set the origData of image 1 to (the imageData of image 1)
You can always restore it later if you mess up:
set the imageData of image 1 to (the origData of image 1)
I know it takes up more space, but in my experience, it’s worth it.
Posted 7/2/2002 by Ken Ray
Updated 7/3/2002 by Ken Ray
|
|
|