Example #1
0
SurfaceImage::SurfaceImage( ImageSourceRef imageSource )
	: SurfaceBase( imageSource->getWidth(), imageSource->getWidth() )
{
	mCairoSurface = cairo_image_surface_create( imageSource->hasAlpha() ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32, imageSource->getWidth(), imageSource->getHeight() );
	initCinderSurface( imageSource->hasAlpha(), cairo_image_surface_get_data( mCairoSurface ), cairo_image_surface_get_stride( mCairoSurface ) );
	writeImage( (ImageTargetRef)mCinderSurface, imageSource );
}
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
}
Example #3
0
void SurfaceT<T>::init( ImageSourceRef imageSource, const SurfaceConstraints &constraints, boost::tribool alpha )
{
	int32_t width = imageSource->getWidth();
	int32_t height = imageSource->getHeight();
	bool hasAlpha;
	if( alpha )
		hasAlpha = true;
	else if( ! alpha )
		hasAlpha = false;
	else
		hasAlpha = imageSource->hasAlpha();

	SurfaceChannelOrder channelOrder = constraints.getChannelOrder( hasAlpha );
	int32_t rowBytes = constraints.getRowBytes( width, channelOrder, sizeof(T) );
	
	T *data = new T[height * rowBytes];

	mObj = std::shared_ptr<Obj>( new Obj( width, height, channelOrder, data, true, rowBytes ) );
	mObj->mIsPremultiplied = imageSource->isPremultiplied();
	
	std::shared_ptr<ImageTargetSurface<T> > target = ImageTargetSurface<T>::createRef( this );
	imageSource->load( target );
	
	// if the image doesn't have alpha but we do, set ourselves to be full alpha
	if( hasAlpha && ( ! imageSource->hasAlpha() ) ) {
		ip::fill( &getChannelAlpha(), CHANTRAIT<T>::max() );
	}	
}
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 );
}
Example #5
0
ChannelT<T>::ChannelT( const ImageSourceRef &imageSource )
{
	mWidth = imageSource->getWidth();
	mHeight = imageSource->getHeight();
	mRowBytes = mWidth * sizeof(T);
	mIncrement = 1;

	mDataStore = shared_ptr<T>( new T[mHeight * (mRowBytes/sizeof(T))], std::default_delete<T[]>() );
	mData = mDataStore.get();
	
	shared_ptr<ImageTargetChannel<T>> target = ImageTargetChannel<T>::createRef( this );
	imageSource->load( target );
}
Example #6
0
ImageTargetFileTinyExr::ImageTargetFileTinyExr( DataTargetRef dataTarget, ImageSourceRef imageSource, ImageTarget::Options options, const std::string & /*extensionData*/ )
{
	if( ! dataTarget->providesFilePath() ) {
		throw ImageIoExceptionFailedWrite( "ImageTargetFileTinyExr only supports writing to files." );
	}

	mFilePath = dataTarget->getFilePath();

	setSize( imageSource->getWidth(), imageSource->getHeight() );
	ImageIo::ColorModel cm = options.isColorModelDefault() ? imageSource->getColorModel() : options.getColorModel();
	
	switch( cm ) {
		case ImageIo::ColorModel::CM_RGB:
			mNumComponents = ( imageSource->hasAlpha() ) ? 4 : 3;
			setColorModel( ImageIo::ColorModel::CM_RGB );
			setChannelOrder( ( mNumComponents == 3 ) ? ImageIo::ChannelOrder::BGR : ImageIo::ChannelOrder::ABGR );
			if( mNumComponents == 3 )
				mChannelNames = { "G", "B", "R" };
			else
				mChannelNames = { "A", "G", "B", "R" };
		break;
		case ImageIo::ColorModel::CM_GRAY:
			mNumComponents = ( imageSource->hasAlpha() ) ? 2 : 1;
			setColorModel( ImageIo::ColorModel::CM_GRAY );
			setChannelOrder( ( mNumComponents == 2 ) ? ImageIo::ChannelOrder::YA : ImageIo::ChannelOrder::Y );
			if( mNumComponents == 2 )
				mChannelNames = { "Y", "A" };
			else
				mChannelNames = { "Y" };
		break;
		default:
			throw ImageIoExceptionIllegalColorModel();
	}

	// TODO: consider supporting half float and uint types as well
	setDataType( ImageIo::DataType::FLOAT32 );
	mData.resize( mHeight * imageSource->getWidth() * mNumComponents );
}
ImageTargetFileStbImage::ImageTargetFileStbImage( DataTargetRef dataTarget, ImageSourceRef imageSource, ImageTarget::Options options, const std::string &extensionData )
{
	if( ! dataTarget->providesFilePath() ) {
		throw ImageIoExceptionFailedWrite( "ImageTargetFileStbImage only supports writing to files." );
	}

	mFilePath = dataTarget->getFilePath();

	setSize( imageSource->getWidth(), imageSource->getHeight() );
	ImageIo::ColorModel cm = options.isColorModelDefault() ? imageSource->getColorModel() : options.getColorModel();
	
	switch( cm ) {
		case ImageIo::ColorModel::CM_RGB:
			mNumComponents = ( imageSource->hasAlpha() ) ? 4 : 3;
			setColorModel( ImageIo::ColorModel::CM_RGB );
			setChannelOrder( ( mNumComponents == 4 ) ? ImageIo::ChannelOrder::RGBA : ImageIo::ChannelOrder::RGB );
		break;
		case ImageIo::ColorModel::CM_GRAY:
			mNumComponents = ( imageSource->hasAlpha() ) ? 2 : 1;
			setColorModel( ImageIo::ColorModel::CM_GRAY );
			setChannelOrder( ( mNumComponents == 2 ) ? ImageIo::ChannelOrder::YA : ImageIo::ChannelOrder::Y );
		break;
		default:
			throw ImageIoExceptionIllegalColorModel();
	}

	mExtension = extensionData;
	if( mExtension == "hdr" ) { // Radiance files are always float*
		setDataType( ImageIo::DataType::FLOAT32 );
		mRowBytes = mNumComponents * imageSource->getWidth() * sizeof(float);
	}
	else {
		setDataType( ImageIo::DataType::UINT8 );
		mRowBytes = mNumComponents * imageSource->getWidth() * sizeof(float);
	}
	
	mData = std::unique_ptr<uint8_t[]>( new uint8_t[mWidth * mRowBytes] );
}
Example #8
0
ChannelT<T>::ChannelT( ImageSourceRef imageSource )
{
	int32_t width = imageSource->getWidth();
	int32_t height = imageSource->getHeight();
	int32_t rowBytes = width * sizeof(T);

	T *data = new T[height * (rowBytes/sizeof(T))];

	mObj = shared_ptr<Obj>( new Obj( width, height, rowBytes, 1, true, data ) );
	mObj->mOwnsData = true;
	
	shared_ptr<ImageTargetChannel<T> > target = ImageTargetChannel<T>::createRef( this );
	imageSource->load( target );	
}
Example #9
0
void Texture::init( ImageSourceRef imageSource, const Format &format )
{
	mObj->mDoNotDispose = false;
	mObj->mTarget = format.mTarget;
	mObj->mWidth = mObj->mCleanWidth = imageSource->getWidth();
	mObj->mHeight = mObj->mCleanHeight = imageSource->getHeight();

#if defined( CINDER_MAC )
	bool supportsTextureFloat = gl::isExtensionAvailable( "GL_ARB_texture_float" );
#elif defined( CINDER_MSW )
	bool supportsTextureFloat = GLEE_ARB_texture_float != 0;
#endif
	
	// Set the internal format based on the image's color space
	if( format.isAutoInternalFormat() ) {
		switch( imageSource->getColorModel() ) {
#if ! defined( CINDER_GLES )
			case ImageIo::CM_RGB:
				if( imageSource->getDataType() == ImageIo::UINT8 )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_RGBA8 : GL_RGB8;
				else if( imageSource->getDataType() == ImageIo::UINT16 )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_RGBA16 : GL_RGB16;
				else if( imageSource->getDataType() == ImageIo::FLOAT32 && supportsTextureFloat )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_RGBA32F_ARB : GL_RGB32F_ARB;
				else
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_RGBA : GL_RGB;
			break;
			case ImageIo::CM_GRAY:
				if( imageSource->getDataType() == ImageIo::UINT8 )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE8_ALPHA8 : GL_LUMINANCE8;
				else if( imageSource->getDataType() == ImageIo::UINT16 )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE16_ALPHA16 : GL_LUMINANCE16;
				else if( imageSource->getDataType() == ImageIo::FLOAT32 && supportsTextureFloat )
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE_ALPHA32F_ARB : GL_LUMINANCE32F_ARB;
				else
					mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
			break;
#else
			case ImageIo::CM_RGB:
				mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_RGBA : GL_RGB;
			break;
			case ImageIo::CM_GRAY:
				mObj->mInternalFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
			break;
			
#endif
			default:
				throw ImageIoExceptionIllegalColorModel();
			break;
		}
	}
	else {
		mObj->mInternalFormat = format.mInternalFormat;
	}

	// setup an appropriate dataFormat/ImageTargetTexture based on the image's color space
	GLint dataFormat;
	ImageIo::ChannelOrder channelOrder;
	bool isGray = false;
	switch( imageSource->getColorModel() ) {
		case ImageSource::CM_RGB:
			dataFormat = ( imageSource->hasAlpha() ) ? GL_RGBA : GL_RGB;
			channelOrder = ( imageSource->hasAlpha() ) ? ImageIo::RGBA : ImageIo::RGB;
		break;
		case ImageSource::CM_GRAY:
			dataFormat = ( imageSource->hasAlpha() ) ? GL_LUMINANCE_ALPHA : GL_LUMINANCE;
			channelOrder = ( imageSource->hasAlpha() ) ? ImageIo::YA : ImageIo::Y;
			isGray = true;
		break;
		default: // if this is some other color space, we'll have to punt and go w/ RGB
			dataFormat = ( imageSource->hasAlpha() ) ? GL_RGBA : GL_RGB;
			channelOrder = ( imageSource->hasAlpha() ) ? ImageIo::RGBA : ImageIo::RGB;
		break;
	}

	glGenTextures( 1, &mObj->mTextureID );
	glBindTexture( mObj->mTarget, mObj->mTextureID );

	glTexParameteri( mObj->mTarget, GL_TEXTURE_WRAP_S, format.mWrapS );
	glTexParameteri( mObj->mTarget, GL_TEXTURE_WRAP_T, format.mWrapT );
	glTexParameteri( mObj->mTarget, GL_TEXTURE_MIN_FILTER, format.mMinFilter );	
	glTexParameteri( mObj->mTarget, GL_TEXTURE_MAG_FILTER, format.mMagFilter );
	if( format.mMipmapping )
		glTexParameteri( mObj->mTarget, GL_GENERATE_MIPMAP, GL_TRUE );
	if( mObj->mTarget == GL_TEXTURE_2D ) {
		mObj->mMaxU = mObj->mMaxV = 1.0f;
	}
	else {
		mObj->mMaxU = (float)mObj->mWidth;
		mObj->mMaxV = (float)mObj->mHeight;
	}	

	glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
	if( imageSource->getDataType() == ImageIo::UINT8 ) {
		shared_ptr<ImageTargetGLTexture<uint8_t> > target = ImageTargetGLTexture<uint8_t>::createRef( this, channelOrder, isGray, imageSource->hasAlpha() );
		imageSource->load( target );
		glTexImage2D( mObj->mTarget, 0, mObj->mInternalFormat, mObj->mWidth, mObj->mHeight, 0, dataFormat, GL_UNSIGNED_BYTE, target->getData() );
	}
	else if( imageSource->getDataType() == ImageIo::UINT16 ) {
		shared_ptr<ImageTargetGLTexture<uint16_t> > target = ImageTargetGLTexture<uint16_t>::createRef( this, channelOrder, isGray, imageSource->hasAlpha() );
		imageSource->load( target );		
		glTexImage2D( mObj->mTarget, 0, mObj->mInternalFormat, mObj->mWidth, mObj->mHeight, 0, dataFormat, GL_UNSIGNED_SHORT, target->getData() );
	
	}
	else {
		shared_ptr<ImageTargetGLTexture<float> > target = ImageTargetGLTexture<float>::createRef( this, channelOrder, isGray, imageSource->hasAlpha() );
		imageSource->load( target );		
		glTexImage2D( mObj->mTarget, 0, mObj->mInternalFormat, mObj->mWidth, mObj->mHeight, 0, dataFormat, GL_FLOAT, target->getData() );
	}
}
Example #10
0
ImageTargetFileWic::ImageTargetFileWic( DataTargetRef dataTarget, ImageSourceRef imageSource, const string &extensionData )
	: ImageTarget(), mDataTarget( dataTarget )
{
	mCodecGUID = getExtensionMap()[extensionData];

	setSize( imageSource->getWidth(), imageSource->getHeight() );

	// determine the pixel format we'll request
	WICPixelFormatGUID formatGUID;
	if( imageSource->hasAlpha() ) {
		bool premultAlpha = imageSource->isPremultiplied();
		// WIC doesn't support gray+alpha, so we need to do RGBA regardless
		if( imageSource->getDataType() == ImageIo::UINT8 )
			formatGUID = premultAlpha ? GUID_WICPixelFormat32bppPBGRA : GUID_WICPixelFormat32bppBGRA;
		else if( imageSource->getDataType() == ImageIo::UINT16 )
			formatGUID = premultAlpha ? GUID_WICPixelFormat64bppPRGBA : GUID_WICPixelFormat64bppRGBA;
		else
			formatGUID = premultAlpha ? GUID_WICPixelFormat128bppPRGBAFloat : GUID_WICPixelFormat128bppRGBAFloat;
	}
	else {
		if( imageSource->getColorModel() == ImageIo::CM_GRAY ) {
			if( imageSource->getDataType() == ImageIo::UINT8 )
				formatGUID = GUID_WICPixelFormat8bppGray;
			else if( imageSource->getDataType() == ImageIo::UINT16 )
				formatGUID = GUID_WICPixelFormat16bppGray;
			else
				formatGUID = GUID_WICPixelFormat32bppGrayFloat;
		}
		else {
			if( imageSource->getDataType() == ImageIo::UINT8 )
				formatGUID = GUID_WICPixelFormat24bppBGR;
			else if( imageSource->getDataType() == ImageIo::UINT16 )
				formatGUID = GUID_WICPixelFormat48bppRGB;
			else
				formatGUID = GUID_WICPixelFormat128bppRGBFloat;
		}
	}
	
	::HRESULT hr = S_OK;

	msw::initializeCom();

 // Create WIC factory
    IWICImagingFactory *IWICFactoryP = NULL;
    hr = ::CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&IWICFactoryP) );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();
	shared_ptr<IWICImagingFactory> IWICFactory = msw::makeComShared( IWICFactoryP );

	IWICBitmapEncoder *encoderP = NULL;
	hr = IWICFactory->CreateEncoder( *mCodecGUID, 0, &encoderP );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();
	mEncoder = msw::makeComShared( encoderP );
	
	// create the stream		
	IWICStream *pIWICStream = NULL;
	hr = IWICFactory->CreateStream( &pIWICStream );
	if( ! SUCCEEDED(hr) )
		throw ImageIoExceptionFailedLoad();
	shared_ptr<IWICStream> stream = msw::makeComShared( pIWICStream );
	
	// initialize the stream based on properties of the cinder::DataSouce
	if( mDataTarget->providesFilePath() ) {
		hr = stream->InitializeFromFilename( toUtf16( mDataTarget->getFilePath() ).c_str(), GENERIC_WRITE );
		if( ! SUCCEEDED(hr) )
			throw ImageIoExceptionFailedLoad();
	}
	else {
		shared_ptr<msw::ComOStream> comOStream = msw::makeComShared( new msw::ComOStream( mDataTarget->getStream() ) );
		hr = stream->InitializeFromIStream( comOStream.get() );
		if( ! SUCCEEDED(hr) )
			throw ImageIoExceptionFailedLoad();		
	}
	
	hr = mEncoder->Initialize( stream.get(), WICBitmapEncoderNoCache );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();

	// create the frame encoder
	IPropertyBag2 *pPropertybag = NULL;
	IWICBitmapFrameEncode *pBitmapFrame = NULL;
	hr = mEncoder->CreateNewFrame( &pBitmapFrame, &pPropertybag );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();
	mBitmapFrame = msw::makeComShared( pBitmapFrame );

	hr = mBitmapFrame->Initialize( 0 );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();	
	
	hr = mBitmapFrame->SetSize( mWidth, mHeight );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();
	
	// ask for our ideal pixel format and then process the one we actually get
	hr = mBitmapFrame->SetPixelFormat( &formatGUID );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedLoad();
	
	setupPixelFormat( formatGUID );
	
	mData = shared_ptr<uint8_t>( new uint8_t[mHeight * mRowBytes], boost::checked_array_delete<uint8_t> );
}
ImageTargetFileWic::ImageTargetFileWic( DataTargetRef dataTarget, ImageSourceRef imageSource, ImageTarget::Options options, const string &extensionData )
	: ImageTarget(), mDataTarget( dataTarget )
{
	mCodecGUID = getExtensionMap()[extensionData];

	setSize( imageSource->getWidth(), imageSource->getHeight() );

	// determine the pixel format we'll request
	WICPixelFormatGUID formatGUID;
	if( imageSource->hasAlpha() ) {
		bool premultAlpha = imageSource->isPremultiplied();
		// WIC doesn't support gray+alpha, so we need to do RGBA regardless
		if( imageSource->getDataType() == ImageIo::UINT8 )
			formatGUID = premultAlpha ? GUID_WICPixelFormat32bppPBGRA : GUID_WICPixelFormat32bppBGRA;
		else if( imageSource->getDataType() == ImageIo::UINT16 )
			formatGUID = premultAlpha ? GUID_WICPixelFormat64bppPRGBA : GUID_WICPixelFormat64bppRGBA;
		else
			formatGUID = premultAlpha ? GUID_WICPixelFormat128bppPRGBAFloat : GUID_WICPixelFormat128bppRGBAFloat;
	}
	else {
		ImageIo::ColorModel cm = options.isColorModelDefault() ? imageSource->getColorModel() : options.getColorModel();
		if( cm == ImageIo::CM_GRAY ) {
			if( imageSource->getDataType() == ImageIo::UINT8 )
				formatGUID = GUID_WICPixelFormat8bppGray;
			else if( imageSource->getDataType() == ImageIo::UINT16 )
				formatGUID = GUID_WICPixelFormat16bppGray;
			else
				formatGUID = GUID_WICPixelFormat32bppGrayFloat;
		}
		else { // RGB
			if( imageSource->getDataType() == ImageIo::UINT8 )
				formatGUID = GUID_WICPixelFormat24bppBGR;
			else if( imageSource->getDataType() == ImageIo::UINT16 )
				formatGUID = GUID_WICPixelFormat48bppRGB;
			else
				formatGUID = GUID_WICPixelFormat128bppRGBFloat;
		}
	}
	
	::HRESULT hr = S_OK;

	msw::initializeCom();

 // Create WIC factory
    IWICImagingFactory *IWICFactoryP = NULL;
    hr = ::CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&IWICFactoryP) );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not create WIC Factory." );
	shared_ptr<IWICImagingFactory> IWICFactory = msw::makeComShared( IWICFactoryP );

	IWICBitmapEncoder *encoderP = NULL;
	hr = IWICFactory->CreateEncoder( *mCodecGUID, 0, &encoderP );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not create WIC Encoder." );
	mEncoder = msw::makeComShared( encoderP );
	
	// create the stream		
	IWICStream *pIWICStream = NULL;
	hr = IWICFactory->CreateStream( &pIWICStream );
	if( ! SUCCEEDED(hr) )
		throw ImageIoExceptionFailedWrite( "Could not create WIC stream." );
	shared_ptr<IWICStream> stream = msw::makeComShared( pIWICStream );
	
	// initialize the stream based on properties of the cinder::DataSouce
	if( mDataTarget->providesFilePath() ) {
#if defined( CINDER_WINRT)
		std::string s = mDataTarget->getFilePath().string();
		std::wstring filePath =	std::wstring(s.begin(), s.end());                 
#else
		std::wstring filePath =	mDataTarget->getFilePath().wstring().c_str();
#endif
		hr = stream->InitializeFromFilename( filePath.c_str(), GENERIC_WRITE );
		if( ! SUCCEEDED(hr) )
			throw ImageIoExceptionFailedWrite( "Could not initialize WIC Stream from filename." );
	}
	else {
		shared_ptr<msw::ComOStream> comOStream = msw::makeComShared( new msw::ComOStream( mDataTarget->getStream() ) );
		hr = stream->InitializeFromIStream( comOStream.get() );
		if( ! SUCCEEDED(hr) )
			throw ImageIoExceptionFailedWrite( "Could not initialize WIC Stream from IStream." );
	}
	
	hr = mEncoder->Initialize( stream.get(), WICBitmapEncoderNoCache );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not initialize WIC Encoder." );

	// create the frame encoder
	IPropertyBag2 *pPropertybag = NULL;
	IWICBitmapFrameEncode *pBitmapFrame = NULL;
	hr = mEncoder->CreateNewFrame( &pBitmapFrame, &pPropertybag );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not ceate WIC Frame." );
	mBitmapFrame = msw::makeComShared( pBitmapFrame );

	// setup the propertyBag to express quality
	PROPBAG2 option = { 0 };
    option.pstrName = L"ImageQuality";
    VARIANT varValue;    
    VariantInit(&varValue);
    varValue.vt = VT_R4;
    varValue.fltVal = options.getQuality();      
    hr = pPropertybag->Write( 1, &option, &varValue );

	hr = mBitmapFrame->Initialize( pPropertybag );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not initialize WIC PROPBAG2." );
	
	hr = mBitmapFrame->SetSize( mWidth, mHeight );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not set WIC Frame size." );
	
	// ask for our ideal pixel format and then process the one we actually get
	hr = mBitmapFrame->SetPixelFormat( &formatGUID );
	if( ! SUCCEEDED( hr ) )
		throw ImageIoExceptionFailedWrite( "Could not set WIC Frame pixel format." );
	
	setupPixelFormat( formatGUID );
	
	mData = shared_ptr<uint8_t>( new uint8_t[mHeight * mRowBytes], std::default_delete<uint8_t[]>() );
}