我写了类封装了一下。只是作业需要,缺少错误处理。
- #include
-
- 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;
- };