2012-08-16 2 views
0

나는 hwnd를 ppm 파일로 저장하는 기능이 있습니다. 이 함수는 msdn 예제에서 영감을 얻었습니다. msdn 샘플과 내 함수 모두 작동하지만 ... 문제가 있습니다 ...hwnd에서 ppm으로 발행

하지만 먼저 여기에 함수가 있습니다. 당신이 볼 수 있듯이, 폭 크기에 문제가

http://imageshack.us/photo/my-images/853/test2ne.jpg/

: 그래서 여기

int CaptureAnImage(HWND hWnd) 
{ 
    HDC hdcWindow; 
    HDC hdcMemDC = NULL; 
    HBITMAP hbmScreen = NULL; 
    RECT rc; 
    BITMAPINFOHEADER bi; 

    DWORD dwBmpSize; 
    HANDLE hDIB; 
    char *lpbitmap; 
    int w, h; 
    FILE *f; 

    // Retrieve the handle to a display device context for the client 
    // area of the window. 
    hdcWindow = GetDC(hWnd); 

    // Create a compatible DC which is used in a BitBlt from the window DC 
    hdcMemDC = CreateCompatibleDC(hdcWindow); 
    if(!hdcMemDC) { 
     MessageBox(hWnd, "CreateCompatibleDC has failed","Failed", MB_OK); 
     goto done; 
    } 

    // Get the client area for size calculation 
    GetClientRect(hWnd, &rc); 
    w = rc.right - rc.left; 
    h=rc.bottom-rc.top; 

    // Create a compatible bitmap from the Window DC 
    hbmScreen = CreateCompatibleBitmap(hdcWindow, w, h); 
    if(!hbmScreen) { 
     MessageBox(hWnd, "CreateCompatibleBitmap Failed","Failed", MB_OK); 
     goto done; 
    } 

    // Select the compatible bitmap into the compatible memory DC. 
    SelectObject(hdcMemDC,hbmScreen); 

    // Bit block transfer into our compatible memory DC. 
    if(!BitBlt(hdcMemDC, 
       0,0, 
       w, h, 
       hdcWindow, 
       0,0, 
       SRCCOPY)) { 
     MessageBox(hWnd, "BitBlt has failed", "Failed", MB_OK); 
     goto done; 
    } 

    bi.biSize = sizeof(BITMAPINFOHEADER);  
    bi.biWidth = w;  
    bi.biHeight = h; 
    bi.biPlanes = 1;  
    bi.biBitCount = 24;  
    bi.biCompression = BI_RGB;  

    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0;  
    bi.biYPelsPerMeter = 0;  
    bi.biClrUsed = 0;  
    bi.biClrImportant = 0; 

    dwBmpSize = w*bi.biBitCount*h; 

    // Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that 
    // call HeapAlloc using a handle to the process's default heap. Therefore, GlobalAlloc and LocalAlloc 

    // have greater overhead than HeapAlloc. 
    hDIB = GlobalAlloc(GHND,dwBmpSize); 
    lpbitmap = (char *)GlobalLock(hDIB);  

    // Gets the "bits" from the bitmap and copies them into a buffer 
    // which is pointed to by lpbitmap. 
    GetDIBits(hdcWindow, hbmScreen, 0, 
     (UINT)h, 
     lpbitmap, 
     (BITMAPINFO *)&bi, DIB_RGB_COLORS); 

    f = fopen("./test.ppm", "wb"); 
    if (!f) { 
     fprintf(stderr, "cannot create ppm file\n"); 
    goto done; 
    } 
    fprintf(f, "P6\n%d %d\n255\n", w, h); 
    fwrite((LPSTR)lpbitmap, dwBmpSize, 1, f); 
    fclose(f); 

    //Unlock and Free the DIB from the heap 
    GlobalUnlock(hDIB);  
    GlobalFree(hDIB); 

    //Clean up 
done: 
    DeleteObject(hbmScreen); 
    DeleteObject(hdcMemDC); 
    ReleaseDC(hWnd,hdcWindow); 

    return 0; 
} 

결과 이미지입니다. 어쩌면 창문 경계 때문일까? 코드에서 "w = rc.right - rc.left;"를 변경합니다. "w = rc.right - rc.left - 10;"으로 변경하는 것이 좋습니다. 그러나 (어쩌면 10 픽셀?) 나는 "-10"나는 넣어야 할 이유를 이해하지 않고 ... 일부 픽셀은 화면의 오른쪽에 누락

http://imageshack.us/photo/my-images/207/test3jq.jpg

그리고 마지막 질문 : 를 GetDIBits 함수에 역순으로 내 바이트를 넣을 수있는 방법이 있습니까? 픽셀 단위의 비용을 지불해야하므로 픽셀 단위로 복사하지 않아도됩니다. (오케이,이 파일을 디스크에 저장하고 있기 때문에 CPU 시간에 신경 쓸 필요는 없지만 디스크에이 그림을 저장하는 것이 목표가 아닙니다. 디버그 목적으로 만 사용하고 있습니다) 어떤 도움

+0

윈도우 기반 코드로 C 표준 라이브러리를 혼합하는 것은 정말 나쁜 생각입니다 ... – perilbrain

+0

왜이게 나쁜가요? 나는 C로 코딩하는 데 익숙하다. (C++이 아니다.) 윈도우 라이브러리는 C 언어로 사용 가능하다. – ramone

+0

http://stackoverflow.com/questions/2185944/why-must-stride-in-the-system-drawing-bitmap-constructor-be-a-multiple-of-4 –

답변

1

귀하의 문제는 DIB에서 이미지 데이터의 각 행은 DWORD 정렬되어 있어야한다는 것입니다 사전에

덕분에 (즉, 4 바이트의 배수로 정렬).

dwBmpSize = w*bi.biBitCount*h; 

이 실제로 있어야한다 : 당신은 다음 PPM 파일을 작성할 때이 차지해야 할 것이다

dwBmpSize = ((w*bi.biBitCount+3)&~3) *h; 

.

또한 기본적으로 DIB는 "상향식"(행 0이 아래쪽에 있음)이기 때문에 이미지가 거꾸로됩니다. "하향식"으로 설정하려면 biHeight 필드를 음수 값으로 설정하십시오.

+0

도움을 주셔서 감사합니다. 정확히 그 것입니다. 내가 필요한 것, 감사합니다 :) – ramone