iDevGames Forums
iPhone pre-multiplied alpha (on PNGs) woes.. - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: iPhone, iPad & iPod Game Development (/forum-11.html)
+--- Thread: iPhone pre-multiplied alpha (on PNGs) woes.. (/thread-314.html)



iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 09:36 AM

Help! Smile

I am having a problem with my PNG files, I believe XCode may be processing them before adding them to the bundle?

To avoid this, I tried changing their file extensions to ._PNG, I also tried the user defined project setting IPHONE_OPTIMIZE_OPTIONS = -skip-PNGs. Neither of these seemed to make much different.

I still have the dark fringe halo, where the PNG image is semi-transparent.

I'm using glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

Rather than glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);

The later blend mode, works, until I render semi-transparent sprites. In which case, they look way too bright and washed out. I'm pretty sure I should be using the former blend mode.

To load in my PNG files, I am using CGImageCreateWithPNGDataProvider..

Could that be messing with or modifying my PNG files?

Or is it something else I'm missing?

Hope someone can help. Smile

Thanks,

EDIT: Here's a pic, so you can see the dark fringing: http://grab.by/2AMR


iPhone pre-multiplied alpha (on PNGs) woes.. - Skorche - Feb 22, 2010 09:41 AM

If your images are pre-multiplied, the GL colors you use need to be too.

You are probably doing this:
Code:
glColor4f(r, g, b, a);

Then you need to do:
Code:
glColor4f(r*a, g*a, b*a, a);



iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 09:59 AM

So this would be using glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);?

In conjunction with modifying the source RGB?

I wasn't actually using glColor, just the glColorPointer thing. I'm create a batch list of GL_TRIANGLES, which may have different values for ALPHA and RGB etc.

I could multiply the RGB values in this color list, by ALPHA, I'm guess that could work, though I think I'd prefer just to get my images loaded non pre-multiplied.

Another thing that occurs to me, is how the various methods of loading PNGs on iPhone, compare with each other in terms of load times on start-up etc. Any thoughts?

Thanks,

EDIT: Yep, that seems to work. I'm still curious if this is the best solution though, and what other methods there are of loading in PNG files, and comparative performance when running on an actual iPhone?


iPhone pre-multiplied alpha (on PNGs) woes.. - Skorche - Feb 22, 2010 10:07 AM

Jamie W Wrote:I could multiply the RGB values in this color list, by ALPHA, I'm guess that could work, though I think I'd prefer just to get my images loaded non pre-multiplied.

Unless you are drawing the images without any scaling or rotation, you really want them to be pre-multiplied. Otherwise you'll just get similar, but smaller fringes around your objects.


iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 10:16 AM

Thanks Skorche,

I guess, I just don't understand why. That's what bugs me (only a little bit). For example, on PC or Mac, I have my images with normal alpha (i.e. not pre-multiplied) and they all work perfectly fine as expected (under DirectX or OpenGL).

I don't understand why it has to be different on iPhone, is there a specific reason for this?

Thanks, Smile


iPhone pre-multiplied alpha (on PNGs) woes.. - ThemsAllTook - Feb 22, 2010 10:36 AM

This thread has an explanation of how premultiplication makes interpolation work better: http://www.idevgames.com/forum/showthread.php?t=7560

In a nutshell: Consider drawing a linearly interpolated image at half its size in each dimension. A quadrant of pixels will be interpolated to produce a single pixel of output. Sample quadrant (0xRRGGBBAA): 0xFF0000FF 0x00000000 0x00000000 0x00000000

That's a 100% opaque red pixel and three 0% opaque black pixels. When interpolated, you end up with 0x3F00003F. Interpreted as nonpremultiplied, this value is 25% opaque red at 25% intensity. Interpreted as premultiplied, this value is 25% opaque red at 100% intensity.

If you can wrap your head around the above (believe me, it took me a long time to work it out for myself), you'll understand why halos occur with nonpremultiplied textures that don't treat transparent pixels specially (for example, by using 0xFF000000 instead of 0x00000000 in the above example).


iPhone pre-multiplied alpha (on PNGs) woes.. - arekkusu - Feb 22, 2010 11:08 AM

Jamie W Wrote:I don't understand why it has to be different on iPhone, is there a specific reason for this?

In a nutshell, it's because UIImage is designed for CoreGraphics, not OpenGL.

The .PNG spec explicitly says that the data is stored without premultiplication. If the forced premultiplication bothers you, file a bug about it.

Or use .TIF, which works correctly on the iPhone.


iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 11:16 AM

Makes sense thanks, and actually explains quite a lot. Though I'm sure the halo artifacts wouldn't exist if using non pre-multiplied (they don't occur on PC / Mac), I do think you'd get a certain amount of blurring around edges and darkening of single, or small pixel groups (actually, this happens on PC / Mac).

I'm now a convert!

Thanks once again,


iPhone pre-multiplied alpha (on PNGs) woes.. - Skorche - Feb 22, 2010 11:56 AM

It does occur on PC/Mac stuff too (and anything else that uses texture filtering), and for the same reason. Wink

There are two solutions actually. You can smear the border pixels so that you don't get a matte color around the edge, or you can pre-multiply. Pre-multiplying actually has an added benefit of letting you do both additive and alpha blending at the same time.


iPhone pre-multiplied alpha (on PNGs) woes.. - Frank C. - Feb 22, 2010 01:34 PM

Skorche Wrote:You can smear the border pixels so that you don't get a matte color around the edge...
Or just let Photoshop do that for you and don't worry about it...

I don't care what anybody says - I *know* when I need premultiplication and when I don't, and I'll premultiply things in the actual art as needed. This is and always has been an art problem, not something you should have to solve or even care about in code.

The trick to using PNG for GL textures on the iPhone is to turn off Xcode's PNG mangling or use a different file extension and use your own PNG loader. The full libpng or pnglite or (my personal fav) stb_image should all work fine.


iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 02:31 PM

Thank you all for the insights. Smile

I think there's 2 kind of artifacts here too..

1. The dark halo effect that occurs when using pre-multiplied alpha images with a blending mode "source_alpha, one_minus_source_alpha", is quite sever and noticeable.

2. The slightly darkened edges you get, when using non pre-multiplied alpha images with a blending mode "source_alpha, one_minus_source_alpha", in contrast to the dark ring halo effect mentioned above; is not so noticeable.

I believe I'm getting artifact 2 on PC/Mac (as ThemsAllTook explains in his post).

Anyhow, it's seems not so bad with 32bit images, but I've just added some code to covert my images (at run-time) to 16bit ARGB4444, and it's looking a bit dicey around the edges with the pre-multiplied images (using blending more "one, one_minus_source_alpha").

The other issue I'm contemplating is load times; how does pnglib etc, compare with using the OS to load in PNG images?


iPhone pre-multiplied alpha (on PNGs) woes.. - Jamie W - Feb 22, 2010 02:33 PM

Frank C. Wrote:The trick to using PNG for GL textures on the iPhone is to turn off Xcode's PNG mangling or use a different file extension and use your own PNG loader.

I tried both these, but didn't seem to work; is that because I was still using the OS to open the PNGs?


iPhone pre-multiplied alpha (on PNGs) woes.. - Frank C. - Feb 22, 2010 02:44 PM

Jamie W Wrote:I tried both these, but didn't seem to work; is that because I was still using the OS to open the PNGs?
Yes, that's what I meant by use your own PNG loader (as in don't use CoreGraphics).