Index: /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp (revision 9880)
+++ /OpenSceneGraph/trunk/src/osgPlugins/imageio/ReaderWriterImageIO.cpp (revision 9880)
@@ -0,0 +1,1256 @@
+// Copyright Eric Wing
+// This plugin is the bridge to OS X's ImageIO framework
+// which provides access to all of Apple's supported image types.
+// This plugin plus the QTKit plugin obsoletes the old QuickTime plugin.
+// This requires 10.4+. (The old QuickTime plugin will not support 64-bit.)
+
+
+// Needs testing, especially in:
+// 8-bits per pixel (256 color vs GL_ALPHA, and what about GL_LUMINANCE)?
+// 16-bits per pixel (is GL_LUMINANCE_ALPHA a safe assumption?)
+// Non-power-of-two textures (especially odd sizes)
+// istream code path
+// ostream code path
+// write image, especially GL_LUMINANCE and GL_ALPHA paths and image formats other than PNG/JPEG
+
+// Enhancements needed:
+// Way to provide image type hint to ImageIO calls (via CFDictionary),
+// probably especially important for istream which lacks extension information.
+// Is there information we can use in the OSG options parameter?
+
+// For ImageIO framework and also LaunchServices framework (for UTIs)
+#include <ApplicationServices/ApplicationServices.h>
+// For the vImage framework (part of the Accerlate framework)
+#include <Accelerate/Accelerate.h>
+
+// Used because CGDataProviderCreate became deprecated in 10.5
+#include <AvailabilityMacros.h>
+
+#include <osg/GL>
+#include <osg/Notify>
+#include <osg/Image>
+
+#include <osgDB/Registry>
+#include <osgDB/FileNameUtils>
+#include <osgDB/FileUtils>
+
+#include <sstream> // for istream
+#include <iostream> // for ios::
+
+
+/**************************************************************
+ ***** Begin Callback functions for istream block reading *****
+ **************************************************************/
+ 
+// This callback reads some bytes from an istream and copies it
+// to a Quartz buffer (supplied by Apple framework).
+size_t MyProviderGetBytesCallback(void* istream_userdata, void* quartz_buffer, size_t the_count)
+{
+	std::istream* the_istream = (std::istream*)istream_userdata;
+	the_istream->read((char*)quartz_buffer, the_count);
+	return the_istream->gcount(); // return the actual number of bytes read
+}
+
+// This callback is triggered when the data provider is released
+// so you can clean up any resources.
+void MyProviderReleaseInfoCallback(void* istream_userdata)
+{
+	// What should I put here? Do I need to close the istream?
+	// The png and tga don't seem to.
+//	std::istream* the_istream = (std::istream*)istream_userdata;
+}
+
+void MyProviderRewindCallback(void* istream_userdata)
+{
+	std::istream* the_istream = (std::istream*)istream_userdata;
+	the_istream->seekg(0, std::ios::beg);
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // CGDataProviderCreateSequential was introduced in 10.5; CGDataProviderCreate is deprecated
+off_t MyProviderSkipForwardBytesCallback(void* istream_userdata, off_t the_count)
+{
+	std::istream* the_istream = (std::istream*)istream_userdata;
+    off_t start_position = the_istream->tellg();
+	the_istream->seekg(the_count, std::ios::cur);
+    off_t end_position = the_istream->tellg();
+    return (end_position - start_position);
+}
+#else // CGDataProviderCreate was deprecated in 10.5
+void MyProviderSkipBytesCallback(void* istream_userdata, size_t the_count)
+{
+	std::istream* the_istream = (std::istream*)istream_userdata;
+	the_istream->seekg(the_count, std::ios::cur);
+}
+#endif
+
+/**************************************************************
+***** End Callback functions for istream block reading ********
+**************************************************************/
+
+
+/**************************************************************
+***** Begin Callback functions for ostream block writing ******
+**************************************************************/
+size_t MyConsumerPutBytesCallback(void* ostream_userdata, const void* quartz_buffer, size_t the_count)
+{
+	std::ostream* the_ostream = (std::ostream*)ostream_userdata;
+	the_ostream->write((char*)quartz_buffer, the_count);
+	// Don't know how to get number of bytes actually written, so
+	// just returning the_count.
+	return the_count;
+}
+
+void MyConsumerReleaseInfoCallback(void* ostream_userdata)
+{
+	std::ostream* the_ostream = (std::ostream*)ostream_userdata;
+	the_ostream->flush();
+}
+/**************************************************************
+***** End Callback functions for ostream block writing ********
+**************************************************************/
+
+
+/**************************************************************
+***** Begin Support functions for reading (stream and file) ***
+**************************************************************/
+
+/* Create a CGImageSourceRef from raw data */
+CGImageRef CreateCGImageFromDataStream(std::istream& fin)
+{
+    CGImageRef image_ref = NULL;
+    CGImageSourceRef source_ref;
+	/* The easy way would be to use CGImageSourceCreateWithData,
+	 * but this presumes you have a known fixed-length buffer of data.
+	 * The istream makes this harder to know, so we use the ProviderCallbacks APIs
+	CFDataRef the_cf_data = CFDataCreateWithBytesNoCopy(
+		kCFAllocatorDefault,
+		(const UInt8*)the_data,
+		CFIndex length,
+		kCFAllocatorNull // do not free data buffer, must do it yourself
+	);
+    source_ref = CGImageSourceCreateWithData(the_cf_data, NULL);
+*/
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // CGDataProviderCreateSequential was introduced in 10.5; CGDataProviderCreate is deprecated
+	CGDataProviderSequentialCallbacks provider_callbacks =
+	{
+        0,
+		MyProviderGetBytesCallback,
+		MyProviderSkipForwardBytesCallback,
+		MyProviderRewindCallback,
+		MyProviderReleaseInfoCallback
+	};
+	
+	CGDataProviderRef data_provider = CGDataProviderCreateSequential(&fin, &provider_callbacks);
+
+
+#else // CGDataProviderCreate was deprecated in 10.5
+
+	CGDataProviderCallbacks provider_callbacks =
+	{
+		MyProviderGetBytesCallback,
+		MyProviderSkipBytesCallback,
+		MyProviderRewindCallback,
+		MyProviderReleaseInfoCallback
+	};
+	
+	CGDataProviderRef data_provider = CGDataProviderCreate(&fin, &provider_callbacks);
+#endif
+	// If we had a way of hinting at what the data type is, we could
+	// pass this hint in the second parameter.
+	source_ref = CGImageSourceCreateWithDataProvider(data_provider, NULL);
+
+	CGDataProviderRelease(data_provider);
+
+
+    if(!source_ref)
+	{
+		return NULL;
+	}
+
+	image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL);
+	
+	/* Don't need the SourceRef any more (error or not) */
+	CFRelease(source_ref);
+
+	return image_ref;
+}
+
+
+/* Create a CGImageSourceRef from a file. */
+/* Remember to CFRelease the created image when done. */
+CGImageRef CreateCGImageFromFile(const char* the_path)
+{
+    CFURLRef the_url = NULL;
+    CGImageRef image_ref = NULL;
+    CGImageSourceRef source_ref = NULL;
+	CFStringRef cf_string = NULL;
+
+	/* Create a CFString from a C string */
+	cf_string = CFStringCreateWithCString(
+		NULL,
+		the_path,
+		kCFStringEncodingUTF8
+	);
+	if(!cf_string)
+	{
+		osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CCFSTring" << std::endl;
+        return NULL;
+	}
+ 
+	/* Create a CFURL from a CFString */
+    the_url = CFURLCreateWithFileSystemPath(
+		NULL, 
+		cf_string,
+		kCFURLPOSIXPathStyle,
+		false
+	);
+
+	/* Don't need the CFString any more (error or not) */
+	CFRelease(cf_string);
+	
+	if(!the_url)
+	{
+		osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create CFUrl" << std::endl;
+        return NULL;
+	}
+
+	
+    source_ref = CGImageSourceCreateWithURL(the_url, NULL);
+	/* Don't need the URL any more (error or not) */
+	CFRelease(the_url);
+
+    if(!source_ref)
+	{
+		osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not create ImageSource" << std::endl;
+        return NULL;
+    }
+
+	// Get the first item in the image source (some image formats may
+	// contain multiple items).
+	image_ref = CGImageSourceCreateImageAtIndex(source_ref, 0, NULL);
+	if (!image_ref) {
+        osg::notify(osg::WARN) << "CreateCGImageFromFile :: could not get Image" << std::endl;
+    }
+    
+	/* Don't need the SourceRef any more (error or not) */
+	CFRelease(source_ref);
+
+	return image_ref;
+}
+
+/* Once we have our image (CGImageRef), we need to get it into an osg::Image */
+osg::Image* CreateOSGImageFromCGImage(CGImageRef image_ref)
+{
+	/* This code is adapted from Apple's Documentation found here:
+	 * http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/index.html
+	 * Listing 9-4â â Using a Quartz image as a texture source.
+	 * Unfortunately, this guide doesn't show what to do about
+	 * non-RGBA image formats so I'm making the rest up
+	 * (and it's probably all wrong).
+	 */
+
+	size_t the_width = CGImageGetWidth(image_ref);
+	size_t the_height = CGImageGetHeight(image_ref);
+	CGRect the_rect = {{0, 0}, {the_width, the_height}};
+
+	size_t bits_per_pixel = CGImageGetBitsPerPixel(image_ref);
+	size_t bytes_per_row = CGImageGetBytesPerRow(image_ref);
+//	size_t bits_per_component = CGImageGetBitsPerComponent(image_ref);
+	size_t bits_per_component = 8;
+	
+	CGImageAlphaInfo alpha_info = CGImageGetAlphaInfo(image_ref);
+	
+	GLint internal_format;
+	GLenum pixel_format;
+	GLenum data_type;
+	
+	void* image_data = calloc(the_width * 4, the_height);
+
+	CGColorSpaceRef color_space;
+	CGBitmapInfo bitmap_info = CGImageGetBitmapInfo(image_ref);
+
+	switch(bits_per_pixel)
+	{
+		// Drat, if 8-bit, how do you distinguish
+		// between a 256 color GIF, a LUMINANCE map
+		// or an ALPHA map?
+		case 8:
+		{
+			// I probably did the formats all wrong for this case,
+			// especially the ALPHA case.
+			if(kCGImageAlphaNone == alpha_info)
+			{
+				/*
+				 internal_format = GL_LUMINANCE;
+				 pixel_format = GL_LUMINANCE;
+				 */
+				internal_format = GL_RGBA8;
+				pixel_format = GL_BGRA_EXT;
+				data_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+				
+				bytes_per_row = the_width*4;
+//				color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+				color_space = CGColorSpaceCreateDeviceRGB();
+//				bitmap_info = kCGImageAlphaPremultipliedFirst;
+#if __BIG_ENDIAN__
+				bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
+#else
+				bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
+#endif 
+			}
+			else
+			{
+				internal_format = GL_ALPHA;
+				pixel_format = GL_ALPHA;
+				data_type = GL_UNSIGNED_BYTE;
+				//			bytes_per_row = the_width;
+//				color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
+				color_space = CGColorSpaceCreateDeviceGray();
+			}
+
+			break;
+		}
+		case 16:
+		{
+			// FIXME: Is this really a reasonable assumption: GL_LUMINANCE_ALPHA?
+			internal_format = GL_LUMINANCE_ALPHA;
+			pixel_format = GL_LUMINANCE_ALPHA;
+			data_type = GL_UNSIGNED_BYTE;
+//			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
+			color_space = CGColorSpaceCreateDeviceGray();
+			break;
+		}
+		case 24:
+		{
+			internal_format = GL_RGBA8;
+			pixel_format = GL_BGRA_EXT;
+			data_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+			bytes_per_row = the_width*4;
+//			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+			color_space = CGColorSpaceCreateDeviceRGB();
+//			bitmap_info = kCGImageAlphaNone;
+#if __BIG_ENDIAN__
+			bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
+#else
+			bitmap_info = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
+#endif       
+			break;
+		}
+		case 32:
+		{
+			
+			internal_format = GL_RGBA8;
+			pixel_format = GL_BGRA_EXT;
+			data_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+			
+			bytes_per_row = the_width*4;
+//			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+			color_space = CGColorSpaceCreateDeviceRGB();
+//			bitmap_info = kCGImageAlphaPremultipliedFirst;
+#if __BIG_ENDIAN__
+			bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
+#else
+			bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
+#endif 
+			break;
+		}
+		default:
+		{
+			// osg::notify(osg::WARN) << "Unknown file type in " << fileName.c_str() << " with " << origDepth << std::endl;
+            return NULL;
+            break;
+		}
+
+	}
+	
+	// Sets up a context to be drawn to with image_data as the area to be drawn to
+	CGContextRef bitmap_context = CGBitmapContextCreate(
+		image_data,
+		the_width,
+		the_height,
+		bits_per_component,
+		bytes_per_row,
+		color_space,
+		bitmap_info
+	);
+	
+	// Draws the image into the context's image_data
+	CGContextDrawImage(bitmap_context, the_rect, image_ref);
+
+	CGContextRelease(bitmap_context);
+
+	osg::Image* osg_image = new osg::Image;
+	
+	osg_image->setImage(
+		the_width,
+		the_height,
+		1,
+		internal_format,
+		pixel_format,
+		data_type,
+		(unsigned char*)image_data,
+		osg::Image::USE_MALLOC_FREE // Assumption: osg_image takes ownership of image_data and will free
+	);
+
+	osg_image->flipVertical();
+	return osg_image;
+
+
+
+}
+/**************************************************************
+***** End Support functions for reading (stream and file) *****
+**************************************************************/
+
+
+/**************************************************************
+***** Begin Support functions for writing (stream and file)****
+**************************************************************/
+
+/* Create a CGImageRef from osg::Image.
+ * Code adapted from
+ * http://developer.apple.com/samplecode/OpenGLScreenSnapshot/listing2.html
+ */
+CGImageRef CreateCGImageFromOSGData(const osg::Image& osg_image)
+{
+	size_t image_width = osg_image.s();
+	size_t image_height = osg_image.t();
+	/* From Apple's header for CGBitmapContextCreate()
+	 * Each row of the bitmap consists of `bytesPerRow' bytes, which must be at
+	 * least `(width * bitsPerComponent * number of components + 7)/8' bytes.
+	 */
+	size_t target_bytes_per_row;
+	 
+	CGColorSpaceRef color_space;
+	CGBitmapInfo bitmap_info;
+	/* From what I can figure out so far...
+	 * We need to create a CGContext connected to the data we want to save
+	 * and then call CGBitmapContextCreateImage() on that context to get
+	 * a CGImageRef.
+	 * However, OS X only allows 4-component image formats (e.g. RGBA) and not
+	 * just RGB for the RGB-based CGContext. So for a 24-bit image coming in,
+	 * we need to expand the data to 32-bit.
+	 * The easiest and fastest way to do that is through the vImage framework
+	 * which is part of the Accelerate framework.
+	 * Also, the osg::Image data coming in is inverted from what we want, so
+	 * we need to invert the image too. Since the osg::Image is const,
+	 * we don't want to touch the data, so again we turn to the vImage framework
+	 * and invert the data.
+	 */
+	vImage_Buffer vimage_buffer_in = 
+	{
+		(void*)osg_image.data(), // need to override const, but we don't modify the data so it's safe
+		image_height,
+		image_width,
+		osg_image.getRowSizeInBytes()
+	};
+
+	void* out_image_data;
+	vImage_Buffer vimage_buffer_out =
+	{
+		NULL, // will fill-in in switch
+		image_height,
+		image_width,
+		0 // will fill-in in switch
+	};	
+	vImage_Error vimage_error_flag;
+
+	// FIXME: Do I want to use format, type, or internalFormat?
+	switch(osg_image.getPixelFormat())
+	{
+		case GL_LUMINANCE:
+		{
+			bitmap_info = kCGImageAlphaNone;
+			target_bytes_per_row = (image_width * 8 + 7)/8;
+			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
+			if(NULL == color_space)
+			{
+				return NULL;
+			}
+			
+			//	out_image_data = calloc(target_bytes_per_row, image_height);
+			out_image_data = malloc(target_bytes_per_row * image_height);			
+			if(NULL == out_image_data)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl;
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}
+
+			vimage_buffer_out.data = out_image_data;
+			vimage_buffer_out.rowBytes = target_bytes_per_row;
+
+			// Now invert the image
+			vimage_error_flag = vImageVerticalReflect_Planar8(
+				&vimage_buffer_in, // since the osg_image is const...
+				&vimage_buffer_out, // don't reuse the buffer
+				kvImageNoFlags
+			);
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_LUMINANCE, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}			
+
+
+			break;
+		}
+		case GL_ALPHA:
+		{
+			bitmap_info = kCGImageAlphaOnly;
+			target_bytes_per_row = (image_width * 8 + 7)/8;
+			// According to:
+			// http://developer.apple.com/qa/qa2001/qa1037.html
+			// colorSpace=NULL is for alpha only
+			color_space = NULL;
+			
+			//	out_image_data = calloc(target_bytes_per_row, image_height);
+			out_image_data = malloc(target_bytes_per_row * image_height);			
+			if(NULL == out_image_data)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl;
+				return NULL;
+			}
+
+			vimage_buffer_out.data = out_image_data;
+			vimage_buffer_out.rowBytes = target_bytes_per_row;
+
+			// Now invert the image
+			vimage_error_flag = vImageVerticalReflect_Planar8(
+				&vimage_buffer_in, // since the osg_image is const...
+				&vimage_buffer_out, // don't reuse the buffer
+				kvImageNoFlags
+			);
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData for GL_ALPHA, vImageVerticalReflect_Planar8 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				return NULL;
+			}			
+
+
+			break;
+		}
+/*
+		case GL_LUMINANCE_ALPHA:
+		{
+			// I don't know if we can support this.
+			// The qa1037 doesn't show both gray+alpha.
+			break;
+		}
+*/
+		case GL_RGB:
+		{
+			bitmap_info = kCGImageAlphaNoneSkipFirst;
+			target_bytes_per_row = (image_width * 8 * 4 + 7)/8;
+			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+			if(NULL == color_space)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl;
+				return NULL;
+			}
+			
+			//	out_image_data = calloc(target_bytes_per_row, image_height);
+			out_image_data = malloc(target_bytes_per_row * image_height);			
+			if(NULL == out_image_data)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl;
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}
+
+			// Use vImage to get an RGB buffer into ARGB.
+			vimage_buffer_out.data = out_image_data;
+			vimage_buffer_out.rowBytes = target_bytes_per_row;
+			vimage_error_flag = vImageConvert_RGB888toARGB8888(
+				&vimage_buffer_in,
+				NULL, // we don't have a buffer containing alpha values
+				255, // The alpha value we want given to all pixels since we don't have a buffer
+				&vimage_buffer_out,
+				0, // premultiply?
+				kvImageNoFlags // Only responds to kvImageDoNotTile, but I think we want tiling/threading
+			);
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageConvert_RGB888toARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}
+			// Now invert the image
+			vimage_error_flag = vImageVerticalReflect_ARGB8888(
+				&vimage_buffer_out,
+				&vimage_buffer_out, // reuse the same buffer
+				kvImageNoFlags
+			);
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}			
+			
+			break;
+		}
+		case GL_RGBA:
+		{
+			bitmap_info = kCGImageAlphaPremultipliedLast;
+			target_bytes_per_row = osg_image.getRowSizeInBytes();
+			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+			if(NULL == color_space)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl;
+				return NULL;
+			}
+			//	out_image_data = calloc(target_bytes_per_row, image_height);
+			out_image_data = malloc(target_bytes_per_row * image_height);			
+			if(NULL == out_image_data)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl;
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}
+			vimage_buffer_out.data = out_image_data;
+			vimage_buffer_out.rowBytes = target_bytes_per_row;
+			// Invert the image
+			vimage_error_flag = vImageVerticalReflect_ARGB8888(
+				&vimage_buffer_in, // since the osg_image is const...
+				&vimage_buffer_out, // don't reuse the buffer
+				kvImageNoFlags
+			);
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}			
+			break;
+		}
+		case GL_BGRA:
+		{
+			if(GL_UNSIGNED_INT_8_8_8_8_REV == osg_image.getDataType())
+			{
+#if __BIG_ENDIAN__
+				bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big; /* XRGB Big Endian */
+#else
+				bitmap_info = kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little; /* XRGB Little Endian */
+#endif 
+			}
+			else
+			{
+				// FIXME: Don't know how to handle this case
+				bitmap_info = kCGImageAlphaPremultipliedLast;
+			}
+
+			target_bytes_per_row = osg_image.getRowSizeInBytes();
+			color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+			if(NULL == color_space)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, CGColorSpaceCreateWithName failed" << std::endl;
+				return NULL;
+			}
+			//	out_image_data = calloc(target_bytes_per_row, image_height);
+			out_image_data = malloc(target_bytes_per_row * image_height);			
+			if(NULL == out_image_data)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, malloc failed" << std::endl;
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}
+			vimage_buffer_out.data = out_image_data;
+			vimage_buffer_out.rowBytes = target_bytes_per_row;
+			// Invert the image
+			vimage_error_flag = vImageVerticalReflect_ARGB8888(
+															   &vimage_buffer_in, // since the osg_image is const...
+															   &vimage_buffer_out, // don't reuse the buffer
+															   kvImageNoFlags
+															   );
+			if(vimage_error_flag != kvImageNoError)
+			{
+				osg::notify(osg::WARN) << "In CreateCGImageFromOSGData, vImageAffineWarp_ARGB8888 failed with vImage Error Code: " << vimage_error_flag << std::endl;
+				free(out_image_data);
+				CGColorSpaceRelease(color_space);
+				return NULL;
+			}			
+			break;
+		}
+		// FIXME: Handle other cases.
+		// Use vImagePermuteChannels_ARGB8888 to swizzle bytes
+		default:
+		{
+			osg::notify(osg::WARN) << "In CreateCGImageFromOSGData: Sorry support for this format is not implemented." << std::endl;
+			return NULL;
+			break;
+		}
+	}
+
+	CGContextRef bitmap_context = CGBitmapContextCreate(
+		vimage_buffer_out.data,
+		vimage_buffer_out.width,
+		vimage_buffer_out.height,
+		8,
+		vimage_buffer_out.rowBytes,
+		color_space,
+		bitmap_info
+	);
+	/* Done with color space */
+	CGColorSpaceRelease(color_space);
+
+	if(NULL == bitmap_context)
+	{
+		free(out_image_data);
+		return NULL;
+	}
+	
+
+	/* Make an image out of our bitmap; does a cheap vm_copy of the bitmap */
+	CGImageRef image_ref = CGBitmapContextCreateImage(bitmap_context);
+
+	/* Done with data */
+	free(out_image_data);
+
+	/* Done with bitmap_context */
+	CGContextRelease(bitmap_context);
+
+	return image_ref;
+}
+
+
+/* Create a CGImageDestinationRef from a file. */
+/* Remember to CFRelease when done. */
+CGImageDestinationRef CreateCGImageDestinationFromFile(const char* the_path,  const osgDB::ReaderWriter::Options* the_options)
+{
+    CFURLRef the_url = NULL;
+	CFStringRef cf_string = NULL;
+	CFStringRef uti_type = NULL;
+    CGImageDestinationRef dest_ref = NULL;
+	bool found_png_option = false;
+	bool found_jpeg_option = false;
+	float compression_quality = 1.0f;
+
+	/* Create a CFString from a C string */
+	cf_string = CFStringCreateWithCString(
+		NULL,
+		the_path,
+		kCFStringEncodingUTF8
+	);
+	if(!cf_string)
+	{
+		return NULL;
+	}
+	
+	/* Create a CFURL from a CFString */
+    the_url = CFURLCreateWithFileSystemPath(
+		NULL, 
+		cf_string,
+		kCFURLPOSIXPathStyle,
+		false
+	);
+	
+	/* Don't need the CFString any more (error or not) */
+	CFRelease(cf_string);
+	
+	if(!the_url)
+	{
+		return NULL;
+	}
+	
+	if(the_options)
+	{
+		std::istringstream iss(the_options->getOptionString());
+		std::string opt;
+		while (iss >> opt)
+		{
+			// Not handled: The user could do something stupid and specify both PNG and JPEG options.
+			
+			if(opt=="PNG_COMPRESSION")
+			{
+				found_png_option = true;
+				// I don't see an option to set PNG compression levels in the API so this info is unused.
+				int level;
+				iss >> level;
+								
+			}
+			else if(opt=="JPEG_QUALITY")
+			{
+				found_jpeg_option = true;
+				// Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges.
+				// ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression.
+				// I am uncertain what libjpeg's range is. I'm guessing 0-100.
+				int quality;
+				iss >> quality;
+				compression_quality = (float)quality/100.0f;
+			}
+		}
+	}
+	
+
+	CFStringRef path_extension = CFURLCopyPathExtension(the_url);
+	if(NULL == path_extension)
+	{
+		if(found_jpeg_option)
+		{
+			uti_type = UTTypeCreatePreferredIdentifierForTag(
+				 kUTTagClassFilenameExtension,
+				 CFSTR("jpg"),
+				 kUTTypeImage // "public.image"
+			);
+		}
+		else
+		{
+			uti_type = UTTypeCreatePreferredIdentifierForTag(
+				 kUTTagClassFilenameExtension,
+				 CFSTR("png"),
+				 kUTTypeImage // "public.image"
+			);
+		}
+	}
+	else
+	{
+		uti_type = UTTypeCreatePreferredIdentifierForTag(
+			kUTTagClassFilenameExtension,
+			path_extension,
+			kUTTypeImage // "public.image"
+		);
+		CFRelease(path_extension);
+	}
+
+													  
+	dest_ref =  CGImageDestinationCreateWithURL(
+		the_url, 
+		uti_type, 
+		1, // image file will contain only one image
+		NULL
+	);
+
+	
+	CFRelease(uti_type);
+	CFRelease(the_url);
+
+
+	// Not handled: The user could do something stupid and specify both PNG and JPEG options.
+	if(found_jpeg_option)
+	{
+		// Do a bunch of work to setup a CFDictionary containing the jpeg compression properties.
+		CFStringRef the_keys[1];
+		CFNumberRef the_values[1];
+		CFDictionaryRef the_dict;
+				
+		the_keys[0] = kCGImageDestinationLossyCompressionQuality;
+		the_values[0] = CFNumberCreate(
+			NULL,
+			kCFNumberFloat32Type,
+			&compression_quality
+		);
+		
+		the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+		CFRelease(the_values[0]);
+
+		// Now that we have the dict, actually set the property.
+		CGImageDestinationSetProperties(dest_ref, the_dict);
+		
+		CFRelease(the_dict);
+	}
+
+	return dest_ref;
+}
+
+
+/* Create a CGImageDestinationRef from a file. */
+/* Remember to CFRelease when done. */
+CGImageDestinationRef CreateCGImageDestinationFromDataStream(std::ostream& fout,  const osgDB::ReaderWriter::Options* the_options)
+{
+	CFStringRef uti_type = NULL;
+    CGImageDestinationRef dest_ref = NULL;
+	bool found_png_option = false;
+	bool found_jpeg_option = false;
+	float compression_quality = 1.0f;
+	
+	CGDataConsumerCallbacks consumer_callbacks =
+	{
+		MyConsumerPutBytesCallback,
+		MyConsumerReleaseInfoCallback
+	};
+	
+	CGDataConsumerRef data_consumer = CGDataConsumerCreate(&fout, &consumer_callbacks);
+
+	if(the_options)
+	{
+		std::istringstream iss(the_options->getOptionString());
+		std::string opt;
+		while (iss >> opt)
+		{
+			// Not handled: The user could do something stupid and specify both PNG and JPEG options.
+			
+			if(opt=="PNG_COMPRESSION")
+			{
+				found_png_option = true;
+				// I don't see an option to set PNG compression levels in the API so this info is unused.
+				int level;
+				iss >> level;
+				
+			}
+			else if(opt=="JPEG_QUALITY")
+			{
+				found_jpeg_option = true;
+				// Chances are that people are specifying values in libjpeg ranges and not ImageIO ranges.
+				// ImageIO is normalized between 0.0 to 1.0 where 1.0 is lossless and 0 is max compression.
+				// I am uncertain what libjpeg's range is. I'm guessing 0-100.
+				int quality;
+				iss >> quality;
+				compression_quality = (float)quality/100.0f;
+			}
+		}
+	}
+	
+
+	if(found_jpeg_option)
+	{
+		uti_type = UTTypeCreatePreferredIdentifierForTag(
+			kUTTagClassFilenameExtension,
+			CFSTR("jpg"),
+			kUTTypeImage // "public.image"
+		);
+	}
+	else // default to png
+	{
+		uti_type = UTTypeCreatePreferredIdentifierForTag(
+			kUTTagClassFilenameExtension,
+			CFSTR("png"),
+			kUTTypeImage // "public.image"
+		);
+	}
+	
+
+	// If we had a way of hinting at what the data type is, we could
+	// pass this hint in the second parameter.
+	dest_ref = CGImageDestinationCreateWithDataConsumer(
+		data_consumer,
+		uti_type,
+		1, // image file will contain only one image
+		NULL
+	);
+	
+	CGDataConsumerRelease(data_consumer);
+	CFRelease(uti_type);
+	
+	
+	// Not handled: The user could do something stupid and specify both PNG and JPEG options.
+	if(found_jpeg_option)
+	{
+		// Do a bunch of work to setup a CFDictionary containing the jpeg compression properties.
+		CFStringRef the_keys[1];
+		CFNumberRef the_values[1];
+		CFDictionaryRef the_dict;
+		
+		the_keys[0] = kCGImageDestinationLossyCompressionQuality;
+		the_values[0] = CFNumberCreate(
+									   NULL,
+									   kCFNumberFloat32Type,
+									   &compression_quality
+									   );
+		
+		the_dict = CFDictionaryCreate(NULL, (const void**)&the_keys, (const void**)&the_values, 1, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+		CFRelease(the_values[0]);
+		
+		// Now that we have the dict, actually set the property.
+		CGImageDestinationSetProperties(dest_ref, the_dict);
+		
+		CFRelease(the_dict);
+	}
+	
+	return dest_ref;
+}
+/**************************************************************
+***** End Support functions for writing (stream and file) *****
+**************************************************************/
+
+
+
+class ReaderWriterImageIO : public osgDB::ReaderWriter
+
+{
+public:
+    ReaderWriterImageIO::ReaderWriterImageIO()
+    {
+
+         supportsExtension("jpg",   "jpg image file"); 
+         supportsExtension("jpeg",  "jpeg image file");
+         supportsExtension("jpe",   "jpe image file");
+         supportsExtension("jp2",   "jp2 image file");
+         supportsExtension("tiff",  "tiff image file"); 
+         supportsExtension("tif",   "tif image file");               
+         supportsExtension("gif",   "gif image file");
+         supportsExtension("png",   "png image file");
+         supportsExtension("pict",  "pict image file");
+         supportsExtension("pct",   "pct image file");
+         supportsExtension("pic",   "pic image file");
+         supportsExtension("bmp",   "bmp image file");
+         supportsExtension("BMPf",  "BMPf image file");
+         supportsExtension("ico",   "ico image file");
+         supportsExtension("icns",  "icns image file");
+         supportsExtension("tga",   "tga image file");
+         supportsExtension("targa", "targa image file");
+         supportsExtension("psd",   "psd image file");
+		 
+         supportsExtension("pdf",   "pdf image file");
+         supportsExtension("eps",   "eps image file");
+         supportsExtension("epi",   "epi image file");
+         supportsExtension("epsf",  "epsf image file");
+         supportsExtension("epsi",  "epsi image file");
+         supportsExtension("ps",    "postscript image file");
+		 
+         supportsExtension("dng",   "dng image file");
+         supportsExtension("cr2",   "cr2 image file");
+         supportsExtension("crw",   "crw image file");
+         supportsExtension("fpx",   "fpx image file");
+         supportsExtension("fpxi",  "fpxi image file");
+         supportsExtension("raf",   "raf image file");
+         supportsExtension("dcr",   "dcr image file");
+         supportsExtension("ptng",  "ptng image file");
+         supportsExtension("pnt",   "pnt image file");
+         supportsExtension("mac",   "mac image file");
+         supportsExtension("mrw",   "mrw image file");
+         supportsExtension("nef",   "nef image file");
+         supportsExtension("orf",   "orf image file");
+         supportsExtension("exr",   "exr image file");
+         supportsExtension("qti",   "qti image file");
+         supportsExtension("qtif",  "qtif image file");
+         supportsExtension("hdr",   "hdr image file");
+         supportsExtension("sgi",   "sgi image file");
+         supportsExtension("srf",   "srf image file");
+         supportsExtension("cur",   "cur image file");
+         supportsExtension("xbm",   "xbm image file");
+
+         supportsExtension("raw",   "raw image file");
+    }
+
+	virtual const char* className() const { return "Mac OS X ImageIO based Image Reader/Writer"; }
+
+
+   virtual bool acceptsExtension(const std::string& extension) const
+   {
+	   // ImageIO speaks in UTIs.
+	   // http://developer.apple.com/graphicsimaging/workingwithimageio.html
+	   // The Cocoa drawing guide lists these and says to use the
+	   // imageFileTypes class method of NSImage to get a complete
+	   // list of extensions. But remember ImageIO may support more formats
+	   // than Cocoa.
+	   // http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/Images/chapter_7_section_3.html
+	   // Apple's UTI guide:
+	   // http://developer.apple.com/documentation/Carbon/Conceptual/understanding_utis/utilist/chapter_4_section_1.html
+      return
+         osgDB::equalCaseInsensitive(extension,"jpg") || 
+         osgDB::equalCaseInsensitive(extension,"jpeg") ||
+         osgDB::equalCaseInsensitive(extension,"jpe") ||
+         osgDB::equalCaseInsensitive(extension,"jp2") ||
+         osgDB::equalCaseInsensitive(extension,"tiff") || 
+         osgDB::equalCaseInsensitive(extension,"tif") ||               
+         osgDB::equalCaseInsensitive(extension,"gif") ||
+         osgDB::equalCaseInsensitive(extension,"png") ||
+         osgDB::equalCaseInsensitive(extension,"pict") ||
+         osgDB::equalCaseInsensitive(extension,"pct") ||
+         osgDB::equalCaseInsensitive(extension,"pic") ||
+         osgDB::equalCaseInsensitive(extension,"bmp") ||
+         osgDB::equalCaseInsensitive(extension,"BMPf") ||
+         osgDB::equalCaseInsensitive(extension,"ico") ||
+         osgDB::equalCaseInsensitive(extension,"icns") ||
+         osgDB::equalCaseInsensitive(extension,"tga") ||
+         osgDB::equalCaseInsensitive(extension,"targa") ||
+         osgDB::equalCaseInsensitive(extension,"psd") ||
+		 
+         osgDB::equalCaseInsensitive(extension,"pdf") ||
+         osgDB::equalCaseInsensitive(extension,"eps") ||
+         osgDB::equalCaseInsensitive(extension,"epi") ||
+         osgDB::equalCaseInsensitive(extension,"epsf") ||
+         osgDB::equalCaseInsensitive(extension,"epsi") ||
+         osgDB::equalCaseInsensitive(extension,"ps") ||
+		 
+         osgDB::equalCaseInsensitive(extension,"dng") ||
+         osgDB::equalCaseInsensitive(extension,"cr2") ||
+         osgDB::equalCaseInsensitive(extension,"crw") ||
+         osgDB::equalCaseInsensitive(extension,"fpx") ||
+         osgDB::equalCaseInsensitive(extension,"fpxi") ||
+         osgDB::equalCaseInsensitive(extension,"raf") ||
+         osgDB::equalCaseInsensitive(extension,"dcr") ||
+         osgDB::equalCaseInsensitive(extension,"ptng") ||
+         osgDB::equalCaseInsensitive(extension,"pnt") ||
+         osgDB::equalCaseInsensitive(extension,"mac") ||
+         osgDB::equalCaseInsensitive(extension,"mrw") ||
+         osgDB::equalCaseInsensitive(extension,"nef") ||
+         osgDB::equalCaseInsensitive(extension,"orf") ||
+         osgDB::equalCaseInsensitive(extension,"exr") ||
+         osgDB::equalCaseInsensitive(extension,"qti") ||
+         osgDB::equalCaseInsensitive(extension,"qtif") ||
+         osgDB::equalCaseInsensitive(extension,"hdr") ||
+         osgDB::equalCaseInsensitive(extension,"sgi") ||
+         osgDB::equalCaseInsensitive(extension,"srf") ||
+         osgDB::equalCaseInsensitive(extension,"cur") ||
+         osgDB::equalCaseInsensitive(extension,"xbm") ||
+
+         osgDB::equalCaseInsensitive(extension,"raw");
+   }
+
+
+	
+	ReadResult readImageStream(std::istream& fin) const
+	{
+		// Call ImageIO to load the image.
+		CGImageRef cg_image_ref = CreateCGImageFromDataStream(fin);
+		if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND;
+
+		// Create an osg::Image from the CGImageRef.
+		osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref);
+	
+		CFRelease(cg_image_ref);
+		return osg_image;
+	}
+
+	virtual ReadResult readImage(std::istream& fin, const osgDB::ReaderWriter::Options* the_options = NULL) const
+	{
+		ReadResult read_result = readImageStream(fin);
+		return read_result;
+	}
+	
+	ReadResult readImageFile(const std::string& file_name) const
+	{
+		osg::notify(osg::INFO) << "imageio readImageFile: " << file_name << std::endl;
+        
+        // Call ImageIO to load the image.
+		CGImageRef cg_image_ref = CreateCGImageFromFile(file_name.c_str());
+		if (NULL == cg_image_ref) return ReadResult::FILE_NOT_FOUND;
+
+		// Create an osg::Image from the CGImageRef.
+		osg::Image* osg_image = CreateOSGImageFromCGImage(cg_image_ref);
+	
+		CFRelease(cg_image_ref);
+
+		return osg_image;
+	}
+
+	virtual ReadResult readImage(const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const
+	{
+		std::string ext = osgDB::getLowerCaseFileExtension(file_name);
+		if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
+
+		std::string full_file_name = osgDB::findDataFile( file_name, the_options );
+		if (full_file_name.empty()) return ReadResult::FILE_NOT_FOUND;
+
+#if 1
+		ReadResult read_result = readImageFile(full_file_name);
+#else
+		// Only here to help test istream backend. The file version is better because 
+		// the filenname.extension could potentially be used by ImageIO to hint what the format type is.
+		std::ifstream istream(full_file_name.c_str(), std::ios::in | std::ios::binary);
+		if(!istream) return ReadResult::FILE_NOT_HANDLED;
+		ReadResult read_result = readImage(istream);
+#endif
+
+		if(read_result.validImage())
+		{
+			read_result.getImage()->setFileName(full_file_name);
+		}
+		return read_result;
+	}
+
+
+	WriteResult writeImageStream(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const
+	{
+		WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE;
+
+		CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromDataStream(fout, the_options);
+		if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE;
+		
+		CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image);
+		if(NULL == cg_image_ref)
+		{
+			CFRelease(cg_dest_ref);
+			return WriteResult::ERROR_IN_WRITING_FILE;
+		}
+		
+		CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL);
+		if(CGImageDestinationFinalize(cg_dest_ref))
+		{
+			ret_val = WriteResult::FILE_SAVED;
+		}
+		else
+		{
+			ret_val = WriteResult::ERROR_IN_WRITING_FILE;
+		}
+		
+		CFRelease(cg_image_ref);
+		CFRelease(cg_dest_ref);
+		
+		return WriteResult::FILE_SAVED;	
+	}
+		
+	virtual WriteResult writeImage(const osg::Image& osg_image, std::ostream& fout, const osgDB::ReaderWriter::Options* the_options) const
+	{
+		WriteResult write_result = writeImageStream(osg_image, fout, the_options);
+		return write_result;
+	}
+
+	WriteResult writeImageFile(const osg::Image& osg_image, const std::string& full_file_name, const osgDB::ReaderWriter::Options* the_options) const
+	{
+		WriteResult ret_val = WriteResult::ERROR_IN_WRITING_FILE;
+		// Call ImageIO to load the image.
+		CGImageDestinationRef cg_dest_ref = CreateCGImageDestinationFromFile(full_file_name.c_str(), the_options);
+		if (NULL == cg_dest_ref) return WriteResult::ERROR_IN_WRITING_FILE;
+
+		CGImageRef cg_image_ref = CreateCGImageFromOSGData(osg_image);
+		if(NULL == cg_image_ref)
+		{
+			CFRelease(cg_dest_ref);
+			return WriteResult::ERROR_IN_WRITING_FILE;
+		}
+
+		CGImageDestinationAddImage(cg_dest_ref, cg_image_ref, NULL);
+		if(CGImageDestinationFinalize(cg_dest_ref))
+		{
+			ret_val = WriteResult::FILE_SAVED;
+		}
+		else
+		{
+			ret_val = WriteResult::ERROR_IN_WRITING_FILE;
+		}
+		
+		CFRelease(cg_image_ref);
+		CFRelease(cg_dest_ref);
+		
+		return WriteResult::FILE_SAVED;
+	}
+
+	virtual WriteResult writeImage(const osg::Image& osg_image, const std::string& file_name, const osgDB::ReaderWriter::Options* the_options) const
+	{
+		std::string ext = osgDB::getFileExtension(file_name);
+		if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
+
+#if 1
+		// FIXME: Something may need to provide a proper writable location for the files.
+		std::string full_file_name;
+		full_file_name = file_name;
+		return writeImageFile(osg_image, full_file_name, the_options);
+#else
+		// Only here to help test ostream backend. The file version is better because 
+		// the filenname.extension could potentially be used by ImageIO to hint what the format type is.
+		std::ofstream fout(file_name.c_str(), std::ios::out | std::ios::binary);
+		if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
+		return writeImage(osg_image, fout, the_options);
+#endif		
+	}
+
+};
+
+// now register with Registry to instantiate the above
+// reader/writer.
+
+osgDB::RegisterReaderWriterProxy<ReaderWriterImageIO> g_readerWriter_ImageIO_Proxy;
+
+
+
+
Index: /OpenSceneGraph/trunk/src/osgPlugins/imageio/CMakeLists.txt
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/imageio/CMakeLists.txt (revision 9880)
+++ /OpenSceneGraph/trunk/src/osgPlugins/imageio/CMakeLists.txt (revision 9880)
@@ -0,0 +1,9 @@
+SET(TARGET_SRC ReaderWriterImageIO.cpp )
+
+SET(TARGET_ADDED_LIBRARIES)
+SET(TARGET_LIBRARIES_VARS IMAGEIO_LIBRARY )
+SET(TARGET_EXTERNAL_LIBRARIES "/System/Library/Frameworks/Accelerate.framework" )
+
+#### end var setup  ###
+SETUP_PLUGIN(imageio)
+
Index: /OpenSceneGraph/trunk/src/osgPlugins/CMakeLists.txt
===================================================================
--- /OpenSceneGraph/trunk/src/osgPlugins/CMakeLists.txt (revision 9855)
+++ /OpenSceneGraph/trunk/src/osgPlugins/CMakeLists.txt (revision 9880)
@@ -205,4 +205,8 @@
 # ENDIF(OPENAL_FOUND)
 
