4

I have a hunch this has been done before but I am a total layman at this and don't know how to begin to ask the right question. So I will describe what I am trying to do...

I have an unknown ARGB color. I only know its absolute RGB value as displayed over two known opaque background colors, for example black 0x000000 and white 0xFFFFFF. So, to continue the example, if I know that the ARGB color is RGB 0x000080 equivalent when displayed over 0x000000 and I know that the same ARGB color is RGB 0x7F7FFF equivalent when displayed over 0xFFFFFF, is there a way to compute what the original ARGB color is?

Or is this even possible???

jpwrunyan
  • 530
  • 5
  • 22

2 Answers2

2

So, you know that putting (a,r,g,b) over (r1,g1,b1) gives you (R1,G1,B1) and that putting it over (r2,g2,b2) gives you (R2,G2,B2). In other words -- incidentally I'm going to work here in units where a ranges from 0 to 1 -- you know (1-a)r1+ar=R1, (1-a)r2+ar=R2, etc. Take those two and subtract: you get (1-a)(r1-r2)=R1-R2 and hence a=1-(R1-R2)/(r1-r2). Once you know a, you can work everything else out.

You should actually compute the values of a you get from doing that calculation on all three of {R,G,B} and average them or something, to reduce the effects of roundoff error. In fact I'd recommend that you take a = 1 - [(R1-R2)sign(r1-r2) + (G1-G2)sign(g1-g2) + (B1-B2)sign(b1-b2)] / (|r1-r2|+|g1-g2|+|b1-b2), which amounts to weighting the more reliable colours more highly.

Now you have, e.g., r = (R1-(1-a)r1)/a = (R2-(1-a)r2)/a. These two would be equal if you had infinite-precision values for a,r,g,b, but of course in practice they may differ slightly. Average them: r = [(R1+R2)-(1-a)(r1+r2)]/2a.

If your value of a happens to be very small then you'll get only rather unreliable information about r,g,b. (In the limit where a=0 you'll get no information at all, and there's obviously nothing you can do about that.) It's possible that you may get numbers outside the range 0..255, in which case I don't think you can do better than just clipping.

Here's how it works out for your particular example. (r1,g1,b1)=(0,0,0); (r2,g2,b2)=(255,255,255); (R1,G1,B1)=(0,0,128); (R2,G2,B2)=(127,127,255). So a = 1 - [127+127+127]/[255+255+255] = 128/255, which happens to be one of the 256 actually-possible values of a. (If it weren't, we should probably round it at this stage.)

Now r = (127-255*127/255)*255/256 = 0; likewise g = 0; and b = (383-255*127/255)*255/256 = 255.

So our ARGB colour was 80,00,00,FF.

Gareth McCaughan
  • 19,888
  • 1
  • 41
  • 62
  • That's interesting... so you can actually work out the alpha from just the red channel... I noticed that when I made my example that even though the red value of the original color was 0, it became 7F when transparent over white. It makes sense, of course, but I had to think about it for a bit. – jpwrunyan Mar 30 '11 at 05:03
  • By the way, you meant to write: a = 1 - [127+127+127]/[255+255+255] = 127/255 right? – jpwrunyan Mar 30 '11 at 05:08
  • I don't think so. That's 1-127/255 = 128/255. But my arithmetic is very unreliable so it's possible I'm all wrong :-). – Gareth McCaughan Mar 30 '11 at 08:40
  • I see the mistake, I misunderstood 127/255 on the next line line has "a" instead of "1-a" which would indeed make "a" 128/255 as you originally wrote. I think I got it anyway! – jpwrunyan Mar 31 '11 at 00:28
1

Choosing black and white as the background colors is the best choice, both for ease of calculation and accuracy of result. With lots of abuse of notation....

  • a(RGB) + (1-a)0xFFFFFF = 0x7F7FFF
  • a(RGB) + (1-a)0x000000 = 0x000080

Subtracting the second from the first...

  • (1-a)0xFFFFFF = 0x7F7FFF-0x000080 = 0x7F7F7F

So

  • (1-a) = 0x7F/0xFF
  • a = (0xFF-0x7F)/0xFF = 0x80/0xFF
  • A = 0x80

and RGB = (a(RGB))/a = 0x000080/a = 0x0000FF

You can do something very similar with other choices of background color. The smaller a is and the closer the two background colors are the less accurately you will be able to determine the RGBA value. Consider the extreme cases where A=0 or where the two background colors are the same.

James Crook
  • 1,600
  • 12
  • 17
  • Thank you! Between you and Gareth, I think I got a grasp for the algebra involved with the problem. And you guys even figured out the original color I had in my example! Amazing! – jpwrunyan Mar 30 '11 at 04:57