My favorites | Sign in
Project Logo
                
Search
for
Updated Nov 16, 2009 by brackeen
TutorialBlendModes  
Tutorial on the alpha blending modes upcoming in version 0.11.4

The nightly builds of PulpCore now integrate new alpha blending modes.
This article explains what are the differences between all these modes and how to use them in PulpCore.

1. What is Alpha compositing

Wikipedia defines "Alpha compositing as :

... the process of combining an image with a background to create the appearance of partial transparency. It is often useful to render image elements in separate passes, and then combine the resulting multiple 2D images into a single, final image in a process called compositing. For example, compositing is used extensively when combining computer rendered image elements with live footage.

Basically, a composite mode explains how colors of each pixel of an image will blend together to create the resulting images. Alpha compositing is also known as "Porter and Duff rules" because they first explained how translucent images could be blend together to create various effects.

2. A bit of theory about image representation

Before going further, let's explain how is composed an image. An image is composed of pixels (a colored dot). Each pixel of an image is composed of 4 components :

Each of these components contains a value, representing the amount of color. Values can go from 0 (no color) to 255 (full color).

All components are then added to create a color. For example :

Each component value is stored as a byte (a byte = 8bits allows to have 256 different values for each component). A color, composed of 4 bytes is stored, in a 32 bits Java datatype : primitive type int.

How about the alpha component ?

Alpha component represents the transparent component of the image. A value of 0 means transparent color, a value of 255 means an opaque color. Values between 0 and 255 means that the color is translucent, it means that this color will react with the underlying color (that'll be explained in next chapter).
Notice that if a color has Alpha (A) component equals to 0, it will be transparent, not matter on Red (R), Green (G) or Blue (B) values. Two representations of translucent pixels exists :

  • Premultiplied representation (also called ARGB_PRE) : R, G and B values are already multiplied with the A value. The amount of color in each component is corresponding to the A value.

Premultiplied representation has an advantage over unpremultiply representation : 3 multiplications are spared for each pixel. Consider big images (800x600) and you'll see that it can spare a lot of operations time.
PulpCore is using premultiplied images to keep good performances on image operations that need color calculations (and composites are part of it).

3. Blending modes

The following blend modes operations are expected to be used with premultiplied colors. They explain how an existing image (a background image or Destination image), DST, will blend with the image that needs to be drawn (the foreground image or Source image) SRC.

Ax represents the Alpha component.
Cx represent each Component of a color.
Cd, Ad are the Component and Alpha of the DESTination image.
Cs, As are the Component and Alpha of the SouRCe image.
Cr, Ar are the Component and Alpha of the resulting image.

2.1 Clear

Ar = 0
Cr = 0

None of the terms are used.

How to use Clear in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.SrcClear());
 add(redSprite);

2.2 Dst

Ar = Ad
Cr = Cd

Only the terms that contribute destination color are used.

How to use Dst in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.Dst());
 add(redSprite);

2.3 Dst Atop

Ar = As * (1 - Ad) + Ad * As
Ar = As
Cr = Cs * (1 - Ad) + Cd * As

The destination that overlaps the source is composited with the source and replaces the destination.

How to use Dst Atop in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.DstAtop());
 add(redSprite);

2.4 Dst In

Ar = Ad * As
Cr = Cd * As

The destination that overlaps the source, replaces the source.

How to use Dst In in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.DstIn());
 add(redSprite);

2.5 Dst Out

Ar = Ad * (1 - As)
Cr = Cd * (1 - As)

The destination that does not overlap the source replaces the source.

How to use Dst Out in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.DstOut());
 add(redSprite);

2.6 Dst Over

Ar = As * (1 - Ad) + Ad
Cr = Cs * (1 - Ad) + Cd

The destination that overlaps the source is composited with the source and replaces the destination.

How to use Dst Over in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.DstOver());
 add(redSprite);

2.7 Src

Ar = As
Cr = Cs

Only the terms that contribute source color are used.

How to use Src in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.Src());
 add(redSprite);

2.8 Src Atop

Ar = As * Ad + Ad * (1 - As)
Ar = Ad
Cr = Cs * Ad + Cd * (1 - As)

The source that overlaps the destination is composited with the destination.

How to use Src Atop in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.SrcAtop());
 add(redSprite);

2.9 Src In

Ar = As * Ad
Cr = Cs * Ad

The source that overlaps the destination, replaces the destination.

How to use Src In in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.SrcIn());
 add(redSprite);

2.10 Src Out

Ar = As * (1 - Ad)
Cr = Cs * (1 - Ad)

The source that does not overlap the destination replaces the destination.

How to use Src Out in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.SrcOut());
 add(redSprite);

2.11 Src Over (Default)

Ar = As + Ad * (1 - As)
Cr = Cs + Cd * (1 - As)

The source color is placed over the destination color.
Default blend mode. Also known as the
Painter's algorithm.

How to use Src Over in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.SrcOver());
 add(redSprite);

or... nothing, because that's the default blend mode !

2.12 Xor

Ar = As * (1 - Ad) + Ad * (1 - As)
Cr = Cs * (1 - Ad) + Cd * (1 - As)

The non-overlapping regions of source and destination are combined.

How to use Xor in PulpCore :

 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.Xor());
 add(redSprite);

3. Applications in PulpCore

3.1 Mixing Two images together

Even if you can add images directly in the Scene2D, you can't change the default blending mode here. You'll have to create a Group and add your images here.
Two options are available to change the blend mode :

Example :

 groupA.setBlendMode(BlendMode.DstIn());
 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 add(redSprite);
  • The other solution is to change the blending mode directly on the Sprite using the same method, but applying it on the Sprite object :
  •  groupA.setBlendMode(BlendMode.DstIn());
     ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
     add(blueSprite);
     ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
     redSprite.setBlendMode(BlendMode.Xor());
     add(redSprite);

Both options are corrects. You'll have to choose one depending on what you want to do.

3. 2 Using the back buffer

You may notice, if you're using some blend modes that the result is not exactly what you expected.
Example below with DST_OUT.

Why do I get this black rectangle ??
That's because we're applying the filter directly on the background image and this image is opaque.
Remember the DST_OUT equation ?

Ar = Ad * (1 - As)
Cr = Cd * (1 - As)
if the destination image is opaque (that's the case of our background), Ad is 1.
Imagine that the source image is also opaque, we have :
Ar = 1 * (1 - 1) = 0
Cr = Cd *(1 - 1) = 0
All the components are 0, the background is painted in black.
This effect is explained in more details in
filthy rich clients.
To avoid this, make sure to apply masks on a back buffer using the createBackBuffer() method :

 groupA = new Group();
 groupA.createBackBuffer();
 groupA.setBlendMode(BlendMode.DstIn());
 ImageSprite blueSprite = new ImageSprite("blue.png", 10, 10);
 add(blueSprite);
 ImageSprite redSprite = new ImageSprite("red.png", 60, 60);
 redSprite.setBlendMode(BlendMode.Xor());
 add(redSprite);

Sign in to add a comment
Hosted by Google Code