21

How can I mix two ARGB pixels ?

Example

Source: en.wikipedia.org/wiki/Alpha_compositing#mediaviewer/File:Alpha_compositing.svg

Here A is (Red with Alpha) and B is ( Blue with Alpha ).

General Grievance
  • 4,555
  • 31
  • 31
  • 45
SunnyShah
  • 28,934
  • 30
  • 90
  • 137

3 Answers3

38

Taken from the same Wikipedia article where you got the image:

C_o = C_a \alpha_a + C_b \alpha_b \left(1 - \alpha_a\right)

Translating to values which range from 0 to 255:

rOut = (rA * aA / 255) + (rB * aB * (255 - aA) / (255*255))
gOut = (gA * aA / 255) + (gB * aB * (255 - aA) / (255*255))
bOut = (bA * aA / 255) + (bB * aB * (255 - aA) / (255*255))
aOut = aA + (aB * (255 - aA) / 255)
General Grievance
  • 4,555
  • 31
  • 31
  • 45
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • I think the formula may have been wrong at the time of posting. From the article as it is now, you still have to divide by a mixed alpha. In TEX-like notation: `C_o = \frac{C_a \alpha_a + C_b \alpha_b (1 - \alpha_a)}{\alpha_a + \alpha_b(1 - \alpha_a)}` – General Grievance Nov 03 '20 at 13:26
  • @Calculuswhiz I don't know what you're talking about. The original formula was an image hosted by Wikimedia, and it's still just as valid as the day I posted it. Your edit is the same formula, if not the same image. Dividing by alpha is a separate step you do when you're done working with alpha, and in fact is unnecessary if your last blend is with a 100% opaque object underneath. – Mark Ransom Nov 03 '20 at 14:52
  • Yes, the edit was only for visibility on dark theme. The Google Charts API makes a cleaner image than the original. I did not attempt to change the formula, as I felt that that may have conflicted with the intention of the post. However, your answer says that the image is from the Wiki article. The article no longer uses that image. The closest formulas I could in the article all use alpha division. Unless there's another article besides this one? http://en.wikipedia.org/wiki/Alpha_compositing – General Grievance Nov 03 '20 at 15:48
  • @Calculuswhiz that is almost certainly the page I was looking at. It never occurred to me that Wikipedia pages aren't stable over time. Dividing by alpha seems wrong to me, I'm not sure why Wikipedia now includes it. – Mark Ransom Nov 03 '20 at 16:36
  • @GeneralGrievance it only took a couple of years, but I finally went back to the Wikipedia article to figure out why we diverged. Yes indeed you need to divide by aOut at the end to convert from premultiplied values back to unassociated. I'll need to update the answer to be consistent. – Mark Ransom Apr 01 '22 at 00:00
  • Well, if it helps, I made a [Google Sheet](https://docs.google.com/spreadsheets/d/1wwwIYKt3IUH7CwmizmTRCHn_35k_lJ17VFlKAYaNr4o/edit?usp=sharing) for using the Google Charts API. It generates markdown (including alt-text) for you. – General Grievance Apr 01 '22 at 13:29
11

The above is the wrong algorithm. This can be verified by substituting aA = 0. Then it turns out that if you are trying to blend color B with completely transparent color A, i.e. invisible, then logically the color B remains unchanged, but according to this formula it will be changed. The result of incorrect blending with gradient transparency. Therefore, the correct solution would be like this:

aOut = aA + (aB * (255 - aA) / 255)
rOut = (rA * aA + rB * aB * (255 - aA) / 255)/aOut 
gOut = (gA * aA + gB * aB * (255 - aA) / 255)/aOut 
bOut = (bA * aA + bB * aB * (255 - aA) / 255)/aOut 

The result of correct blending with gradient transparency.

Nikolai Semko
  • 111
  • 1
  • 5
2

It seems like this is what you want: http://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending, but I'm a little confused by your notation since wikipedia says that argb values should range from 0.0 to 1.0. So I don't think this formula will give you FA=19. Can you clarify?

Edit: now that you took out the business about FA=19, I'm inclined to go with that formula.

danben
  • 80,905
  • 18
  • 123
  • 145
  • You can use also values from 0 to 255 for the RGB components; if you need to use the values to calculate something, then it's probably better to use values between 0, and 255. The formula can be changed to work with values between 0 and 255, though. – apaderno Dec 22 '09 at 04:13
  • I think the formula expects each value to be a percentage, so you could use 0.0-1.0 for the formula and then multiply by 255 afterward. – danben Dec 22 '09 at 04:17
  • Thanks danben, I will take care to convert this formula from (0 to 1.0) to ( 0 to 255 ). – SunnyShah Dec 22 '09 at 04:25