Changeset 10854

Show
Ignore:
Timestamp:
12/04/09 18:24:27 (5 years ago)
Author:
robert
Message:

Converted tabs to four space

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp

    r10623 r10854  
    4747size_t MyProviderGetBytesCallback(void* istream_userdata, void* quartz_buffer, size_t the_count) 
    4848{ 
    49         std::istream* the_istream = (std::istream*)istream_userdata; 
    50         the_istream->read((char*)quartz_buffer, the_count); 
    51         return the_istream->gcount(); // return the actual number of bytes read 
     49    std::istream* the_istream = (std::istream*)istream_userdata; 
     50    the_istream->read((char*)quartz_buffer, the_count); 
     51    return the_istream->gcount(); // return the actual number of bytes read 
    5252} 
    5353 
     
    5656void MyProviderReleaseInfoCallback(void* istream_userdata) 
    5757{ 
    58         // What should I put here? Do I need to close the istream? 
    59         // The png and tga don't seem to. 
    60 //      std::istream* the_istream = (std::istream*)istream_userdata; 
     58    // What should I put here? Do I need to close the istream? 
     59    // The png and tga don't seem to. 
     60//    std::istream* the_istream = (std::istream*)istream_userdata; 
    6161} 
    6262 
    6363void MyProviderRewindCallback(void* istream_userdata) 
    6464{ 
    65         std::istream* the_istream = (std::istream*)istream_userdata; 
    66         the_istream->seekg(0, std::ios::beg); 
     65    std::istream* the_istream = (std::istream*)istream_userdata; 
     66    the_istream->seekg(0, std::ios::beg); 
    6767} 
    6868 
     
    7070off_t MyProviderSkipForwardBytesCallback(void* istream_userdata, off_t the_count) 
    7171{ 
    72         std::istream* the_istream = (std::istream*)istream_userdata; 
     72    std::istream* the_istream = (std::istream*)istream_userdata; 
    7373    off_t start_position = the_istream->tellg(); 
    74         the_istream->seekg(the_count, std::ios::cur); 
     74    the_istream->seekg(the_count, std::ios::cur); 
    7575    off_t end_position = the_istream->tellg(); 
    7676    return (end_position - start_position); 
     
    7979void MyProviderSkipBytesCallback(void* istream_userdata, size_t the_count) 
    8080{ 
    81         std::istream* the_istream = (std::istream*)istream_userdata; 
    82         the_istream->seekg(the_count, std::ios::cur); 
     81    std::istream* the_istream = (std::istream*)istream_userdata; 
     82    the_istream->seekg(the_count, std::ios::cur); 
    8383} 
    8484#endif 
     
    9494size_t MyConsumerPutBytesCallback(void* ostream_userdata, const void* quartz_buffer, size_t the_count) 
    9595{ 
    96         std::ostream* the_ostream = (std::ostream*)ostream_userdata; 
    97         the_ostream->write((char*)quartz_buffer, the_count); 
    98         // Don't know how to get number of bytes actually written, so 
    99         // just returning the_count. 
    100         return the_count; 
     96    std::ostream* the_ostream = (std::ostream*)ostream_userdata; 
     97    the_ostream->write((char*)quartz_buffer, the_count); 
     98    // Don't know how to get number of bytes actually written, so 
     99    // just returning the_count. 
     100    return the_count; 
    101101} 
    102102 
    103103void MyConsumerReleaseInfoCallback(void* ostream_userdata) 
    104104{ 
    105         std::ostream* the_ostream = (std::ostream*)ostream_userdata; 
    106         the_ostream->flush(); 
     105    std::ostream* the_ostream = (std::ostream*)ostream_userdata; 
     106    the_ostream->flush(); 
    107107} 
    108108/************************************************************** 
     
    120120    CGImageRef image_ref = NULL; 
    121121    CGImageSourceRef source_ref; 
    122         /* The easy way would be to use CGImageSourceCreateWithData, 
    123         * but this presumes you have a known fixed-length buffer of data. 
    124         * The istream makes this harder to know, so we use the ProviderCallbacks APIs 
    125         CFDataRef the_cf_data = CFDataCreateWithBytesNoCopy( 
    126                 kCFAllocatorDefault, 
    127                 (const UInt8*)the_data, 
    128                 CFIndex length, 
    129                 kCFAllocatorNull // do not free data buffer, must do it yourself 
    130         ); 
     122    /* The easy way would be to use CGImageSourceCreateWithData, 
     123    * but this presumes you have a known fixed-length buffer of data. 
     124    * The istream makes this harder to know, so we use the ProviderCallbacks APIs 
     125    CFDataRef the_cf_data = CFDataCreateWithBytesNoCopy( 
     126        kCFAllocatorDefault, 
     127        (const UInt8*)the_data, 
     128        CFIndex length, 
     129        kCFAllocatorNull // do not free data buffer, must do it yourself 
     130    ); 
    131131    source_ref = CGImageSourceCreateWithData(the_cf_data, NULL); 
    132132*/ 
    133133 
    134134#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // CGDataProviderCreateSequential was introduced in 10.5; CGDataProviderCreate is deprecated 
    135         CGDataProviderSequentialCallbacks provider_callbacks = 
    136         { 
     135    CGDataProviderSequentialCallbacks provider_callbacks = 
     136    { 
    137137        0, 
    138                 MyProviderGetBytesCallback, 
    139                 MyProviderSkipForwardBytesCallback, 
    140                 MyProviderRewindCallback, 
    141                 MyProviderReleaseInfoCallback 
    142         }; 
    143          
    144         CGDataProviderRef data_provider = CGDataProviderCreateSequential(&fin, &provider_callbacks); 
     138        MyProviderGetBytesCallback, 
     139        MyProviderSkipForwardBytesCallback, 
     140        MyProviderRewindCallback, 
     141        MyProviderReleaseInfoCallback 
     142    }; 
     143     
     144    CGDataProviderRef data_provider = CGDataProviderCreateSequential(&fin, &provider_callbacks); 
    145145 
    146146 
    147147#else // CGDataProviderCreate was deprecated in 10.5 
    148148 
    149         CGDataProviderCallbacks provider_callbacks = 
    150         { 
    151                 MyProviderGetBytesCallback, 
    152                 MyProviderSkipBytesCallback, 
    153                 MyProviderRewindCallback, 
    154                 MyProviderReleaseInfoCallback 
    155         }; 
    156          
    157         CGDataProviderRef data_provider = CGDataProviderCreate(&fin, &provider_callbacks); 
     149    CGDataProviderCallbacks provider_callbacks = 
     150    { 
     151        MyProviderGetBytesCallback, 
     152        MyProviderSkipBytesCallback, 
     153        MyProviderRewindCallback, 
     154        MyProviderReleaseInfoCallback 
     155    }; 
     156     
     157    CGDataProviderRef data_provider = CGDataProviderCreate(&fin, &provider_callbacks); 
    158158#endif 
    159         // If we had a way of hinting at what the data type is, we could 
    160         // pass this hint in the second parameter. 
    161         source_ref = CGImageSourceCreateWithDataProvider(data_provider, NULL); 
    162  
    163         CGDataProviderRelease(data_provider); 
     159    // If we had a way of hinting at what the data type is, we could 
     160    // pass this hint in the second parameter. 
     161    source_ref = CGImageSourceCreateWithDataProvider(data_provider, NULL); 
     162 
     163    CGDataProviderRelease(data_provider); 
    164164 
    165165 
    166166    if(!source_ref) 
    167         { 
    168                 return NULL; 
    169         } 
    170  
    171         image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); 
    172          
    173         /* Don't need the SourceRef any more (error or not) */ 
    174         CFRelease(source_ref); 
    175  
    176         return image_ref; 
     167    { 
     168        return NULL; 
     169    } 
     170 
     171    image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); 
     172     
     173    /* Don't need the SourceRef any more (error or not) */ 
     174    CFRelease(source_ref); 
     175 
     176    return image_ref; 
    177177} 
    178178 
     
    185185    CGImageRef image_ref = NULL; 
    186186    CGImageSourceRef source_ref = NULL; 
    187         CFStringRef cf_string = NULL; 
    188  
    189         /* Create a CFString from a C string */ 
    190         cf_string = CFStringCreateWithCString( 
    191                 NULL, 
    192                 the_path, 
    193                 kCFStringEncodingUTF8 
    194         ); 
    195         if(!cf_string) 
    196         { 
    197                 osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CCFSTring" << std::endl; 
     187    CFStringRef cf_string = NULL; 
     188 
     189    /* Create a CFString from a C string */ 
     190    cf_string = CFStringCreateWithCString( 
     191        NULL, 
     192        the_path, 
     193        kCFStringEncodingUTF8 
     194    ); 
     195    if(!cf_string) 
     196    { 
     197        osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CCFSTring" << std::endl; 
    198198        return NULL; 
    199         } 
     199    } 
    200200  
    201         /* Create a CFURL from a CFString */ 
     201    /* Create a CFURL from a CFString */ 
    202202    the_url = CFURLCreateWithFileSystemPath( 
    203                 NULL,  
    204                 cf_string, 
    205                 kCFURLPOSIXPathStyle, 
    206                 false 
    207         ); 
    208  
    209         /* Don't need the CFString any more (error or not) */ 
    210         CFRelease(cf_string); 
    211          
    212         if(!the_url) 
    213         { 
    214                 osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CFUrl" << std::endl; 
     203        NULL,  
     204        cf_string, 
     205        kCFURLPOSIXPathStyle, 
     206        false 
     207    ); 
     208 
     209    /* Don't need the CFString any more (error or not) */ 
     210    CFRelease(cf_string); 
     211     
     212    if(!the_url) 
     213    { 
     214        osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CFUrl" << std::endl; 
    215215        return NULL; 
    216         } 
    217  
    218          
     216    } 
     217 
     218     
    219219    source_ref = CGImageSourceCreateWithURL(the_url, NULL); 
    220         /* Don't need the URL any more (error or not) */ 
    221         CFRelease(the_url); 
     220    /* Don't need the URL any more (error or not) */ 
     221    CFRelease(the_url); 
    222222 
    223223    if(!source_ref) 
    224         { 
    225                 osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create ImageSource" << std::endl; 
     224    { 
     225        osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create ImageSource" << std::endl; 
    226226        return NULL; 
    227227    } 
    228228 
    229         // Get the first item in the image source (some image formats may 
    230         // contain multiple items). 
    231         image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); 
    232         if (!image_ref) { 
     229    // Get the first item in the image source (some image formats may 
     230    // contain multiple items). 
     231    image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL); 
     232    if (!image_ref) { 
    233233        osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not get Image" << std::endl; 
    234234    } 
    235235     
    236         /* Don't need the SourceRef any more (error or not) */ 
    237         CFRelease(source_ref); 
    238  
    239         return image_ref; 
     236    /* Don't need the SourceRef any more (error or not) */ 
     237    CFRelease(source_ref); 
     238 
     239    return image_ref; 
    240240} 
    241241 
     
    243243osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref) 
    244244{ 
    245         /* This code is adapted from Apple's Documentation found here: 
    246         * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html 
    247         * Listing 9-4††Using a Quartz image as a texture source. 
    248         * Unfortunately, this guide doesn't show what to do about 
    249         * non-RGBA image formats so I'm making the rest up 
    250         * (and it's probably all wrong). 
    251         */ 
    252  
    253         size_t the_width = CGImageGetWidth(image_ref); 
    254         size_t the_height = CGImageGetHeight(image_ref); 
    255         CGRect the_rect = {{0, 0}, {the_width, the_height}}; 
    256  
    257         size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); 
    258         size_t bytes_per_row = CGImageGetBytesPerRow(image_ref); 
    259 //      size_t bits_per_component = CGImageGetBitsPerComponent(image_ref); 
    260         size_t bits_per_component = 8; 
    261          
    262         CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref); 
    263          
    264         GLint internal_format; 
    265         GLenum pixel_format; 
    266         GLenum data_type; 
    267          
    268         void* image_data = calloc(the_width * 4, the_height); 
    269  
    270         CGColorSpaceRef color_space; 
    271         CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); 
    272  
    273         switch(bits_per_pixel) 
    274         { 
    275                 // Drat, if 8-bit, how do you distinguish 
    276                 // between a 256 color GIF, a LUMINANCE map 
    277                 // or an ALPHA map? 
    278                 case 8: 
    279                 { 
    280                         // I probably did the formats all wrong for this case, 
    281                         // especially the ALPHA case. 
    282                         if(kCGImageAlphaNone == alpha_info) 
    283                         { 
    284                                 /* 
    285                                 internal_format = GL_LUMINANCE; 
    286                                 pixel_format = GL_LUMINANCE; 
    287                                 */ 
    288                                 internal_format = GL_RGBA8; 
    289                                 pixel_format = GL_BGRA_EXT; 
    290                                 data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
    291                                  
    292                                 bytes_per_row = the_width*4; 
    293 //                              color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    294                                 color_space = CGColorSpaceCreateDeviceRGB(); 
    295 //                              bitmap_info = kCGImageAlphaPremultipliedFirst; 
     245    /* This code is adapted from Apple's Documentation found here: 
     246    * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html 
     247    * Listing 9-4††Using a Quartz image as a texture source. 
     248    * Unfortunately, this guide doesn't show what to do about 
     249    * non-RGBA image formats so I'm making the rest up 
     250    * (and it's probably all wrong). 
     251    */ 
     252 
     253    size_t the_width = CGImageGetWidth(image_ref); 
     254    size_t the_height = CGImageGetHeight(image_ref); 
     255    CGRect the_rect = {{0, 0}, {the_width, the_height}}; 
     256 
     257    size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref); 
     258    size_t bytes_per_row = CGImageGetBytesPerRow(image_ref); 
     259//    size_t bits_per_component = CGImageGetBitsPerComponent(image_ref); 
     260    size_t bits_per_component = 8; 
     261     
     262    CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref); 
     263     
     264    GLint internal_format; 
     265    GLenum pixel_format; 
     266    GLenum data_type; 
     267     
     268    void* image_data = calloc(the_width * 4, the_height); 
     269 
     270    CGColorSpaceRef color_space; 
     271    CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref); 
     272 
     273    switch(bits_per_pixel) 
     274    { 
     275        // Drat, if 8-bit, how do you distinguish 
     276        // between a 256 color GIF, a LUMINANCE map 
     277        // or an ALPHA map? 
     278        case 8: 
     279        { 
     280            // I probably did the formats all wrong for this case, 
     281            // especially the ALPHA case. 
     282            if(kCGImageAlphaNone == alpha_info) 
     283            { 
     284                /* 
     285                internal_format = GL_LUMINANCE; 
     286                pixel_format = GL_LUMINANCE; 
     287                */ 
     288                internal_format = GL_RGBA8; 
     289                pixel_format = GL_BGRA_EXT; 
     290                data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
     291                 
     292                bytes_per_row = the_width*4; 
     293//                color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     294                color_space = CGColorSpaceCreateDeviceRGB(); 
     295//                bitmap_info = kCGImageAlphaPremultipliedFirst; 
    296296#if __BIG_ENDIAN__ 
    297                                 bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
     297                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
    298298#else 
    299                                 bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
     299                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
    300300#endif  
    301                         } 
    302                         else 
    303                         { 
    304                                 internal_format = GL_ALPHA; 
    305                                 pixel_format = GL_ALPHA; 
    306                                 data_type = GL_UNSIGNED_BYTE; 
    307                                 //                      bytes_per_row = the_width; 
    308 //                              color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
    309                                 color_space = CGColorSpaceCreateDeviceGray(); 
    310                         } 
    311  
    312                         break; 
    313                 } 
    314                 case 16: 
    315                 { 
    316                         // FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA? 
    317                         internal_format = GL_LUMINANCE_ALPHA; 
    318                         pixel_format = GL_LUMINANCE_ALPHA; 
    319                         data_type = GL_UNSIGNED_BYTE; 
    320 //                      color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
    321                         color_space = CGColorSpaceCreateDeviceGray(); 
    322                         break; 
    323                 } 
    324                 case 24: 
    325                 { 
    326                         internal_format = GL_RGBA8; 
    327                         pixel_format = GL_BGRA_EXT; 
    328                         data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
    329                         bytes_per_row = the_width*4; 
    330 //                      color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    331                         color_space = CGColorSpaceCreateDeviceRGB(); 
    332 //                      bitmap_info = kCGImageAlphaNone; 
     301            } 
     302            else 
     303            { 
     304                internal_format = GL_ALPHA; 
     305                pixel_format = GL_ALPHA; 
     306                data_type = GL_UNSIGNED_BYTE; 
     307                //            bytes_per_row = the_width; 
     308//                color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
     309                color_space = CGColorSpaceCreateDeviceGray(); 
     310            } 
     311 
     312            break; 
     313        } 
     314        case 16: 
     315        { 
     316            // FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA? 
     317            internal_format = GL_LUMINANCE_ALPHA; 
     318            pixel_format = GL_LUMINANCE_ALPHA; 
     319            data_type = GL_UNSIGNED_BYTE; 
     320//            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
     321            color_space = CGColorSpaceCreateDeviceGray(); 
     322            break; 
     323        } 
     324        case 24: 
     325        { 
     326            internal_format = GL_RGBA8; 
     327            pixel_format = GL_BGRA_EXT; 
     328            data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
     329            bytes_per_row = the_width*4; 
     330//            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     331            color_space = CGColorSpaceCreateDeviceRGB(); 
     332//            bitmap_info = kCGImageAlphaNone; 
    333333#if __BIG_ENDIAN__ 
    334                         bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
     334            bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
    335335#else 
    336                         bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
     336            bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
    337337#endif        
    338                         break; 
    339                 } 
    340                 case 32: 
    341                 { 
    342                          
    343                         internal_format = GL_RGBA8; 
    344                         pixel_format = GL_BGRA_EXT; 
    345                         data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
    346                          
    347                         bytes_per_row = the_width*4; 
    348 //                      color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    349                         color_space = CGColorSpaceCreateDeviceRGB(); 
    350 //                      bitmap_info = kCGImageAlphaPremultipliedFirst; 
     338            break; 
     339        } 
     340        case 32: 
     341        { 
     342             
     343            internal_format = GL_RGBA8; 
     344            pixel_format = GL_BGRA_EXT; 
     345            data_type = GL_UNSIGNED_INT_8_8_8_8_REV; 
     346             
     347            bytes_per_row = the_width*4; 
     348//            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     349            color_space = CGColorSpaceCreateDeviceRGB(); 
     350//            bitmap_info = kCGImageAlphaPremultipliedFirst; 
    351351#if __BIG_ENDIAN__ 
    352                         bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
     352            bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
    353353#else 
    354                         bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
     354            bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
    355355#endif  
    356                         break; 
    357                 } 
    358                 default: 
    359                 { 
    360                         // osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl; 
     356            break; 
     357        } 
     358        default: 
     359        { 
     360            // osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl; 
    361361            return NULL; 
    362362            break; 
    363                 } 
    364  
    365         } 
    366          
    367         // Sets up a context to be drawn to with image_data as the area to be drawn to 
    368         CGContextRef bitmap_context = CGBitmapContextCreate( 
    369                 image_data, 
    370                 the_width, 
    371                 the_height, 
    372                 bits_per_component, 
    373                 bytes_per_row, 
    374                 color_space, 
    375                 bitmap_info 
    376         ); 
    377          
    378         // Draws the image into the context's image_data 
    379         CGContextDrawImage(bitmap_context, the_rect, image_ref); 
    380  
    381         CGContextRelease(bitmap_context); 
    382  
    383         osg::Image* osg_image = new osg::Image; 
    384          
    385         osg_image->setImage( 
    386                 the_width, 
    387                 the_height, 
    388                 1, 
    389                 internal_format, 
    390                 pixel_format, 
    391                 data_type, 
    392                 (unsigned char*)image_data, 
    393                 osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free 
    394         ); 
    395  
    396         osg_image->flipVertical(); 
    397         return osg_image; 
     363        } 
     364 
     365    } 
     366     
     367    // Sets up a context to be drawn to with image_data as the area to be drawn to 
     368    CGContextRef bitmap_context = CGBitmapContextCreate( 
     369        image_data, 
     370        the_width, 
     371        the_height, 
     372        bits_per_component, 
     373        bytes_per_row, 
     374        color_space, 
     375        bitmap_info 
     376    ); 
     377     
     378    // Draws the image into the context's image_data 
     379    CGContextDrawImage(bitmap_context, the_rect, image_ref); 
     380 
     381    CGContextRelease(bitmap_context); 
     382 
     383    osg::Image* osg_image = new osg::Image; 
     384     
     385    osg_image->setImage( 
     386        the_width, 
     387        the_height, 
     388        1, 
     389        internal_format, 
     390        pixel_format, 
     391        data_type, 
     392        (unsigned char*)image_data, 
     393        osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free 
     394    ); 
     395 
     396    osg_image->flipVertical(); 
     397    return osg_image; 
    398398 
    399399 
     
    415415CGImageRef CreateCGImageFromOSGData(const osg::Image& osg_image) 
    416416{ 
    417         size_t image_width = osg_image.s(); 
    418         size_t image_height = osg_image.t(); 
    419         /* From Apple's header for CGBitmapContextCreate() 
    420         * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at 
    421         * least `(width * bitsPerComponent * number of components + 7)/8' bytes. 
    422         */ 
    423         size_t target_bytes_per_row; 
    424          
    425         CGColorSpaceRef color_space; 
    426         CGBitmapInfo bitmap_info; 
    427         /* From what I can figure out so far... 
    428         * We need to create a CGContext connected to the data we want to save 
    429         * and then call CGBitmapContextCreateImage() on that context to get 
    430         * a CGImageRef. 
    431         * However, OS X only allows 4-component image formats (e.g. RGBA) and not 
    432         * just RGB for the RGB-based CGContext. So for a 24-bit image coming in, 
    433         * we need to expand the data to 32-bit. 
    434         * The easiest and fastest way to do that is through the vImage framework 
    435         * which is part of the Accelerate framework. 
    436         * Also, the osg::Image data coming in is inverted from what we want, so 
    437         * we need to invert the image too. Since the osg::Image is const, 
    438         * we don't want to touch the data, so again we turn to the vImage framework 
    439         * and invert the data. 
    440         */ 
    441         vImage_Buffer vimage_buffer_in =  
    442         { 
    443                 (void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe 
    444                 image_height, 
    445                 image_width, 
    446                 osg_image.getRowSizeInBytes() 
    447         }; 
    448  
    449         void* out_image_data; 
    450         vImage_Buffer vimage_buffer_out = 
    451         { 
    452                 NULL, // will fill-in in switch 
    453                 image_height, 
    454                 image_width, 
    455                 0 // will fill-in in switch 
    456         };       
    457         vImage_Error vimage_error_flag; 
    458  
    459         // FIXME: Do I want to use format, type, or internalFormat? 
    460         switch(osg_image.getPixelFormat()) 
    461         { 
    462                 case GL_LUMINANCE: 
    463                 { 
    464                         bitmap_info = kCGImageAlphaNone; 
    465                         target_bytes_per_row = (image_width * 8 + 7)/8; 
    466                         color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
    467                         if(NULL == color_space) 
    468                         { 
    469                                 return NULL; 
    470                         } 
    471                          
    472                         //      out_image_data = calloc(target_bytes_per_row, image_height); 
    473                         out_image_data = malloc(target_bytes_per_row * image_height);                    
    474                         if(NULL == out_image_data) 
    475                         { 
    476                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
    477                                 CGColorSpaceRelease(color_space); 
    478                                 return NULL; 
    479                         } 
    480  
    481                         vimage_buffer_out.data = out_image_data; 
    482                         vimage_buffer_out.rowBytes = target_bytes_per_row; 
    483  
    484                         // Now invert the image 
    485                         vimage_error_flag = vImageVerticalReflect_Planar8( 
    486                                 &vimage_buffer_in, // since the osg_image is const... 
    487                                 &vimage_buffer_out, // don't reuse the buffer 
    488                                 kvImageNoFlags 
    489                         ); 
    490                         if(vimage_error_flag != kvImageNoError) 
    491                         { 
    492                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    493                                 free(out_image_data); 
    494                                 CGColorSpaceRelease(color_space); 
    495                                 return NULL; 
    496                         }                        
    497  
    498  
    499                         break; 
    500                 } 
    501                 case GL_ALPHA: 
    502                 { 
    503                         bitmap_info = kCGImageAlphaOnly; 
    504                         target_bytes_per_row = (image_width * 8 + 7)/8; 
    505                         // According to: 
    506                         // http://developer.apple.com/qa/qa2001/qa1037.html 
    507                         // colorSpace=NULL is for alpha only 
    508                         color_space = NULL; 
    509                          
    510                         //      out_image_data = calloc(target_bytes_per_row, image_height); 
    511                         out_image_data = malloc(target_bytes_per_row * image_height);                    
    512                         if(NULL == out_image_data) 
    513                         { 
    514                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
    515                                 return NULL; 
    516                         } 
    517  
    518                         vimage_buffer_out.data = out_image_data; 
    519                         vimage_buffer_out.rowBytes = target_bytes_per_row; 
    520  
    521                         // Now invert the image 
    522                         vimage_error_flag = vImageVerticalReflect_Planar8( 
    523                                 &vimage_buffer_in, // since the osg_image is const... 
    524                                 &vimage_buffer_out, // don't reuse the buffer 
    525                                 kvImageNoFlags 
    526                         ); 
    527                         if(vimage_error_flag != kvImageNoError) 
    528                         { 
    529                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    530                                 free(out_image_data); 
    531                                 return NULL; 
    532                         }                        
    533  
    534  
    535                         break; 
    536                 } 
     417    size_t image_width = osg_image.s(); 
     418    size_t image_height = osg_image.t(); 
     419    /* From Apple's header for CGBitmapContextCreate() 
     420    * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at 
     421    * least `(width * bitsPerComponent * number of components + 7)/8' bytes. 
     422    */ 
     423    size_t target_bytes_per_row; 
     424     
     425    CGColorSpaceRef color_space; 
     426    CGBitmapInfo bitmap_info; 
     427    /* From what I can figure out so far... 
     428    * We need to create a CGContext connected to the data we want to save 
     429    * and then call CGBitmapContextCreateImage() on that context to get 
     430    * a CGImageRef. 
     431    * However, OS X only allows 4-component image formats (e.g. RGBA) and not 
     432    * just RGB for the RGB-based CGContext. So for a 24-bit image coming in, 
     433    * we need to expand the data to 32-bit. 
     434    * The easiest and fastest way to do that is through the vImage framework 
     435    * which is part of the Accelerate framework. 
     436    * Also, the osg::Image data coming in is inverted from what we want, so 
     437    * we need to invert the image too. Since the osg::Image is const, 
     438    * we don't want to touch the data, so again we turn to the vImage framework 
     439    * and invert the data. 
     440    */ 
     441    vImage_Buffer vimage_buffer_in =  
     442    { 
     443        (void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe 
     444        image_height, 
     445        image_width, 
     446        osg_image.getRowSizeInBytes() 
     447    }; 
     448 
     449    void* out_image_data; 
     450    vImage_Buffer vimage_buffer_out = 
     451    { 
     452        NULL, // will fill-in in switch 
     453        image_height, 
     454        image_width, 
     455        0 // will fill-in in switch 
     456    };     
     457    vImage_Error vimage_error_flag; 
     458 
     459    // FIXME: Do I want to use format, type, or internalFormat? 
     460    switch(osg_image.getPixelFormat()) 
     461    { 
     462        case GL_LUMINANCE: 
     463        { 
     464            bitmap_info = kCGImageAlphaNone; 
     465            target_bytes_per_row = (image_width * 8 + 7)/8; 
     466            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray); 
     467            if(NULL == color_space) 
     468            { 
     469                return NULL; 
     470            } 
     471             
     472            //    out_image_data = calloc(target_bytes_per_row, image_height); 
     473            out_image_data = malloc(target_bytes_per_row * image_height);             
     474            if(NULL == out_image_data) 
     475            { 
     476                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
     477                CGColorSpaceRelease(color_space); 
     478                return NULL; 
     479            } 
     480 
     481            vimage_buffer_out.data = out_image_data; 
     482            vimage_buffer_out.rowBytes = target_bytes_per_row; 
     483 
     484            // Now invert the image 
     485            vimage_error_flag = vImageVerticalReflect_Planar8( 
     486                &vimage_buffer_in, // since the osg_image is const... 
     487                &vimage_buffer_out, // don't reuse the buffer 
     488                kvImageNoFlags 
     489            ); 
     490            if(vimage_error_flag != kvImageNoError) 
     491            { 
     492                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     493                free(out_image_data); 
     494                CGColorSpaceRelease(color_space); 
     495                return NULL; 
     496            }             
     497 
     498 
     499            break; 
     500        } 
     501        case GL_ALPHA: 
     502        { 
     503            bitmap_info = kCGImageAlphaOnly; 
     504            target_bytes_per_row = (image_width * 8 + 7)/8; 
     505            // According to: 
     506            // http://developer.apple.com/qa/qa2001/qa1037.html 
     507            // colorSpace=NULL is for alpha only 
     508            color_space = NULL; 
     509             
     510            //    out_image_data = calloc(target_bytes_per_row, image_height); 
     511            out_image_data = malloc(target_bytes_per_row * image_height);             
     512            if(NULL == out_image_data) 
     513            { 
     514                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
     515                return NULL; 
     516            } 
     517 
     518            vimage_buffer_out.data = out_image_data; 
     519            vimage_buffer_out.rowBytes = target_bytes_per_row; 
     520 
     521            // Now invert the image 
     522            vimage_error_flag = vImageVerticalReflect_Planar8( 
     523                &vimage_buffer_in, // since the osg_image is const... 
     524                &vimage_buffer_out, // don't reuse the buffer 
     525                kvImageNoFlags 
     526            ); 
     527            if(vimage_error_flag != kvImageNoError) 
     528            { 
     529                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     530                free(out_image_data); 
     531                return NULL; 
     532            }             
     533 
     534 
     535            break; 
     536        } 
    537537/* 
    538                 case GL_LUMINANCE_ALPHA: 
    539                 { 
    540                         // I don't know if we can support this. 
    541                         // The qa1037 doesn't show both gray+alpha. 
    542                         break; 
    543                 } 
     538        case GL_LUMINANCE_ALPHA: 
     539        { 
     540            // I don't know if we can support this. 
     541            // The qa1037 doesn't show both gray+alpha. 
     542            break; 
     543        } 
    544544*/ 
    545                 case GL_RGB: 
    546                 { 
    547                         bitmap_info = kCGImageAlphaNoneSkipFirst; 
    548                         target_bytes_per_row = (image_width * 8 * 4 + 7)/8; 
    549                         color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    550                         if(NULL == color_space) 
    551                         { 
    552                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
    553                                 return NULL; 
    554                         } 
    555                          
    556                         //      out_image_data = calloc(target_bytes_per_row, image_height); 
    557                         out_image_data = malloc(target_bytes_per_row * image_height);                    
    558                         if(NULL == out_image_data) 
    559                         { 
    560                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
    561                                 CGColorSpaceRelease(color_space); 
    562                                 return NULL; 
    563                         } 
    564  
    565                         // Use vImage to get an RGB buffer into ARGB. 
    566                         vimage_buffer_out.data = out_image_data; 
    567                         vimage_buffer_out.rowBytes = target_bytes_per_row; 
    568                         vimage_error_flag = vImageConvert_RGB888toARGB8888( 
    569                                 &vimage_buffer_in, 
    570                                 NULL, // we don't have a buffer containing alpha values 
    571                                 255, // The alpha value we want given to all pixels since we don't have a buffer 
    572                                 &vimage_buffer_out, 
    573                                 0, // premultiply? 
    574                                 kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading 
    575                         ); 
    576                         if(vimage_error_flag != kvImageNoError) 
    577                         { 
    578                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    579                                 free(out_image_data); 
    580                                 CGColorSpaceRelease(color_space); 
    581                                 return NULL; 
    582                         } 
    583                         // Now invert the image 
    584                         vimage_error_flag = vImageVerticalReflect_ARGB8888( 
    585                                 &vimage_buffer_out, 
    586                                 &vimage_buffer_out, // reuse the same buffer 
    587                                 kvImageNoFlags 
    588                         ); 
    589                         if(vimage_error_flag != kvImageNoError) 
    590                         { 
    591                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    592                                 free(out_image_data); 
    593                                 CGColorSpaceRelease(color_space); 
    594                                 return NULL; 
    595                         }                        
    596                          
    597                         break; 
    598                 } 
    599                 case GL_RGBA: 
    600                 { 
    601                         bitmap_info = kCGImageAlphaPremultipliedLast; 
    602                         target_bytes_per_row = osg_image.getRowSizeInBytes(); 
    603                         color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    604                         if(NULL == color_space) 
    605                         { 
    606                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
    607                                 return NULL; 
    608                         } 
    609                         //      out_image_data = calloc(target_bytes_per_row, image_height); 
    610                         out_image_data = malloc(target_bytes_per_row * image_height);                    
    611                         if(NULL == out_image_data) 
    612                         { 
    613                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
    614                                 CGColorSpaceRelease(color_space); 
    615                                 return NULL; 
    616                         } 
    617                         vimage_buffer_out.data = out_image_data; 
    618                         vimage_buffer_out.rowBytes = target_bytes_per_row; 
    619                         // Invert the image 
    620                         vimage_error_flag = vImageVerticalReflect_ARGB8888( 
    621                                 &vimage_buffer_in, // since the osg_image is const... 
    622                                 &vimage_buffer_out, // don't reuse the buffer 
    623                                 kvImageNoFlags 
    624                         ); 
    625                         if(vimage_error_flag != kvImageNoError) 
    626                         { 
    627                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    628                                 free(out_image_data); 
    629                                 CGColorSpaceRelease(color_space); 
    630                                 return NULL; 
    631                         }                        
    632                         break; 
    633                 } 
    634                 case GL_BGRA: 
    635                 { 
    636                         if(GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType()) 
    637                         { 
     545        case GL_RGB: 
     546        { 
     547            bitmap_info = kCGImageAlphaNoneSkipFirst; 
     548            target_bytes_per_row = (image_width * 8 * 4 + 7)/8; 
     549            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     550            if(NULL == color_space) 
     551            { 
     552                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
     553                return NULL; 
     554            } 
     555             
     556            //    out_image_data = calloc(target_bytes_per_row, image_height); 
     557            out_image_data = malloc(target_bytes_per_row * image_height);             
     558            if(NULL == out_image_data) 
     559            { 
     560                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
     561                CGColorSpaceRelease(color_space); 
     562                return NULL; 
     563            } 
     564 
     565            // Use vImage to get an RGB buffer into ARGB. 
     566            vimage_buffer_out.data = out_image_data; 
     567            vimage_buffer_out.rowBytes = target_bytes_per_row; 
     568            vimage_error_flag = vImageConvert_RGB888toARGB8888( 
     569                &vimage_buffer_in, 
     570                NULL, // we don't have a buffer containing alpha values 
     571                255, // The alpha value we want given to all pixels since we don't have a buffer 
     572                &vimage_buffer_out, 
     573                0, // premultiply? 
     574                kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading 
     575            ); 
     576            if(vimage_error_flag != kvImageNoError) 
     577            { 
     578                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     579                free(out_image_data); 
     580                CGColorSpaceRelease(color_space); 
     581                return NULL; 
     582            } 
     583            // Now invert the image 
     584            vimage_error_flag = vImageVerticalReflect_ARGB8888( 
     585                &vimage_buffer_out, 
     586                &vimage_buffer_out, // reuse the same buffer 
     587                kvImageNoFlags 
     588            ); 
     589            if(vimage_error_flag != kvImageNoError) 
     590            { 
     591                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     592                free(out_image_data); 
     593                CGColorSpaceRelease(color_space); 
     594                return NULL; 
     595            }             
     596             
     597            break; 
     598        } 
     599        case GL_RGBA: 
     600        { 
     601            bitmap_info = kCGImageAlphaPremultipliedLast; 
     602            target_bytes_per_row = osg_image.getRowSizeInBytes(); 
     603            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     604            if(NULL == color_space) 
     605            { 
     606                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
     607                return NULL; 
     608            } 
     609            //    out_image_data = calloc(target_bytes_per_row, image_height); 
     610            out_image_data = malloc(target_bytes_per_row * image_height);             
     611            if(NULL == out_image_data) 
     612            { 
     613                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
     614                CGColorSpaceRelease(color_space); 
     615                return NULL; 
     616            } 
     617            vimage_buffer_out.data = out_image_data; 
     618            vimage_buffer_out.rowBytes = target_bytes_per_row; 
     619            // Invert the image 
     620            vimage_error_flag = vImageVerticalReflect_ARGB8888( 
     621                &vimage_buffer_in, // since the osg_image is const... 
     622                &vimage_buffer_out, // don't reuse the buffer 
     623                kvImageNoFlags 
     624            ); 
     625            if(vimage_error_flag != kvImageNoError) 
     626            { 
     627                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     628                free(out_image_data); 
     629                CGColorSpaceRelease(color_space); 
     630                return NULL; 
     631            }             
     632            break; 
     633        } 
     634        case GL_BGRA: 
     635        { 
     636            if(GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType()) 
     637            { 
    638638#if __BIG_ENDIAN__ 
    639                                 bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
     639                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */ 
    640640#else 
    641                                 bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
     641                bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */ 
    642642#endif  
    643                         } 
    644                         else 
    645                         { 
    646                                 // FIXME: Don't know how to handle this case 
    647                                 bitmap_info = kCGImageAlphaPremultipliedLast; 
    648                         } 
    649  
    650                         target_bytes_per_row = osg_image.getRowSizeInBytes(); 
    651                         color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
    652                         if(NULL == color_space) 
    653                         { 
    654                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
    655                                 return NULL; 
    656                         } 
    657                         //      out_image_data = calloc(target_bytes_per_row, image_height); 
    658                         out_image_data = malloc(target_bytes_per_row * image_height);                    
    659                         if(NULL == out_image_data) 
    660                         { 
    661                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
    662                                 CGColorSpaceRelease(color_space); 
    663                                 return NULL; 
    664                         } 
    665                         vimage_buffer_out.data = out_image_data; 
    666                         vimage_buffer_out.rowBytes = target_bytes_per_row; 
    667                         // Invert the image 
    668                         vimage_error_flag = vImageVerticalReflect_ARGB8888( 
    669                                                                                                                            &vimage_buffer_in, // since the osg_image is const... 
    670                                                                                                                            &vimage_buffer_out, // don't reuse the buffer 
    671                                                                                                                            kvImageNoFlags 
    672                                                                                                                            ); 
    673                         if(vimage_error_flag != kvImageNoError) 
    674                         { 
    675                                 osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
    676                                 free(out_image_data); 
    677                                 CGColorSpaceRelease(color_space); 
    678                                 return NULL; 
    679                         }                        
    680                         break; 
    681                 } 
    682                 // FIXME: Handle other cases. 
    683                 // Use vImagePermuteChannels_ARGB8888 to swizzle bytes 
    684                 default: 
    685                 { 
    686                         osg::notify(osg::WARN) << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl; 
    687                         return NULL; 
    688                         break; 
    689                 } 
    690         } 
    691  
    692         CGContextRef bitmap_context = CGBitmapContextCreate( 
    693                 vimage_buffer_out.data, 
    694                 vimage_buffer_out.width, 
    695                 vimage_buffer_out.height, 
    696                 8, 
    697                 vimage_buffer_out.rowBytes, 
    698                 color_space, 
    699                 bitmap_info 
    700         ); 
    701         /* Done with color space */ 
    702         CGColorSpaceRelease(color_space); 
    703  
    704         if(NULL == bitmap_context) 
    705         { 
    706                 free(out_image_data); 
    707                 return NULL; 
    708         } 
    709          
    710  
    711         /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ 
    712         CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context); 
    713  
    714         /* Done with data */ 
    715         free(out_image_data); 
    716  
    717         /* Done with bitmap_context */ 
    718         CGContextRelease(bitmap_context); 
    719  
    720         return image_ref; 
     643            } 
     644            else 
     645            { 
     646                // FIXME: Don't know how to handle this case 
     647                bitmap_info = kCGImageAlphaPremultipliedLast; 
     648            } 
     649 
     650            target_bytes_per_row = osg_image.getRowSizeInBytes(); 
     651            color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
     652            if(NULL == color_space) 
     653            { 
     654                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl; 
     655                return NULL; 
     656            } 
     657            //    out_image_data = calloc(target_bytes_per_row, image_height); 
     658            out_image_data = malloc(target_bytes_per_row * image_height);             
     659            if(NULL == out_image_data) 
     660            { 
     661                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl; 
     662                CGColorSpaceRelease(color_space); 
     663                return NULL; 
     664            } 
     665            vimage_buffer_out.data = out_image_data; 
     666            vimage_buffer_out.rowBytes = target_bytes_per_row; 
     667            // Invert the image 
     668            vimage_error_flag = vImageVerticalReflect_ARGB8888( 
     669                                                               &vimage_buffer_in, // since the osg_image is const... 
     670                                                               &vimage_buffer_out, // don't reuse the buffer 
     671                                                               kvImageNoFlags 
     672                                                               ); 
     673            if(vimage_error_flag != kvImageNoError) 
     674            { 
     675                osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl; 
     676                free(out_image_data); 
     677                CGColorSpaceRelease(color_space); 
     678                return NULL; 
     679            }             
     680            break; 
     681        } 
     682        // FIXME: Handle other cases. 
     683        // Use vImagePermuteChannels_ARGB8888 to swizzle bytes 
     684        default: 
     685        { 
     686            osg::notify(osg::WARN) << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl; 
     687            return NULL; 
     688            break; 
     689        } 
     690    } 
     691 
     692    CGContextRef bitmap_context = CGBitmapContextCreate( 
     693        vimage_buffer_out.data, 
     694        vimage_buffer_out.width, 
     695        vimage_buffer_out.height, 
     696        8, 
     697        vimage_buffer_out.rowBytes, 
     698        color_space, 
     699        bitmap_info 
     700    ); 
     701    /* Done with color space */ 
     702    CGColorSpaceRelease(color_space); 
     703 
     704    if(NULL == bitmap_context) 
     705    { 
     706        free(out_image_data); 
     707        return NULL; 
     708    } 
     709     
     710 
     711    /* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */ 
     712    CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context); 
     713 
     714    /* Done with data */ 
     715    free(out_image_data); 
     716 
     717    /* Done with bitmap_context */ 
     718    CGContextRelease(bitmap_context); 
     719 
     720    return image_ref; 
    721721} 
    722722 
     
    727727{ 
    728728    CFURLRef the_url = NULL; 
    729         CFStringRef cf_string = NULL; 
    730         CFStringRef uti_type = NULL; 
     729    CFStringRef cf_string = NULL; 
     730    CFStringRef uti_type = NULL; 
    731731    CGImageDestinationRef dest_ref = NULL; 
    732         bool found_png_option = false; 
    733         bool found_jpeg_option = false; 
    734         float compression_quality = 1.0f; 
    735  
    736         /* Create a CFString from a C string */ 
    737         cf_string = CFStringCreateWithCString( 
    738                 NULL, 
    739                 the_path, 
    740                 kCFStringEncodingUTF8 
    741         ); 
    742         if(!cf_string) 
    743         { 
    744                 return NULL; 
    745         } 
    746          
    747         /* Create a CFURL from a CFString */ 
     732    bool found_png_option = false; 
     733    bool found_jpeg_option = false; 
     734    float compression_quality = 1.0f; 
     735 
     736    /* Create a CFString from a C string */ 
     737    cf_string = CFStringCreateWithCString( 
     738        NULL, 
     739        the_path, 
     740        kCFStringEncodingUTF8 
     741    ); 
     742    if(!cf_string) 
     743    { 
     744        return NULL; 
     745    } 
     746     
     747    /* Create a CFURL from a CFString */ 
    748748    the_url = CFURLCreateWithFileSystemPath( 
    749                 NULL,  
    750                 cf_string, 
    751                 kCFURLPOSIXPathStyle, 
    752                 false 
    753         ); 
    754          
    755         /* Don't need the CFString any more (error or not) */ 
    756         CFRelease(cf_string); 
    757          
    758         if(!the_url) 
    759         { 
    760                 return NULL; 
    761         } 
    762          
    763         if(the_options) 
    764         { 
    765                 std::istringstream iss(the_options->getOptionString()); 
    766                 std::string opt; 
    767                 while (iss >> opt) 
    768                 { 
    769                         // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
    770                          
    771                         if(opt=="PNG_COMPRESSION") 
    772                         { 
    773                                 found_png_option = true; 
    774                                 // I don't see an option to set PNG compression levels in the API so this info is unused. 
    775                                 int level; 
    776                                 iss >> level; 
    777                                                                  
    778                         } 
    779                         else if(opt=="JPEG_QUALITY") 
    780                         { 
    781                                 found_jpeg_option = true; 
    782                                 // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. 
    783                                 // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. 
    784                                 // I am uncertain what libjpeg's range is. I'm guessing 0-100. 
    785                                 int quality; 
    786                                 iss >> quality; 
    787                                 compression_quality = (float)quality/100.0f; 
    788                         } 
    789                 } 
    790         } 
    791          
    792  
    793         CFStringRef path_extension = CFURLCopyPathExtension(the_url); 
    794         if(NULL == path_extension) 
    795         { 
    796                 if(found_jpeg_option) 
    797                 { 
    798                         uti_type = UTTypeCreatePreferredIdentifierForTag( 
    799                                 kUTTagClassFilenameExtension, 
    800                                 CFSTR("jpg"), 
    801                                 kUTTypeImage // "public.image" 
    802                         ); 
    803                 } 
    804                 else 
    805                 { 
    806                         uti_type = UTTypeCreatePreferredIdentifierForTag( 
    807                                 kUTTagClassFilenameExtension, 
    808                                 CFSTR("png"), 
    809                                 kUTTypeImage // "public.image" 
    810                         ); 
    811                 } 
    812         } 
    813         else 
    814         { 
    815                 uti_type = UTTypeCreatePreferredIdentifierForTag( 
    816                         kUTTagClassFilenameExtension, 
    817                         path_extension, 
    818                         kUTTypeImage // "public.image" 
    819                 ); 
    820                 CFRelease(path_extension); 
    821         } 
    822  
    823                                                                                                            
    824         dest_ref =  CGImageDestinationCreateWithURL( 
    825                 the_url,  
    826                 uti_type,  
    827                 1, // image file will contain only one image 
    828                 NULL 
    829         ); 
    830  
    831          
    832         CFRelease(uti_type); 
    833         CFRelease(the_url); 
    834  
    835  
    836         // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
    837         if(found_jpeg_option) 
    838         { 
    839                 // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. 
    840                 CFStringRef the_keys[1]; 
    841                 CFNumberRef the_values[1]; 
    842                 CFDictionaryRef the_dict; 
    843                                  
    844                 the_keys[0] = kCGImageDestinationLossyCompressionQuality; 
    845                 the_values[0] = CFNumberCreate( 
    846                         NULL, 
    847                         kCFNumberFloat32Type, 
    848                         &compression_quality 
    849                 ); 
    850                  
    851                 the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
    852                 CFRelease(the_values[0]); 
    853  
    854                 // Now that we have the dict, actually set the property. 
    855                 CGImageDestinationSetProperties(dest_ref, the_dict); 
    856                  
    857                 CFRelease(the_dict); 
    858         } 
    859  
    860         return dest_ref; 
     749        NULL,  
     750        cf_string, 
     751        kCFURLPOSIXPathStyle, 
     752        false 
     753    ); 
     754     
     755    /* Don't need the CFString any more (error or not) */ 
     756    CFRelease(cf_string); 
     757     
     758    if(!the_url) 
     759    { 
     760        return NULL; 
     761    } 
     762     
     763    if(the_options) 
     764    { 
     765        std::istringstream iss(the_options->getOptionString()); 
     766        std::string opt; 
     767        while (iss >> opt) 
     768        { 
     769            // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
     770             
     771            if(opt=="PNG_COMPRESSION") 
     772            { 
     773                found_png_option = true; 
     774                // I don't see an option to set PNG compression levels in the API so this info is unused. 
     775                int level; 
     776                iss >> level; 
     777                                 
     778            } 
     779            else if(opt=="JPEG_QUALITY") 
     780            { 
     781                found_jpeg_option = true; 
     782                // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. 
     783                // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. 
     784                // I am uncertain what libjpeg's range is. I'm guessing 0-100. 
     785                int quality; 
     786                iss >> quality; 
     787                compression_quality = (float)quality/100.0f; 
     788            } 
     789        } 
     790    } 
     791     
     792 
     793    CFStringRef path_extension = CFURLCopyPathExtension(the_url); 
     794    if(NULL == path_extension) 
     795    { 
     796        if(found_jpeg_option) 
     797        { 
     798            uti_type = UTTypeCreatePreferredIdentifierForTag( 
     799                kUTTagClassFilenameExtension, 
     800                CFSTR("jpg"), 
     801                kUTTypeImage // "public.image" 
     802            ); 
     803        } 
     804        else 
     805        { 
     806            uti_type = UTTypeCreatePreferredIdentifierForTag( 
     807                kUTTagClassFilenameExtension, 
     808                CFSTR("png"), 
     809                kUTTypeImage // "public.image" 
     810            ); 
     811        } 
     812    } 
     813    else 
     814    { 
     815        uti_type = UTTypeCreatePreferredIdentifierForTag( 
     816            kUTTagClassFilenameExtension, 
     817            path_extension, 
     818            kUTTypeImage // "public.image" 
     819        ); 
     820        CFRelease(path_extension); 
     821    } 
     822 
     823                                                       
     824    dest_ref =  CGImageDestinationCreateWithURL( 
     825        the_url,  
     826        uti_type,  
     827        1, // image file will contain only one image 
     828        NULL 
     829    ); 
     830 
     831     
     832    CFRelease(uti_type); 
     833    CFRelease(the_url); 
     834 
     835 
     836    // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
     837    if(found_jpeg_option) 
     838    { 
     839        // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. 
     840        CFStringRef the_keys[1]; 
     841        CFNumberRef the_values[1]; 
     842        CFDictionaryRef the_dict; 
     843                 
     844        the_keys[0] = kCGImageDestinationLossyCompressionQuality; 
     845        the_values[0] = CFNumberCreate( 
     846            NULL, 
     847            kCFNumberFloat32Type, 
     848            &compression_quality 
     849        ); 
     850         
     851        the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
     852        CFRelease(the_values[0]); 
     853 
     854        // Now that we have the dict, actually set the property. 
     855        CGImageDestinationSetProperties(dest_ref, the_dict); 
     856         
     857        CFRelease(the_dict); 
     858    } 
     859 
     860    return dest_ref; 
    861861} 
    862862 
     
    866866CGImageDestinationRef CreateCGImageDestinationFromDataStream(std::ostream& fout,  const osgDB::ReaderWriter::Options* the_options) 
    867867{ 
    868         CFStringRef uti_type = NULL; 
     868    CFStringRef uti_type = NULL; 
    869869    CGImageDestinationRef dest_ref = NULL; 
    870         bool found_png_option = false; 
    871         bool found_jpeg_option = false; 
    872         float compression_quality = 1.0f; 
    873          
    874         CGDataConsumerCallbacks consumer_callbacks = 
    875         { 
    876                 MyConsumerPutBytesCallback, 
    877                 MyConsumerReleaseInfoCallback 
    878         }; 
    879          
    880         CGDataConsumerRef data_consumer = CGDataConsumerCreate(&fout, &consumer_callbacks); 
    881  
    882         if(the_options) 
    883         { 
    884                 std::istringstream iss(the_options->getOptionString()); 
    885                 std::string opt; 
    886                 while (iss >> opt) 
    887                 { 
    888                         // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
    889                          
    890                         if(opt=="PNG_COMPRESSION") 
    891                         { 
    892                                 found_png_option = true; 
    893                                 // I don't see an option to set PNG compression levels in the API so this info is unused. 
    894                                 int level; 
    895                                 iss >> level; 
    896                                  
    897                         } 
    898                         else if(opt=="JPEG_QUALITY") 
    899                         { 
    900                                 found_jpeg_option = true; 
    901                                 // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. 
    902                                 // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. 
    903                                 // I am uncertain what libjpeg's range is. I'm guessing 0-100. 
    904                                 int quality; 
    905                                 iss >> quality; 
    906                                 compression_quality = (float)quality/100.0f; 
    907                         } 
    908                 } 
    909         } 
    910          
    911  
    912         if(found_jpeg_option) 
    913         { 
    914                 uti_type = UTTypeCreatePreferredIdentifierForTag( 
    915                         kUTTagClassFilenameExtension, 
    916                         CFSTR("jpg"), 
    917                         kUTTypeImage // "public.image" 
    918                 ); 
    919         } 
    920         else // default to png 
    921         { 
    922                 uti_type = UTTypeCreatePreferredIdentifierForTag( 
    923                         kUTTagClassFilenameExtension, 
    924                         CFSTR("png"), 
    925                         kUTTypeImage // "public.image" 
    926                 ); 
    927         } 
    928          
    929  
    930         // If we had a way of hinting at what the data type is, we could 
    931         // pass this hint in the second parameter. 
    932         dest_ref = CGImageDestinationCreateWithDataConsumer( 
    933                 data_consumer, 
    934                 uti_type, 
    935                 1, // image file will contain only one image 
    936                 NULL 
    937         ); 
    938          
    939         CGDataConsumerRelease(data_consumer); 
    940         CFRelease(uti_type); 
    941          
    942          
    943         // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
    944         if(found_jpeg_option) 
    945         { 
    946                 // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. 
    947                 CFStringRef the_keys[1]; 
    948                 CFNumberRef the_values[1]; 
    949                 CFDictionaryRef the_dict; 
    950                  
    951                 the_keys[0] = kCGImageDestinationLossyCompressionQuality; 
    952                 the_values[0] = CFNumberCreate( 
    953                                                                            NULL, 
    954                                                                            kCFNumberFloat32Type, 
    955                                                                            &compression_quality 
    956                                                                            ); 
    957                  
    958                 the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
    959                 CFRelease(the_values[0]); 
    960                  
    961                 // Now that we have the dict, actually set the property. 
    962                 CGImageDestinationSetProperties(dest_ref, the_dict); 
    963                  
    964                 CFRelease(the_dict); 
    965         } 
    966          
    967         return dest_ref; 
     870    bool found_png_option = false; 
     871    bool found_jpeg_option = false; 
     872    float compression_quality = 1.0f; 
     873     
     874    CGDataConsumerCallbacks consumer_callbacks = 
     875    { 
     876        MyConsumerPutBytesCallback, 
     877        MyConsumerReleaseInfoCallback 
     878    }; 
     879     
     880    CGDataConsumerRef data_consumer = CGDataConsumerCreate(&fout, &consumer_callbacks); 
     881 
     882    if(the_options) 
     883    { 
     884        std::istringstream iss(the_options->getOptionString()); 
     885        std::string opt; 
     886        while (iss >> opt) 
     887        { 
     888            // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
     889             
     890            if(opt=="PNG_COMPRESSION") 
     891            { 
     892                found_png_option = true; 
     893                // I don't see an option to set PNG compression levels in the API so this info is unused. 
     894                int level; 
     895                iss >> level; 
     896                 
     897            } 
     898            else if(opt=="JPEG_QUALITY") 
     899            { 
     900                found_jpeg_option = true; 
     901                // Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges. 
     902                // ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression. 
     903                // I am uncertain what libjpeg's range is. I'm guessing 0-100. 
     904                int quality; 
     905                iss >> quality; 
     906                compression_quality = (float)quality/100.0f; 
     907            } 
     908        } 
     909    } 
     910     
     911 
     912    if(found_jpeg_option) 
     913    { 
     914        uti_type = UTTypeCreatePreferredIdentifierForTag( 
     915            kUTTagClassFilenameExtension, 
     916            CFSTR("jpg"), 
     917            kUTTypeImage // "public.image" 
     918        ); 
     919    } 
     920    else // default to png 
     921    { 
     922        uti_type = UTTypeCreatePreferredIdentifierForTag( 
     923            kUTTagClassFilenameExtension, 
     924            CFSTR("png"), 
     925            kUTTypeImage // "public.image" 
     926        ); 
     927    } 
     928     
     929 
     930    // If we had a way of hinting at what the data type is, we could 
     931    // pass this hint in the second parameter. 
     932    dest_ref = CGImageDestinationCreateWithDataConsumer( 
     933        data_consumer, 
     934        uti_type, 
     935        1, // image file will contain only one image 
     936        NULL 
     937    ); 
     938     
     939    CGDataConsumerRelease(data_consumer); 
     940    CFRelease(uti_type); 
     941     
     942     
     943    // Not handled: The user could do something stupid and specify both PNG and JPEG options. 
     944    if(found_jpeg_option) 
     945    { 
     946        // Do a bunch of work to setup a CFDictionary containing the jpeg compression properties. 
     947        CFStringRef the_keys[1]; 
     948        CFNumberRef the_values[1]; 
     949        CFDictionaryRef the_dict; 
     950         
     951        the_keys[0] = kCGImageDestinationLossyCompressionQuality; 
     952        the_values[0] = CFNumberCreate( 
     953                                       NULL, 
     954                                       kCFNumberFloat32Type, 
     955                                       &compression_quality 
     956                                       ); 
     957         
     958        the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 
     959        CFRelease(the_values[0]); 
     960         
     961        // Now that we have the dict, actually set the property. 
     962        CGImageDestinationSetProperties(dest_ref, the_dict); 
     963         
     964        CFRelease(the_dict); 
     965    } 
     966     
     967    return dest_ref; 
    968968} 
    969969/************************************************************** 
     
    998998         supportsExtension("targa", "targa image file"); 
    999999         supportsExtension("psd",   "psd image file"); 
    1000                  
     1000         
    10011001         supportsExtension("pdf",   "pdf image file"); 
    10021002         supportsExtension("eps",   "eps image file"); 
     
    10051005         supportsExtension("epsi",  "epsi image file"); 
    10061006         supportsExtension("ps",    "postscript image file"); 
    1007                  
     1007         
    10081008         supportsExtension("dng",   "dng image file"); 
    10091009         supportsExtension("cr2",   "cr2 image file"); 
     
    10311031    } 
    10321032 
    1033         virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; } 
     1033    virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; } 
    10341034 
    10351035 
    10361036   virtual bool acceptsExtension(const std::string& extension) const 
    10371037   { 
    1038            // ImageIO speaks in UTIs. 
    1039            // http://developer.apple.com/graphicsimaging/workingwithimageio.html 
    1040            // The Cocoa drawing guide lists these and says to use the 
    1041            // imageFileTypes class method of NSImage to get a complete 
    1042            // list of extensions. But remember ImageIO may support more formats 
    1043            // than Cocoa. 
    1044            // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html 
    1045            // Apple's UTI guide: 
    1046            // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html 
     1038       // ImageIO speaks in UTIs. 
     1039       // http://developer.apple.com/graphicsimaging/workingwithimageio.html 
     1040       // The Cocoa drawing guide lists these and says to use the 
     1041       // imageFileTypes class method of NSImage to get a complete 
     1042       // list of extensions. But remember ImageIO may support more formats 
     1043       // than Cocoa. 
     1044       // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html 
     1045       // Apple's UTI guide: 
     1046       // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html 
    10471047      return 
    10481048         osgDB::equalCaseInsensitive(extension,"jpg") ||  
     
    10641064         osgDB::equalCaseInsensitive(extension,"targa") || 
    10651065         osgDB::equalCaseInsensitive(extension,"psd") || 
    1066                  
     1066         
    10671067         osgDB::equalCaseInsensitive(extension,"pdf") || 
    10681068         osgDB::equalCaseInsensitive(extension,"eps") || 
     
    10711071         osgDB::equalCaseInsensitive(extension,"epsi") || 
    10721072         osgDB::equalCaseInsensitive(extension,"ps") || 
    1073                  
     1073         
    10741074         osgDB::equalCaseInsensitive(extension,"dng") || 
    10751075         osgDB::equalCaseInsensitive(extension,"cr2") || 
     
    10981098 
    10991099 
    1100          
    1101         ReadResult readImageStream(std::istream& fin) const 
    1102         { 
    1103                 // Call ImageIO to load the image. 
    1104                 CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin); 
    1105                 if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; 
    1106  
    1107                 // Create an osg::Image from the CGImageRef. 
    1108                 osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); 
    1109          
    1110                 CFRelease(cg_image_ref); 
    1111                 return osg_image; 
    1112         } 
    1113  
    1114         virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const 
    1115         { 
    1116                 ReadResult read_result = readImageStream(fin); 
    1117                 return read_result; 
    1118         } 
    1119          
    1120         ReadResult readImageFile(const std::string& file_name) const 
    1121         { 
    1122                 osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl; 
    1123          
     1100     
     1101    ReadResult readImageStream(std::istream& fin) const 
     1102    { 
    11241103        // Call ImageIO to load the image. 
    1125                 CGImageRef cg_image_ref = CreateCGImageFromFile(file_name.c_str()); 
    1126                 if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; 
    1127  
    1128                 // Create an osg::Image from the CGImageRef. 
    1129                 osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); 
    1130          
    1131                 CFRelease(cg_image_ref); 
    1132  
    1133                 return osg_image; 
    1134         } 
    1135  
    1136         virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const 
    1137         { 
    1138                 std::string ext = osgDB::getLowerCaseFileExtension(file_name); 
    1139                 if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; 
    1140  
    1141                 std::string full_file_name = osgDB::findDataFile( file_name, the_options ); 
    1142                 if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND; 
     1104        CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin); 
     1105        if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; 
     1106 
     1107        // Create an osg::Image from the CGImageRef. 
     1108        osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); 
     1109     
     1110        CFRelease(cg_image_ref); 
     1111        return osg_image; 
     1112    } 
     1113 
     1114    virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const 
     1115    { 
     1116        ReadResult read_result = readImageStream(fin); 
     1117        return read_result; 
     1118    } 
     1119     
     1120    ReadResult readImageFile(const std::string& file_name) const 
     1121    { 
     1122        osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl; 
     1123         
     1124        // Call ImageIO to load the image. 
     1125        CGImageRef cg_image_ref = CreateCGImageFromFile(file_name.c_str()); 
     1126        if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND; 
     1127 
     1128        // Create an osg::Image from the CGImageRef. 
     1129        osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref); 
     1130     
     1131        CFRelease(cg_image_ref); 
     1132 
     1133        return osg_image; 
     1134    } 
     1135 
     1136    virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const 
     1137    { 
     1138        std::string ext = osgDB::getLowerCaseFileExtension(file_name); 
     1139        if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED; 
     1140 
     1141        std::string full_file_name = osgDB::findDataFile( file_name, the_options ); 
     1142        if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND; 
    11431143 
    11441144#if 1 
    1145                 ReadResult read_result = readImageFile(full_file_name); 
     1145        ReadResult read_result = readImageFile(full_file_name); 
    11461146#else 
    1147                 // Only here to help test istream backend. The file version is better because  
    1148                 // the filenname.extension could potentially be used by ImageIO to hint what the format type is. 
    1149                 std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary); 
    1150                 if(!istream) return ReadResult::FILE_NOT_HANDLED; 
    1151                 ReadResult read_result = readImage(istream); 
     1147        // Only here to help test istream backend. The file version is better because  
     1148        // the filenname.extension could potentially be used by ImageIO to hint what the format type is. 
     1149        std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary); 
     1150        if(!istream) return ReadResult::FILE_NOT_HANDLED; 
     1151        ReadResult read_result = readImage(istream); 
    11521152#endif 
    11531153 
    1154                 if(read_result.validImage()) 
    1155                 { 
    1156                         read_result.getImage()->setFileName(full_file_name); 
    1157                 } 
    1158                 return read_result; 
    1159         } 
    1160  
    1161  
    1162         WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const 
    1163         { 
    1164                 WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
    1165  
    1166                 CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options); 
    1167                 if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; 
    1168                  
    1169                 CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); 
    1170                 if(NULL == cg_image_ref) 
    1171                 { 
    1172                         CFRelease(cg_dest_ref); 
    1173                         return WriteResult::ERROR_IN_WRITING_FILE; 
    1174                 } 
    1175                  
    1176                 CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); 
    1177                 if(CGImageDestinationFinalize(cg_dest_ref)) 
    1178                 { 
    1179                         ret_val = WriteResult::FILE_SAVED; 
    1180                 } 
    1181                 else 
    1182                 { 
    1183                         ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
    1184                 } 
    1185                  
    1186                 CFRelease(cg_image_ref); 
    1187                 CFRelease(cg_dest_ref); 
    1188                  
    1189                 return WriteResult::FILE_SAVED;  
    1190         } 
    1191                  
    1192         virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const 
    1193         { 
    1194                 WriteResult write_result = writeImageStream(osg_image, fout, the_options); 
    1195                 return write_result; 
    1196         } 
    1197  
    1198         WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const 
    1199         { 
    1200                 WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
    1201                 // Call ImageIO to load the image. 
    1202                 CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options); 
    1203                 if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; 
    1204  
    1205                 CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); 
    1206                 if(NULL == cg_image_ref) 
    1207                 { 
    1208                         CFRelease(cg_dest_ref); 
    1209                         return WriteResult::ERROR_IN_WRITING_FILE; 
    1210                 } 
    1211  
    1212                 CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); 
    1213                 if(CGImageDestinationFinalize(cg_dest_ref)) 
    1214                 { 
    1215                         ret_val = WriteResult::FILE_SAVED; 
    1216                 } 
    1217                 else 
    1218                 { 
    1219                         ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
    1220                 } 
    1221                  
    1222                 CFRelease(cg_image_ref); 
    1223                 CFRelease(cg_dest_ref); 
    1224                  
    1225                 return WriteResult::FILE_SAVED; 
    1226         } 
    1227  
    1228         virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const 
    1229         { 
    1230                 std::string ext = osgDB::getFileExtension(file_name); 
    1231                 if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; 
     1154        if(read_result.validImage()) 
     1155        { 
     1156            read_result.getImage()->setFileName(full_file_name); 
     1157        } 
     1158        return read_result; 
     1159    } 
     1160 
     1161 
     1162    WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const 
     1163    { 
     1164        WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
     1165 
     1166        CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options); 
     1167        if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; 
     1168         
     1169        CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); 
     1170        if(NULL == cg_image_ref) 
     1171        { 
     1172            CFRelease(cg_dest_ref); 
     1173            return WriteResult::ERROR_IN_WRITING_FILE; 
     1174        } 
     1175         
     1176        CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); 
     1177        if(CGImageDestinationFinalize(cg_dest_ref)) 
     1178        { 
     1179            ret_val = WriteResult::FILE_SAVED; 
     1180        } 
     1181        else 
     1182        { 
     1183            ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
     1184        } 
     1185         
     1186        CFRelease(cg_image_ref); 
     1187        CFRelease(cg_dest_ref); 
     1188         
     1189        return WriteResult::FILE_SAVED;     
     1190    } 
     1191         
     1192    virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const 
     1193    { 
     1194        WriteResult write_result = writeImageStream(osg_image, fout, the_options); 
     1195        return write_result; 
     1196    } 
     1197 
     1198    WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const 
     1199    { 
     1200        WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
     1201        // Call ImageIO to load the image. 
     1202        CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options); 
     1203        if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE; 
     1204 
     1205        CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image); 
     1206        if(NULL == cg_image_ref) 
     1207        { 
     1208            CFRelease(cg_dest_ref); 
     1209            return WriteResult::ERROR_IN_WRITING_FILE; 
     1210        } 
     1211 
     1212        CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL); 
     1213        if(CGImageDestinationFinalize(cg_dest_ref)) 
     1214        { 
     1215            ret_val = WriteResult::FILE_SAVED; 
     1216        } 
     1217        else 
     1218        { 
     1219            ret_val = WriteResult::ERROR_IN_WRITING_FILE; 
     1220        } 
     1221         
     1222        CFRelease(cg_image_ref); 
     1223        CFRelease(cg_dest_ref); 
     1224         
     1225        return WriteResult::FILE_SAVED; 
     1226    } 
     1227 
     1228    virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const 
     1229    { 
     1230        std::string ext = osgDB::getFileExtension(file_name); 
     1231        if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED; 
    12321232 
    12331233#if 1 
    1234                 // FIXME: Something may need to provide a proper writable location for the files. 
    1235                 std::string full_file_name; 
    1236                 full_file_name = file_name; 
    1237                 return writeImageFile(osg_image, full_file_name, the_options); 
     1234        // FIXME: Something may need to provide a proper writable location for the files. 
     1235        std::string full_file_name; 
     1236        full_file_name = file_name; 
     1237        return writeImageFile(osg_image, full_file_name, the_options); 
    12381238#else 
    1239                 // Only here to help test ostream backend. The file version is better because  
    1240                 // the filenname.extension could potentially be used by ImageIO to hint what the format type is. 
    1241                 std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary); 
    1242                 if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; 
    1243                 return writeImage(osg_image, fout, the_options); 
    1244 #endif           
    1245         } 
     1239        // Only here to help test ostream backend. The file version is better because  
     1240        // the filenname.extension could potentially be used by ImageIO to hint what the format type is. 
     1241        std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary); 
     1242        if(!fout) return WriteResult::ERROR_IN_WRITING_FILE; 
     1243        return writeImage(osg_image, fout, the_options); 
     1244#endif         
     1245    } 
    12461246 
    12471247};