From 039455ef3078ccb9f096bd0232a6110c596bb9d1 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 4 Dec 2009 17:24:27 +0000 Subject: [PATCH] Converted tabs to four space --- .../imageio/ReaderWriterImageIO.cpp | 1736 ++++++++--------- 1 file changed, 868 insertions(+), 868 deletions(-) diff --git a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp index 9fe997ffe..919e219b1 100644 --- a/src/osgPlugins/imageio/ReaderWriterImageIO.cpp +++ b/src/osgPlugins/imageio/ReaderWriterImageIO.cpp @@ -46,40 +46,40 @@ // to a Quartz buffer (supplied by Apple framework). size_t MyProviderGetBytesCallback(void* istream_userdata, void* quartz_buffer, size_t the_count) { - std::istream* the_istream = (std::istream*)istream_userdata; - the_istream->read((char*)quartz_buffer, the_count); - return the_istream->gcount(); // return the actual number of bytes read + std::istream* the_istream = (std::istream*)istream_userdata; + the_istream->read((char*)quartz_buffer, the_count); + return the_istream->gcount(); // return the actual number of bytes read } // This callback is triggered when the data provider is released // so you can clean up any resources. void MyProviderReleaseInfoCallback(void* istream_userdata) { - // What should I put here? Do I need to close the istream? - // The png and tga don't seem to. -// std::istream* the_istream = (std::istream*)istream_userdata; + // What should I put here? Do I need to close the istream? + // The png and tga don't seem to. +// std::istream* the_istream = (std::istream*)istream_userdata; } void MyProviderRewindCallback(void* istream_userdata) { - std::istream* the_istream = (std::istream*)istream_userdata; - the_istream->seekg(0, std::ios::beg); + std::istream* the_istream = (std::istream*)istream_userdata; + the_istream->seekg(0, std::ios::beg); } #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // CGDataProviderCreateSequential was introduced in 10.5; CGDataProviderCreate is deprecated off_t MyProviderSkipForwardBytesCallback(void* istream_userdata, off_t the_count) { - std::istream* the_istream = (std::istream*)istream_userdata; + std::istream* the_istream = (std::istream*)istream_userdata; off_t start_position = the_istream->tellg(); - the_istream->seekg(the_count, std::ios::cur); + the_istream->seekg(the_count, std::ios::cur); off_t end_position = the_istream->tellg(); return (end_position - start_position); } #else // CGDataProviderCreate was deprecated in 10.5 void MyProviderSkipBytesCallback(void* istream_userdata, size_t the_count) { - std::istream* the_istream = (std::istream*)istream_userdata; - the_istream->seekg(the_count, std::ios::cur); + std::istream* the_istream = (std::istream*)istream_userdata; + the_istream->seekg(the_count, std::ios::cur); } #endif @@ -93,17 +93,17 @@ void MyProviderSkipBytesCallback(void* istream_userdata, size_t the_count) **************************************************************/ size_t MyConsumerPutBytesCallback(void* ostream_userdata, const void* quartz_buffer, size_t the_count) { - std::ostream* the_ostream = (std::ostream*)ostream_userdata; - the_ostream->write((char*)quartz_buffer, the_count); - // Don't know how to get number of bytes actually written, so - // just returning the_count. - return the_count; + std::ostream* the_ostream = (std::ostream*)ostream_userdata; + the_ostream->write((char*)quartz_buffer, the_count); + // Don't know how to get number of bytes actually written, so + // just returning the_count. + return the_count; } void MyConsumerReleaseInfoCallback(void* ostream_userdata) { - std::ostream* the_ostream = (std::ostream*)ostream_userdata; - the_ostream->flush(); + std::ostream* the_ostream = (std::ostream*)ostream_userdata; + the_ostream->flush(); } /************************************************************** ***** End Callback functions for ostream block writing ******** @@ -119,61 +119,61 @@ CGImageRef CreateCGImageFromDataStream(std::istream& fin) { CGImageRef image_ref = NULL; CGImageSourceRef source_ref; - /* The easy way would be to use CGImageSourceCreateWithData, - * but this presumes you have a known fixed-length buffer of data. - * The istream makes this harder to know, so we use the ProviderCallbacks APIs - CFDataRef the_cf_data = CFDataCreateWithBytesNoCopy( - kCFAllocatorDefault, - (const UInt8*)the_data, - CFIndex length, - kCFAllocatorNull // do not free data buffer, must do it yourself - ); + /* The easy way would be to use CGImageSourceCreateWithData, + * but this presumes you have a known fixed-length buffer of data. + * The istream makes this harder to know, so we use the ProviderCallbacks APIs + CFDataRef the_cf_data = CFDataCreateWithBytesNoCopy( + kCFAllocatorDefault, + (const UInt8*)the_data, + CFIndex length, + kCFAllocatorNull // do not free data buffer, must do it yourself + ); source_ref = CGImageSourceCreateWithData(the_cf_data, NULL); */ #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // CGDataProviderCreateSequential was introduced in 10.5; CGDataProviderCreate is deprecated - CGDataProviderSequentialCallbacks provider_callbacks = - { + CGDataProviderSequentialCallbacks provider_callbacks = + { 0, - MyProviderGetBytesCallback, - MyProviderSkipForwardBytesCallback, - MyProviderRewindCallback, - MyProviderReleaseInfoCallback - }; - - CGDataProviderRef data_provider = CGDataProviderCreateSequential(&fin, &provider_callbacks); + MyProviderGetBytesCallback, + MyProviderSkipForwardBytesCallback, + MyProviderRewindCallback, + MyProviderReleaseInfoCallback + }; + + CGDataProviderRef data_provider = CGDataProviderCreateSequential(&fin, &provider_callbacks); #else // CGDataProviderCreate was deprecated in 10.5 - CGDataProviderCallbacks provider_callbacks = - { - MyProviderGetBytesCallback, - MyProviderSkipBytesCallback, - MyProviderRewindCallback, - MyProviderReleaseInfoCallback - }; - - CGDataProviderRef data_provider = CGDataProviderCreate(&fin, &provider_callbacks); + CGDataProviderCallbacks provider_callbacks = + { + MyProviderGetBytesCallback, + MyProviderSkipBytesCallback, + MyProviderRewindCallback, + MyProviderReleaseInfoCallback + }; + + CGDataProviderRef data_provider = CGDataProviderCreate(&fin, &provider_callbacks); #endif - // If we had a way of hinting at what the data type is, we could - // pass this hint in the second parameter. - source_ref = CGImageSourceCreateWithDataProvider(data_provider, NULL); + // If we had a way of hinting at what the data type is, we could + // pass this hint in the second parameter. + source_ref = CGImageSourceCreateWithDataProvider(data_provider, NULL); - CGDataProviderRelease(data_provider); + CGDataProviderRelease(data_provider); if(!source_ref) - { - return NULL; - } + { + return NULL; + } - image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); - - /* Don't need the SourceRef any more (error or not) */ - CFRelease(source_ref); + image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); + + /* Don't need the SourceRef any more (error or not) */ + CFRelease(source_ref); - return image_ref; + return image_ref; } @@ -184,217 +184,217 @@ CGImageRef CreateCGImageFromFile(const char* the_path) CFURLRef the_url = NULL; CGImageRef image_ref = NULL; CGImageSourceRef source_ref = NULL; - CFStringRef cf_string = NULL; + CFStringRef cf_string = NULL; - /* Create a CFString from a C string */ - cf_string = CFStringCreateWithCString( - NULL, - the_path, - kCFStringEncodingUTF8 - ); - if(!cf_string) - { - osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CCFSTring" << std::endl; + /* Create a CFString from a C string */ + cf_string = CFStringCreateWithCString( + NULL, + the_path, + kCFStringEncodingUTF8 + ); + if(!cf_string) + { + osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CCFSTring" << std::endl; return NULL; - } + } - /* Create a CFURL from a CFString */ + /* Create a CFURL from a CFString */ the_url = CFURLCreateWithFileSystemPath( - NULL, - cf_string, - kCFURLPOSIXPathStyle, - false - ); + NULL, + cf_string, + kCFURLPOSIXPathStyle, + false + ); - /* Don't need the CFString any more (error or not) */ - CFRelease(cf_string); - - if(!the_url) - { - osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CFUrl" << std::endl; - return NULL; - } - - - source_ref = CGImageSourceCreateWithURL(the_url, NULL); - /* Don't need the URL any more (error or not) */ - CFRelease(the_url); - - if(!source_ref) - { - osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create ImageSource" << std::endl; + /* Don't need the CFString any more (error or not) */ + CFRelease(cf_string); + + if(!the_url) + { + osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CFUrl" << std::endl; return NULL; } - // Get the first item in the image source (some image formats may - // contain multiple items). - image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); - if (!image_ref) { + + source_ref = CGImageSourceCreateWithURL(the_url, NULL); + /* Don't need the URL any more (error or not) */ + CFRelease(the_url); + + if(!source_ref) + { + osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create ImageSource" << std::endl; + return NULL; + } + + // Get the first item in the image source (some image formats may + // contain multiple items). + image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); + if (!image_ref) { osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not get Image" << std::endl; } - /* Don't need the SourceRef any more (error or not) */ - CFRelease(source_ref); + /* Don't need the SourceRef any more (error or not) */ + CFRelease(source_ref); - return image_ref; + return image_ref; } /* Once we have our image (CGImageRef), we need to get it into an osg::Image */ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) { - /* This code is adapted from Apple's Documentation found here: - * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html - * Listing 9-4††Using a Quartz image as a texture source. - * Unfortunately, this guide doesn't show what to do about - * non-RGBA image formats so I'm making the rest up - * (and it's probably all wrong). - */ + /* This code is adapted from Apple's Documentation found here: + * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html + * Listing 9-4††Using a Quartz image as a texture source. + * Unfortunately, this guide doesn't show what to do about + * non-RGBA image formats so I'm making the rest up + * (and it's probably all wrong). + */ - size_t the_width = CGImageGetWidth(image_ref); - size_t the_height = CGImageGetHeight(image_ref); - CGRect the_rect = {{0, 0}, {the_width, the_height}}; + size_t the_width = CGImageGetWidth(image_ref); + size_t the_height = CGImageGetHeight(image_ref); + CGRect the_rect = {{0, 0}, {the_width, the_height}}; - size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); - size_t bytes_per_row = CGImageGetBytesPerRow(image_ref); -// size_t bits_per_component = CGImageGetBitsPerComponent(image_ref); - size_t bits_per_component = 8; - - CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref); - - GLint internal_format; - GLenum pixel_format; - GLenum data_type; - - void* image_data = calloc(the_width * 4, the_height); + size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); + size_t bytes_per_row = CGImageGetBytesPerRow(image_ref); +// size_t bits_per_component = CGImageGetBitsPerComponent(image_ref); + size_t bits_per_component = 8; + + CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref); + + GLint internal_format; + GLenum pixel_format; + GLenum data_type; + + void* image_data = calloc(the_width * 4, the_height); - CGColorSpaceRef color_space; - CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); + CGColorSpaceRef color_space; + CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); - switch(bits_per_pixel) - { - // Drat, if 8-bit, how do you distinguish - // between a 256 color GIF, a LUMINANCE map - // or an ALPHA map? - case 8: - { - // I probably did the formats all wrong for this case, - // especially the ALPHA case. - if(kCGImageAlphaNone == alpha_info) - { - /* - internal_format = GL_LUMINANCE; - pixel_format = GL_LUMINANCE; - */ - internal_format = GL_RGBA8; - pixel_format = GL_BGRA_EXT; - data_type = GL_UNSIGNED_INT_8_8_8_8_REV; - - bytes_per_row = the_width*4; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - color_space = CGColorSpaceCreateDeviceRGB(); -// bitmap_info = kCGImageAlphaPremultipliedFirst; + switch(bits_per_pixel) + { + // Drat, if 8-bit, how do you distinguish + // between a 256 color GIF, a LUMINANCE map + // or an ALPHA map? + case 8: + { + // I probably did the formats all wrong for this case, + // especially the ALPHA case. + if(kCGImageAlphaNone == alpha_info) + { + /* + internal_format = GL_LUMINANCE; + pixel_format = GL_LUMINANCE; + */ + internal_format = GL_RGBA8; + pixel_format = GL_BGRA_EXT; + data_type = GL_UNSIGNED_INT_8_8_8_8_REV; + + bytes_per_row = the_width*4; +// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + color_space = CGColorSpaceCreateDeviceRGB(); +// bitmap_info = kCGImageAlphaPremultipliedFirst; #if __BIG_ENDIAN__ - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif - } - else - { - internal_format = GL_ALPHA; - pixel_format = GL_ALPHA; - data_type = GL_UNSIGNED_BYTE; - // bytes_per_row = the_width; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); - color_space = CGColorSpaceCreateDeviceGray(); - } + } + else + { + internal_format = GL_ALPHA; + pixel_format = GL_ALPHA; + data_type = GL_UNSIGNED_BYTE; + // bytes_per_row = the_width; +// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + color_space = CGColorSpaceCreateDeviceGray(); + } - break; - } - case 16: - { - // FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA? - internal_format = GL_LUMINANCE_ALPHA; - pixel_format = GL_LUMINANCE_ALPHA; - data_type = GL_UNSIGNED_BYTE; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); - color_space = CGColorSpaceCreateDeviceGray(); - break; - } - case 24: - { - internal_format = GL_RGBA8; - pixel_format = GL_BGRA_EXT; - data_type = GL_UNSIGNED_INT_8_8_8_8_REV; - bytes_per_row = the_width*4; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - color_space = CGColorSpaceCreateDeviceRGB(); -// bitmap_info = kCGImageAlphaNone; + break; + } + case 16: + { + // FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA? + internal_format = GL_LUMINANCE_ALPHA; + pixel_format = GL_LUMINANCE_ALPHA; + data_type = GL_UNSIGNED_BYTE; +// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + color_space = CGColorSpaceCreateDeviceGray(); + break; + } + case 24: + { + internal_format = GL_RGBA8; + pixel_format = GL_BGRA_EXT; + data_type = GL_UNSIGNED_INT_8_8_8_8_REV; + bytes_per_row = the_width*4; +// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + color_space = CGColorSpaceCreateDeviceRGB(); +// bitmap_info = kCGImageAlphaNone; #if __BIG_ENDIAN__ - bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ + bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else - bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ + bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif - break; - } - case 32: - { - - internal_format = GL_RGBA8; - pixel_format = GL_BGRA_EXT; - data_type = GL_UNSIGNED_INT_8_8_8_8_REV; - - bytes_per_row = the_width*4; -// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - color_space = CGColorSpaceCreateDeviceRGB(); -// bitmap_info = kCGImageAlphaPremultipliedFirst; + break; + } + case 32: + { + + internal_format = GL_RGBA8; + pixel_format = GL_BGRA_EXT; + data_type = GL_UNSIGNED_INT_8_8_8_8_REV; + + bytes_per_row = the_width*4; +// color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + color_space = CGColorSpaceCreateDeviceRGB(); +// bitmap_info = kCGImageAlphaPremultipliedFirst; #if __BIG_ENDIAN__ - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif - break; - } - default: - { - // osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl; + break; + } + default: + { + // osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl; return NULL; break; - } + } - } - - // Sets up a context to be drawn to with image_data as the area to be drawn to - CGContextRef bitmap_context = CGBitmapContextCreate( - image_data, - the_width, - the_height, - bits_per_component, - bytes_per_row, - color_space, - bitmap_info - ); - - // Draws the image into the context's image_data - CGContextDrawImage(bitmap_context, the_rect, image_ref); + } + + // Sets up a context to be drawn to with image_data as the area to be drawn to + CGContextRef bitmap_context = CGBitmapContextCreate( + image_data, + the_width, + the_height, + bits_per_component, + bytes_per_row, + color_space, + bitmap_info + ); + + // Draws the image into the context's image_data + CGContextDrawImage(bitmap_context, the_rect, image_ref); - CGContextRelease(bitmap_context); + CGContextRelease(bitmap_context); - osg::Image* osg_image = new osg::Image; - - osg_image->setImage( - the_width, - the_height, - 1, - internal_format, - pixel_format, - data_type, - (unsigned char*)image_data, - osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free - ); + osg::Image* osg_image = new osg::Image; + + osg_image->setImage( + the_width, + the_height, + 1, + internal_format, + pixel_format, + data_type, + (unsigned char*)image_data, + osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free + ); - osg_image->flipVertical(); - return osg_image; + osg_image->flipVertical(); + return osg_image; @@ -414,310 +414,310 @@ osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) */ CGImageRef CreateCGImageFromOSGData(const osg::Image& osg_image) { - size_t image_width = osg_image.s(); - size_t image_height = osg_image.t(); - /* From Apple's header for CGBitmapContextCreate() - * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at - * least `(width * bitsPerComponent * number of components + 7)/8' bytes. - */ - size_t target_bytes_per_row; - - CGColorSpaceRef color_space; - CGBitmapInfo bitmap_info; - /* From what I can figure out so far... - * We need to create a CGContext connected to the data we want to save - * and then call CGBitmapContextCreateImage() on that context to get - * a CGImageRef. - * However, OS X only allows 4-component image formats (e.g. RGBA) and not - * just RGB for the RGB-based CGContext. So for a 24-bit image coming in, - * we need to expand the data to 32-bit. - * The easiest and fastest way to do that is through the vImage framework - * which is part of the Accelerate framework. - * Also, the osg::Image data coming in is inverted from what we want, so - * we need to invert the image too. Since the osg::Image is const, - * we don't want to touch the data, so again we turn to the vImage framework - * and invert the data. - */ - vImage_Buffer vimage_buffer_in = - { - (void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe - image_height, - image_width, - osg_image.getRowSizeInBytes() - }; + size_t image_width = osg_image.s(); + size_t image_height = osg_image.t(); + /* From Apple's header for CGBitmapContextCreate() + * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at + * least `(width * bitsPerComponent * number of components + 7)/8' bytes. + */ + size_t target_bytes_per_row; + + CGColorSpaceRef color_space; + CGBitmapInfo bitmap_info; + /* From what I can figure out so far... + * We need to create a CGContext connected to the data we want to save + * and then call CGBitmapContextCreateImage() on that context to get + * a CGImageRef. + * However, OS X only allows 4-component image formats (e.g. RGBA) and not + * just RGB for the RGB-based CGContext. So for a 24-bit image coming in, + * we need to expand the data to 32-bit. + * The easiest and fastest way to do that is through the vImage framework + * which is part of the Accelerate framework. + * Also, the osg::Image data coming in is inverted from what we want, so + * we need to invert the image too. Since the osg::Image is const, + * we don't want to touch the data, so again we turn to the vImage framework + * and invert the data. + */ + vImage_Buffer vimage_buffer_in = + { + (void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe + image_height, + image_width, + osg_image.getRowSizeInBytes() + }; - void* out_image_data; - vImage_Buffer vimage_buffer_out = - { - NULL, // will fill-in in switch - image_height, - image_width, - 0 // will fill-in in switch - }; - vImage_Error vimage_error_flag; + void* out_image_data; + vImage_Buffer vimage_buffer_out = + { + NULL, // will fill-in in switch + image_height, + image_width, + 0 // will fill-in in switch + }; + vImage_Error vimage_error_flag; - // FIXME: Do I want to use format, type, or internalFormat? - switch(osg_image.getPixelFormat()) - { - case GL_LUMINANCE: - { - bitmap_info = kCGImageAlphaNone; - target_bytes_per_row = (image_width * 8 + 7)/8; - color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); - if(NULL == color_space) - { - return NULL; - } - - // out_image_data = calloc(target_bytes_per_row, image_height); - out_image_data = malloc(target_bytes_per_row * image_height); - if(NULL == out_image_data) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; - CGColorSpaceRelease(color_space); - return NULL; - } + // FIXME: Do I want to use format, type, or internalFormat? + switch(osg_image.getPixelFormat()) + { + case GL_LUMINANCE: + { + bitmap_info = kCGImageAlphaNone; + target_bytes_per_row = (image_width * 8 + 7)/8; + color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); + if(NULL == color_space) + { + return NULL; + } + + // out_image_data = calloc(target_bytes_per_row, image_height); + out_image_data = malloc(target_bytes_per_row * image_height); + if(NULL == out_image_data) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; + CGColorSpaceRelease(color_space); + return NULL; + } - vimage_buffer_out.data = out_image_data; - vimage_buffer_out.rowBytes = target_bytes_per_row; + vimage_buffer_out.data = out_image_data; + vimage_buffer_out.rowBytes = target_bytes_per_row; - // Now invert the image - vimage_error_flag = vImageVerticalReflect_Planar8( - &vimage_buffer_in, // since the osg_image is const... - &vimage_buffer_out, // don't reuse the buffer - kvImageNoFlags - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - CGColorSpaceRelease(color_space); - return NULL; - } + // Now invert the image + vimage_error_flag = vImageVerticalReflect_Planar8( + &vimage_buffer_in, // since the osg_image is const... + &vimage_buffer_out, // don't reuse the buffer + kvImageNoFlags + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + CGColorSpaceRelease(color_space); + return NULL; + } - break; - } - case GL_ALPHA: - { - bitmap_info = kCGImageAlphaOnly; - target_bytes_per_row = (image_width * 8 + 7)/8; - // According to: - // http://developer.apple.com/qa/qa2001/qa1037.html - // colorSpace=NULL is for alpha only - color_space = NULL; - - // out_image_data = calloc(target_bytes_per_row, image_height); - out_image_data = malloc(target_bytes_per_row * image_height); - if(NULL == out_image_data) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; - return NULL; - } + break; + } + case GL_ALPHA: + { + bitmap_info = kCGImageAlphaOnly; + target_bytes_per_row = (image_width * 8 + 7)/8; + // According to: + // http://developer.apple.com/qa/qa2001/qa1037.html + // colorSpace=NULL is for alpha only + color_space = NULL; + + // out_image_data = calloc(target_bytes_per_row, image_height); + out_image_data = malloc(target_bytes_per_row * image_height); + if(NULL == out_image_data) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; + return NULL; + } - vimage_buffer_out.data = out_image_data; - vimage_buffer_out.rowBytes = target_bytes_per_row; + vimage_buffer_out.data = out_image_data; + vimage_buffer_out.rowBytes = target_bytes_per_row; - // Now invert the image - vimage_error_flag = vImageVerticalReflect_Planar8( - &vimage_buffer_in, // since the osg_image is const... - &vimage_buffer_out, // don't reuse the buffer - kvImageNoFlags - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - return NULL; - } + // Now invert the image + vimage_error_flag = vImageVerticalReflect_Planar8( + &vimage_buffer_in, // since the osg_image is const... + &vimage_buffer_out, // don't reuse the buffer + kvImageNoFlags + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + return NULL; + } - break; - } + break; + } /* - case GL_LUMINANCE_ALPHA: - { - // I don't know if we can support this. - // The qa1037 doesn't show both gray+alpha. - break; - } + case GL_LUMINANCE_ALPHA: + { + // I don't know if we can support this. + // The qa1037 doesn't show both gray+alpha. + break; + } */ - case GL_RGB: - { - bitmap_info = kCGImageAlphaNoneSkipFirst; - target_bytes_per_row = (image_width * 8 * 4 + 7)/8; - color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if(NULL == color_space) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; - return NULL; - } - - // out_image_data = calloc(target_bytes_per_row, image_height); - out_image_data = malloc(target_bytes_per_row * image_height); - if(NULL == out_image_data) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; - CGColorSpaceRelease(color_space); - return NULL; - } + case GL_RGB: + { + bitmap_info = kCGImageAlphaNoneSkipFirst; + target_bytes_per_row = (image_width * 8 * 4 + 7)/8; + color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + if(NULL == color_space) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; + return NULL; + } + + // out_image_data = calloc(target_bytes_per_row, image_height); + out_image_data = malloc(target_bytes_per_row * image_height); + if(NULL == out_image_data) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; + CGColorSpaceRelease(color_space); + return NULL; + } - // Use vImage to get an RGB buffer into ARGB. - vimage_buffer_out.data = out_image_data; - vimage_buffer_out.rowBytes = target_bytes_per_row; - vimage_error_flag = vImageConvert_RGB888toARGB8888( - &vimage_buffer_in, - NULL, // we don't have a buffer containing alpha values - 255, // The alpha value we want given to all pixels since we don't have a buffer - &vimage_buffer_out, - 0, // premultiply? - kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - CGColorSpaceRelease(color_space); - return NULL; - } - // Now invert the image - vimage_error_flag = vImageVerticalReflect_ARGB8888( - &vimage_buffer_out, - &vimage_buffer_out, // reuse the same buffer - kvImageNoFlags - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - CGColorSpaceRelease(color_space); - return NULL; - } - - break; - } - case GL_RGBA: - { - bitmap_info = kCGImageAlphaPremultipliedLast; - target_bytes_per_row = osg_image.getRowSizeInBytes(); - color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if(NULL == color_space) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; - return NULL; - } - // out_image_data = calloc(target_bytes_per_row, image_height); - out_image_data = malloc(target_bytes_per_row * image_height); - if(NULL == out_image_data) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; - CGColorSpaceRelease(color_space); - return NULL; - } - vimage_buffer_out.data = out_image_data; - vimage_buffer_out.rowBytes = target_bytes_per_row; - // Invert the image - vimage_error_flag = vImageVerticalReflect_ARGB8888( - &vimage_buffer_in, // since the osg_image is const... - &vimage_buffer_out, // don't reuse the buffer - kvImageNoFlags - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - CGColorSpaceRelease(color_space); - return NULL; - } - break; - } - case GL_BGRA: - { - if(GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType()) - { + // Use vImage to get an RGB buffer into ARGB. + vimage_buffer_out.data = out_image_data; + vimage_buffer_out.rowBytes = target_bytes_per_row; + vimage_error_flag = vImageConvert_RGB888toARGB8888( + &vimage_buffer_in, + NULL, // we don't have a buffer containing alpha values + 255, // The alpha value we want given to all pixels since we don't have a buffer + &vimage_buffer_out, + 0, // premultiply? + kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + CGColorSpaceRelease(color_space); + return NULL; + } + // Now invert the image + vimage_error_flag = vImageVerticalReflect_ARGB8888( + &vimage_buffer_out, + &vimage_buffer_out, // reuse the same buffer + kvImageNoFlags + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + CGColorSpaceRelease(color_space); + return NULL; + } + + break; + } + case GL_RGBA: + { + bitmap_info = kCGImageAlphaPremultipliedLast; + target_bytes_per_row = osg_image.getRowSizeInBytes(); + color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + if(NULL == color_space) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; + return NULL; + } + // out_image_data = calloc(target_bytes_per_row, image_height); + out_image_data = malloc(target_bytes_per_row * image_height); + if(NULL == out_image_data) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; + CGColorSpaceRelease(color_space); + return NULL; + } + vimage_buffer_out.data = out_image_data; + vimage_buffer_out.rowBytes = target_bytes_per_row; + // Invert the image + vimage_error_flag = vImageVerticalReflect_ARGB8888( + &vimage_buffer_in, // since the osg_image is const... + &vimage_buffer_out, // don't reuse the buffer + kvImageNoFlags + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + CGColorSpaceRelease(color_space); + return NULL; + } + break; + } + case GL_BGRA: + { + if(GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType()) + { #if __BIG_ENDIAN__ - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ #else - bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ + bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ #endif - } - else - { - // FIXME: Don't know how to handle this case - bitmap_info = kCGImageAlphaPremultipliedLast; - } + } + else + { + // FIXME: Don't know how to handle this case + bitmap_info = kCGImageAlphaPremultipliedLast; + } - target_bytes_per_row = osg_image.getRowSizeInBytes(); - color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - if(NULL == color_space) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; - return NULL; - } - // out_image_data = calloc(target_bytes_per_row, image_height); - out_image_data = malloc(target_bytes_per_row * image_height); - if(NULL == out_image_data) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; - CGColorSpaceRelease(color_space); - return NULL; - } - vimage_buffer_out.data = out_image_data; - vimage_buffer_out.rowBytes = target_bytes_per_row; - // Invert the image - vimage_error_flag = vImageVerticalReflect_ARGB8888( - &vimage_buffer_in, // since the osg_image is const... - &vimage_buffer_out, // don't reuse the buffer - kvImageNoFlags - ); - if(vimage_error_flag != kvImageNoError) - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; - free(out_image_data); - CGColorSpaceRelease(color_space); - return NULL; - } - break; - } - // FIXME: Handle other cases. - // Use vImagePermuteChannels_ARGB8888 to swizzle bytes - default: - { - osg::notify(osg::WARN) << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl; - return NULL; - break; - } - } + target_bytes_per_row = osg_image.getRowSizeInBytes(); + color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); + if(NULL == color_space) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; + return NULL; + } + // out_image_data = calloc(target_bytes_per_row, image_height); + out_image_data = malloc(target_bytes_per_row * image_height); + if(NULL == out_image_data) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; + CGColorSpaceRelease(color_space); + return NULL; + } + vimage_buffer_out.data = out_image_data; + vimage_buffer_out.rowBytes = target_bytes_per_row; + // Invert the image + vimage_error_flag = vImageVerticalReflect_ARGB8888( + &vimage_buffer_in, // since the osg_image is const... + &vimage_buffer_out, // don't reuse the buffer + kvImageNoFlags + ); + if(vimage_error_flag != kvImageNoError) + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; + free(out_image_data); + CGColorSpaceRelease(color_space); + return NULL; + } + break; + } + // FIXME: Handle other cases. + // Use vImagePermuteChannels_ARGB8888 to swizzle bytes + default: + { + osg::notify(osg::WARN) << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl; + return NULL; + break; + } + } - CGContextRef bitmap_context = CGBitmapContextCreate( - vimage_buffer_out.data, - vimage_buffer_out.width, - vimage_buffer_out.height, - 8, - vimage_buffer_out.rowBytes, - color_space, - bitmap_info - ); - /* Done with color space */ - CGColorSpaceRelease(color_space); + CGContextRef bitmap_context = CGBitmapContextCreate( + vimage_buffer_out.data, + vimage_buffer_out.width, + vimage_buffer_out.height, + 8, + vimage_buffer_out.rowBytes, + color_space, + bitmap_info + ); + /* Done with color space */ + CGColorSpaceRelease(color_space); - if(NULL == bitmap_context) - { - free(out_image_data); - return NULL; - } - + if(NULL == bitmap_context) + { + free(out_image_data); + return NULL; + } + - /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ - CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context); + /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ + CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context); - /* Done with data */ - free(out_image_data); + /* Done with data */ + free(out_image_data); - /* Done with bitmap_context */ - CGContextRelease(bitmap_context); + /* Done with bitmap_context */ + CGContextRelease(bitmap_context); - return image_ref; + return image_ref; } @@ -726,138 +726,138 @@ CGImageRef CreateCGImageFromOSGData(const osg::Image& osg_image) CGImageDestinationRef CreateCGImageDestinationFromFile(const char* the_path, const osgDB::ReaderWriter::Options* the_options) { CFURLRef the_url = NULL; - CFStringRef cf_string = NULL; - CFStringRef uti_type = NULL; + CFStringRef cf_string = NULL; + CFStringRef uti_type = NULL; CGImageDestinationRef dest_ref = NULL; - bool found_png_option = false; - bool found_jpeg_option = false; - float compression_quality = 1.0f; + bool found_png_option = false; + bool found_jpeg_option = false; + float compression_quality = 1.0f; - /* Create a CFString from a C string */ - cf_string = CFStringCreateWithCString( - NULL, - the_path, - kCFStringEncodingUTF8 - ); - if(!cf_string) - { - return NULL; - } - - /* Create a CFURL from a CFString */ + /* Create a CFString from a C string */ + cf_string = CFStringCreateWithCString( + NULL, + the_path, + kCFStringEncodingUTF8 + ); + if(!cf_string) + { + return NULL; + } + + /* Create a CFURL from a CFString */ the_url = CFURLCreateWithFileSystemPath( - NULL, - cf_string, - kCFURLPOSIXPathStyle, - false - ); - - /* Don't need the CFString any more (error or not) */ - CFRelease(cf_string); - - if(!the_url) - { - return NULL; - } - - if(the_options) - { - std::istringstream iss(the_options->getOptionString()); - std::string opt; - while (iss >> opt) - { - // Not handled: The user could do something stupid and specify both PNG and JPEG options. - - if(opt=="PNG_COMPRESSION") - { - found_png_option = true; - // I don't see an option to set PNG compression levels in the API so this info is unused. - int level; - iss >> level; - - } - else if(opt=="JPEG_QUALITY") - { - found_jpeg_option = true; - // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. - // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. - // I am uncertain what libjpeg's range is. I'm guessing 0-100. - int quality; - iss >> quality; - compression_quality = (float)quality/100.0f; - } - } - } - + NULL, + cf_string, + kCFURLPOSIXPathStyle, + false + ); + + /* Don't need the CFString any more (error or not) */ + CFRelease(cf_string); + + if(!the_url) + { + return NULL; + } + + if(the_options) + { + std::istringstream iss(the_options->getOptionString()); + std::string opt; + while (iss >> opt) + { + // Not handled: The user could do something stupid and specify both PNG and JPEG options. + + if(opt=="PNG_COMPRESSION") + { + found_png_option = true; + // I don't see an option to set PNG compression levels in the API so this info is unused. + int level; + iss >> level; + + } + else if(opt=="JPEG_QUALITY") + { + found_jpeg_option = true; + // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. + // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. + // I am uncertain what libjpeg's range is. I'm guessing 0-100. + int quality; + iss >> quality; + compression_quality = (float)quality/100.0f; + } + } + } + - CFStringRef path_extension = CFURLCopyPathExtension(the_url); - if(NULL == path_extension) - { - if(found_jpeg_option) - { - uti_type = UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - CFSTR("jpg"), - kUTTypeImage // "public.image" - ); - } - else - { - uti_type = UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - CFSTR("png"), - kUTTypeImage // "public.image" - ); - } - } - else - { - uti_type = UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - path_extension, - kUTTypeImage // "public.image" - ); - CFRelease(path_extension); - } + CFStringRef path_extension = CFURLCopyPathExtension(the_url); + if(NULL == path_extension) + { + if(found_jpeg_option) + { + uti_type = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + CFSTR("jpg"), + kUTTypeImage // "public.image" + ); + } + else + { + uti_type = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + CFSTR("png"), + kUTTypeImage // "public.image" + ); + } + } + else + { + uti_type = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + path_extension, + kUTTypeImage // "public.image" + ); + CFRelease(path_extension); + } - - dest_ref = CGImageDestinationCreateWithURL( - the_url, - uti_type, - 1, // image file will contain only one image - NULL - ); + + dest_ref = CGImageDestinationCreateWithURL( + the_url, + uti_type, + 1, // image file will contain only one image + NULL + ); - - CFRelease(uti_type); - CFRelease(the_url); + + CFRelease(uti_type); + CFRelease(the_url); - // Not handled: The user could do something stupid and specify both PNG and JPEG options. - if(found_jpeg_option) - { - // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. - CFStringRef the_keys[1]; - CFNumberRef the_values[1]; - CFDictionaryRef the_dict; - - the_keys[0] = kCGImageDestinationLossyCompressionQuality; - the_values[0] = CFNumberCreate( - NULL, - kCFNumberFloat32Type, - &compression_quality - ); - - the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(the_values[0]); + // Not handled: The user could do something stupid and specify both PNG and JPEG options. + if(found_jpeg_option) + { + // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. + CFStringRef the_keys[1]; + CFNumberRef the_values[1]; + CFDictionaryRef the_dict; + + the_keys[0] = kCGImageDestinationLossyCompressionQuality; + the_values[0] = CFNumberCreate( + NULL, + kCFNumberFloat32Type, + &compression_quality + ); + + the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(the_values[0]); - // Now that we have the dict, actually set the property. - CGImageDestinationSetProperties(dest_ref, the_dict); - - CFRelease(the_dict); - } + // Now that we have the dict, actually set the property. + CGImageDestinationSetProperties(dest_ref, the_dict); + + CFRelease(the_dict); + } - return dest_ref; + return dest_ref; } @@ -865,106 +865,106 @@ CGImageDestinationRef CreateCGImageDestinationFromFile(const char* the_path, co /* Remember to CFRelease when done. */ CGImageDestinationRef CreateCGImageDestinationFromDataStream(std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) { - CFStringRef uti_type = NULL; + CFStringRef uti_type = NULL; CGImageDestinationRef dest_ref = NULL; - bool found_png_option = false; - bool found_jpeg_option = false; - float compression_quality = 1.0f; - - CGDataConsumerCallbacks consumer_callbacks = - { - MyConsumerPutBytesCallback, - MyConsumerReleaseInfoCallback - }; - - CGDataConsumerRef data_consumer = CGDataConsumerCreate(&fout, &consumer_callbacks); + bool found_png_option = false; + bool found_jpeg_option = false; + float compression_quality = 1.0f; + + CGDataConsumerCallbacks consumer_callbacks = + { + MyConsumerPutBytesCallback, + MyConsumerReleaseInfoCallback + }; + + CGDataConsumerRef data_consumer = CGDataConsumerCreate(&fout, &consumer_callbacks); - if(the_options) - { - std::istringstream iss(the_options->getOptionString()); - std::string opt; - while (iss >> opt) - { - // Not handled: The user could do something stupid and specify both PNG and JPEG options. - - if(opt=="PNG_COMPRESSION") - { - found_png_option = true; - // I don't see an option to set PNG compression levels in the API so this info is unused. - int level; - iss >> level; - - } - else if(opt=="JPEG_QUALITY") - { - found_jpeg_option = true; - // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. - // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. - // I am uncertain what libjpeg's range is. I'm guessing 0-100. - int quality; - iss >> quality; - compression_quality = (float)quality/100.0f; - } - } - } - + if(the_options) + { + std::istringstream iss(the_options->getOptionString()); + std::string opt; + while (iss >> opt) + { + // Not handled: The user could do something stupid and specify both PNG and JPEG options. + + if(opt=="PNG_COMPRESSION") + { + found_png_option = true; + // I don't see an option to set PNG compression levels in the API so this info is unused. + int level; + iss >> level; + + } + else if(opt=="JPEG_QUALITY") + { + found_jpeg_option = true; + // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. + // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. + // I am uncertain what libjpeg's range is. I'm guessing 0-100. + int quality; + iss >> quality; + compression_quality = (float)quality/100.0f; + } + } + } + - if(found_jpeg_option) - { - uti_type = UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - CFSTR("jpg"), - kUTTypeImage // "public.image" - ); - } - else // default to png - { - uti_type = UTTypeCreatePreferredIdentifierForTag( - kUTTagClassFilenameExtension, - CFSTR("png"), - kUTTypeImage // "public.image" - ); - } - + if(found_jpeg_option) + { + uti_type = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + CFSTR("jpg"), + kUTTypeImage // "public.image" + ); + } + else // default to png + { + uti_type = UTTypeCreatePreferredIdentifierForTag( + kUTTagClassFilenameExtension, + CFSTR("png"), + kUTTypeImage // "public.image" + ); + } + - // If we had a way of hinting at what the data type is, we could - // pass this hint in the second parameter. - dest_ref = CGImageDestinationCreateWithDataConsumer( - data_consumer, - uti_type, - 1, // image file will contain only one image - NULL - ); - - CGDataConsumerRelease(data_consumer); - CFRelease(uti_type); - - - // Not handled: The user could do something stupid and specify both PNG and JPEG options. - if(found_jpeg_option) - { - // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. - CFStringRef the_keys[1]; - CFNumberRef the_values[1]; - CFDictionaryRef the_dict; - - the_keys[0] = kCGImageDestinationLossyCompressionQuality; - the_values[0] = CFNumberCreate( - NULL, - kCFNumberFloat32Type, - &compression_quality - ); - - the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFRelease(the_values[0]); - - // Now that we have the dict, actually set the property. - CGImageDestinationSetProperties(dest_ref, the_dict); - - CFRelease(the_dict); - } - - return dest_ref; + // If we had a way of hinting at what the data type is, we could + // pass this hint in the second parameter. + dest_ref = CGImageDestinationCreateWithDataConsumer( + data_consumer, + uti_type, + 1, // image file will contain only one image + NULL + ); + + CGDataConsumerRelease(data_consumer); + CFRelease(uti_type); + + + // Not handled: The user could do something stupid and specify both PNG and JPEG options. + if(found_jpeg_option) + { + // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. + CFStringRef the_keys[1]; + CFNumberRef the_values[1]; + CFDictionaryRef the_dict; + + the_keys[0] = kCGImageDestinationLossyCompressionQuality; + the_values[0] = CFNumberCreate( + NULL, + kCFNumberFloat32Type, + &compression_quality + ); + + the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(the_values[0]); + + // Now that we have the dict, actually set the property. + CGImageDestinationSetProperties(dest_ref, the_dict); + + CFRelease(the_dict); + } + + return dest_ref; } /************************************************************** ***** End Support functions for writing (stream and file) ***** @@ -997,14 +997,14 @@ public: supportsExtension("tga", "tga image file"); supportsExtension("targa", "targa image file"); supportsExtension("psd", "psd image file"); - + supportsExtension("pdf", "pdf image file"); supportsExtension("eps", "eps image file"); supportsExtension("epi", "epi image file"); supportsExtension("epsf", "epsf image file"); supportsExtension("epsi", "epsi image file"); supportsExtension("ps", "postscript image file"); - + supportsExtension("dng", "dng image file"); supportsExtension("cr2", "cr2 image file"); supportsExtension("crw", "crw image file"); @@ -1030,20 +1030,20 @@ public: supportsExtension("raw", "raw image file"); } - virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; } + virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; } virtual bool acceptsExtension(const std::string& extension) const { - // ImageIO speaks in UTIs. - // http://developer.apple.com/graphicsimaging/workingwithimageio.html - // The Cocoa drawing guide lists these and says to use the - // imageFileTypes class method of NSImage to get a complete - // list of extensions. But remember ImageIO may support more formats - // than Cocoa. - // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html - // Apple's UTI guide: - // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html + // ImageIO speaks in UTIs. + // http://developer.apple.com/graphicsimaging/workingwithimageio.html + // The Cocoa drawing guide lists these and says to use the + // imageFileTypes class method of NSImage to get a complete + // list of extensions. But remember ImageIO may support more formats + // than Cocoa. + // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html + // Apple's UTI guide: + // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html return osgDB::equalCaseInsensitive(extension,"jpg") || osgDB::equalCaseInsensitive(extension,"jpeg") || @@ -1063,14 +1063,14 @@ public: osgDB::equalCaseInsensitive(extension,"tga") || osgDB::equalCaseInsensitive(extension,"targa") || osgDB::equalCaseInsensitive(extension,"psd") || - + osgDB::equalCaseInsensitive(extension,"pdf") || osgDB::equalCaseInsensitive(extension,"eps") || osgDB::equalCaseInsensitive(extension,"epi") || osgDB::equalCaseInsensitive(extension,"epsf") || osgDB::equalCaseInsensitive(extension,"epsi") || osgDB::equalCaseInsensitive(extension,"ps") || - + osgDB::equalCaseInsensitive(extension,"dng") || osgDB::equalCaseInsensitive(extension,"cr2") || osgDB::equalCaseInsensitive(extension,"crw") || @@ -1097,152 +1097,152 @@ public: } - - ReadResult readImageStream(std::istream& fin) const - { - // Call ImageIO to load the image. - CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin); - if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; + + ReadResult readImageStream(std::istream& fin) const + { + // Call ImageIO to load the image. + CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin); + if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; - // Create an osg::Image from the CGImageRef. - osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); - - CFRelease(cg_image_ref); - return osg_image; - } + // Create an osg::Image from the CGImageRef. + osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); + + CFRelease(cg_image_ref); + return osg_image; + } - virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const - { - ReadResult read_result = readImageStream(fin); - return read_result; - } - - ReadResult readImageFile(const std::string& file_name) const - { - osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl; + virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const + { + ReadResult read_result = readImageStream(fin); + return read_result; + } + + ReadResult readImageFile(const std::string& file_name) const + { + osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl; // Call ImageIO to load the image. - CGImageRef cg_image_ref = CreateCGImageFromFile(file_name.c_str()); - if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; + CGImageRef cg_image_ref = CreateCGImageFromFile(file_name.c_str()); + if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; - // Create an osg::Image from the CGImageRef. - osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); - - CFRelease(cg_image_ref); + // Create an osg::Image from the CGImageRef. + osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); + + CFRelease(cg_image_ref); - return osg_image; - } + return osg_image; + } - virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const - { - std::string ext = osgDB::getLowerCaseFileExtension(file_name); - if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; + virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const + { + std::string ext = osgDB::getLowerCaseFileExtension(file_name); + if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; - std::string full_file_name = osgDB::findDataFile( file_name, the_options ); - if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND; + std::string full_file_name = osgDB::findDataFile( file_name, the_options ); + if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND; #if 1 - ReadResult read_result = readImageFile(full_file_name); + ReadResult read_result = readImageFile(full_file_name); #else - // Only here to help test istream backend. The file version is better because - // the filenname.extension could potentially be used by ImageIO to hint what the format type is. - std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary); - if(!istream) return ReadResult::FILE_NOT_HANDLED; - ReadResult read_result = readImage(istream); + // Only here to help test istream backend. The file version is better because + // the filenname.extension could potentially be used by ImageIO to hint what the format type is. + std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary); + if(!istream) return ReadResult::FILE_NOT_HANDLED; + ReadResult read_result = readImage(istream); #endif - if(read_result.validImage()) - { - read_result.getImage()->setFileName(full_file_name); - } - return read_result; - } + if(read_result.validImage()) + { + read_result.getImage()->setFileName(full_file_name); + } + return read_result; + } - WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const - { - WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; + WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; - CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options); - if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; - - CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); - if(NULL == cg_image_ref) - { - CFRelease(cg_dest_ref); - return WriteResult::ERROR_IN_WRITING_FILE; - } - - CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); - if(CGImageDestinationFinalize(cg_dest_ref)) - { - ret_val = WriteResult::FILE_SAVED; - } - else - { - ret_val = WriteResult::ERROR_IN_WRITING_FILE; - } - - CFRelease(cg_image_ref); - CFRelease(cg_dest_ref); - - return WriteResult::FILE_SAVED; - } - - virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const - { - WriteResult write_result = writeImageStream(osg_image, fout, the_options); - return write_result; - } + CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options); + if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; + + CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); + if(NULL == cg_image_ref) + { + CFRelease(cg_dest_ref); + return WriteResult::ERROR_IN_WRITING_FILE; + } + + CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); + if(CGImageDestinationFinalize(cg_dest_ref)) + { + ret_val = WriteResult::FILE_SAVED; + } + else + { + ret_val = WriteResult::ERROR_IN_WRITING_FILE; + } + + CFRelease(cg_image_ref); + CFRelease(cg_dest_ref); + + return WriteResult::FILE_SAVED; + } + + virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult write_result = writeImageStream(osg_image, fout, the_options); + return write_result; + } - WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const - { - WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; - // Call ImageIO to load the image. - CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options); - if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; + WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const + { + WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; + // Call ImageIO to load the image. + CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options); + if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; - CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); - if(NULL == cg_image_ref) - { - CFRelease(cg_dest_ref); - return WriteResult::ERROR_IN_WRITING_FILE; - } + CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); + if(NULL == cg_image_ref) + { + CFRelease(cg_dest_ref); + return WriteResult::ERROR_IN_WRITING_FILE; + } - CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); - if(CGImageDestinationFinalize(cg_dest_ref)) - { - ret_val = WriteResult::FILE_SAVED; - } - else - { - ret_val = WriteResult::ERROR_IN_WRITING_FILE; - } - - CFRelease(cg_image_ref); - CFRelease(cg_dest_ref); - - return WriteResult::FILE_SAVED; - } + CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); + if(CGImageDestinationFinalize(cg_dest_ref)) + { + ret_val = WriteResult::FILE_SAVED; + } + else + { + ret_val = WriteResult::ERROR_IN_WRITING_FILE; + } + + CFRelease(cg_image_ref); + CFRelease(cg_dest_ref); + + return WriteResult::FILE_SAVED; + } - virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const - { - std::string ext = osgDB::getFileExtension(file_name); - if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; + virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const + { + std::string ext = osgDB::getFileExtension(file_name); + if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; #if 1 - // FIXME: Something may need to provide a proper writable location for the files. - std::string full_file_name; - full_file_name = file_name; - return writeImageFile(osg_image, full_file_name, the_options); + // FIXME: Something may need to provide a proper writable location for the files. + std::string full_file_name; + full_file_name = file_name; + return writeImageFile(osg_image, full_file_name, the_options); #else - // Only here to help test ostream backend. The file version is better because - // the filenname.extension could potentially be used by ImageIO to hint what the format type is. - std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary); - if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; - return writeImage(osg_image, fout, the_options); -#endif - } + // Only here to help test ostream backend. The file version is better because + // the filenname.extension could potentially be used by ImageIO to hint what the format type is. + std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary); + if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; + return writeImage(osg_image, fout, the_options); +#endif + } };