如何将资源中的PNG加载到CImage中

时间:2017-08-01 15:07:37

标签: mfc

根据LoadFromResource的此文档,它声明:

  

BITMAP 资源

加载图像

所以,我的代码中有这个:

rImage.LoadFromResource(AfxFindResourceHandle(), IDB_PNG1);

不起作用。然后我意识到我使用的是PNG文件而不是BMP文件。我认为这就是无法找到资源的原因。

我也尝试过使用AfxGetInstanceHandle()。但这也行不通。

因此,目前我正在使用外部PNG文件。它工作正常。但有任何方式将资源中的PNG加载到CImage吗?

更新

提供给我的评论很有帮助。

它引领了我here。所以,如果我有这个方法:

IStream* CreateStreamOnResource(LPCTSTR lpName, LPCTSTR lpType)
{
    IStream * ipStream = NULL;

    HRSRC hrsrc = FindResource(NULL, lpName, lpType);
    if (hrsrc == NULL)
        goto Return;

    DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
    HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
    if (hglbImage == NULL)
        goto Return;

    LPVOID pvSourceResourceData = LockResource(hglbImage);
    if (pvSourceResourceData == NULL)
        goto Return;

    HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
    if (hgblResourceData == NULL)
        goto Return;

    LPVOID pvResourceData = GlobalLock(hgblResourceData);

    if (pvResourceData == NULL)
        goto FreeData;

    CopyMemory(pvResourceData, pvSourceResourceData, dwResourceSize);

    GlobalUnlock(hgblResourceData);

    if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream)))
        goto Return;

FreeData:
    GlobalFree(hgblResourceData);

Return:
    return ipStream;
}

并称之为:

rImage.Load(CreateStreamOnResource(MAKEINTRESOURCE(IDB_PNG1), _T("PNG")));

工作得很好......谢谢你们。

更新

根据提供的评论。现在好多了?我看到没有泄漏:

IStream *pStream = CreateStreamOnResource(MAKEINTRESOURCE(uPNGResourceID), _T("PNG"));
if (pStream != nullptr)
{
    rImage.Load(pStream);
    rImage.SetHasAlphaChannel(true);
    pStream->Release();
}

旁注:如果这些是我自己的嵌入式资源并且知道是透明的32位资源,我是否真的需要致电SetHasAlphaChannel

2 个答案:

答案 0 :(得分:2)

  1. AfxFindResource
  2. LoadResource
  3. 的GlobalAlloc
  4. CopyMemory的
  5. 了CreateStreamOnHGlobal
  6. 的CImage ::负荷(的IStream * ...)
  7. 或者您编写自己的IStream实现,它从LoadResource获取指针和大小。 CSharedFile也是一种选择。

答案 1 :(得分:0)

您可以从硬编码路径或流加载图像。要从 Stream 加载它,请使用以下代码。首先,添加一个用于从资源创建流的函数。

IStream* ZDlg::CreateStreamOnResource(LPCTSTR lpName, LPCTSTR lpType)
{
    IStream * ipStream = NULL;

    HRSRC hrsrc = FindResource(NULL, lpName, lpType);
    if (hrsrc == NULL)
        goto Return;

    DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
    HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
    if (hglbImage == NULL)
        goto Return;

    LPVOID pvSourceResourceData = LockResource(hglbImage);
    if (pvSourceResourceData == NULL)
        goto Return;

    HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
    if (hgblResourceData == NULL)
        goto Return;

    LPVOID pvResourceData = GlobalLock(hgblResourceData);

    if (pvResourceData == NULL)
        goto FreeData;

    CopyMemory(pvResourceData, pvSourceResourceData, dwResourceSize);

    GlobalUnlock(hgblResourceData);

    if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream)))
        goto Return;

FreeData:
    GlobalFree(hgblResourceData);

Return:
    return ipStream;
}

然后使用如下函数:

pImage = new CImage;
IStream *pStream = CreateStreamOnResource(MAKEINTRESOURCE(IDB_MYIMAGE), _T("PNG"));
if (pStream != nullptr)
{
    pImage->Load(pStream);
    pImage->SetHasAlphaChannel(true);
    pStream->Release();
}