代码之家  ›  专栏  ›  技术社区  ›  jdolan

在OS X上加载surface时SDL2预乘alpha通道?

  •  3
  • jdolan  · 技术社区  · 8 年前

    这些纹理中的每个像素都有一个非零RGB值,编码一个方向法向量。(0,0,0)的方向向量(即。 黑色 )无效。

    然而,当我通过SDL2_图像加载这样的纹理时,alpha值为0的纹理区域 而且 产生0的RGB值。我认为SDL可能是预先乘以这些像素的alpha值?

    附加的是这些法线贴图纹理之一。您可以通过在例如GIMP中打开纹理并在其中一个透明区域上使用颜色选择器来确认其有效性。你会看到,事实上,透明区域仍然有一个淡蓝色的RGB颜色(编码法向量)。

    32 bit RGBA normalmap with alpha-encoded heightmap for parallax mapping

    下面是一个最小的测试用例,说明了所附PNG文件的问题:

    #include <SDL_image.h>
    #include <assert.h>
    
    int main(int argc, char **argv) {
    
        SDL_Surface *s = IMG_Load("green3_2_nm.png");
        assert(s);
    
        for (int i = 0; i < s->w * s->h; i++) {
            const Uint32 *in = (Uint32 *) (s->pixels + i * s->format->BytesPerPixel);
    
            SDL_Color color;
            SDL_GetRGBA(*in, s->format, &color.r, &color.g, &color.b, &color.a);
    
            assert(color.r || color.g || color.b);
        }
    
        SDL_FreeSurface(s);
    
        return 0;
    }
    

    我正在编译这个测试用例 gcc $(pkg-config --cflags --libs sdl2_image) test.c

    第15行上的断言将在图像中的几行失败,即alpha值下降到0的位置。

    我试过TGA和PNG两种图像格式,但SDL对它们都做了相同的事情。

    这是SDL中的一个bug,还是我遗漏了什么?我很好奇人们是否也在其他平台上看到同样的问题。

    ===

    总是 . 解决方案是在不支持核心图形的情况下重新编译SDL2_图像,而是启用libpng、libjpeg和您需要的任何其他图像编解码器:

    ./configure \
    --disable-imageio \
    --disable-png-shared \
    --disable-tif-shared \
    --disable-jpg-shared \
    --disable-webp-shared
    

    在我的系统上,我不得不禁用核心图形( imageio 而且 如您所见,其他编解码器的共享库加载。这产生了一种脂肪 SDL2_image.so 它与libpng、libjpg等静态链接。。但效果如期。

    1 回复  |  直到 8 年前
        1
  •  4
  •   Community Mohan Dere    6 年前

    SDL_image是平台特定图像加载代码的包装器,而不是在所有平台上使用相同的图像加载程序。

    • Linux:LibPNG、LibJPEG
    • macOS、iOS:核心图形
    • Windows:WinCodec

    这样做的好处是减少了SDL_图像的大小,因为它不需要附带任何图像解码代码,而是可以动态链接到可能已经安装在系统上的内容。然而,在macOS和iOS上,核心图形不支持非预乘alpha,因此SDL_image必须将其反转。

    请参阅: mac-opengl - Re: kCGImageAlphaFirst not implemented (Was: (no subject)) 从2007年5月起(从Wayback机器):

    老实说,我没想到 CGBitmapContextCreate() 支持非预乘alpha。

    ...

    我不确定使用ImageIO+CoreGraphics是否真的旨在用于OpenGL应用程序的图像加载方案。

    LibSDL bug #838 - OSX SDL darkens colours proportional to increase in alpha 在SDL_图像中引入了一种变通方法 changeset 240 .

    你可以看到,变通方法仅仅是对α进行非预乘,这是一个非常有损的过程。

    为了解决这个问题,您可以在使用LibPNG的macOS上构建自己版本的SDL_image。这应该可以通过配置实现,您不必对SDL_图像代码本身进行任何更改。为此,请使用 --disable-imageio 选项SDL_image附带了自己的LibPNG代码副本,因此您不需要安装LibPNG即可实现。