i'm trying to apply a box blur to an transparent image, and i'm getting a "dark halo" around the edges.
Jerry Huxtable has a short mention of the problem, and a very good demonstration showing the problem happen:
But i, for the life of me, cannot understand how "pre-multiplied alpha" can fix the problem. Now for a very simple example. i have a 3x3 image, containing one red and one green pixel:
In reality the remaining pixels are transparent:
Now we will apply a 3x3 Box Blur to the image. For simplicities sake, we'll only calculate the new value of the center pixel. The way a box blur works is that since we have a 9 position square (3x3, called the kernel) we take 1/9th of each pixels in the kernel, and add it up:
So
finalRed = 1/9 * red1 + 1/9 * red2 + 1/9 * red3+ ... + 1/9 * red9
finalGreen = 1/9*green1 + 1/9*green2 + 1/9*green3+ ... + 1/9*green9
finalBlue = 1/9* blue1 + 1/9* blue2 + 1/9* blue3+ ... + 1/9* blue9
finalAlpha = 1/9*alpha1 + 1/9*alpha2 + 1/9*alpha3+ ... + 1/9*alpha9
In this very simplified example, the calculations become very simple:
finalRed = 1/9 * 255
finalGreen = 1/9 * 255
finalBlue = 0
finalAlpha = 1/9*255 + 1/9*255
This gives me a final color value of:
finalRed = 28
finalGreen = 28
finalBlue = 0
finalAlpha = 56 (22.2%)
This color is too dark. When i perform a 3px Box blur on the same 3x3 pixel image in Photoshop, i get what i expect:
Which is clearer when displayed over white:
In reality i'm performing a box blur on a bitmap containing transparent text, and the text gains the tell-tale dark around the fringes:
i'm starting with a GDI+ Bitmap that is in PixelFormat32bppARGB
format
How do i use "pre-multiplied alpha" when applying 3x3 convolution kernel?
Any answer will have to include new forumla, since:
final = 1/9*(pixel1+pixel2+pixel3...+pixel9)
Is getting me the wrong answer.
Edit: A simpler example is:
i'll perform this math with color and alpha values in the range of 0..1:
i'm going to apply the box blur convolution filter to the middle pixel:
ARGB'
= 1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) +
1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0) +
1/9 * (0,1,0,1) + 1/9 * (0,0,0,0) + 1/9 * (0,0,0,0);
= (0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
(0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0) +
(0, 0.11, 0, 0.11) + (0,0,0,0) + (0,0,0,0)
= (0, 0.33, 0, 0.33)
Which gives a fairly transparent dark green.
Which is not what i expect to see. And by comparison Photoshop's Box Blur is:
If i assume (0, 0.33, 0, 0.33)
is pre-multiplied alpha, and un-multiply it, i get:
(0, 1, 0, 0.33)
Which looks right for my all-opaque example; but i don't know what to do when i begin to involve partially transparent pixels.
preRed1 = red1 * alpha1 / 255;
etc. – Mark Ransom