如何访问在 IWICBitmap 解码器中打开的图像?

问题描述

我正在制作一个用于图像编辑的 .NET 应用程序。为了在 PictureBox显示图像,我使用 IWIC 打开它以转换为 HBITMAP,然后使用 FromHbitmap 方法将其粘贴到 PictureBox 中。这意味着虽然应用程序中存在 Image 实例,但我无法使用它。那么如何更改我的阅读器类以访问图像?

IMGReader.h

tf.keras.callbacks.EarlyStopping(
    monitor='val_loss',<------------ 
    min_delta=0,patience=0,verbose=0,mode='auto',baseline=None,restore_best_weights=False
)

IMGReader.cpp

#pragma once

#include <wincodec.h> // WIC codec header for decoding image from file

#include "StringConverter.h"

#pragma comment (lib,"windowscodecs")

class IMGReader
{
    IWICFormatConverter* wConverter;

    UINT BitHeight;
    UINT BitWidth;

    IMGReader() {};
    
    BOOLEAN pathExist(LPCWSTR path);
public:
    IMGReader(LPCWSTR path) { load(path); };
    ~IMGReader() { wConverter->Release(); };

    void load(LPCWSTR path);

    UINT getBitmapHeight()  { return BitHeight; };
    UINT getBitmapWidth()   { return BitWidth; };

    HBITMAP IWICBitmapToHBITMAP();
};

以主要形式使用:

#include "IMGReader.h"
#include "MTTErrorLogger.h"

#include <filesystem>
#include <vector>

void IMGReader::load(LPCWSTR path)
{
    HRESULT hr;     // For checking errors

    if (!pathExist(path)) { path = L"nodata.jpg"; }; // Check if image really exist in this derectory

    // Craete WIC factory
    IWICImagingFactory* wicFactory = NULL;
    hr = CoCreateInstance(
        CLSID_WICImagingFactory,// CLS ID of the object making
        NULL,// Not part of agregate 
        CLSCTX_INPROC_SERVER,// DLL runs in the same process
        IID_IWICImagingFactory,// Ref to interface that communicates with the object
        (LPVOID*)&wicFactory        // The pointer that'll contain factory
    );

    // Create decoder
    IWICBitmapDecoder* wicDecoder = NULL;
    hr = wicFactory->CreateDecoderFromFilename(
        path,// Path to reading file
        NULL,// No preferred vendor
        GENERIC_READ,// Reading file
        WICDecodeMetadataCacheOnLoad,// Cache on load 
        &wicDecoder                     // Making decoder
    );

    // Read frame from the image
    IWICBitmapFrameDecode* wicFrame = NULL;
    hr = wicDecoder->GetFrame(0,&wicFrame);

    //Create converter
    IWICFormatConverter* wicConverter = NULL;
    hr = wicFactory->CreateFormatConverter(&wicConverter);

    // Setup the converter
    hr = wicConverter->Initialize(
        wicFrame,// Frame
        GUID_WICPixelFormat32bppPBGRA,// Pixel format
        WICBitmapDitherTypeNone,// Irrelevant
        NULL,// No palette needed,irrelevant
        0.0,// Alpha transparency % irrelevant
        WICBitmapPaletteTypeCustom      // Irrelevant
    );

    wicConverter->GetSize(&BitHeight,&BitWidth);

    wConverter = wicConverter;
}

HBITMAP IMGReader::IWICBitmapToHBITMAP()
{
    UINT height = BitHeight;    // Bitmap height
    UINT width  = BitWidth;     // Bitmap width
    wConverter->GetSize(&width,&height);

    std::vector<BYTE> buffer(width * height * 4);
    wConverter->copyPixels(0,width * 4,buffer.size(),buffer.data());

    HBITMAP bitmap = CreateBitmap(width,height,1,32,buffer.data()); // Create bitmap from IWICBitmap data

    return bitmap;
}

BOOLEAN IMGReader::pathExist(LPCWSTR path)
{
    if (std::filesystem::exists(path)) {
        return true;
    }
    return false;
}

谢谢。

解决方法

所以我解决了这个问题。问题似乎是我没有将图像数据存储在特定位置,而是每次在加载方法中创建新的。我在代码中做了以下修改:

标题:

#pragma once

#include <wincodec.h> // WIC codec header for decoding image from file
#include <atlcomcli.h>

    #include "StringConverter.h"
    
    #pragma comment (lib,"windowscodecs")
    
    class IMGReader
    {
        CComPtr<IWICImagingFactory>     m_pImagingFactory;
        CComPtr<IWICBitmapDecoder>      m_pBitmapDecoder;
        CComPtr<IWICBitmapFrameDecode>  m_pFrameDecoder;
        CComPtr<IWICFormatConverter>    m_pConverter;
    
        UINT BitHeight;
        UINT BitWidth;
    
        BOOLEAN pathExist(LPCWSTR path);
    
        IMGReader() {};
    public:
        IMGReader(LPCWSTR path) { load(path); };
        ~IMGReader() { SafeRelease(&m_pConverter); };
    
        void load(LPCWSTR path);
        void clean();
        template <class T> void SafeRelease(T** ppT)
        {
            if (*ppT)
            {
                (*ppT)->Release();
                *ppT = NULL;
            }
        }
    
        UINT getBitmapHeight()  { return BitHeight; };
        UINT getBitmapWidth()   { return BitWidth; };
    
        HBITMAP IWICBitmapToHBITMAP();
    };

实施:

void IMGReader::load(LPCWSTR path)
{
    HRESULT hr;

    m_pImagingFactory   = NULL;
    m_pBitmapDecoder    = NULL;
    m_pFrameDecoder     = NULL;
    m_pConverter        = NULL;

    hr = CoCreateInstance(
        CLSID_WICImagingFactory,// CLS ID of the object making
        NULL,// Not part of agregate 
        CLSCTX_INPROC_SERVER,// DLL runs in the same process
        IID_IWICImagingFactory,// Ref to interface that communicates with the object
        (LPVOID*)&m_pImagingFactory // The pointer that'll contain factory
    );

    hr = m_pImagingFactory->CreateDecoderFromFilename(
        path,// Path to reading file
        NULL,// No preferred vendor
        GENERIC_READ,// Reading file
        WICDecodeMetadataCacheOnLoad,// Cache on load 
        &m_pBitmapDecoder               // Making decoder
    );

    hr = m_pBitmapDecoder->GetFrame(0,&m_pFrameDecoder);

    hr = m_pImagingFactory->CreateFormatConverter(&m_pConverter);

    hr = m_pConverter->Initialize(
        m_pFrameDecoder,// Frame
        GUID_WICPixelFormat32bppPBGRA,// Pixel format
        WICBitmapDitherTypeNone,// Irrelevant
        NULL,// No palette needed,irrelevant
        0.0,// Alpha transparency % irrelevant
        WICBitmapPaletteTypeCustom      // Irrelevant
    );

    this->m_pConverter->GetSize(&BitHeight,&BitWidth);
}