Изображения, сохраненные с помощью D3DXSaveSurfaceToFile, будут открываться в Paint, а не в Photoshop. - PullRequest
2 голосов
/ 19 марта 2010

Я использую D3DXSaveSurfaceToFile для сохранения оконных поверхностей Direct3D 9 в файлы PNG, BMP и JPG. После вызова D3DXSaveSurfaceToFile ошибок не возвращается, и все файлы открываются в Windows Photo Viewer и Paint. Но они не откроются в более высокой программе редактирования изображений, такой как Paint Shop Pro или Photoshop. Сообщения об ошибках от этих программ в основном говорят, что файл поврежден. Если я открою файлы в Paint, а затем сохраню их в том же формате с другим именем, они будут открываться в других программах.

Это наводит меня на мысль, что D3DXSaveSurfaceToFile записывает нестандартные версии этих форматов файлов. Есть ли какой-нибудь способ заставить эту функцию записывать файлы, которые можно открывать в таких программах, как Photoshop, без промежуточного этапа восстановления файлов в Paint? Или есть другая функция, которую я должен использовать, которая лучше сохраняет поверхности Direct3D в изображение?

Ответы [ 3 ]

2 голосов
/ 19 марта 2010

К сожалению, D3DXSaveSurfaceToFile () не самый стабильный (он также чрезвычайно медленный). Лично я делаю что-то вроде приведенного ниже кода. Он работает даже на сглаженных дисплеях, выполняя закадровый рендер, чтобы сделать снимок экрана и затем поместить его в буфер. Он также поддерживает только самые распространенные форматы пикселей. Извините за любые ошибки в нем, вытащил его из приложения, над которым я работал.

Затем вы можете, в своем коде и, возможно, в другом потоке, затем преобразовать указанное «растровое изображение» во что угодно, используя множество другого кода.

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();
    }
}
2 голосов
/ 19 марта 2010

Посмотрите на файл в изображении meta viewer . Что это говорит тебе?

1 голос
/ 19 марта 2010

Оказывается, это была ошибка в моем коде, и Paint был более щадящим, чем Photoshop, когда дело доходит до чтения файлов. Ошибка в моем коде привела к тому, что файлы были сохранены с неправильным расширением (т.е. Image.bmp был фактически сохранен с использованием D3DXIFF_JPG). При открытии файла, который содержал изображение JPG, но имел расширение BMP, Photoshop просто отказал файлу. Я думаю, что Paint работал, так как он игнорировал расширение файла и просто декодировал содержимое файла.

Просмотр файла в мета-программе просмотра изображений помог мне увидеть проблему.

...