Download 4-channel texture data in iOS

I want to load 4-channel texture data from a file in iOS, so I view 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 fileformat .png , Xcode / iOS treats the file as an image and therefore multiplies each rgb component by a (premultiplex alpha), distorting my data. How do i solve this? Examples may be

  • use two textures with rgb components (3 channel)
  • postdivide alpha
  • use a different file format

Of these, I consider the best solution to use a different file format. The compressed GL file format (PVRTC?) Is not independent of the Apple platform and seems to have a low resolution (4 bits) ( link ).

EDIT: If my own answer is below, it is not possible to get 4-channel png data in iOS. Since OpenGL is intended for creating images, not for representing images, it should be possible to somehow load 4-channel data. png is a file format for images ( and compression depends on all 4 channels , but the compression of one channel does not depend on other channels), so it can be argued that I should use a different file format. So, what other compressed file formats should I use that are easy to read / integrate on iOS?

UPDATE: "combinatorial" mentioned a way to load 4-channel continuous textures, so I had to give it the correct answer. However, this solution had some limitations that I did not like. My next question is: "Access to raw 4-channel data from png files in iOS" :)

I think this is a bad library design that does not allow reading 4-channel png data. I don't like systems that try to be smarter than me.

+4
source share
5 answers

As you considered PVRTC, using the GLKit option may be an option. This includes the GLKTextureLoader , which allows you to load textures without first multiplying alpha. Usage, for example:

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

and passing an options dictionary containing:

 GLKTextureLoaderApplyPremultiplication = NO 
+4
source

You can simply request that Xcode not "compress" your PNG files. Select the project in the upper left corner, select "Build Settings", find "Compress PNG Files" and set it to "None".

As for your other options, postdividing is not a bad decision, but obviously you will lose overall accuracy, and I believe that TIFF and BMP are supported. PVRTC is specific to PowerVR, so it is not specific to Apple, but is also not completely platform independent and is specifically designed for lossy compression, which trivially decompresses with a small amount of input on the GPU. Usually you increase the resolution of the texture to improve the number of bits per pixel.

enter image description here

+3
source

You must use libpng to load PNGs without pre-multiplied colors.

It is written in C and should compile for iOS.

I had similar problems with Android, and also had to use a third-party library to load PNG files with non-spoiled colors.

+2
source

This is an attempt to answer my own question.

Unable to load non-multiplex .png files.

The kCGImageAlphaLast option is a valid parameter, but does not provide a valid combination for CGBitmapContextCreate ( link ). This is, however, a valid option for CGImageRef .

What is setting the COMPRESS_PNG_FILES assembly in Xcode mentioned above is to convert the .png files to another file format, and also multiply the rgb channels by a ( link ). I was hoping that disabling this option would get the channel data in my real .png files. But I'm not sure that this is possible. The following example is an attempt to access .png data at a low level, like 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; } } 

which gives "kCGImageAlphaPremultipliedLast" with COMPRESS_PNG_FILES disabled. Therefore, I think iOS always converts .png files even at runtime.

+1
source

Not 100% what you want, but I ran into a problem using this approach: put the alpha channel in a separate black and white png and save the original png without alpha. Thus, the space is occupied approximately the same. Then, in my texture, the bootloader loads both images and merges into one texture.

I know that this is just a workaround, but at least it gives the correct result. And yes, it is very annoying that iOS does not allow you to download textures from PNG without previously multiplied alpha.

0
source

All Articles