hwnd到ppm问题

我有一个将hwnd保存到ppm文件的function。 此函数的灵感来自msdn示例。 msdn示例和我的函数都工作但是…我有一个问题……

但首先,这是function。

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; } 

所以这是结果图像:

http://sofzh.miximages.com/c/nptest2nej/

如您所见,宽度尺寸存在问题。 也许是因为窗户的边界? 如果在代码中,我更改“w = rc.right – rc.left;” 进入“w = rc.right – rc.left – 10;”,它会更好。 但是我不明白为什么我要把“-10”和……某些像素丢失在图片的右边(可能是10个像素?)

http://sofzh.miximages.com/c/5rtest3jqj

最后一个问题:有没有办法要求GetDIBits函数将我的字节按倒序排列? 我没有魔杖做像素复制,因为它将花费一些CPU时间。 (好吧,你可能会说,因为我将这个文件保存到磁盘,然后我不应该关心cpu时间,但我的目标不是将这些图片保存到磁盘。我这样做只是为了调试目的)

提前感谢您的帮助

您的问题是DIB中的每行图像数据必须是DWORD对齐的(即在4个字节的倍数上对齐)。

 dwBmpSize = w*bi.biBitCount*h; 

这应该是:

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

然后,在编写PPM文件时,您必须考虑到这一点。

此外,图像是颠倒的,因为默认情况下DIB是“自下而上”(第0行位于底部)。 要使其“自上而下”,请将biHeight字段设置为负值。