gpt4 book ai didi

c - hwnd 转 ppm 问题

转载 作者:行者123 更新时间:2023-11-30 15:55:35 24 4
gpt4 key购买 nike

我有一个将 hwnd 保存到 ppm 文件中的函数。这个函数的灵感来自于msdn的一个例子。msdn 示例和我的函数都可以工作,但是...我有一个问题...

但首先,这是函数。

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://imageshack.us/photo/my-images/853/test2ne.jpg/

可以看到,宽度尺寸有问题。也许是因为窗口的边框?如果在代码中,我更改“w = rc.right - rc.left;”改成“w = rc.right - rc.left - 10;”,效果更好。但我不明白为什么我必须输入“-10”并且......图片右侧缺少一些像素(也许是10个像素?)

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

最后一个问题:有什么方法可以要求 GetDIBits 函数将我的字节按相反的顺序放置吗?我不想逐像素复制,因为这会花费一些CPU时间。 (好吧,你可能会说,既然我将这个文件保存到磁盘,那么我不应该关心CPU时间,但我的目标不是将此图片保存到磁盘。我这样做只是为了调试目的)

提前感谢您的帮助

最佳答案

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

dwBmpSize = w*bi.biBitCount*h;

这实际上应该是:

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

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

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

关于c - hwnd 转 ppm 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11991675/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com