【问题标题】:D3DXLoadSurfaceFromMemory + GDI+: How to Show Image?D3DXLoadSurfaceFromMemory + GDI+:如何显示图像?
【发布时间】:2013-10-29 11:57:08
【问题描述】:

我想将以前使用 GDI+ 加载的图像加载到 Direct X 中;可能吗?我知道我可以将图像保存到磁盘,然后使用:

D3DXLoadSurfaceFromFile

但我想用

D3DXLoadSurfaceFromMemory

将 GDI+ 图像加载到内存中; GDI+ 图像是 GdiPlus::Image 类型。

我正在使用 Visual C++ 2010。

提前致谢。

更新:

using namespace Gdiplus;
std::string decodedImage = base64_decode(Base64EncodedImage); 
DWORD imageSize = decodedImage.length();
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);
LPVOID pImage = ::GlobalLock(hMem);
memcpy(pImage, decodedImage.c_str(), imageSize);
IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);
Image image(pStream);

上面的代码让我将base64(Base64EncodedImage)编码的图像转换为GDI+图像;到目前为止一切顺利,接下来我将图像转换为字节数组(buffer):

int stride = 4 * ((image.GetWidth() + 3) / 4);
    size_t safeSize = 
    stride * image.GetHeight() * 4 + sizeof(BITMAPINFOHEADER) + 
    sizeof(BITMAPFILEHEADER) + 256 * sizeof(RGBQUAD);
HGLOBAL mem = GlobalAlloc(GHND, safeSize);
LARGE_INTEGER seekPos = {0};
ULARGE_INTEGER imageSizeEx;
HRESULT hr = pStream->Seek(seekPos, STREAM_SEEK_CUR, &imageSizeEx); 
BYTE* buffer = new BYTE[imageSizeEx.LowPart];
hr = pStream->Seek(seekPos, STREAM_SEEK_SET, 0);    
hr = pStream->Read(buffer, imageSizeEx.LowPart, 0); 

附带说明一下,我可以将字节数组作为 png 图像保存到磁盘而不会丢失,然后使用 D3DXLoadSurfaceFromFile 加载它。

接下来我创建并加载表面:

hr = d3ddevex->CreateOffscreenPlainSurface(image.GetWidth(), image.GetHeight(), D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);

RECT srcRect;  
srcRect.left = 0;   
srcRect.top = 0;  
srcRect.bottom = image.GetWidth();  
srcRect.right = image.GetHeight();

hr = D3DXLoadSurfaceFromMemory(surf, NULL, NULL, buffer, D3DFMT_X8R8G8B8,image.GetWidth(), NULL, &srcRect,D3DX_FILTER_NONE,0);

这是可行的,但是图像到处都是杂乱无章的彩色像素,但根本不是“可读”图像(就像街机游戏中的测试图案一样)。

【问题讨论】:

    标签: c++ directx gdi+


    【解决方案1】:

    您需要确定合适的 DirectX 纹理格式(例如 DXGI_FORMAT_R32G32B32A32_UINT),以便 DirectX 纹理无需修改即可从 GDI+ 接收数据。您可以使用 ID3D11DeviceContext::CopyResource() 或您使用的任何版本的 DirectX 中的等效项复制数据。 要绘制图像,您需要设置一些形成四边形的几何体(三角形)并将其传递给管道(谷歌“全屏四边形”以获得更多详细信息)。

    【讨论】:

    • 您好,感谢您的回答,但应用纹理不是我想要的。到目前为止,我已经能够将 GDI+ 图像转换为 BYTE* 数组;然后将其传递给函数:D3DXLoadSurfaceFromMemory(surf, NULL, NULL, buffer, D3DFMT_X8R8G8B8,image.GetWidth(), NULL, &srcRect,D3DX_FILTER_NONE,0);buffer 包含图像数据的缓冲区(从网络流式传输的 png 文件)。但是我收到以下错误: Access violation at 0x00ed0000 ,所以我被困在那里。
    • 我已经能够加载图像并将其显示在屏幕上。但是所有的像素都是乱七八糟的,不是按顺序排列的;我猜它可能是 D3DFMT_X8R8G8B8 参数?
    • 可能。您是否使用 DirectX 的调试输出来帮助您进行故障排除?您可以在 DirectX 控制面板中启用它。输出到 VisualStudio 控制台窗口。它通常提供非常丰富的信息(尽管听起来你已经过去了)。
    • 我要去看看。我被告知要使用IDirect3DSurface9->LockRect,所以我要看看它是怎么回事。
    【解决方案2】:

    SrcPicht参数si img.GetWidth()*4,以字节为单位:

    hr = D3DXLoadSurfaceFromMemory(
        spSurface,
        NULL,
        &rectDes, 
        bd.Scan0, 
        D3DFMT_X8R8G8B8,
        image.GetWidth()*4, //@ here is different only
        NULL, 
        &rectSrc,
        D3DX_FILTER_NONE,0);
    

    我测试过,它有效。

    【讨论】:

      猜你喜欢
      • 2014-05-27
      • 1970-01-01
      • 2016-03-30
      • 2011-12-11
      • 1970-01-01
      • 2023-03-12
      • 2012-10-31
      • 2021-12-20
      • 1970-01-01
      相关资源
      最近更新 更多