[Mono-winforms-list] [Mono-osx] DrawImage alpha blend broken in libgdiplus

Alex Shulgin alexander.shulgin at yessoftware.com
Thu Apr 16 08:38:15 EDT 2009


Alex Shulgin wrote:
> Sebastien Pouliot wrote:
>> On Thu, 2009-04-09 at 18:22 +0300, Alex Shulgin wrote:
>>>
>>> I'm trying to run the tests in mcs/class/System.Drawing/Test under 
>>> MonoDevelop and I have 144 failing tests (out of 1377) to begin with...
>>>
>>> Is this normal situation or my system is severely broken?
>>
>> It's definitively not normal.
>> It could be some path issues since some tests depends on external files
>> (and MD compiled output could be at the "wrong" place).
>>> I'm on x86 Ubuntu 8.10 with the following packages freshly built from 
>>> svn:
>>>
>>> libgdiplus
>>> mono
>>> mcs
>>> gtk-sharp
>>> mono-addins
>>> monodevelop
>>>
>>> The number of failing tests doesn't change if I apply my patch to 
>>> libgdiplus, though.
>>>
>>> How do I proceed?
>>
>> You can try a "make run-test" at the prompt.
>>
>> If that works (or you can't make it work) then email a patch with the
>> new test(s) and I'll try it on my box.
> 
> Hi again,
> 
> I've tried
> 
> ~/src/mono/trunk/mcs/class/System.Drawing$ make run-test MCS=gmcs
> 
> where gmcs is built & installed from trunk.
> 
> This time I get only 6 failures (two related to XML serialization and 
> the rest in PrintingPermissionTest), so I've tried to apply my patch and 
> see what happens.
> 
> The result was that some tests that save an image, then load it and 
> check pixel format failed (on png and .ico).  The tests expect to get 
> Format32bppArgb, but they get Format32bppPArgb per my change.
> 
> Thinking further about this situation, I've looked into pngcodec.c to 
> see how does it save the image if it's data is in PARGB format.  It 
> turned out, that there's no special handling for this!
> 
> There's a simple code to demonstrate what happens if you load an ARGB 
> PNG image, save it untouched, then load it again.
> 
> using System;
> using System.Drawing;
> 
> namespace AlphaBlend
> {
>     class MainClass
>     {
>         public static void Main(string[] args)
>         {
>             Bitmap pngmask = new Bitmap("gimpmask.png");
>             Console.WriteLine("orig: PixelFormat={0}, pixel at (4,4): {1}",
>                               pngmask.PixelFormat, pngmask.GetPixel(4,4));
> 
>             pngmask.Save("savedmask.png");
> 
>             Bitmap loadedmask = new Bitmap("savedmask.png");
>             Console.WriteLine("load: PixelFormat={0}, pixel at (4,4): {1}",
>                               loadedmask.PixelFormat, 
> loadedmask.GetPixel(4,4));
>         }
>     }
> }
> 
> On the attached test image this code gives:
> 
> orig: PixelFormat=Format32bppArgb, pixel at (4,4): Color [A=51, R=49, 
> G=49, B=49]
> load: PixelFormat=Format32bppArgb, pixel at (4,4): Color [A=51, R=9, 
> G=9, B=9]
> 
> The RGB channels get premultiplied twice...
> 
> To resolve this mess I propose the following:
> 
> 1. Postpone premultiplication until actual use of cairo functions which 
> require it.
> 
> 2. Add premultiplication code where it's currently missing (as in my 
> original patch + few similar places).
> 
> 3. Add code to handle saving of PARGB bitmaps created by user like this: 
> new Bitmap(w, h, PixelFormat.Format32bppPArgb).  Possibly just throw 
> NotImplementedException for now.
> 
> This way we'll fix current problem with creating mask in memory and 
> alpha blending it on some background.
> 
> We'll avoid post-multiplication otherwise needed before saving an ARGB 
> PNG image.  Also, libgdiplus won't lie anymore that loaded image data is 
> in ARGB format while it's actually in PARGB. :)
> 
> What do you think?

Any comments?

--
Alex



More information about the Mono-winforms-list mailing list