Transparency with JPEGs done right
A few months ago, Square published a great article on Transparency with JPEGs on Android. It’s definitely worth reading! Just don’t use the provided code yet :) .
Romain Guy suggested in the comments that you can do this in a much more efficient and simpler way, either by using a BitmapShader or by playing with Porter-Duff blending modes.
Using a bitmap shader is great for dynamic masks. To apply a static mask to a bitmap loaded from a JPEG, Porter-Duff is the way to go, as we will see in this article.
We just need to load the bitmap, and then draw the mask on top of it with the right Porter-Duff mode.
Here is what the Android documentation has to say about the different modes:
- ADD Saturate(S + D)
- CLEAR [0, 0]
- DARKEN [Sa + Da - SaDa, Sc(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)]
- DST [Da, Dc]
- DST_ATOP [Sa, Sa * Dc + Sc * (1 - Da)]
- DST_IN [Sa * Da, Sa * Dc]
- DST_OUT [Da * (1 - Sa), Dc * (1 - Sa)]
- DST_OVER [Sa + (1 - Sa)Da, Rc = Dc + (1 - Da)Sc]
- LIGHTEN [Sa + Da - SaDa, Sc(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)]
- MULTIPLY [Sa * Da, Sc * Dc]
- SCREEN [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc]
- SRC [Sa, Sc]
- SRC_ATOP [Da, Sc * Da + (1 - Sa) * Dc]
- SRC_IN [Sa * Da, Sc * Da]
- SRC_OUT [Sa * (1 - Da), Sc * (1 - Da)]
- SRC_OVER [Sa + (1 - Sa)Da, Rc = Sc + (1 - Sa)Dc]
- XOR [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
Crystal clear! Hopefully the Xfermodes example in the API Demos demonstrates what the different modes do:
The yellow circle is the destination bitmap and the blue rectangle is the source bitmap. The destination is drawn normally, then the source is drawn on top of that using the given Porter-Duff mode.
To apply the alpha mask, we will therefore use
Let’s say we have a nice JPEG:
And a PNG that we want to use as a mask:
First, we load the bitmap:
Next we draw the mask on the bitmap with a canvas, using the
DST_IN Porter-Duff mode:
Finally we just use the bitmap:
There you go, Troll Face Golden Gate!
Here is a helper method to do this all at once:
Brilliant! Thanks for the pictures demonstrating the different Porter-Duff modes! I had been wondering about them for a long time!
Very useful! I’m writing a children’s puzzle app and this is a quick and easy way to create a base (ie. a square with the puzzle shape cut out of it) for the puzzle with an interesting texture. Thanks =)