2010-03-18 45 views
2

我使用D3DXSaveSurfaceToFile將窗口化的Direct3D 9表面保存爲PNG,BMP和JPG文件。 D3DXSaveSurfaceToFile調用沒有返回任何錯誤,並且所有文件在Windows照片查看器和畫圖中均可正常打開。但他們不會在更高端的圖像編輯程序(如Paint Shop Pro或Photoshop)中打開。這些程序的錯誤信息基本上說該文件已損壞。如果我在Paint中打開這些文件,然後用不同的文件名將它們保存爲相同的文件格式,那麼它們會在其他程序中正常打開。用D3DXSaveSurfaceToFile保存的圖像將在Paint中打開,而不是Photoshop

這使我相信D3DXSaveSurfaceToFile正在寫出這些文件格式的非標準版本。有沒有什麼辦法可以讓我用這個函數寫出可以在Photoshop等程序中打開的文件,而無需在Paint中保存文件的中間步驟?或者,我應該使用另一個功能,將Direct3D表面保存爲圖像更好嗎?

回答

1

原來,這是我的代碼中的一個bug的組合,而Paint在閱讀文件時比Photoshop更寬容。我的代碼中的錯誤導致文件被保存爲錯誤的擴展名(即Image.bmp實際上是使用D3DXIFF_JPG保存的)。打開包含JPG圖像但具有BMP擴展名的文件時,Photoshop僅使文件失敗。我猜畫圖工作,因爲它忽略文件擴展名,只是解碼文件內容。

看着image meta viewer中的文件幫助我看到了問題。

2

看一看圖片中的文件meta viewer。它告訴你什麼?

+0

原來文件保存不正確。感謝您指點我的實用工具。 – bsruth 2010-03-18 23:22:31

+1

如果他的解決方案奏效......不要忘記接受它作爲解決方案。 – Lee 2010-03-19 06:33:39

+0

我向上投票,因爲它幫助找到答案,但並不是問題的確切答案。 – bsruth 2010-03-22 15:30:58

2

不幸的是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(); 
    } 
} 
相關問題