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;
};
相关推荐
汉克老师5 分钟前
GESP2024年12月认证C++二级( 第二部分判断题(1-10))
c++·循环结构·分支结构·gesp二级·gesp2级
魑-魅-魍-魉15 分钟前
金仓数据库(KingbaseES)V8R3 Windows 版大小写敏感设置详解
数据库·windows·金仓
Ronin30520 分钟前
虚拟机数据管理模块
开发语言·c++·rabbitmq
一叶之秋141234 分钟前
基石之力:掌握 C++ 继承的核心奥秘
开发语言·c++·算法
见牛羊35 分钟前
CMakeLists 写法总结3.0
开发语言·c++
柒儿吖36 分钟前
rudp Reliable UDP 库在 OpenHarmony 的 lycium 适配与 CRC32 测试
c++·c#·openharmony
拾光Ծ37 分钟前
【优选算法】滑动窗口算法:专题一
c++·算法·滑动窗口·c++算法·滑动窗口算法·笔试面试
闻缺陷则喜何志丹42 分钟前
【动态规划 AC自动机】P9188 [USACO23OPEN] Pareidolia S|普及+
c++·算法·动态规划·洛谷·ac自动机
cpp_250144 分钟前
P10250 [GESP样题 六级] 下楼梯
数据结构·c++·算法·动态规划·题解·洛谷
xiaoye-duck1 小时前
深入解析 STL 优先级队列:从原理到实战
c++·算法·stl