[Mono-bugs] [Bug 495516] New: DrawImage and PNGCodec broken w.r.t. alpha channel

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Thu Apr 16 10:17:21 EDT 2009


http://bugzilla.novell.com/show_bug.cgi?id=495516


           Summary: DrawImage and PNGCodec broken w.r.t. alpha channel
    Classification: Mono
           Product: Mono: Class Libraries
           Version: 2.4.x
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Major
          Priority: P5 - None
         Component: libgdiplus
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: alexander.shulgin at yessoftware.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


Created an attachment (id=286116)
 --> (http://bugzilla.novell.com/attachment.cgi?id=286116)
Test image for sample code.

User-Agent:       Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8)
Gecko/2009032609 Firefox/3.0.8 (.NET CLR 3.5.30729)

Alpha blending is broken in libgdiplus.

Below is sample code to demonstrate the problem.  I create the sample mask: a
linear gradient from LT- to BR-corner with increasing opacity; then I create
the sample background filled with red color.

After I draw the mask over the background I get all white rectangle.  Sample
code:

--8<----8<----8<----8<----8<----8<--

using System;
using System.Drawing;

namespace AlphaBlend
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Bitmap mask = new Bitmap(128, 128);
            using (Graphics g = Graphics.FromImage(mask))
            {
                for (int y = 0; y < mask.Height; ++y)
                    for (int x = 0; x < mask.Width; ++x)
                        mask.SetPixel(x, y, Color.FromArgb(x + y, 255, 255,
255));
            }
            mask.Save("mask.png");

            Bitmap bg = new Bitmap(mask.Width, mask.Height);
            using (Graphics g = Graphics.FromImage(bg))
            {
                using (SolidBrush b = new SolidBrush(Color.Red))
                    g.FillRectangle(b, Rectangle.FromLTRB(0, 0, bg.Width,
bg.Height));
                g.DrawImage(mask, 0, 0);
            }
            bg.Save("composite.png");
        }
    }
}

--8<----8<----8<----8<----8<----8<--

Also PNGCodec is broken.  If we load a sample ARGB PNG image, then save it
untouched and load again, we get corrupted image data (pre-multiplied twice).

Sample code:

--8<----8<----8<----8<----8<----8<--

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));
        }
    }
}

--8<----8<----8<----8<----8<----8<--

On the attached test image (gimpmask.png) 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]

Proposed solution:

1. Postpone pre-multiplication until actual use of cairo functions which
require it.

2. Add pre-multiplication code where it's currently missing.

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. :)

I'll try to prepare the patch shortly.

Reproducible: Always

Steps to Reproduce:
1. Run sample code.

Actual Results:  
1. For the first test case, the resulting image (composite.png) is all-white.

2. For the second one, image data in memory differs after save/load from disk.

Expected Results:  
1. The resulting image should have nice linear gradient from red to white.

2. Image data should not change after save/load from disk of PNG file.


Initial thread in mono-winforms-list:
http://www.nabble.com/DrawImage-alpha-blend-broken-in-libgdiplus-to22931264.html

-- 
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list