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:
You can see that theon 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
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:
Conclusions and a Note of Cautionon 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
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