SDL2 pre-multiplying alpha channel when loading surface on OS X?

I posted a question on StackOverflow that, based on feedback from other users, is leaning more towards a bug report than a general question. And so I’m sharing it here:

I’m loading 32 bit RGBA normalmap textures, with a heightmap encoded in the alpha channel, via SDL2 2.0.7 and SDL2_image 2.0.2 on OS X Sierra.

Every pixel in these textures has a non-zero RGB value, encoding a directional normal vector. A directional vector of (0, 0, 0) (i.e. black) is invalid.

And yet, when I load such a texture via SDL2_image, the areas of the texture with an alpha value of 0 also yield RGB values of 0. I think SDL is perhaps pre-multiplying the alpha value for these pixels?

A thorough explanation of the issue and a minimal test case are available on the SO issue page. Any help or input is very welcome!

I ran into this issue some years ago on iOS. The issue is with how apple always does premultiplication when loading pngs. I investigated the issue then and I don’t think there is anything sdl can do about it other than to not use the image loading provided by the platform. As suggested by the answer to your question you should be able to configure SDL_image on compile time to do so so.

Personally I solved the issue by not using pngs and use a variety of compressed texture formats like ETC and ASTC depending on the platform. It has a lot of upsides but honestly is a massive hassle.

Just as a warning I’ve also had trouble with other libs/tools with images that use the alpha channel for other data than opacity. The easiest solution to avoid all these issues is to use two separate images. The downside is of course that it adds one more texture lookup to your shader.

Thanks so much, Oli. Someone pointed out the same thing on StackOverflow, and I was able to rebuild SDL2_image without ImageIO support in order to fallback on libpng, libjpeg, and libtiff. Works like a charm.

Thanks again,

Jay

Shameless plug: I wrote a minimal SDL_image like thing that uses
stb_image.h:


If the filetypes supported by stb_image.h (jpg, png, tga, bmp, subset of
psd, one frame of gif, pic, pnm) are sufficient for your usecase, this
might be easier to use (esp. as it doesn’t need to be built separately
and linked against) :slight_smile:

Cheers,
Daniel

Thanks Daniel, that’s actually pretty badass, and I was not familiar with stbimage.h. If SDL_image were not already in my dependency graph, I would totally consider this. The dilemma for me is that I’m already bringing SDL_image into my project via ObjectivelyMVC:

Still, I may just grab this if more issues crop up.

1 Like

You can build SDL_image without ImageIO support, you’ll just need to add the appropriate graphics libraries in external as dependencies. I haven’t done this, so it may be a bit of work. Feel free to post a patch to bugzilla.libsdl.org so other people can benefit from your work!

That’s exactly what I did, and it was honestly very easy.

I’ve installed SDL2_image via Macports, which, interestingly, includes libpng, libjpeg and libtiff as dependencies (tho it doesn’t really use them!) So, the libraries were already available on my system. It was just a matter of re-configuring SDL2_image, and killing the ImageIO backend:

./configure --prefix=/opt/local \
    --disable-imageio \
    --disable-jpg-shared \
    --disable-png-shared \
    --disable-tif-shared \
    --disable-webp-shared

I’ve proposed to the Macports maintainer of SDL2_image that this become the default build configuration for the port, or at least a supported variant:
https://trac.macports.org/ticket/55184

Thank you again for your replies.