使用 ATL CImage 从内存缓冲区加载图像

Posted

技术标签:

【中文标题】使用 ATL CImage 从内存缓冲区加载图像【英文标题】:Load image from memory buffer using ATL CImage 【发布时间】:2011-03-31 16:00:10 【问题描述】:

如何使用 CImage 从 BYTE* 数组加载图像? 到目前为止,我的解决方法是简单地创建一个临时文件,但这个操作有时非常昂贵...... 可能有库,但我不想链接到其他库,我只需要获取图像大小并有效地显示到屏幕上,而 CImage 就是我所需要的......

p->pbData 是一个 BYTE* 数组,p->dwDataLen 是一个保存数组大小的 DWORD

我的代码:

ATL::CAtlTemporaryFile TempFile;  
TempFile.Create(NULL, GENERIC_WRITE | GENERIC_READ);  
TempFile.Write(p->pbData, p->dwDataLen);  
TempFile.HandsOff();  
ATL::CImage m_image;  
m_image.Load(TempFile.TempFileName());  
    TempFile.Close();
int h = m_image.GetHeight();  
int w = m_image.GetWidth();  
// rest of code here

    m_image.Destroy();  
m_image.ReleaseGDIPlus();` 

【问题讨论】:

【参考方案1】:
bool Create(BYTE* heap, DWORD heap_len, CImage& img)

    bool ret = false;
    HGLOBAL hGlobal = ::GlobalAlloc(GHND, heap_len);
    LPBYTE  lpByte  = (LPBYTE)::GlobalLock(hGlobal);
    CopyMemory(lpByte, heap, heap_len);
    ::GlobalUnlock(hGlobal);
    IStream* pStream = NULL;
    if ( SUCCEEDED(::CreateStreamOnHGlobal(hGlobal, FALSE, &pStream)) )
    
        img.Destroy();
        img.Load(pStream);
        pStream->Release();
        ret = true;
    
    GlobalFree(hGlobal);
    return ret;

【讨论】:

【参考方案2】:

您可以使用 CImage::Load(IStream*) 函数来完成。您可以从 CreateStreamOnHGlobal() 获取 IStream 或创建自己的。

请注意,使用文件实际上是更好的解决方案。 CImage 创建一个内存映射文件来按需加载图像中的像素。当你从内存加载时,你需要双倍的内存,你会对页面文件施加压力。如果图像很大,你会遇到麻烦。

【讨论】:

【参考方案3】:
HRESULT Load(
   IStream* pStream
) throw();

pStream 指向包含要加载的图像文件的名称的流的指针。

所以上面的解决方案是行不通的,除非堆缓冲区包含文件路径..;)

【讨论】:

首先,这不是一个有效的答案。然后,您所指的方法是在内部调用GdiPlus::Bitmap 构造函数,它确实需要流,而不仅仅是文件名。

以上是关于使用 ATL CImage 从内存缓冲区加载图像的主要内容,如果未能解决你的问题,请参考以下文章

VC6.0中加载图片并实现放大功能

ATL 中的 CImage 类

如何在 OpenCV 中显示流图像?

ATL ActiveX DLL 作为映射类型图像和数据加载两次

用CImage加载内存里的Image(转)

CImage::Load() 从内存而不使用 CreateStreamOnHGlobal