我写了类封装了一下。只是作业需要,缺少错误处理。
cpp
#include <wincodec.h>
enum PixColor { B, G, R };
struct ComEnv {
ComEnv()
{
CoInitialize(nullptr);
CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&fac));
}
~ComEnv()
{
fac->Release();
CoUninitialize();
}
static IWICImagingFactory* fac;
}g_comEnvDummy;
IWICImagingFactory* ComEnv::fac;
// 位深度为 24,BGR 格式的 bmp 文件
struct ImgDec {
ImgDec(LPCWSTR fname)
{
ComEnv::fac->CreateDecoderFromFilename(fname, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &dec);
dec->GetFrame(0, &fram);
ComEnv::fac->CreateBitmapFromSource(fram, WICBitmapCacheOnDemand, &bmp);
bmp->GetSize(&w, &h);
WICRect rc = { .X = 0, .Y = 0, .Width = (INT)w, .Height = (INT)h };
bmp->Lock(nullptr, WICBitmapLockRead, &lck);
lck->GetStride(&stride);
lck->GetDataPointer(&bufsiz, &v);
}
BYTE& operator()(int i, int j, PixColor c)
{
BYTE* row = v + (UINT64)i * stride;
BYTE* p = row + 3ull * j;
return p[c];
}
void saveAs(LPCWSTR newName)
{
IWICStream* str;
ComEnv::fac->CreateStream(&str);
str->InitializeFromFilename(newName, GENERIC_WRITE);
IWICBitmapEncoder* enc;
ComEnv::fac->CreateEncoder(GUID_ContainerFormatBmp, nullptr, &enc);
enc->Initialize(str, WICBitmapEncoderNoCache);
IWICBitmapFrameEncode* fram;
IPropertyBag2* opt = nullptr;
enc->CreateNewFrame(&fram, &opt); // opt 既是入参也是出参
// 现在 opt 是默认选项
fram->Initialize(opt);
fram->SetSize(w, h);
WICPixelFormatGUID fmt = GUID_WICPixelFormat24bppBGR;
fram->SetPixelFormat(&fmt);
fram->WritePixels(h, stride, h * stride, v);
fram->Commit();
enc->Commit();
fram->Release();
opt->Release();
enc->Release();
str->Release();
}
~ImgDec()
{
lck->Release();
bmp->Release();
fram->Release();
dec->Release();
}
IWICBitmapDecoder* dec;
IWICBitmapFrameDecode* fram;
IWICBitmap* bmp;
IWICBitmapLock* lck;
UINT w, h;
UINT stride;
UINT bufsiz;
BYTE* v;
};