+IF(APPLE)
+    ADD_SUBDIRECTORY(imageio)
+ENDIF(APPLE)
+
 IF(QUICKTIME_FOUND)
     ADD_SUBDIRECTORY(quicktime)
Index: /OpenSceneGraph/trunk/src/osgDB/Registry.cpp
===================================================================
--- /OpenSceneGraph/trunk/src/osgDB/Registry.cpp (revision 9717)
+++ /OpenSceneGraph/trunk/src/osgDB/Registry.cpp (revision 9880)
@@ -239,4 +239,17 @@
     addFileExtensionAlias("vert",   "glsl");
     addFileExtensionAlias("frag",   "glsl");
+
+
+#if defined(DARWIN_IMAGEIO)
+    addFileExtensionAlias("jpg",  "imageio");
+    addFileExtensionAlias("jpe",  "imageio");
+    addFileExtensionAlias("jpeg", "imageio");
+    addFileExtensionAlias("tif",  "imageio");
+    addFileExtensionAlias("tiff", "imageio");
+    addFileExtensionAlias("gif",  "imageio");
+    addFileExtensionAlias("png",  "imageio");
+    addFileExtensionAlias("psd",  "imageio");
+    addFileExtensionAlias("tga",  "imageio");
+#endif
 
 #if defined(DARWIN_QUICKTIME)
Index: /OpenSceneGraph/trunk/src/osgDB/CMakeLists.txt
===================================================================
--- /OpenSceneGraph/trunk/src/osgDB/CMakeLists.txt (revision 9671)
+++ /OpenSceneGraph/trunk/src/osgDB/CMakeLists.txt (revision 9880)
@@ -77,5 +77,14 @@
     # Needs CoreFoundation calls and a Carbon function
     SET(OSGDB_PLATFORM_SPECIFIC_LIBRARIES ${CARBON_LIBRARY})
-    ADD_DEFINITIONS(-DDARWIN_QUICKTIME)
+ 
+    SET(OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX "quicktime" CACHE STRING "standard image plugin for os x, options are quicktime, imageio")
+
+
+    IF(${OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX} STREQUAL "quicktime")
+        ADD_DEFINITIONS(-DDARWIN_QUICKTIME)
+    ELSE(${OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX} STREQUAL "quicktime")
+        ADD_DEFINITIONS(-DDARWIN_IMAGEIO)
+    ENDIF(${OSG_DEFAULT_IMAGE_PLUGIN_FOR_OSX} STREQUAL "quicktime")
+
 ENDIF(APPLE)
 
