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] ); }
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() ); } }
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[]>() ); }