Windows 图像处理组件(WIC)读写位深度24位的 bmp 文件

我写了类封装了一下。只是作业需要,缺少错误处理。

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;
};
相关推荐
DexterLien2 小时前
使用 privacyIDEA 实现 Windows RDP 多因素认证 (MFA)
windows·rdp·等保·mfa
qt_dog2 小时前
普通大龄程序员的工作十年(一)
c语言·c++·程序人生·职场和发展·车载系统·跳槽
bugs_more_more2 小时前
[java]集合类stream的相关操作
java·windows·python
aaasssdddd963 小时前
C++的模板(九):模板的实例化问题
开发语言·c++·容器·stl
叛逆性=4 小时前
windows桌面运维----第六天
运维·网络·windows
盛溪的猫猫4 小时前
马蹄集 oj赛(双周赛第二十九次)
c++·算法·马蹄集
陌尘(MoCheeen)5 小时前
C++数据格式化5 - uint转换成十六进制字符串&二进制的data打印成十六进制字符串
c++·跨平台·字符串处理·数据格式化
古月居GYH6 小时前
CMakeList整理大全
java·c++·算法
ULTRA??7 小时前
C++的元祖tuple,{}的初始化列表
开发语言·c++·容器
root_dream7 小时前
python3 List常用函数详细解释
windows·python·list