D3DXLoadSurfaceFromMemory + GDI +: Hoe beeld tonen?

Ik zou graag een afbeelding laden die eerder met GDI + was geladen in Direct X; is dit mogelijk? Ik weet dat ik de afbeelding op schijf kan opslaan en vervolgens kan laden met behulp van:

D3DXLoadSurfaceFromFile

Maar ik zou graag gebruiken

D3DXLoadSurfaceFromMemory

met de GDI + -afbeelding in het geheugen geladen; de GDI + -afbeelding is een GdiPlus :: afbeeldingstype.

Ik gebruik Visual C ++ 2010.

Bij voorbaat dank.

Update:

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

Het bovenstaande stukje code laat me een afbeelding gecodeerd in base64 ( Base64EncodedImage ) omzetten in een GDI + -afbeelding; tot nu toe zo goed, vervolgens converteer ik de afbeelding als een bytearray ( 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); 

Als een kanttekening, kan ik de bytearray opslaan op schijf als een png-afbeelding zonder verlies en vervolgens laden met D3DXLoadSurfaceFromFile .

Vervolgens maak en laad ik het oppervlak:

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

Dit IS WERK, MAAR de afbeelding verschijnt overal ongeordende, gekleurde pixels, maar helemaal geen "leesbare" afbeelding (alsof het een testpatroon van een arcadespel zou zijn).

1

2 antwoord

U moet een geschikte DirectX-structuurindeling identificeren (bijvoorbeeld DXGI_FORMAT_R32G32B32A32_UINT), zodat de DirectX-structuur de gegevens van de GDI + zonder wijziging kan ontvangen. U kunt de gegevens kopiëren met behulp van ID3D11DeviceContext :: CopyResource() of equivalent in elke versie van DirectX die u gebruikt. Als u de afbeelding wilt tekenen, moet u een aantal geometrie (driehoeken) instellen die een quad vormen en deze doorgeven aan de pijplijn (Google "fullscreen quad" voor meer informatie).

0
toegevoegd
Waarschijnlijk. Gebruikt u de foutopsporingsuitvoer van DirectX om te helpen bij het oplossen van problemen? U kunt dit inschakelen in het DirectX-configuratiescherm. De uitvoer is naar het VisualStudio-consolevenster. Het is meestal erg informatief (hoewel het klinkt alsof je dat voorbij bent).
toegevoegd de auteur axon, de bron
Hallo bedankt voor je antwoord maar toe te passen als een textuur is niet wat ik zoek. Tot nu toe heb ik de GDI + -afbeelding geconverteerd naar een BYTE * -array; en geef het vervolgens door aan de functie: D3DXLoadSurfaceFromMemory (surf, NULL, NULL, buffer, D3DFMT_X8R8G8B8, image.GetWidth (), NULL, & srcRect, D3DX_FILTER_NONE, 0); zijnde buffer de buffer die de afbeeldingsgegevens bevat (een png-bestand gestreamd vanaf het web). Maar ik krijg de volgende foutmelding: Toegangsfout op 0x00ed0000 , dus ik zit vast.
toegevoegd de auteur Maximiliano Santa Cruz, de bron
Ik heb de afbeelding kunnen laden en deze op het scherm kunnen weergeven. Maar alle pixels zijn rommelig, niet in de juiste volgorde; Ik denk dat het de parameter D3DFMT_X8R8G8B8 zou kunnen zijn?
toegevoegd de auteur Maximiliano Santa Cruz, de bron
Ik ga dat controleren. Mij ​​is verteld om IDirect3DSurface9-> LockRect te gebruiken, dus ik ga kijken hoe het gaat.
toegevoegd de auteur Maximiliano Santa Cruz, de bron

De SrcPicht-parameter si img.GetWidth() * 4, het is in bytes:

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

Ik heb getest, het werkte.

0
toegevoegd