[ANN] More about masks (+ sample stack)
Wilhelm Sanke
sanke at hrz.uni-kassel.de
Fri Nov 25 09:45:00 EST 2011
Accompanying is a sample stack with a side-by-side comparison of a
number of approaches produce and use masks and containing most of the
discussions below with examples:
<http://www.sanke.org/Software/MoreAboutMasks.zip>
To run the stack you need Rev 2.9 or higher.
As a starter for this overview about how to produce masked images in
Revolution here is a "two-liner":
"on mouseup
crop image "to-be-masked" to the rect of image "SelectionOval"
set the alphadata of image "to-be-masked" to the alphadata of image
"SelectionOval"
end mouseup"
This is the essential "core"-procedure to create masked images, one of
several options. Usually such a two-liner would be sandwiched between
"lock screen" and hide "SelectionOval", and additionally there would be
procedures in separate buttons that determine what to do with the newly
masked image, copy it elsewhere, save it as an external file, patch it
onto another image etc.
Image "to-be-masked" can be of any format, JPEG, GIF, PNG, image
"SelectionOval" must be a PNG of course.
If a graphic is used as a selection tool to determine the area of the
resulting masked image by capturing the transparency of the graphic with
a snapshot, it is *not* necessary to group graphic "SelectionOval". The
selection graphics and images in my sample stack *are* all grouped, but
only because they are combined with a "handle"-graphic for resizing and
reshaping, otherwise a grouping of the selection tools as a prerequisite
to capture transparency is not required.
And, contrary to what the Rev docs state for "import snapshot" ("The
format of the resulting image depends on the current setting of the
paintCompression property."), since Rev version 2.7 the resulting images
are invariably PNGs, irrespective of what the current general setting of
the paintcompression is, RLE, PNG, or JPEG. Although with pre-2.7
versions the snapshot images would not be PNGs, their formats are also
not directly determined by the current paintcompression.
Paintcompression, however, plays a role for the speed of processing
imagedata and alphadata, RLE is fastest here, PNG the slowest setting.-
Graphics do contain transparency in the area outside of the shape of the
graphic, but this transparency is not represented by mask- and alphadata
properties of the graphic. We have to make detours to get at these data
or to reconstruct them. I hope that with future versions of Revolution
graphics will additionally have alphadata and maskdata properties. If
that would be the case, we could mask images using graphics as selection
tools with two-liners like in the "starter" script above, too.
What follows here is mainly an overview of such detours, of different
attempts to build masks along with the discussion of details and
possible problems - derived partly from individual experience, but much
of it is based on the results of a number of offlist-contacts and
discussions during the last weeks between James Hurley, Bernd Niggemann,
and myself about problems, solutions, and workarounds concerning the
creation and application of masks to images. I have also considered the
onlist exchange between Scott Rossi and myself - at the time after I had
announced my first sample stack "Three Masks". On Ken Ray's website
(<http://www.sonsothunder.com/devres/revolution/tips/imag009.htm>, we
found the trick to produce transparency with the help of the "bucket
tool". Ken presents a two-liner from Jeanne DeVoto, which I managed to
integrate into one of the script examples.
==================
We could distinguish between two major categories: "Creating masks 'on
the fly'" and " Using prefabricated masks".
1. Creating masks "on the fly"
a) ====== "within"-functions"======
Jim Hurley has experimented with the native Rev "within" function to
produce masks and encountered the "edge problem", flat edges appearing
at the right and bottom of the masked images. Variations of the original
script did not help to overcome this problem.
Curiously enough, when you reverse the direction of the "scan" in Jim's
script, you get the edges on the left and on top.
I found three workarounds for this problem (but not a real solution of
the basic problem), namely "super-imposing" the edged alphamasks:
1. Double scan from right and left, and then superimposing the two
resulting masks.
2. Flipping - by script - the left half of the alphadata onto the right
half, and the top half onto the bottom half.
3. Capitalizing on the feature that since 2.9 flipped images preserve
their alphamasks (and flip them also), I run a normal scan, after that
flip the image horizontally and vertically, get the resulting second
mask (then return the image to its previous state) and superimpose the
two masks.
All three workarounds produce masked images without edges.-
Eventually Jim - as an expert in matters of mathematics and geometry -
has now developed a "within ellpse"-function on the basis of the
mathematical properties of an ellipse, which due to the more complex
nature of the script takes a bit longer to implement, but produces
perfectly rounded masked images.
Script examples for the solutions and workarounds of this section are
contained in the sample stack, as are all solutions discussed below in
the other sections.
b) ====== Comparing imagedata values from snapshot ======
First, I need to mention that "lock screen" prevents all kinds of
"import snapshot"-routines when working on Windows. This is nowhere
documented, at least I could find nothing in the docs. "lock screen"
would be handy to avoid the flickering that happens when a snapshot is
imported. On MacOS "lock screen" does not prevent importing a snapshot
and thus circumvents the flickering.
Bernd Niggemann offers an interesting alternative approach to determine
the pixels "within" the oval graphic by comparing the imagedata values
inside and outside of the graphic. He first hides the basic image (that
is intended to be masked) and imports a snapshot of the selection
graphic on the background of the card:
"import snapshot from rect (the rect of grc "oval") of this cd" (or "of
window tStackWindowID").
No transparency values are captured with this snapshot format. For
creating a mask he then assigns opaque values for the background colors
of the graphic area of the snapshot and transparent values for the
backgroundcolor of the card. To speed up the process of building the
masks, he compares only the values of one color channel, e.g. "green".
This requires, of course, to make sure that the values of the chosen
color channel are indeed different. If, for instance, you have got a red
graphic on a white card background, then you cannot use the "red"
channel, because both the values for red and white would be "255".
The results of this approach are well rounded masked images without
showing "edge effects".
I have added an "export snapshot"-variant - exporting the snapshot to an
external file and the reimporting it immediately to avoid the flickering
caused by "import snapshot" on Windows (without "lock screen").
In another example in this section I have integrated the "bucket
tool"-two-liner for producing the transparency found by Jeanne DeVoto
and listed by Ken Ray. As Devin Asay found out, information about this
solution is buried deeply in the Rev "User Guide" - on page 380 of the
PDF of Rev 3.0 - but is nowhere to be found in the Dictionary
Finally I have added a script in which all three color channels are
compared to create the mask.
c) ====== Capturing the transparency of the selection graphic with a
snapshot ======
Since engine version 2.7 it is possible to capture the transparency of a
control - maskdata and alphadata - along with an image of this control,
provided the snapshot is taken from the area of the control and the
control in question possesses mask- or alphadata like an image or a
graphic. In the case of a graphic, no real maskdata and alphadata as
directly accessible properties are of course available, but they are
then part of the image produced by the snapshot of the graphic area. The
"blendlevel" of an image or graphic - connected to the "ink"-property -
can *not* be captured with a snapshot.
The syntax is like this:
"snapshot of rect (trect: any rect-definition) of grc "X""
either with "import" or "export".
As the first example in this section I chose Scott Rossi's script (which
had to be adapted to the settings of the sample stack) from his stack
for Jim Hurley
<http://www.tactilemedia.com/site_files/downloads/masked_abe.rev">.
Taking a snapshot from the area of the graphic, either by import or
export, produces an especially smooth border of the mask, provided the
selection graphic has its antialiased property set to true.
Scott's assumptions - expressed in the comments of his script - that the
image "to-be-masked" must be in PNG-format and the selection graphic
(from which the snapshot for the mask is being taken) must be grouped,
could not be verified here, at least not on Windows. See my introductory
remarks in this context at the beginning of this post.
I have added a variant for this section with "export snapshot" to avoid
the flickering, similar to the approach in the section featuring Bernd's
solutions.
Concerning the role of paintcompression when taking a snapshot also see
the introductory remarks of this post.
To demonstrate the irrelevance of the paintcompression when taking a
snapshot I have added two scripts and buttons to this section of the
sample stack where you can choose the general paintcompression, one
button to transfer the alphadata, the other for the maskdata.
The only case where the current paintcompression matters here is that
with "JPEG" - i.e. for the general paintcompression, not for the format
of the involved images - you cannot transfer the "maskdata" from the
snapshot image to the basic image (the image "to-be-masked"), but you
can do this for the "alphadata".
By the way, transferring the "maskdata" from the snapshot image to the
image-to-be-masked produces somewhat rougher, pixelated borders,
transferring the "alphadata" produces smooth borders, provided the
"antialiased" of the graphic from which the snapshot was taken was set
to "true", as I have already mentioned.
2. Using prefabricated masks
a) ====== Masks with Selection Graphics ======
For my own work, I have for quite a time preferred to work with
"prefabricated" masks, i.e. such masks that are not created
simultaneously during the masking procedure, but which have been created
before in separate processes inside Revolution or with external photo tools.
One advantage of such an approach is that you can more easily finetune
the character of the mask than with taking a snapshot from a graphic
during the masking process (the latter resulting in one single format: a
mask with smooth edges and otherwise full opaqueness, meaning without
possible transitions of the transparency towards the fringes of the mask
etc.).
My favourite tool has been so far "RealDraw Pro" from
<http://www.mediachance.com>, a tool that unfortunately only runs on
Windows. Especially useful in "RealDraw Pro" is the "burst" transition.
A "radial" transition produces good results with varying transition
areas only for oval objects, with "burst" you can get
fitting transitional transparency for any shape - semicircle, triangle,
rhomb, star, or any other kind of polygon.
I have also experimented with the new gradient tools of Rev 3.0. The
process to produce masks this way is somewhat complicated, but the
resulting masks are fine.
The basic procedure to create masked images with ready-made masks is:
1. Select a portion of the image-to-be-masked with the selection
graphic, in which process the selection graphic can be moved, resized,
and reshaped.
2. Adjust the rect of the (hidden) mask image to the rect of the
selection graphic
3. Crop the image-to-be-masked to the rect
4. Transfer the alphamask of the mask image to the image-to-be-masked.
Much depends here on the quality of the mask. It should have been
created with its antialiased set to true, which is especially important
when you want to create masked images with sharp borders without
transitional transparency. You should set the resizequality of the mask
to "best" - to better adjust the mask to the variable sizes of the
chosen shape of the selection graphic. Bernd Niggemann has recommended
in this context to create a larger mask-image object as the working
template: Decreasing the size of the mask image during the adaptation to
the rect of the selection graphic affects the quality of the mask less
than the other way round.
In the corresponding section of the sample stack, you can try out masks
with varying degrees of transitional transparency and also of different
non-oval shapes.
A final observation concerning the creation of masks inside Revolution
and using the "import snapshot" format:
If the resulting mask image is not first saved as an external file and
then imported again, meaning if it remains as freshly created inside a
stack or was just copied from another mask-producing stack, then this
mask image will have a different quality, which we might call a "pre-PNG".
Pre-PNGs behave somewhat differently than normal PNGs: You cannot
transfer its alphamask to the image-to-be-masked when the pre-PNG is
hidden, at least not several times with resizing. After you have resized
a pre-PNG during the masking process, you might find that it is suddenly
"empty", but it can be restored when you copy and paste it (it then
appears in its original size and shape).
A workaround to overcome this problem is to store the mask in a custom
property of its own and then to "initialize" the mask each time before
it is used in the calling script:
"put the CPimg of img "transition" into img "transition""
But of course you can easily convert a pre-PNG to a full PNG by saving
the image as an external file.
b) ====== Mask Images as Selection Tool =======
At the end of this overview we return to the two-line "starter" script
of the beginning which requires an image as a selection tool instead of
a graphic.
I have added one card to the sample stack where this option can be tried
out.
One feature is especially helpful when using a resizable and reshapable
selection image: You can set the blendlevel of the image separately
without affecting its alphamask and thus create a selection image which
lets you see the image-to-be-masked underneath the selection area.
On this card you can choose between 10 shapes for the mask. There is
only one selection tool - consisting of a group with the mask image and
a graphic "handle" - into which these shapes are then inserted when you
select one of the shape buttons.
The produced masked images can then be saved as external files or
transferred to a "composition" card, on which you can arrange the
collected masked images as a new picture. The options on the composition
card are stiil on a very preliminary level, this serves only to indicate
one of further possibilities of using masked images.--
Best regards,
Wilhelm Sanke
<http://www.sanke.org/MetaMedia>
More information about the use-livecode
mailing list