void ImageTargetFileWic::finalize() { ::HRESULT hr = S_OK; hr = mBitmapFrame->WritePixels( mHeight, mRowBytes, mHeight * mRowBytes, mData.get() ); if( ! SUCCEEDED( hr ) ) throw ImageIoExceptionFailedLoad(); hr = mBitmapFrame->Commit(); if( ! SUCCEEDED( hr ) ) throw ImageIoExceptionFailedLoad(); hr = mEncoder->Commit(); if( ! SUCCEEDED( hr ) ) throw ImageIoExceptionFailedLoad(); }
ImageSourceRef ImageIoRegistrar::Inst::createSource( DataSourceRef dataSource, ImageSource::Options options, string extension ) { std::transform( extension.begin(), extension.end(), extension.begin(), static_cast<int(*)(int)>( tolower ) ); // for non-empty extensions we'll walk everyone who is registered for this extension if( ! extension.empty() ) { map<string,multimap<int32_t,ImageIoRegistrar::SourceCreationFunc> >::iterator sIt = mSources.find( extension ); if( sIt != mSources.end() ) { for( multimap<int32_t,ImageIoRegistrar::SourceCreationFunc>::const_iterator sourcesIt = sIt->second.begin(); sourcesIt != sIt->second.end(); ++sourcesIt ) { try { return (*(sourcesIt->second))( dataSource, options ); } catch( ... ) { // we'll ignore exceptions and move to the next handler } } } } // if there is no extension, or none of the registered types got it, we'll have try the generic loaders for( map<int32_t, ImageIoRegistrar::SourceCreationFunc>::const_iterator genericIt = mGenericSources.begin(); genericIt != mGenericSources.end(); ++genericIt ) { try { return (*(genericIt->second))( dataSource, options ); } catch( ... ) { // we'll ignore exceptions and move to the next handler } } // failure throw ImageIoExceptionFailedLoad(); }
/////////////////////////////////////////////////////////////////////////////// // 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 ImageIoExceptionFailedLoad(); 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(); 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(); } else throw ImageIoExceptionFailedLoad(); 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 ) ); }
/////////////////////////////////////////////////////////////////////////////// // ImageSourceFileQuartz ImageSourceFileQuartzRef ImageSourceFileQuartz::createFileQuartzRef( DataSourceRef dataSourceRef ) { ::CGImageSourceRef sourceRef = NULL; ::CGImageRef imageRef = NULL; ::CFStringRef keys[1] = { kCGImageSourceShouldAllowFloat }; ::CFBooleanRef values[1] = { kCFBooleanTrue }; ::CFDictionaryRef optionsDict = ::CFDictionaryCreate( kCFAllocatorDefault, (const void **)&keys, (const void **)&values, 1, NULL, NULL ); if( dataSourceRef->isFilePath() ) { ::CFStringRef pathString = cocoa::createCfString( dataSourceRef->getFilePath() ); ::CFURLRef urlRef = ::CFURLCreateWithFileSystemPath( kCFAllocatorDefault, pathString, kCFURLPOSIXPathStyle, false ); sourceRef = ::CGImageSourceCreateWithURL( urlRef, optionsDict ); ::CFRelease( pathString ); ::CFRelease( urlRef ); } else if( dataSourceRef->isUrl() ) { ::CFURLRef urlRef = cocoa::createCfUrl( dataSourceRef->getUrl() ); if( ! urlRef ) throw ImageIoExceptionFailedLoad(); sourceRef = ::CGImageSourceCreateWithURL( urlRef, optionsDict ); ::CFRelease( urlRef ); } else { // last ditch, we'll use a dataref from the buffer ::CFDataRef dataRef = cocoa::createCfDataRef( dataSourceRef->getBuffer() ); if( ! dataRef ) throw ImageIoExceptionFailedLoad(); sourceRef = ::CGImageSourceCreateWithData( dataRef, optionsDict ); ::CFRelease( dataRef ); } if( sourceRef ) { imageRef = ::CGImageSourceCreateImageAtIndex( sourceRef, 0, optionsDict ); ::CFRelease( sourceRef ); if( ! imageRef ) throw ImageIoExceptionFailedLoad(); } else throw ImageIoExceptionFailedLoad(); return ImageSourceFileQuartzRef( new ImageSourceFileQuartz( imageRef ) ); }
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> ); }
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 ImageIoExceptionFailedLoad(); 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; }
ImageSourceFileWic::ImageSourceFileWic( DataSourceRef dataSourceRef, ImageSource::Options options ) : ImageSource() { ::HRESULT hr = S_OK; // Initialize COM 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(); std::shared_ptr<IWICImagingFactory> IWICFactory = msw::makeComShared( IWICFactoryP ); // Create a decoder IWICBitmapDecoder *decoderP = NULL; if( dataSourceRef->isFilePath() ) { hr = IWICFactory->CreateDecoderFromFilename( toUtf16( dataSourceRef->getFilePath().string() ).c_str(), // Image to be decoded NULL, // Do not prefer a particular vendor GENERIC_READ, // Desired read access to the file WICDecodeMetadataCacheOnDemand, // Cache metadata when needed &decoderP // Pointer to the decoder ); if( ! SUCCEEDED(hr) ) throw ImageIoExceptionFailedLoad(); } else { // have to use a buffer IWICStream *pIWICStream = NULL; hr = IWICFactory->CreateStream( &pIWICStream ); if( ! SUCCEEDED(hr) ) throw ImageIoExceptionFailedLoad(); std::shared_ptr<IWICStream> stream = msw::makeComShared( pIWICStream ); Buffer buffer = dataSourceRef->getBuffer(); hr = stream->InitializeFromMemory( reinterpret_cast<BYTE*>( buffer.getData() ), buffer.getDataSize() ); if( ! SUCCEEDED(hr) ) throw ImageIoExceptionFailedLoad(); hr = IWICFactory->CreateDecoderFromStream( stream.get(), NULL, WICDecodeMetadataCacheOnDemand, &decoderP ); if( ! SUCCEEDED(hr) ) throw ImageIoExceptionFailedLoad(); } std::shared_ptr<IWICBitmapDecoder> decoder = msw::makeComShared( decoderP ); // Retrieve the 'index' frame of the image from the decoder IWICBitmapFrameDecode *frameP = NULL; hr = decoder->GetFrame( options.getIndex(), &frameP ); if( ! SUCCEEDED(hr) ) throw ImageIoExceptionFailedLoad(); std::shared_ptr<IWICBitmapFrameDecode> frame = msw::makeComShared( frameP ); UINT width = 0, height = 0; frame->GetSize( &width, &height ); mWidth = width; mHeight = height; GUID pixelFormat = { 0 }, convertPixelFormat; frame->GetPixelFormat( &pixelFormat ); bool requiresConversion = processFormat( pixelFormat, &convertPixelFormat ); mRowBytes = mWidth * ImageIo::dataTypeBytes( mDataType ) * channelOrderNumChannels( mChannelOrder ); mData = std::shared_ptr<uint8_t>( new uint8_t[mRowBytes * mHeight], boost::checked_array_delete<uint8_t> ); if( requiresConversion ) { IWICFormatConverter *pIFormatConverter = NULL; hr = IWICFactory->CreateFormatConverter( &pIFormatConverter ); if( ! SUCCEEDED( hr ) ) throw ImageIoExceptionFailedLoad(); std::shared_ptr<IWICFormatConverter> formatConverter = msw::makeComShared( pIFormatConverter ); hr = formatConverter->Initialize( frame.get(), convertPixelFormat, WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom ); if( ! SUCCEEDED( hr ) ) throw ImageIoExceptionFailedLoad(); hr = formatConverter->CopyPixels( NULL, (UINT)mRowBytes, mRowBytes * mHeight, mData.get() ); } else hr = frame->CopyPixels( NULL, (UINT)mRowBytes, mRowBytes * mHeight, mData.get() ); }