2010-03-18 5 views
2

D3DXSaveSurfaceToFile을 사용하여 창으로 표시된 Direct3D 9 표면을 PNG, BMP 및 JPG 파일에 저장합니다. D3DXSaveSurfaceToFile 호출에서 반환 된 오류가없고 Windows 사진 뷰어 및 그림판에서 모든 파일이 제대로 열립니다. 그러나 Paint Shop Pro 나 Photoshop과 같은 고급 이미지 편집 프로그램에서는 열지 않습니다. 이러한 프로그램의 오류 메시지는 기본적으로 파일이 손상되었다고 말합니다. 그림판에서 파일을 열고 다른 파일 이름으로 같은 파일 형식으로 저장하면 다른 프로그램에서도 제대로 열립니다.D3DXSaveSurfaceToFile로 저장된 이미지가 Photoshop이 아닌 Paint에서 열립니다.

D3DXSaveSurfaceToFile이 이러한 파일 형식의 비표준 버전을 작성한다고 생각합니다. 이 기능을 사용하여 페인트에서 파일을 다시 저장하는 중간 단계없이 Photoshop과 같은 프로그램에서 열 수있는 파일을 쓸 수있는 방법이 있습니까? 또는 Direct3D 표면을 이미지에 저장하는 더 나은 작업을 수행해야하는 또 다른 함수가 있습니까?

답변

1

내 코드의 버그와 파일을 읽을 때 Photoshop보다 더 용서가되는 그림판의 조합이라고 밝혀졌습니다. 내 코드의 버그로 인해 파일이 잘못된 확장자로 저장되었습니다 (즉, Image.bmp가 D3DXIFF_JPG를 사용하여 실제로 저장되었습니다). JPG 이미지를 포함하지만 BMP 확장자를 가진 파일을 열 때 Photoshop은 파일을 방금 실패했습니다. 나는 Paint가 파일 확장자를 무시하고 파일 내용을 해독 한 이후로 작업했다고 생각합니다.

image meta viewer에있는 파일을 보면이 문제를 확인하는 데 도움이되었습니다.

2

이미지 파일 meta viewer을보십시오. 그것은 무엇을 말하는가?

+0

파일이 잘못 저장되었습니다. 그 유틸리티를 가르쳐 주셔서 고마워요. – bsruth

+1

그의 해결책이 효과가 있다면 ... 해결책으로 받아 들여야한다는 것을 잊지 마십시오. – Lee

+0

답변을 찾는데 도움이 되었기 때문에 나는 업 투표했습니다. 그러나 질문에 대한 정확한 대답은 아니 었습니다. – bsruth

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(); 
    } 
} 
관련 문제