D3DXLoadSurfaceFromMemory + GDI +: как показать изображение? - PullRequest
1 голос
/ 06 декабря 2011

Я хотел бы загрузить изображение, ранее загруженное с помощью GDI +, в Direct X;Является ли это возможным?Я знаю, что могу сохранить образ на диск и затем загрузить его, используя:

D3DXLoadSurfaceFromFile

Но я хотел бы использовать

D3DXLoadSurfaceFromMemory

с изображением GDI +, загруженным в память;образ GDI + представляет собой GdiPlus :: Тип изображения.

Я использую 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 +;пока все хорошо, затем я преобразую изображение в виде байтового массива ( буфер ):

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);

Это работает, НО изображение кажется все неупорядоченнымповсюду цветные пиксели, но не «читаемое» изображение вообще (как если бы это был тестовый образец из аркадной игры).

Ответы [ 2 ]

0 голосов
/ 29 октября 2013

Параметр 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);

Я тестировал, это работало.

0 голосов
/ 07 декабря 2011

Вам необходимо определить подходящий формат текстур DirectX (например, DXGI_FORMAT_R32G32B32A32_UINT), чтобы текстура DirectX могла получать данные из GDI + без изменений.Вы можете скопировать данные, используя ID3D11DeviceContext :: CopyResource () или эквивалент в любой версии DirectX, которую вы используете.Чтобы нарисовать изображение, вам нужно настроить геометрию (треугольники), которые образуют квад, и передать ее в конвейер (Google "полноэкранный квад" для более подробной информации).

...