Make my vector shape Black/White
by ericlin

There is no such actionScript function that can convert color shape into Black/White shape. The movie in this article is composed of two movieClip shapes. There is a colorful one on top of the other which is Black/White. The animation effect is created by setting the _alpha of the top colorful one.

How to create the Black/White one ?

For bitmap graph, there are many softwares that are capable of handling this job. For vector shape, there should be also some softwares that can create colorful and B/W ones if the shapes are in supported format. But, I am not sure whether they can import Flash shape and handle the color for it.

Here is my experience.

The algorithm

The basic unit for vector shape is either stroke or fill. If we modify the color for each fill and stroke then we can successfully convert the colorful shape into a black and white one.

The algorithm is that: luminance=0.3*red+0.6*green+0.1*blue

For a color such as pure red, (0xFF0000), the luminance is 76.5, If we round the number and convert it into hexdecimal number, the corresponding color should be (0x4d4d4d), a color of gray.

So, our work is to select each fill region and stroke in the shape and to modify the color as described above.

For a shape like the "lady bug"  in this movie, there are tens of such strokes and fills. It is a tedeious work.

Can we take advantage of the JSFL command to do this repeated job ?

Failed attemp through JSFL

If we have 3 movieClip instances on the stage, when we select all, we get selections , an array of 3 elements. We target those clips by selections[0], selections[1] and selections[2]. By this we can modify some properties of one specific clip.

If we have 3 Fills area and 2 strokes on the stage, when we select all, do you expect we should get a selections array containg 5 elements ? No, we get selections containing only one single element. A shape. Those fill area and strokes are treated in a whole as a shape,  We have no way to target specific Fill area or Stroke in the shape by javascript. We are not able to modify some properties of specific fill area in the shape.

In fact, shape is more likely a storage of "path". It stores the process of "drawing". Shape object contains array of "contour" which stores the x, y coordinates of control nodes. Roughly, a closed contour can hold a fill, and open contour can hold only strokes. But, whether we "fill" the closed contour or how we fill it is another thing. Shape object itself does not contain information about the fill. We can not obtain the fill style (solid or gradient) from shape object. We can not obtain the fill color of those closed contour from shape object. Nothing like this is stored in Edge or HalfEdge object.

Yes, to achive our goal, we need the original fill style and fill color in a specific area. So, we get to figure out a way to select a pure close fill area or stroke and then call the Document.getCustomFill method, or Document.getCustomStroke method to modify. How to do the selection ?

Well, the first way is Eye-and-Hand.  Open our eye, stare at the fill region, click our mouse accurately among the bounds of the fill. This is not a good way, if we have 50 fills scattered here and there.

Another way is to get the contour data out of the shape. Retrieve out the coordinates about the path of this contour. Choose a proper point and call "mouse click" and Flash will select that fill region. Well, to choose a proper point to click is not easy. That point should within the fill region. The calculation is not a simple thing. To select a Stroke is even troublesome.

Even if we can succeed in selecting each fill area and strokes, we still have a problem about alpha. This is the main reason that I abandon the attemps.

For some reason, the Fill.color retrieved from getCustomFill() is not enough for alpha. In my computer, if the alpha is not 100%, the fill.color appears like this: "#ff0000%02x"; It contains correct rgb color value and an alpha flag. If there is "%02x" after the rgb value, then the alpha is not 100.  However, it does not give me the real alpha value.  If we apply this fill object back to the original selected area,  the Fill becomes transparent because the alpha is set to 0.

Finally,  I could get limited success by a long list of "mouse click" to mimick the mouse operations on the Color Mixer. When we "set" the Fill, we do get the correct rgb and alpha value appear in the commands of history window. But I dont like this. A JSFL file full of "mouse click" with coordinate in the argument is not portable enough to other computer.

So, I decide to achieve the goal through modification of the SWF file.

Manipulate the color data in SWF

It is relatively easy and straight forward to change the color value directly through manipulation of SWF file. Of-course, the pitfall is that we have no proper software to do this.

In previous article, I wrote a php file to parse the shape data out of the SWF file. Just a little modification will serve out goal.

The color value stored in SWF is 8 bit for red, 8 bit for green and 8 bit for blue. If we know the offsets in the file, where it stores the color value, then we can modify it.

The function is modified as such:

```function parse(\$swfio){
\$swfio->colorFlag=true;
\$this->red=\$swfio->UI(8);
\$this->green=\$swfio->UI(8);
\$this->blue=\$swfio->UI(8);
\$luminance=((int)\$this->red*0.3+(int)\$this->green*0.6+(int)\$this->blue*0.1);
\$lum=chr(round(\$luminance));
fwrite(\$swfio->outputFileHandle,\$lum);
fwrite(\$swfio->outputFileHandle,\$lum);
fwrite(\$swfio->outputFileHandle,\$lum);
\$swfio->colorFlag=false;
\$this->alpha=\$swfio->UI(8);
}```

Basically, it read a byte from source swf and write a byte to destine swf until we meet a color structure.  We read 3 byte to get r,g,b to  calculate the luminance. Then we write the luminance byte as r,g,b to the destine SWF. The alpha value is untouched.

By single click, the resulted destine SWF will be a Black/White one. All the interaction and functions are preserved the same as original one. We dont need to build another source fla.

Also, I can import the SWF into my Flash authoring enviroment if I want that shape.

Unlike the manipulation in the Flash authoring enviroment, we need not consider the necessary ungrouping for grouped shape. In Flash enviroment, we may need to handle nested symbols and do our job from parent symbol to child symbols.

Of-course, there are common limitations when doing the job wither in Flahs enviroment of by manipulation of SWF. To turn bitmap B/W, we need other software. Also, if the color is created by Color object such as color.setTransform or setRGB, it is impractical to make it Black and White.