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;
};
相关推荐
小王C语言4 小时前
【7. 实现登录注册模块】:实现会话管理、注册/登录/退出 API
网络·c++
笨鸟先飞,勤能补拙4 小时前
AI 赋能网络安全领域深度剖析
网络·人工智能·windows·安全·web安全·网络安全·github
ThsPool4 小时前
【遥感学习整理 02】ENVI遥感图像处理基础:从数据读取到遥感信息产品
图像处理·人工智能·学习
我上去就是一套QWER然后等待复活5 小时前
Windows 清理 CC Switch 并恢复官方 Codex CLI 登录流程(完整记录)
windows
吾儿良辰6 小时前
一个被BCL遗忘的高性能集合:C# CircularBuffer<T>深度解析
开发语言·windows·c#
哎呦喂我去去去6 小时前
C#实现屏幕墙:同时监控多个电脑桌面(支持Windows、信创Linux、银河麒麟、统信UOS)
linux·windows·c#
峥无7 小时前
C++11 深度详解:现代 C++ 基石全梳理
开发语言·c++·笔记
阿米亚波7 小时前
【C++ STL】std::unordered_multimap
开发语言·数据结构·c++·笔记·stl
小王C语言7 小时前
【3. 基于 Vibe Coding 的 OJ 平台】. 构建仓库、环境准备、需求梳理、安装依赖
网络·c++
小王C语言8 小时前
【8.进行接口测试】:通过 curl 进行接口自动化测试 / 通过 python 程序进行接口自动化测试
网络·c++