How to load a png file without alpha premultiplying in ios?

| | August 6, 2015

I am making a game in which I use the alpha value, in some cases for transparency, in others for occlusion, and for HDR in others.

I’m loading the images like this (this is MonoTouch, but objective-c can be easily converted to c#):

CGImage bitmap = new UIImage(resourcePath).CGImage;
width = bitmap.Width;
height = bitmap.Height;
IntPtr pixels = Marshal.AllocHGlobal(bitmap.Width * bitmap.Height * 4);
using (var context = new CGBitmapContext(pixels, bitmap.Width, bitmap.Height, 8, bitmap.Width * 4, CGColorSpace.CreateDeviceRGB(), CGImageAlphaInfo.PremultipliedLast))
{
    var dest = new RectangleF(0, 0, bitmap.Width, bitmap.Height);
    context.ClearRect(dest);
    context.DrawImage(dest, bitmap);
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);
}
Marshal.FreeHGlobal(pixels);
bitmap.Dispose();

However, this butchers all my pixels by premultiplying them by the alpha value.

The reason behind this is that I’m creating CGBitmapContext with CGImageAlphaInfo.PremultipliedLast. I tried with CGImageAlphaInfo.Last, but creating the context fails. Core Graphics only works with premultiplied alpha, as explained here.

I tried using CGDataProviderCopyData, as well as pngcs. However, they both simply decode the bitmap, and don’t convert the pixels to RGBA, which is relevant when you’re storing 8-bit, 24-bit PNGs, or indexed PNGs (I have lots of these, which are the result of optimizing my PNG files for size).

So I’m lost. I need a way to decode PNG files in a way that they are converted to RGBA without premultiplying my colors by the alpha value. Is that too much to ask? GDI, GDI+, System.Drawing, DirectX, Mono for Android as well as PSM do it just fine…

Also, why does iOS development has to be so picky?

One Response to “How to load a png file without alpha premultiplying in ios?”

  1. I tried using CGDataProviderCopyData, as well as pngcs. However, they
    both simply decode the bitmap, and don’t convert the pixels to RGBA,
    which is relevant when you’re storing 8-bit, 24-bit PNGs, or indexed
    PNGs.

    Did you look at ImageLineHelper.Palette2rgb()? What functionality are you missing?

    (disclaimer: I’m the PngCs developer)

Leave a Reply