Skip to content

Instantly share code, notes, and snippets.

@Junch
Created May 25, 2021 06:08
Show Gist options
  • Select an option

  • Save Junch/de5a69fcaf72539a936a4701762641be to your computer and use it in GitHub Desktop.

Select an option

Save Junch/de5a69fcaf72539a936a4701762641be to your computer and use it in GitHub Desktop.
Windows Imaging Component Overview
#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