# [Image-SIG] Antialiased text on transparent image fails?

Laszlo Nagy gandalf at shopzeus.com
Tue Nov 20 18:59:49 CET 2007

```  Hi Coen,

I'm sorry for the late answer.  I was out of the country.

>
> Isn't this the way it should work? The alpha value of a pixel is
> treated the same way as any other channel. When a pixel is half
> covered by a shape, PIL wil draw 50% of the foreground and 50% of the
> background. In your case: a green shape 0, 255, 0, 255 (rgba) and
> background 255, 0, 0, 0. If you take the average of the two you come
> up with R=128 in the pixel and will be visible for 50% A=128. Isn't
> this the desired effect?
Not desired for me. When you put a transparent image I1 on another image
I2, then you should see what you would see from I2, plus what you would
see from I2 that is under I1. Let me tell you an example. Let's have two
pieces of glass, G1 and G2.

G1 is:  (0,255,0,128), representing a material that is, when you put
white light on it:

a.) 50% the red component is absorbed, 50% goes through
b.) 50% is reflected, 50% goes through
c.) 50% the blue component is absorbed, 50% goes through

G2 is:  (255,0,0,2), representing an almost clear, fully transparent
glass, when you put white light on it:

a.) a very few of the red component is reflected, the remaining goes
through
b.) a very few of the green component is absorbed, the remaining
goes through
c.) a very few of the blue component is absorbed, the remaining goes
through

Maybe my interpretation is bad, but this is how I think it is - the
alpha channel gives transparency, the other channels tells us how many
of the remaining light is reflected vs. absorbed. 255 means full
reflect, whereas 0 means full absorption.

Now what happens if you put a piece of G1 on top of G2, put a white lamp
(255,255,255) over it and examine the result? How much red you will see
in it? Will it be (128,128,0) or (1,128,0)? Of course, the later.

There are other scenarios: you can put the lamp behind it, you can let
them shine etc. Any scenario you choose, you will not see too much red
in it because there is nothing in G1 or G2 that could reflect or let
throught much more red then green or blue.

Maybe I'm wrong and I have misinterpreted the meaning of the alpha
channel. In that case I wonder what it means?

And finally, I'm still interested in the good method, e.g. how can I
achieve the same effect with PIL, effectively? I'm asking this because
all of the methods in PIL will take the average of the two alpha
channels, and this is bad for me. Calculating pixels values one by one
would work but it is not effective.

Thanks,

Laszlo

p.s.: I do not like top posting, but once you started with it, I did not
want to "mid post". :-)

> And if it would be a color? Don't you want the same to happen?
>
> The solution? Render the shape on a 0,0,0,0 background. No red will be
> added, your half filled pixel with a correct alpha value will blend
> with new backgrounds as it is supposed to. You can save this image in
> various ways for later use.
>
> Just my thought... and i hope it helps.
> Greetings,
>
> Coen
>
>
> Laszlo Nagy wrote:
>>
>> Hi All,
>>
>> I tried to put a text on a transparent image. Here is a test:
>>
>> import Image
>> import ImageDraw
>> import ImageFont
>>
>> img = Image.new('RGBA',(100,20),(255,0,0,0))
>> drawer = ImageDraw.Draw(img)
>> fnt = ImageFont.truetype("Vera.ttf",20) #
>> http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/
>> drawer.text((0,0),"ABCDE",font=fnt,fill="#00ff00")
>> img.save("test.png") # Result image
>>
>> I'm working on a rendering engine but I created this example to show
>> the problem. The rendering engine should be able to create an image
>> with transparent parts, and one should be able to put the rendered
>> image on top of any other image.
>>
>> The problem itself: font edges are interpolated between the
>> background and foreground color. You can see it on the resulting
>> image. If you open the created "test.png" file in GIMP and use the
>> color picker tool then you can see values like:
>>
>> (203,52,0,52)
>> (215,40,0,40)
>>
>>
>> I think that this is bad. The background was fully transparent. If
>> you put a green object on a fully transparent thing, you should never
>> see any red in it. I believe that the result should be something like
>>
>> (0,52,0,52)
>> (0,40,0,40)
>>
>> In other words, when antialiasing a text, the background pixel's
>> color should be weighted with its transparency. In my example, the
>> background pixel is fully red but should have zero weight.
>>
>> Workarounds?
>>
>> Working with black or white initial background is not a workaround,
>> because PIL will darken/lighten the pixels. I used red+green just to
>> make the problem more visible. A correct workaround is to use the
>> actual target background that will finally be used, but it is not a
>> good workaround. This is obvious: I want to render the result image
>> once, then put it on different target images. Rendering the result
>> image each time I need to put it on a target would be very slow.
>>
>> Can you please confirm if this is a bug in PIL?  Comments welcome.
>>
>> Best,
>>
>>   Laszlo
>>
>>
>> ------------------------------------------------------------------------
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Image-SIG maillist  -  Image-SIG at python.org
>> http://mail.python.org/mailman/listinfo/image-sig
>>
>

```