HWND以PPM问题 [英] hwnd to ppm issue

查看:179
本文介绍了HWND以PPM问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有保存HWND到一个PPM文件的功能。
此功能是通过MSDN榜样的鼓舞。
无论是MSDN样品和我的功能工作,但...我有一个问题...

I have a function which save a hwnd into a ppm file. This function is inspired by a msdn example. Both the msdn sample and my function work but ... I have an issue ...

但首先,这里是功能。

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

因此​​,这里产生的图像:

So here is the resulting image:

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

正如你所看到的,有在宽度尺寸的问题。也许是因为窗口的边界?
如果在code,我变W = rc.right - rc.left;进入W = rc.right - rc.left - 10;,它的更好。但我不明白,为什么我不得不把-10和......一些像素缺少对图片的右侧(也许10个像素?)

As you can see, there is a problem in the width size. Maybe because of the border of the window ? If in the code, I change "w = rc.right - rc.left;" into "w = rc.right - rc.left - 10;", it's better. But I don't understand why I have to put "-10" and ... some pixel are missing on the right of the picture (maybe 10 pixels ?)

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

和最后一个问题:
有没有什么办法来问的GetDIBits函数把我的字节的顺序颠倒?
我没有魔杖通过做副本像素像素,因为它会花费一些CPU时间。 (好吧,你可能会说,因为我保存此文件到磁盘,那么我不应该由CPU时间有关,但我的目标不是这张照片保存到磁盘中。我只是这样做是为了调试的目的)

And the last question: is there any way to ask to GetDIBits function to put my byte in the inverted order ? I don't wand to do a pixel by pixel copy since it will cost some cpu time. (ok, you may say that since I'm saving this file to disk, then I should not be concerned by cpu time, but my goal is not to save this picture to the disk. I'm doing it for debug purpose only)

在此先感谢您的帮助。

推荐答案

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

Your problem is that each row of image data in a DIB must be DWORD aligned (i.e. aligned on a multiple of 4 bytes).

dwBmpSize = w*bi.biBitCount*h;

这实际上应该是:

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

您届时将有写PPM文件时考虑到这一点。

You will then have to account for this when writing the PPM file.

另外,图像是上下颠倒因为默认的DIB是自下而上(行0是在底部)。以使其自上而下的biHeight字段设置为负值。

Also, the image is upside down because by default DIBs are "bottom-up" (row 0 is at the bottom). To make it "top-down" set the biHeight field to a negative value.

这篇关于HWND以PPM问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