ImageTargetGWorld::ImageTargetGWorld( ImageSourceRef imageSource )
	: ImageTarget(), mGWorld( 0 ), mPixMap( 0 )
{
	setSize( (size_t)imageSource->getWidth(), (size_t)imageSource->getHeight() );
	
	OSType formatType;
	// for now all we support is 8 bit RGBA
	setDataType( ImageIo::UINT8 );
	formatType = k32ARGBPixelFormat;
	setChannelOrder( ImageIo::ARGB );
	setColorModel( ImageIo::CM_RGB );

	::Rect boundsRect;
	boundsRect.left = boundsRect.top = 0;
	boundsRect.right = (short)imageSource->getWidth();
	boundsRect.bottom = (short)imageSource->getHeight();
	if( ::QTNewGWorld( &mGWorld, formatType, &boundsRect, NULL, NULL, 0 ) != noErr )
		throw ImageIoException();
	
	mPixMap = ::GetGWorldPixMap( mGWorld );
    if( ! ::LockPixels( mPixMap ) ) {
		::DisposeGWorld( mGWorld );
        throw ImageIoException();
	}

#if defined( CINDER_MSW )
	mData = reinterpret_cast<uint8_t*>( (**mPixMap).baseAddr );
	mRowBytes = ( (**mPixMap).rowBytes ) & 0x3FFF;
#else
	mData = reinterpret_cast<uint8_t*>( ::GetPixBaseAddr( mPixMap ) );
	mRowBytes = ::GetPixRowBytes( mPixMap );
#endif
}
ImageTargetCvPixelBuffer::ImageTargetCvPixelBuffer( ImageSourceRef imageSource, bool convertToYpCbCr )
	: ImageTarget(), mPixelBufferRef( 0 ), mConvertToYpCbCr( convertToYpCbCr )
{
	setSize( (size_t)imageSource->getWidth(), (size_t)imageSource->getHeight() );
	
	//http://developer.apple.com/mac/library/qa/qa2006/qa1501.html
	
	// if we're converting to YCbCr, we'll load all of the data as RGB in terms of ci::ImageIo
	// but we run color space conversion over it later in the finalize method
	OSType formatType;
	if( ! mConvertToYpCbCr ) {
		switch( imageSource->getDataType() ) {
			// for now all we support is 8 bit RGB(A)
			case ImageIo::UINT16:
			case ImageIo::FLOAT32:
			case ImageIo::UINT8:
				setDataType( ImageIo::UINT8 );
				if( imageSource->hasAlpha () ) {
					formatType = k32ARGBPixelFormat;
					setChannelOrder( ImageIo::ARGB );
				}
				else {
					formatType = k24RGBPixelFormat;
					setChannelOrder( ImageIo::RGB );
				}
				setColorModel( ImageIo::CM_RGB );
			break;
			default:
				throw ImageIoException();
		}
	}
	else {
		formatType = 'v408';/*k4444YpCbCrA8PixelFormat;*/
		setDataType( ImageIo::UINT8 );
		setChannelOrder( ImageIo::RGBA );
		setColorModel( ImageIo::CM_RGB );
	}

	if( ::CVPixelBufferCreate( kCFAllocatorDefault, imageSource->getWidth(), imageSource->getHeight(), 
				formatType, NULL, &mPixelBufferRef ) != kCVReturnSuccess )
		throw ImageIoException();
	
	if( ::CVPixelBufferLockBaseAddress( mPixelBufferRef, 0 ) != kCVReturnSuccess )
		throw ImageIoException();
	mData = reinterpret_cast<uint8_t*>( ::CVPixelBufferGetBaseAddress( mPixelBufferRef ) );
	mRowBytes = ::CVPixelBufferGetBytesPerRow( mPixelBufferRef );
}
///////////////////////////////////////////////////////////////////////////////
// ImageSourceFileQuartz
ImageSourceFileQuartzRef ImageSourceFileQuartz::createFileQuartzRef( DataSourceRef dataSourceRef, ImageSource::Options options )
{
	std::shared_ptr<CGImageSource> sourceRef;
	std::shared_ptr<CGImage> imageRef;
	
	::CFStringRef keys[1] = { kCGImageSourceShouldAllowFloat };
	::CFBooleanRef values[1] = { kCFBooleanTrue };
	const std::shared_ptr<__CFDictionary> optionsDict( (__CFDictionary*)CFDictionaryCreate( kCFAllocatorDefault, (const void **)&keys, (const void **)&values, 1, NULL, NULL ), cocoa::safeCfRelease );

	if( dataSourceRef->isFilePath() ) {
		::CFStringRef pathString = cocoa::createCfString( dataSourceRef->getFilePath().string() );
		::CFURLRef urlRef = ::CFURLCreateWithFileSystemPath( kCFAllocatorDefault, pathString, kCFURLPOSIXPathStyle, false );
		sourceRef = std::shared_ptr<CGImageSource>( ::CGImageSourceCreateWithURL( urlRef, optionsDict.get() ), cocoa::safeCfRelease );
		::CFRelease( pathString );
		::CFRelease( urlRef );
	}
	else if( dataSourceRef->isUrl() ) {
		::CFURLRef urlRef = cocoa::createCfUrl( dataSourceRef->getUrl() );
		if( ! urlRef )
			throw ImageIoException( "Could not create CFURLRef from data source." );
		sourceRef = std::shared_ptr<CGImageSource>( ::CGImageSourceCreateWithURL( urlRef, optionsDict.get() ), cocoa::safeCfRelease );
		::CFRelease( urlRef );		
	}
	else { // last ditch, we'll use a dataref from the buffer
		::CFDataRef dataRef = cocoa::createCfDataRef( dataSourceRef->getBuffer() );
		if( ! dataRef )
			throw ImageIoExceptionFailedLoad( "Could not create CFDataRef from data source." );
		
		sourceRef = std::shared_ptr<CGImageSource>( ::CGImageSourceCreateWithData( dataRef, optionsDict.get() ), cocoa::safeCfRelease );
		::CFRelease( dataRef );
	}
	
	if( sourceRef ) {
		imageRef = std::shared_ptr<CGImage>( ::CGImageSourceCreateImageAtIndex( sourceRef.get(), options.getIndex(), optionsDict.get() ), CGImageRelease );
		if( ! imageRef )
			throw ImageIoExceptionFailedLoad( "Core Graphics coult not create image data." );
	}
	else
		throw ImageIoExceptionFailedLoad( "Failed to load CGImageSource." );

	const std::shared_ptr<__CFDictionary> imageProperties( (__CFDictionary*)::CGImageSourceCopyProperties( sourceRef.get(), NULL ), ::CFRelease );
	const std::shared_ptr<__CFDictionary> imageIndexProperties( (__CFDictionary*)::CGImageSourceCopyPropertiesAtIndex( sourceRef.get(), options.getIndex(), NULL ), ::CFRelease );

	return ImageSourceFileQuartzRef( new ImageSourceFileQuartz( imageRef.get(), options, imageProperties, imageIndexProperties ) );
}
void ImageTargetFileWic::setupPixelFormat( const GUID &guid )
{
	if( guid == GUID_WICPixelFormat24bppBGR ) {		
		setChannelOrder( ImageIo::BGR ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT8 );
	}
	else if( guid == GUID_WICPixelFormat24bppRGB ) {
		setChannelOrder( ImageIo::RGB ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT8 );
	}
	else if( guid == GUID_WICPixelFormat32bppBGR ) {
		setChannelOrder( ImageIo::BGRX ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT8 );
	}
	else if( guid == GUID_WICPixelFormat32bppBGRA ) {
		setChannelOrder( ImageIo::BGRA ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT8 );
	}
	else if( guid == GUID_WICPixelFormat32bppPBGRA ) {
		setChannelOrder( ImageIo::BGRA ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT8 );// mIsPremultipliedAlpha = true;
	}
	else if( guid == GUID_WICPixelFormat48bppRGB ) {
		setChannelOrder( ImageIo::RGB ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT16 );
	}
	else if( guid == GUID_WICPixelFormat64bppRGBA ) {
		setChannelOrder( ImageIo::RGBA ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT16 );
	}
	else if( guid == GUID_WICPixelFormat64bppPRGBA ) {
		setChannelOrder( ImageIo::RGBA ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::UINT16 ); // mIsPremultipliedAlpha = true;
	}
	else if( guid == GUID_WICPixelFormat128bppRGBFloat ) {
		setChannelOrder( ImageIo::RGB ); setColorModel( ImageIo::CM_RGB ); setDataType( ImageIo::FLOAT32 );
	}
	else if( guid == GUID_WICPixelFormat8bppGray ) {
		setChannelOrder( ImageIo::Y ); setColorModel( ImageIo::CM_GRAY ); setDataType( ImageIo::UINT8 );
	}
	else if( guid == GUID_WICPixelFormat16bppGray ) {
		setChannelOrder( ImageIo::Y ); setColorModel( ImageIo::CM_GRAY ); setDataType( ImageIo::UINT16 );
	}
	else if( guid == GUID_WICPixelFormat32bppGrayFloat ) {
		setChannelOrder( ImageIo::Y ); setColorModel( ImageIo::CM_GRAY ); setDataType( ImageIo::FLOAT32 );
	}
	else
		throw ImageIoException( "Unsupported format." );
	
	int32_t bitsPerComponent;
	bool writingAlpha = hasAlpha();
	bool isFloat = true;
	switch( getDataType() ) {
		case ImageIo::UINT8: bitsPerComponent = 8; isFloat = false; break;
		case ImageIo::UINT16: bitsPerComponent = 16; isFloat = false; break;
		default: bitsPerComponent = 32; isFloat = true;
	}
	uint8_t numChannels;
	switch( getColorModel() ) {
		case ImageIo::CM_GRAY:
			numChannels = ( writingAlpha ) ? 2 : 1; break;
		default:
			numChannels = ( writingAlpha ) ? 4 : 3;
	}
	int32_t bitsPerPixel = numChannels * bitsPerComponent;
	mRowBytes = ( mWidth * ( bitsPerPixel / 8 ) + 3 ) & ~3;

	return;
}