If you're using ImageIO to read Radiance .hdr files, and you're getting garbage, check the type parameter you're passing to glTexImage2D. The Apple documentation concerning ImageIO and OpenGL uses the format GL_UNSIGNED_INT_8_8_8_8_REV. While .hdr files are floating point, its the REV you should take note of. The byte ordering of each R, G, B component is individually reversed between what ImageIO provides and OpenGL expects. Simply call glPixelStorei(GL_UNPACK_SWAP_BYTES,1) and things should look a bit more normal.
I hope this saves someone else a few minutes.
Boolean osx_CGImageSupportsFileFormat(std::string format) {
CFArrayRef imageFormats = CGImageSourceCopyTypeIdentifiers();
CFStringRef targetImageFormat = CFStringCreateWithCString( kCFAllocatorDefault, format.c_str(), kCFStringEncodingUTF8 );
CFRange imageFormatsRange = CFRangeMake( 0, CFArrayGetCount( imageFormats ) );
Boolean didContainFormat = CFArrayContainsValue(imageFormats, CFRangeMake(0, CFArrayGetCount(imageFormats)), targetImageFormat);
CFRelease(targetImageFormat);
CFRelease(imageFormats);
return didContainFormat;
}
CGImageRef osx_CGImageCreateFromFile(std::string filename) {
CGImageRef image = 0;
CFStringRef fileString = 0;
CFURLRef fileURL = 0;
CGImageSourceRef imageSource = 0;
CFDictionaryRef imageSourceOptions = 0;
CFStringRef imageSourceKeys[] = { kCGImageSourceShouldAllowFloat, kCGImageSourceShouldCache };
CFBooleanRef imageSourceValues[] = { kCFBooleanTrue, kCFBooleanTrue };
try {
fileString = CFStringCreateWithCString( kCFAllocatorDefault, filename.c_str(), kCFStringEncodingUTF8 );
if (fileString == 0) throw std::runtime_error("CFStringCreateWithCString");
fileURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, fileString, kCFURLPOSIXPathStyle, 0);
if (fileURL == 0) throw std::runtime_error("CFURLCreateWithFileSystemPath");
imageSource = CGImageSourceCreateWithURL(fileURL, 0);
if (imageSource == 0) throw std::runtime_error("CGImageSourceCreateWithURL");
imageSourceOptions = CFDictionaryCreate( kCFAllocatorDefault, (const void**)&imageSourceKeys, (const void**)&imageSourceValues, 1, 0, 0 );
if (imageSourceOptions == 0) throw std::runtime_error("CFDictionaryCreate");
image = CGImageSourceCreateImageAtIndex(imageSource, 0, imageSourceOptions);
if (image == 0) throw std::runtime_error("CGImageSourceCreateImageAtIndex");
}
catch(std::runtime_error &problem) {
std::cerr << problem.what() << std::endl;
}
CFRelease(imageSourceOptions);
CFRelease(imageSource);
CFRelease(fileURL);
CFRelease(fileString);
return image;
}
void osx_CGImageCrossCubeToImageCube(CGImageRef source, ImageCube &imageCube) {
size_t x = CGImageGetWidth(source) / 3;
size_t y = CGImageGetHeight(source) / 4;
assert( x == y ); // Images should be square. Could scale to ensure this instead of aborting.
CGRect imageBounds[6] = {0};
imageBounds[0] = CGRectMake(2*x, y, x, y); // +x 1
imageBounds[1] = CGRectMake(0, y, x, y); // -x 0
imageBounds[2] = CGRectMake(x, 2*y, x, y); // -y 2
imageBounds[3] = CGRectMake(x, 0, x, y); // +y 3
imageBounds[4] = CGRectMake(x, y, x, y); // -z 4
imageBounds[5] = CGRectMake(x, 3*y, x, y); // +z 5
imageCube.size = x;
imageCube.bitsPerComponent = CGImageGetBitsPerComponent(source);
imageCube.numComponents = 4;
const size_t bytesPerRow = imageCube.size * imageCube.numComponents * imageCube.bitsPerComponent / 8;
CGImageRef partitions[6] = {0};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
for (int i = 0; i < 6; ++i) {
imageCube.image[i].resize( imageCube.size * bytesPerRow );
partitions[i] = CGImageCreateWithImageInRect(source, imageBounds[i]);
CGContextRef imageContext = CGBitmapContextCreate( &imageCube.image[i][0],
imageCube.size, imageCube.size,
imageCube.bitsPerComponent,
bytesPerRow,
colorSpace,
kCGImageAlphaNoneSkipLast | kCGBitmapFloatComponents );
CGContextSaveGState(imageContext);
// Up Down and Backwards are flipped in the cube cross format
if ( i == 2 || i == 3 || i == 5 ) {
CGContextTranslateCTM(imageContext, imageCube.size, imageCube.size);
CGContextScaleCTM(imageContext, -1.0f, -1.0f);
}
CGContextDrawImage(imageContext, CGRectMake(0, 0, imageCube.size, imageCube.size), partitions[i]);
CGContextRestoreGState(imageContext);
CGContextRelease(imageContext);
CGImageRelease(partitions[i]);
}
CGColorSpaceRelease(colorSpace);
}
No comments:
Post a Comment