HBITMAPをWICを使ってファイルに保存

制作:KrK (Knuth for Kludge)

情報・ご感想はこちら

KrK's Cracked Text > はしくれコード


環境

ソース


#include <wincodec.h>   // WIC
#include <objbase.h>    // COM

#define kMODE_PNG    0
#define kMODE_BMP    1
#define kMODE_JPG    2

//---------------------------------------------------------------------
// HBITMAPをWICを使ってファイルに保存
// 作成 20251219 KrK
// 引数 hBmp:ビットマップハンドル
// 引数 filename:保存ファイル名
// 引数 mode:モード
// 引数 quality:JPEG品質
//---------------------------------------------------------------------
VOID SaveWicFile(HBITMAP hBmp, WCHAR* filename, LONG mode, ULONG quality)
{
    IWICImagingFactory *pFactory = NULL;
    IWICBitmap *pWICBitmap = NULL;
    IWICStream *pStream = NULL;
    IWICBitmapEncoder *pEncoder = NULL;
    IWICBitmapFrameEncode *pFrameEncode = NULL;
    IPropertyBag2* pPropertybag = NULL;

    // 初期化
    HRESULT hr = CoCreateInstance(
        CLSID_WICImagingFactory,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pFactory));

    // HBITMAPからWICビットマップを生成
    if (SUCCEEDED(hr))
    {
        hr = pFactory->CreateBitmapFromHBITMAP(
            hBmp,
            NULL,
            WICBitmapUseAlpha,
            &pWICBitmap);
    }

    // WICストリームを生成
    if (SUCCEEDED(hr))
    {
        hr = pFactory->CreateStream(&pStream);
    }
    if (SUCCEEDED(hr))
    {
        hr = pStream->InitializeFromFilename(filename, GENERIC_WRITE);
    }

    // エンコーダ生成
    if (SUCCEEDED(hr))
    {
        // Use the GUID for container format
        if (mode == kMODE_BMP)
        {
            hr = pFactory->CreateEncoder(GUID_ContainerFormatBmp,
                NULL, &pEncoder);
        }
        else if (mode == kMODE_PNG)
        {
            hr = pFactory->CreateEncoder(GUID_ContainerFormatPng,
                NULL, &pEncoder);
        }
        else
        {
            hr = pFactory->CreateEncoder(GUID_ContainerFormatJpeg,
                NULL, &pEncoder);
        }
    }

    // ストリームでエンコーダを初期化
    if (SUCCEEDED(hr))
    {
        hr = pEncoder->Initialize(pStream, WICBitmapEncoderNoCache);
    }

    // フレームを生成
    if (SUCCEEDED(hr))
    {
        hr = pEncoder->CreateNewFrame(&pFrameEncode, &pPropertybag);
    }

    // JPEGオプション
    if (mode == kMODE_JPG)
    {
        if (SUCCEEDED(hr))
        {
            PROPBAG2 option = { 0 };
            option.vt = VT_R4;
            WCHAR wstr[64];
            wcscpy_s(wstr, L"ImageQuality");
            option.pstrName = (LPOLESTR)wstr;
            VARIANT varValue;
            VariantInit(&varValue);
            varValue.vt = VT_R4;
            varValue.fltVal = (FLOAT)quality / 100;
            hr = pPropertybag->Write(1, &option, &varValue);
        }
    }

    // フレームを初期化
    if (SUCCEEDED(hr))
    {
        hr = pFrameEncode->Initialize(pPropertybag);
    }

    // ビットマップデータをフレームに書き込む
    if (SUCCEEDED(hr))
    {
        hr = pFrameEncode->WriteSource(
            static_cast<IWICBitmapSource*>(pWICBitmap), NULL);
    }

    // ファイルに書き込む
    if (SUCCEEDED(hr))
    {
        hr = pFrameEncode->Commit();
    }
    if (SUCCEEDED(hr))
    {
        hr = pEncoder->Commit();
    }

    // 解放
    if (pPropertybag != NULL)
    {
        pPropertybag->Release();
    }
    if (pFrameEncode != NULL)
    {
        pFrameEncode->Release();
    }
    if (pEncoder != NULL)
    {
        pEncoder->Release();
    }
    if (pStream != NULL)
    {
        pStream->Release();
    }
    if (pWICBitmap != NULL)
    {
        pWICBitmap->Release();
    }
    if (pFactory != NULL)
    {
        pFactory->Release();
    }
}

使い方


HBITMAP hBmp;               // ビットマップハンドル
WCHAR filename[_MAX_PATH];  // ファイル名

// COM初期化
CoInitialize(NULL);

// ビットマップを読み込む
hBmp = ~;

// ビットマップをファイルに保存
SaveWicFile(hBmp, filename, kMODE_PNG, 100);

// 解放
CoUninitialize();
DeleteObject(hBmp);

使用条件


最終更新:2025/12/19

免責事項