Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Alpha Compositing and shyts
#1
Alpha compositing images and getting the colors right has been proving to be a royal PITA for me. I've crunched numbers on paper and I've determined the formulas to be correct, +-1 for each of the values RGBA. Wiki's Alpha Compositing; I'm using the preferred method found in Photoshop and paint.NET.

An example of my problem is readily apparent when dealing with white color with low alpha (FF FF FF 11) on top of a completely transparent black (00 00 00 00) The result should be FF FF FF 11, yet when my code does the job, it turns out to be 11 11 11 11 instead, which is black with low alpha. Everything else generally turns out okay.

Below is the code tasked to merging images on top of each other. The stuff of most interest is at the end, where all the formula goodness is, with all the lines starting with newImage[index] = byte;.

And as a friendly reminder, Java doesn't support unsigned primitives. R3tarded, I know.

 mergeImage() method


This is actually part of a much larger program, so the error(s) could be from somewhere else. But I figure the method is a good place to start and perhaps the most easily verifiable for errors. Especially since I can't imagine the input to be incorrect, and it'd be pretty dam hard to verify. Case in point, the program I'm working on outputs animated components separately, then combines animations for a final result and outputs that as well. The component-only animations turn out perfect, but the composite animation is botched.

Additional comments are appreciated xD
Reply
#2
Assuming you want to blend. That is, alpha is added, and then a percent of a and a percent of b is gained:

Code:
double tot = a1 + a2;
newImage[offset + j*4 + 3] = (byte)a0;    //alpha result
newImage[offset + j*4] = (byte)(r1 * a1/tot + r2 * a2/tot);
newImage[offset + j*4] = (byte)(g1 * a1/tot + g2 * a2/tot);
newImage[offset + j*4] = (byte)(b1 * a1/tot + b2 * a2/tot);

This blows up if both alphas are zero, btw. Shouldn't matter, as zeroes shouldn't be added anyway (if ((a1 == 0) && (a2 == 0)) continueWink

What are you really trying to do though? There are a ton of ways to blend them, so uh.
Reply
#3
((r1*a1 + r2*(255-a1)*(a2/(double)255))/a0 + .5)

((r1*a1/(double)255/a0 + r2*(255-a1)*(a2/(double)255))/a0 + .5)

Hope that makes sense, you need to scale back r1, g1, b1 with respect to their overall alpha (a0), or you're multiplying by 11 twice.


At least that's how I understand the formula to work. I might be off by a factor of 255 because I'm not exactly sure how that works.


Anyway, conceptually if a1 + a2 ~= a0, then you have a1/a0 + a2/a0 ~= 1 -> multiply 1 by original colours, weighted by their relative alpha.
Reply
#4
Devil's Sunrise Wrote:Assuming you want to blend. That is, alpha is added, and then a percent of a and a percent of b is gained:

Code:
double tot = a1 + a2;
newImage[offset + j*4 + 3] = (byte)a0;    //alpha result
newImage[offset + j*4] = (byte)(r1 * a1/tot + r2 * a2/tot);
newImage[offset + j*4] = (byte)(g1 * a1/tot + g2 * a2/tot);
newImage[offset + j*4] = (byte)(b1 * a1/tot + b2 * a2/tot);

This blows up if both alphas are zero, btw. Shouldn't matter, as zeroes shouldn't be added anyway (if ((a1 == 0) && (a2 == 0)) continueWink

What are you really trying to do though? There are a ton of ways to blend them, so uh.

With the method I'm using, when you put one image on top of another, the alphas are NOT given equal weight. Here's a simplistic example:
Code:
RR GG BB AA
Top layer:    FF 00 00 80
Bottom layer: 00 FF 00 80
Result layer: AA 55 00 C0
This is how it turned out at least in paint.NET.

Stereo Wrote:((r1*a1 + r2*(255-a1)*(a2/(double)255))/a0 + .5)

((r1*a1/(double)255/a0 + r2*(255-a1)*(a2/(double)255))/a0 + .5)

Hope that makes sense, you need to scale back r1, g1, b1 with respect to their overall alpha (a0), or you're multiplying by 11 twice.


At least that's how I understand the formula to work. I might be off by a factor of 255 because I'm not exactly sure how that works.


Anyway, conceptually if a1 + a2 ~= a0, then you have a1/a0 + a2/a0 ~= 1 -> multiply 1 by original colours, weighted by their relative alpha.

Uhhh I'm not sure I quite understand what you're doing here o.O

a1 + a2 != a0. Otherwise we get illegal values for alpha.

As for that second formula you provided, I could swear that you divided r1 by a0 twice. For practical matters, you and I would agree that if the second color is completely transparent, then only the first color would show unmodified, right? Given that, and a2 = 0, it should be fairly easy to see that you just greatly reduced the value of r1. And since a2 = 0, r1 = r0 (red result). That doesn't look right.
Reply
#5
Uh, if you're trying to alpha-compose using over:

Code:
double alpha1 = a1/255.,
           alpha2 = a2/255. * (1 - alpha1);
    newImage[offset + j*4 + 3] = (byte)(a1 * alpha1 + a2 * alpha2);
    newImage[offset + j*4] = (byte)(r1 * alpha1 + r2 * alpha2);
    newImage[offset + j*4 + 1] = (byte)(g1 * alpha1 + g2 * alpha2);
    newImage[offset + j*4 + 2] = (byte)(b1 * alpha1 + b2 * alpha2);
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)