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;
};
相关推荐
小眼哥31 分钟前
SpringBoot整合Vue代码生成exe运行程序以及windows安装包
vue.js·windows·spring boot
xiaoshuaishuai81 小时前
C# GPU算力与管理
开发语言·windows·c#
墨尘笔尖1 小时前
最大最小值降采样算法的优化
c++·算法
YIN_尹3 小时前
【Linux系统编程】进程地址空间
linux·c++
EverestVIP3 小时前
C++中空类通常大小为1的原理
c++
网域小星球4 小时前
C++ 从 0 入门(六)|C++ 面试必知:运算符重载、异常处理、动态内存进阶(终极补充)
开发语言·c++·面试
晚会者荣4 小时前
红黑树的插入(有图)
c++
꯭爿꯭巎꯭4 小时前
千鹿PR助手邀请码
windows
John.Lewis4 小时前
C++进阶(12)附加学习:STL之空间配置器(了解)
开发语言·c++·笔记
汉克老师4 小时前
GESP2023年12月认证C++三级( 第三部分编程题(2、单位转换))
c++·string·单位转换·gesp三级·gesp3级