Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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.DrawImage(dest, bitmap);
    GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels);

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?

share|improve this question

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)

share|improve this answer
Well, I could of course process all fifteen possible PNG pixel formats and convert them to 32 bit non-premultiplied RGBA. It would however be a minor pain to create files with all possible formats and then test them. Since you're the PngCS dev, I would like to propose you add a helper class/function that decodes the entire file into memory (and optimally converts it to a user-defined pixel format) instead of having to do it line by line. Line-by-line is certainly useful, but IMO only for very specific applications with huge files or very little memory. – Panda Pajama Jan 23 '13 at 2:25
Certainly, I'm open to proposals. But 1) to load the full image as a matrix instead of a series of rows takes three lines of code 2) to convert to a format like "32 bit RGBA" is quite easy also, what is difficult is to provide a general helper function, because there are potentially tons of user defined pixel formats, and strategies (what to do with indexed images, with low-depth or high-depth images, etc). I might consider implementing a particular convertion function (RGBA32) with some ad-hoc strategy, that could serve as template. – leonbloy Jan 23 '13 at 2:41
That's precisely my point. I would prefer a general solution, at least for all standard pixel formats. As a library user I appreciate it when it allows me to do the most common thing (in this case loading a whole image into memory) in just one line, which is exactly one third of what you propose (when I did it, it took me like 8 or 9 lines though, but certainly the author can do a better job than somebody who just downloaded the library and tried to make it work). It's just a suggestion to make the library more user-friendly, but feel free to disregard it if it doesn't align with your views. – Panda Pajama Jan 23 '13 at 3:22
"for all standard pixel formats" And these would be...? Bear in mind that PngCs/PngJ is a general low level PNG library, uncoupled from high level/platform-specific image classes (.Net, IOS, Android). I'm willing to provide a method that returns the full image as a matrix of bytes or integers (perhaps preallocated) in some format but : 1) which format or formats would you suggest? (I'm doubting among bytes ARGB, integer packed ARGB32 or RGBA32...) and 2) are you sure that this would not require another allocation+copy to fill the high level image class? – leonbloy Jan 23 '13 at 17:13
I am not a PNG expert, so I am most likely wrong; but as I understand the IHDR chunk, there are five different color types defined, and considering the allowed bit depths for each color type, I can count 15 different pixel formats. Now, if you convert the pixels as you read them, instead of reading the whole image and then converting it, you do everything in a single pass, so you can save the allocations for the raw data, which may be interesting. As for the converstion format, I think 32-bit ARGB is the most common, but ABGR, RGBA, BGRA, XRGB and so on may also be interesting. – Panda Pajama Jan 23 '13 at 19:23

C code:

CFURLRef url = CFURLCreateWith...("path/to/file.png");
CGDataProviderRef dp = CGDataProviderCreateWithURL(url);
CGImageRef img = CGImageCreateWithPNGDataProvider(dp, nil, NO, kCGRenderingIntentDefault);
CFDataRef data = CGDataProviderCopyData(CGImageGetDataProvider(img));
UInt8* pixelData = CFDataGetBytePtr(data);  // not premultiplied RGBA8 data
// use pixelData

share|improve this answer
While a block of code may solve the issue, we like to see a description of what is the train of though or an explanation behind these blocks of code. – Alexandre Vaillancourt Mar 24 at 14:15

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.