The easy answer for trivial cases is to use the CGImageSourceRef:
Code Block Cint main(int argc, const char * argv[]) { |
|
int error = 0; |
id <MTLTexture> tex = MakeMipMapEXRTexture(argc, argv, & error); |
|
|
// load arg1 as the path to the EXR file |
CFStringRef s = CFStringCreateWithCString(NULL, argv[1], kCFStringEncodingUTF8 ); |
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, s, kCFURLPOSIXPathStyle, false); |
CFRelease(s); |
|
// Create a CGImageSource and make a CGImage out of it |
CGImageSourceRef source = CGImageSourceCreateWithURL( url, NULL); |
CFRelease(url); |
CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL); |
CFRelease(source); |
|
// Create a RGBAf16 context and draw the image into it |
CGContextRef context = CGBitmapContextCreate( NULL, |
CGImageGetWidth(image), |
CGImageGetHeight(image), |
16, |
CGImageGetWidth(image) * 8, |
CGColorSpaceCreateWithName( kCGColorSpaceSRGB ), |
kCGBitmapByteOrder16Host | kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents ); |
CGRect where = CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)); |
CGContextClearRect( context, where); |
CGContextDrawImage( context, where, image); |
CGContextFlush(context); |
|
unsigned long width = CGImageGetWidth(image); |
unsigned long height = CGImageGetHeight(image); |
void * bytes = CGBitmapContextGetData(context); |
size_t rowBytes = CGBitmapContextGetBytesPerRow(context); |
|
CGImageRelease(image); |
|
@autoreleasepool { |
id <MTLDevice> device = MTLCreateSystemDefaultDevice(); |
|
MTLTextureDescriptor * d = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat: MTLPixelFormatRGBA16Float |
width: width |
height: height |
mipmapped: NO]; |
id <MTLTexture> tex = [device newTextureWithDescriptor: d]; |
[tex replaceRegion: (MTLRegion){ {0,0,0}, {width, height, 1}} |
mipmapLevel: 0 |
withBytes: bytes |
bytesPerRow: rowBytes]; |
|
} |
|
CGContextRelease(context); |
|
return 0; |
} |
That said, this isn't going to get you very far with complex cases like cube maps, ripmaps/mipmaps and depth buffers, which are also representable in OpenEXR. So there is that. You also need to pay attention to color with OpenEXR. It is encoded in linear gamma, defined by a set of chromaticities, and not something necessarily simple like SRGB. You have to actually look at the chromaticities, for example to distinguish between sRGB, another RGB or XYZ, and sometimes the data is YCbCr which is another level of stuff. In so far as colorspace conversions go, if your drawing pipeline is in linear gamma already, then great! Otherwise, you may find yourself having to do some color conversions so that the artwork in your assets aren't completely off.