How to decode raw png data from Assimp to CGImage?

746 views Asked by At

I am using Assimp and when using FBX with embedded textures, Assimp provides the embedded texture data in the following struct aiTexture's pcData slot. The documentation for pcData says:

Appropriate decoders (such as libjpeg, libpng, D3DX, DevIL) are required to load theses textures. aiTexture::mWidth specifies the size of the texture data in bytes, aiTexture::pcData is a pointer to the raw image data

I understand that pcData will have the png header, chunks etc and libPNG can give me back the actual image data with other specs (width, height etc).

What is the native iOS/macOS API to do this instead of using libPNG? For example: CGImageCreateWithPNGDataProvider source property describes it as a data provider supplying PNG encoded data. I tried with some code like this but that doesn't work:

                 CGDataProviderRef dataProvider = NULL;
                 dataProvider = CGDataProviderCreateWithData(NULL,
                                                            (const void*)texture->pcData,
                                                             texture->mWidth,
                                                             rgbReleaseRampData);
                  if(dataProvider) {
                        NSLog(@" ********* Created image data provider ");
                  }

                  // fails at this line            
                  CGImageRef  imageRef =   CGImageCreateWithPNGDataProvider(dataProvider, 
                                             NULL,false, kCGRenderingIntentDefault);
1

There are 1 answers

0
3d-indiana-jones On

Well, at least for iOS/macOS; it seems to be a problem with the assimp library.

The following, if not the perfect fix, works:

adding a uint_8 to hold raw image data in texture.h:

uint8_t *rawImageData;

Then reinterpret the pcData in FBXConverter.cpp as such:

 out_tex->pcData = reinterpret_cast< aiTexel * >(const_cast<Video&>( video   
).RelinquishContent());
 out_tex->rawImageData = reinterpret_cast< uint8_t * >(out_tex->pcData);

fixes the above problem. Without reinterpreting the pcData, in iOS/macOS one gets the invalid memory address for the memory buffer.

With the above fix, generating an image object requires only the following:

const struct aiTexture *aiTexture = aiScene->mTextures[index];
NSData *imageData = [NSData dataWithBytes:aiTexture->pcData
                                   length:aiTexture->mWidth];
self.imageDataProvider =
    CGDataProviderCreateWithCFData((CFDataRef)imageData);
NSString* format = [NSString stringWithUTF8String:aiTexture->achFormatHint];
if([format isEqualToString:@"png"]) {
    DLog(@" Created png embedded texture ");
    self.image = CGImageCreateWithPNGDataProvider(
        self.imageDataProvider, NULL, true, kCGRenderingIntentDefault);
}
if([format isEqualToString:@"jpg"]) {
    DLog(@" Created jpg embedded texture");
    self.image = CGImageCreateWithJPEGDataProvider(
        self.imageDataProvider, NULL, true, kCGRenderingIntentDefault);
}

The GH Issue.