[Mono-bugs] [Bug 679242] New: loading PNG looses data -- seems to be forcing premultiplied alpha
bugzilla_noreply at novell.com
bugzilla_noreply at novell.com
Mon Mar 14 01:03:44 EDT 2011
https://bugzilla.novell.com/show_bug.cgi?id=679242
https://bugzilla.novell.com/show_bug.cgi?id=679242#c0
Summary: loading PNG looses data -- seems to be forcing
premultiplied alpha
Classification: Mono
Product: Mono: Runtime
Version: 2.8.x
Platform: i686
OS/Version: Mac OS X 10.6
Status: NEW
Severity: Critical
Priority: P5 - None
Component: misc
AssignedTo: mono-bugs at lists.ximian.com
ReportedBy: danny at sooloos.com
QAContact: mono-bugs at lists.ximian.com
Found By: ---
Blocker: ---
User-Agent: Mozilla/5.0 (Windows; Windows NT 6.1) AppleWebKit/534.23
(KHTML, like Gecko) Chrome/11.0.686.3 Safari/534.23
When I load a PNG file from disk, the R/G/B values in it come premultiplied
with the Alpha.
This is bad because it looses data (if alpha is 0, the r/g/b values are totally
lost forever), and it is also inconsistent with Microsoft's .NET, which
preserves the proper values from the PNG.
Reproducible: Always
Steps to Reproduce:
using System;
using System.Drawing;
using System.Drawing.Imaging;
namespace AlphaBlend
{
class MainClass
{
static void Print(string pass, Bitmap bmp)
{
BitmapData data =
bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
unsafe {
int j = 0;
while (j < bmp.Height) {
byte *inb = (byte*)data.Scan0.ToPointer() + data.Stride*j;
int i = 0;
Console.Write(pass + ": |");
while (i < bmp.Width) {
Console.Write("{0:X2},{1:X2},{2:X2},{3:X2}|",
*inb, *(inb+1), *(inb+2), *(inb+3));
inb += 4;
i++;
}
Console.WriteLine();
j++;
}
}
bmp.UnlockBits(data);
}
public static void Main(string[] args)
{
using (Bitmap bmp = new Bitmap(4, 4, PixelFormat.Format32bppArgb))
{
using (Graphics g = Graphics.FromImage(bmp)) {
for (int y = 0; y < bmp.Height; ++y)
for (int x = 0; x < bmp.Width; ++x)
bmp.SetPixel(x, y,
Color.FromArgb(0x80,0xff,0xff,0xff));
}
Print(" half alpha white", bmp);
bmp.Save("tmp.png");
}
Console.WriteLine();
using (Bitmap bmp = (Bitmap)Image.FromFile("tmp.png")) {
Print("loaded half alpha white", bmp);
}
Console.WriteLine(); Console.WriteLine();
using (Bitmap bmp = new Bitmap(4, 4, PixelFormat.Format32bppArgb))
{
using (Graphics g = Graphics.FromImage(bmp)) {
for (int y = 0; y < bmp.Height; ++y)
for (int x = 0; x < bmp.Width; ++x)
bmp.SetPixel(x, y,
Color.FromArgb(0x0,0xff,0xff,0xff));
}
Print(" no alpha white", bmp);
bmp.Save("tmp.png");
}
Console.WriteLine();
using (Bitmap bmp = (Bitmap)Image.FromFile("tmp.png")) {
Print(" loaded no alpha white", bmp);
}
}
}
}
Actual Results:
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
loaded half alpha white: |80,80,80,80|80,80,80,80|80,80,80,80|80,80,80,80|
loaded half alpha white: |80,80,80,80|80,80,80,80|80,80,80,80|80,80,80,80|
loaded half alpha white: |80,80,80,80|80,80,80,80|80,80,80,80|80,80,80,80|
loaded half alpha white: |80,80,80,80|80,80,80,80|80,80,80,80|80,80,80,80|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
loaded no alpha white: |00,00,00,00|00,00,00,00|00,00,00,00|00,00,00,00|
loaded no alpha white: |00,00,00,00|00,00,00,00|00,00,00,00|00,00,00,00|
loaded no alpha white: |00,00,00,00|00,00,00,00|00,00,00,00|00,00,00,00|
loaded no alpha white: |00,00,00,00|00,00,00,00|00,00,00,00|00,00,00,00|
Expected Results:
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
loaded half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
loaded half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
loaded half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
loaded half alpha white: |FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|FF,FF,FF,80|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
loaded no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
loaded no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
loaded no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
loaded no alpha white: |FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|FF,FF,FF,00|
The expected results came from a windows 7 .net 4 machine compiled with csc.
The bad results came from an OS X 10.6.6 machine running Mono 2.8.2 and
compiled with dmcs. gmcs and mcs product the same incorrect result.
This problem is exceptionally annoying when trying to load OpenGl textures
using Mono, and other people on the internet are having similar issues. Some
have suggested a workaround of un-premultiplying the values by dividing the
r/g/b by the alpha/255, but not only is this a terrible fix for quality sake,
but it doesn't work at all when the alpha value is 0.
I was unsure how to mark the severity of the bug, but given that 'Critical'
includes the descriptive text of 'causes you to lose data', I chose that.
--
Configure bugmail: https://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