在IOS装载4通道的纹理数据(Loading 4-channel texture data in i

2019-08-02 14:23发布

I want to load 4-channel texture data from a file in iOS, so I consider the texture as a (continuous) map

[0,1]x[0,1] -> [0,1]x[0,1]x[0,1]x[0,1]

If I use the fileformat .png, XCode/iOS consider the file as an image, and so multiplies each component rgb with a (premultiplied alpha), corrupting my data. How should I solve this? Examples may be

  • use two textures with components rgb (3-channel)
  • postdivide alpha
  • use another file format

Of these, I consider the best solution to be to use another file format. The GL-compressed file format (PVRTC?) is not Apple-platform independent and seems to be of low resolution (4 bits) (reference).

EDIT: If my own answer below is true, it is not possible to get the 4 channel data of png's in iOS. Since OpenGL is about creating images rather than presenting images, it should be possible to load 4-channel data in some way. png is a fileformat for images (and compression depends on all 4 channels but compression of one channel is independent of the other channels), so one may argue that I should use another file format. So which other compressed file formats should I use, which is easy to read/integrated in iOS?

UPDATE: "combinatorial" mentioned a way to load 4-channel non-premultiplied textures, so I had to give him the correct answer. However, that solution had some restrictions I didn't like. My next question is then "Access raw 4-channel data from png files in iOS" :)

I think it is a bad library design not making it possible to read 4 channel png data. I don't like systems trying to be smarter than myself.

Answer 1:

当你认为PVRTC然后使用GLKit可能是一个选项。 这包括GLKTextureLoader它允许您加载纹理不预相乘的alpha。 例如使用:

+ (GLKTextureInfo *)textureWithContentsOfFile:(NSString *)fileName options:(NSDictionary *)textureOperations error:(NSError **)outError

和使含有一个选项词典:

GLKTextureLoaderApplyPremultiplication = NO


Answer 2:

你可以简单地要求Xcode中没有“压缩”您的PNG文件。 点击您的项目在左上角,选择“构建设置”,找到“压缩PNG文件”,并设置选项设置为“无”。

至于你的其他选择,postdividing是个不错的解决方案,但很明显,你将失去整体精度,相信无论是TIFF和BMP也支持。 PVRTC是PowerVR的特殊,所以它不是苹果专用,但它也并非完全独立于平台,并专门设计为一种有损压缩这是琐碎的GPU投入很少解压。 你通常会增加你的纹理分辨率,以改善每像素数的低位。



Answer 3:

您应该使用的libpng加载PNG不预乘颜色。

它是用C语言编写,并应编译为iOS。

我已经与Android类似的问题,也不得不使用第三方库加载与非预乘颜色的PNG文件。



Answer 4:

这是一个试图回答我的问题。

这是不可能的加载非预乘.png文件。

该选项kCGImageAlphaLast是一个有效的选择,但没有给出一个有效的组合CGBitmapContextCreate ( 参考 )。 然而,这是一个有效的选项CGImageRef的。

什么是构建设置COMPRESS_PNG_FILES上述XCode中那样,是将文件转换成巴纽一些其他的文件格式,并乘以通道rgba ( 参考 )。 我希望禁用此选项将有可能在我的实际.png文件到达通道数据。 但我不知道这是可能的。 下面的例子是在低电平来访问.PNG数据的尝试,作为CGImageRef

void test_cgimage(const char* path)
{
    CGDataProviderRef dataProvider = CGDataProviderCreateWithFilename(path);
    CGImageRef cg_image = CGImageCreateWithPNGDataProvider(dataProvider, NULL, NO,
                                                           kCGRenderingIntentDefault);
    CGImageAlphaInfo info = CGImageGetAlphaInfo(cg_image);
    switch (info)
    {
        case kCGImageAlphaNone:               printf("kCGImageAlphaNone\n");                break;
        case kCGImageAlphaPremultipliedLast:  printf("kCGImageAlphaPremultipliedLast\n");   break;
        case kCGImageAlphaPremultipliedFirst: printf("kCGImageAlphaPremultipliedFirst\n");  break;
        case kCGImageAlphaLast:               printf("kCGImageAlphaLast\n");                break;
        case kCGImageAlphaFirst:              printf("kCGImageAlphaFirst\n");               break;
        case kCGImageAlphaNoneSkipLast:       printf("kCGImageAlphaNoneSkipLast\n");        break;
        case kCGImageAlphaNoneSkipFirst:      printf("kCGImageAlphaNoneSkipFirst\n");       break;
        default: break;
    }

}

这给“kCGImageAlphaPremultipliedLast”与COMPRESS_PNG_FILES禁用。 所以我认为iOS的转换总是.png文件,甚至在运行时。



Answer 5:

不是100%,你想要什么,但我得到了周围使用这种方法的问题:把alpha通道到一个单独的黑白PNG并保存原始PNG不带alpha。 因此,采取空间是差不多的。 然后在我的纹理加载加载图像和合并成一个纹理。

我知道这是一个只有一个解决办法,但至少它给出正确的结果。 是的,这是很烦人的,那的iOS不允许你从PNG加载纹理不预乘alpha。



文章来源: Loading 4-channel texture data in iOS