Les images enregistrées avec D3DXSaveSurfaceToFile ouvrira dans Paint, Photoshop ne

StackOverflow https://stackoverflow.com/questions/2473549

  •  20-09-2019
  •  | 
  •  

Question

J'utilise D3DXSaveSurfaceToFile pour sauver Direct3D 9 fenêtré surfaces en PNG, les fichiers BMP et JPG. Il n'y a aucune erreur de retour de l'appel D3DXSaveSurfaceToFile et tous les fichiers ouverts dans bien Visionneuse de photos Windows et Paint. Mais ils ne seront pas ouvrir dans un programme d'édition d'image haut de gamme tels que Paint Shop Pro ou Photoshop. Les messages d'erreur de ces programmes disent essentiellement que le fichier est corrompu. Si j'ouvre les fichiers dans la peinture, puis les enregistrer dans le même format de fichier avec un nom de fichier différent, puis ils vont ouvrir bien dans les autres programmes.

Cela me conduit à croire que D3DXSaveSurfaceToFile est en train d'écrire des versions non standard de ces formats de fichier. Est-il possible que je peux obtenir cette fonction pour écrire des fichiers qui peuvent être ouverts dans des programmes comme Photoshop sans l'étape intermédiaire de resaving les fichiers dans Paint? Ou est-il une autre fonction que je devrais utiliser ce fait un meilleur travail de sauver une surface Direct3D à une image?

Était-ce utile?

La solution 3

Il s'avère que c'était une combinaison d'un bug dans mon code et de la peinture étant plus tolérant que Photoshop quand il vient à la lecture des fichiers. Le bug dans mon code causé les fichiers à sauvegarder avec la mauvaise extension (à savoir Image.bmp a été effectivement enregistré à l'aide D3DXIFF_JPG). Lors de l'ouverture d'un fichier contenant une image JPG, mais avait une extension BMP, Photoshop vient d'échouer le fichier. Je suppose que la peinture a travaillé car elle ignorait l'extension de fichier et juste décodé le contenu du fichier.

Regarder un fichier dans un l'image viewer méta m'a aidé à voir le problème.

Autres conseils

Jetez un coup d'oeil au fichier dans une image meta spectateur . Que faut-il vous dire?

Malheureusement D3DXSaveSurfaceToFile () n'est pas le plus stable (il est aussi exceptionnellement lent). Personnellement, je fais quelque chose comme le code ci-dessous. Il fonctionne même sur les écrans anticrénelage en faisant un offscreen rendu pour prendre la capture d'écran, puis l'obtenir dans un tampon. Il soutient également que le plus commun des formats de pixels. Désolé pour les erreurs qu'il contient, tiré hors d'une application que je travaillais sur.

Vous pouvez alors, dans votre code et probablement dans un autre thread, puis convertir ledit « bitmap » pour tout ce que vous aimez en utilisant une variété de code différent.

void HandleScreenshot(IDirect3DDevice9* device)
{
    DWORD tcHandleScreenshot = GetTickCount();
    LPDIRECT3DSURFACE9 pd3dsBack = NULL;
    LPDIRECT3DSURFACE9 pd3dsTemp = NULL;

    // Grab the back buffer into a surface
    if ( SUCCEEDED ( device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pd3dsBack) ))
    {
        D3DSURFACE_DESC desc;
        pd3dsBack->GetDesc(&desc);

        LPDIRECT3DSURFACE9 pd3dsCopy = NULL;
        if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
        {
            if (SUCCEEDED(device->CreateRenderTarget(desc.Width, desc.Height, desc.Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pd3dsCopy, NULL)))
            {
                if (SUCCEEDED(device->StretchRect(pd3dsBack, NULL, pd3dsCopy, NULL, D3DTEXF_NONE)))
                {
                    pd3dsBack->Release();
                    pd3dsBack = pd3dsCopy;
                }
                else
                {
                    pd3dsCopy->Release();
                }
            }
        }

        if (SUCCEEDED(device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pd3dsTemp, NULL)))
        {
            DWORD tmpTimeGRTD = GetTickCount();
            if (SUCCEEDED(device->GetRenderTargetData(pd3dsBack, pd3dsTemp)))
            {
                D3DLOCKED_RECT lockedSrcRect;
                if (SUCCEEDED(pd3dsTemp->LockRect(&lockedSrcRect, NULL, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE)))
                {

                    int nSize = desc.Width * desc.Height * 3;
                    BYTE* pixels = new BYTE[nSize +1];
                    int iSrcPitch = lockedSrcRect.Pitch;
                    BYTE* pSrcRow = (BYTE*)lockedSrcRect.pBits;

                    LPBYTE lpDest = pixels;
                    LPDWORD lpSrc;

                    switch (desc.Format)
                    {
                    case D3DFMT_A8R8G8B8:
                    case D3DFMT_X8R8G8B8:
                        for (int y = desc.Height - 1; y >= 0; y--)
                        {
                            lpSrc = reinterpret_cast<LPDWORD>(lockedSrcRect.pBits) + y * desc.Width;
                            for (unsigned int x = 0; x < desc.Width; x++)
                            {
                                *reinterpret_cast<LPDWORD>(lpDest) = *lpSrc;
                                lpSrc++;        // increment source pointer by 1 DWORD
                                lpDest += 3;    // increment destination pointer by 3 bytes
                            }
                        }
                        break;
                    default:
                        ZeroMemory(pixels, nSize);
                    }

                    pd3dsTemp->UnlockRect();

                    BITMAPINFOHEADER header;
                    header.biWidth = desc.Width; 
                    header.biHeight = desc.Height; 
                    header.biSizeImage = nSize; 
                    header.biSize = sizeof(BITMAPINFOHEADER); 
                    header.biPlanes = 1;
                    header.biBitCount =  3 * 8; // RGB 
                    header.biCompression = 0; 
                    header.biXPelsPerMeter = 0; 
                    header.biYPelsPerMeter = 0; 
                    header.biClrUsed = 0; 
                    header.biClrImportant = 0; 

                    BITMAPFILEHEADER bfh = {0};
                    bfh.bfType = 0x4d42;
                    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
                    bfh.bfSize = bfh.bfOffBits + nSize;

                    unsigned int rough_size = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) + nSize;
                    unsigned char* p = new unsigned char[rough_size]

                    memcpy(p, &bfh, sizeof(BITMAPFILEHEADER));
                    p += sizeof(BITMAPFILEHEADER);
                    memcpy(p, &header, sizeof(BITMAPINFOHEADER));
                    p += sizeof(BITMAPINFOHEADER);
                    memcpy(p, pixels, nSize);

                    delete [] pixels;

                    /**********************************************/
                    // p now has a full BMP file, write it out here
                }
            }
            pd3dsTemp->Release();
        }
        pd3dsBack->Release();
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top