iPhone pre-multiplied alpha (on PNGs) woes..

Member
Posts: 129
Joined: 2009.03
Post: #1
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
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
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);

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 129
Joined: 2009.03
Post: #3
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?
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #4
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.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 129
Joined: 2009.03
Post: #5
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
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
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).
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #7
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.
Quote this message in a reply
Member
Posts: 129
Joined: 2009.03
Post: #8
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,
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #9
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.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 446
Joined: 2002.09
Post: #10
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.
Quote this message in a reply
Member
Posts: 129
Joined: 2009.03
Post: #11
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?
Quote this message in a reply
Member
Posts: 129
Joined: 2009.03
Post: #12
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?
Quote this message in a reply
Member
Posts: 446
Joined: 2002.09
Post: #13
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).
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  How do you load PNGs on a C++ program? riruilo 8 6,250 Oct 20, 2009 05:20 PM
Last Post: miketucker
  How can I avoid XCODE transform my PNGs when moved to iPhone? riruilo 7 5,612 Apr 24, 2009 12:02 AM
Last Post: smallstepforman
  PNGs scaled smaller jeonghyunhan 0 1,783 Feb 10, 2009 06:04 PM
Last Post: jeonghyunhan