need to use WIC to convert any image file format file to bmp file
-
Wednesday, September 05, 2012 12:49 AM
I need a converter that converts any image file format WIC supports to .bmp file format. I can handle the file extensions, that's not a problem.
I have seen no code like this on the internet, no examples like this. very few code examples for using WIC, and I am having a hard time getting started. I haven't done much COM programming in 20 years. I have been sticking to C++ and Win32. documentation needs a lot more examples (right now it has pretty much none for COM stuff).
but now I am forced into COM because I need to convert an image. can someone show me full code to convert from png (if you need a concrete format, assume 24bpp color with alpha) to BMP (if you need a concrete format, 24bpp color or whatever equivalent format)? it would be nice if all I have to do is change the filename on the outside.
thanks.I am lost in a sea of factories. here is what I have so far.
std::string stripValidFileExt(std::string filepath, std::string extToAdd) { std::string ext, newfilepath; filepath=strToLower(filepath); for (uint64_t i=0; i < validFileExts.size(); i++) { ext=strToLower(filepath.substr(filepath.size()-validFileExts[i].size())); //std::cerr<<"ext="<<ext<<','; if (0==validFileExts[i].compare(ext)) { newfilepath = filepath.substr(0,filepath.size()-validFileExts[i].size()); newfilepath+= extToAdd; return newfilepath; } } return filepath; } void convertToBMP(std::string sourceImagefilepath, std::string& bmpfilepath) { bmpfilepath = stripFilePathExt(sourceImagefilepath, ".bmp"); std::string bmpfilepath = strToLower(sourceImagefilepath); IWICImagingFactory* m_pImagingFactory = NULL; IWICComponentFactory* m_pComponentFactory = NULL; HRESULT hr; hr = CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (LPVOID*) m_pImagingFactory ); hr = m_pImagingFactory->QueryInterface( IID_IWICComponentFactory, (void**)&m_pComponentFactory ); HRESULT hr = S_OK; IWICBitmapDecoder *pIDecoder = NULL; IWICBitmapFrameDecode *pIDecoderFrame = NULL; IWICFormatConverter *pIFormatConverter = NULL; // Create the decoder. WHICH FACTORY?????!!!!! hr = m_pIWICFactory->CreateDecoderFromFilename( sourceImageFilepath.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 &pIDecoder // Pointer to the decoder ); // Retrieve the first bitmap frame. if (SUCCEEDED(hr)) { hr = pIDecoder->GetFrame(0, &pIDecoderFrame); } // Create the flip/rotator. if (SUCCEEDED(hr)) { hr = m_pIWICFactory->CreateFormatConverter(&pIFormatConverter); } // Initialize the format converter. if (SUCCEEDED(hr)) { hr = pIFormatConverter->Initialize( pIDecoderFrame, // Input source to convert GUID_WICPixelFormat32bppPBGRA, // Destination pixel format WICBitmapDitherTypeNone, // Specified dither pattern NULL, // Specify a particular palette 0.D, // Alpha threshold WICBitmapPaletteTypeCustom // Palette translation type ); } //Create render target and D2D bitmap from IWICBitmapSource if (SUCCEEDED(hr)) { hr = CreateDeviceResources(hWnd); } if (SUCCEEDED(hr)) { // Need to release the previous D2DBitmap if there is one SafeRelease(&m_pD2DBitmap); hr = m_pRT->CreateBitmapFromWicBitmap(pIFormatConverter, NULL, &m_pD2DBitmap); } SafeRelease(&pIFormatConverter); SafeRelease(&pIDecoderFrame); SafeRelease(&pIDecoder); //HOW!!!!! IWICBitmapEncoder * pIWICBitmapEncoder; IWICBitmapFrameEncode * pIWICBitmapFrameEncode; IPropertyBag2 * pIPropertyBag2; hr = CreateEncoder( CLSID_WICBmpEncoder,//[in] REFGUID guidContainerFormat, GUID_VendorMicrosoft,//[in, optional] const GUID *pguidVendor, &pIWICBitmapEncoder//[out, retval] IWICBitmapEncoder **ppIEncoder ); IStream _is; if (SUCCEEDED(hr)) { hr = Initialize( &is,//[in] IStream *pIStream, WICBitmapEncoderNoCache//[in] WICBitmapEncoderCacheOption cacheOption ); if (SUCCEEDED(hr)) { hr = CreateNewFrame( &pIWICBitmapFrameEncode;//[out] IWICBitmapFrameEncode **ppIFrameEncode, &pIPropertyBag2//[in, out, unique] IPropertyBag2 **ppIEncoderOptions ); }
All Replies
-
Wednesday, September 05, 2012 3:09 AM
I have a general image conversion program based on WIC that I use to test encoders, and I've decided to publish that in gist with a permissive license. It's written in C rather than C++, but hopefully it will be easy to follow: https://gist.github.com/3629620
ComponentFactory and ImagingFactory are the same for the methods they share. ComponentFactory has some additional methods for people who are writing WIC components. Unless you need something from ComponentFactory you should probably use ImagingFactory.
-
Wednesday, September 05, 2012 4:42 AM
2 questions:
- why is there anything even referencing a mime type?
- does mime type apply to source or destination?
-
Wednesday, September 05, 2012 4:48 AMThe mime type applies to the destination, and it's only there to give me a convenient way to select an encoder from the command line. You can skip that since you only need CLSID_WICBmpEncoder.
-
Wednesday, September 05, 2012 4:53 AM
Thanks. just looked at the code again. it appears that (correct me if I am wrong)
mime type applies to destination
it's required (?) to make the encoding. the mime type can easily be determined entirely within the software itself with an array and looked up based on file extension (the filepath being temporarily converted to lowercase first of course), so that the user does not have to specify a mime type.
that can be easily done in C or C++.
-
Wednesday, September 05, 2012 5:00 AMIt's only used to get an encoder CLSID which is then passed to CoCreateInstance. You could easily hard-code an encoder CLSID or search by some other criteria including file extension. I chose not to because this was a test program for my own use, and searching the comma-separated list of filenames I can get for an encoder would've been more work.


