Created
May 25, 2021 06:08
-
-
Save Junch/de5a69fcaf72539a936a4701762641be to your computer and use it in GitHub Desktop.
Windows Imaging Component Overview
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <atlbase.h> | |
| #include <gtest/gtest.h> | |
| #include <wincodec.h> | |
| #include <tchar.h> | |
| #pragma comment(lib, "windowscodecs") | |
| #define RETURN_IF_FAILED(hr) \ | |
| if (FAILED(hr)) \ | |
| return (hr) | |
| #define THROW_IF_FAILED(expr) \ | |
| { \ | |
| HRESULT hr = (expr); \ | |
| if (FAILED(hr)) \ | |
| throw hr; \ | |
| } | |
| void getImageFromFile(LPCWSTR file, IWICBitmap **bitmap) | |
| { | |
| CComPtr<IWICImagingFactory> pFactory; | |
| THROW_IF_FAILED(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory))); | |
| CComPtr<IWICBitmapDecoder> pIDecoder; | |
| CComPtr<IWICBitmapFrameDecode> pIDecoderFrame; | |
| THROW_IF_FAILED(pFactory->CreateDecoderFromFilename(file, // 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 | |
| )); | |
| THROW_IF_FAILED(pIDecoder->GetFrame(0, &pIDecoderFrame)); | |
| UINT uiWidth = 0; | |
| UINT uiHeight = 0; | |
| pIDecoderFrame->GetSize(&uiWidth, &uiHeight); | |
| printf("width=%u, heigth=%u\n", uiWidth, uiHeight); | |
| // Create the bitmap from the image frame. | |
| THROW_IF_FAILED(pFactory->CreateBitmapFromSource(pIDecoderFrame, // Create a bitmap from the image frame | |
| WICBitmapCacheOnDemand, // Cache metadata when needed | |
| bitmap)); // Pointer to the bitmap | |
| } | |
| void saveImageToFile(IWICBitmap *bitmap, LPCWSTR file) | |
| { | |
| CComPtr<IWICImagingFactory> pFactory; | |
| THROW_IF_FAILED(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory))); | |
| CComPtr<IWICStream> pStream; | |
| THROW_IF_FAILED(pFactory->CreateStream(&pStream)); | |
| THROW_IF_FAILED(pStream->InitializeFromFilename(file, GENERIC_WRITE)); | |
| CComPtr<IWICBitmapEncoder> pEncoder; | |
| THROW_IF_FAILED(pFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &pEncoder)); | |
| THROW_IF_FAILED(pEncoder->Initialize(pStream, WICBitmapEncoderNoCache)); | |
| CComPtr<IWICBitmapFrameEncode> pBitmapFrame; | |
| CComPtr<IPropertyBag2> pPropertybag; | |
| THROW_IF_FAILED(pEncoder->CreateNewFrame(&pBitmapFrame, &pPropertybag)); | |
| { | |
| // customize the TIFF output | |
| PROPBAG2 option = {0}; | |
| option.pstrName = L"TiffCompressionMethod"; | |
| VARIANT varValue; | |
| VariantInit(&varValue); | |
| varValue.vt = VT_UI1; | |
| varValue.bVal = WICTiffCompressionZIP; | |
| THROW_IF_FAILED(pPropertybag->Write(1, &option, &varValue)); | |
| THROW_IF_FAILED(pBitmapFrame->Initialize(pPropertybag)); | |
| } | |
| UINT uiWidth = 0; | |
| UINT uiHeight = 0; | |
| bitmap->GetSize(&uiWidth, &uiHeight); | |
| pBitmapFrame->SetSize(uiWidth, uiHeight); | |
| WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR; | |
| pBitmapFrame->SetPixelFormat(&formatGUID); | |
| THROW_IF_FAILED(IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL); | |
| WICRect rc = {0, 0, (INT)uiWidth, (INT)uiHeight}; | |
| THROW_IF_FAILED(pBitmapFrame->WriteSource(bitmap, &rc)); | |
| THROW_IF_FAILED(pBitmapFrame->Commit()); | |
| THROW_IF_FAILED(pEncoder->Commit()); | |
| } | |
| void saveImageToPng(IWICBitmap *bitmap, LPCWSTR file) | |
| { | |
| CComPtr<IWICImagingFactory> pFactory; | |
| THROW_IF_FAILED(CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory))); | |
| CComPtr<IWICStream> pStream; | |
| THROW_IF_FAILED(pFactory->CreateStream(&pStream)); | |
| THROW_IF_FAILED(pStream->InitializeFromFilename(file, GENERIC_WRITE)); | |
| CComPtr<IWICBitmapEncoder> pEncoder; | |
| THROW_IF_FAILED(pFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &pEncoder)); | |
| THROW_IF_FAILED(pEncoder->Initialize(pStream, WICBitmapEncoderNoCache)); | |
| CComPtr<IWICBitmapFrameEncode> pBitmapFrame; | |
| THROW_IF_FAILED(pEncoder->CreateNewFrame(&pBitmapFrame, NULL)); | |
| THROW_IF_FAILED(pBitmapFrame->Initialize(NULL)); | |
| // UINT uiWidth = 0; | |
| // UINT uiHeight = 0; | |
| // bitmap->GetSize(&uiWidth, &uiHeight); | |
| // pBitmapFrame->SetSize(uiWidth, uiHeight); | |
| // WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR; | |
| // THROW_IF_FAILED(pBitmapFrame->SetPixelFormat(&formatGUID)); | |
| // THROW_IF_FAILED(IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL); | |
| THROW_IF_FAILED(pBitmapFrame->WriteSource(bitmap, NULL)); | |
| THROW_IF_FAILED(pBitmapFrame->Commit()); | |
| THROW_IF_FAILED(pEncoder->Commit()); | |
| } | |
| TEST(wic, simple) | |
| { | |
| // How to Modify the Pixels of a Bitmap Source | |
| // https://docs.microsoft.com/en-us/windows/desktop/wic/-wic-bitmapsources-howto-modifypixels | |
| // Initialize COM | |
| CoInitialize(NULL); | |
| CComPtr<IWICBitmap> pIBitmap; | |
| getImageFromFile(L"turtle.jpg", &pIBitmap); | |
| saveImageToPng(pIBitmap, L"turtle.png"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment