2013-06-27 48 views
-1

我在位圖中捕獲桌面窗口的特定部分並嘗試打印 BGR像素顏色值。桌面窗口的這個捕獲部分完全充滿了16,0,16色。如何在16/24/32位顏色中正確捕獲屏幕位圖

當我的窗口顏色深度爲32時捕獲並打印數據一切正常 但如果我的窗口是在24/16位彩色模式,那麼我得到不同的像素值而不是16,16,16。

我捕獲屏幕左= 150,頂部= 150,右= 200,底部= 200。 * ** * ** * **捕獲圖像從臺式* ** * ** * **

iLeft = 150; 
    iTop = 150; 
    iRight = iLeft + 50; 
    iBottom = iTop + 50; 



     /* 

    HDC hdcScreen; 
    HDC hdcWindow; 
    HDC hdcMemDC = NULL; 
    HBITMAP hbmScreen = NULL; 
    BITMAP bmpScreen; 

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

    // Create a compatible DC which is used in a BitBlt from the window DC 
    hdcMemDC = CreateCompatibleDC(hdcWindow); 

    if(!hdcMemDC) 
    { 
     MessageBox(hWnd, L"CreateCompatibleDC has failed",L"Failed", MB_OK); 
     goto done; 
    } 

    // Get the client area for size calculation 
    RECT rcClient; 
    GetClientRect(hWnd, &rcClient); 

    //This is the best stretch mode 
    SetStretchBltMode(hdcWindow,HALFTONE); 

    //The source DC is the entire screen and the destination DC is the current window (HWND) 
    if(!StretchBlt(hdcWindow, 
       0,0, 
       rcClient.right, rcClient.bottom, 
       hdcScreen, 
       0,0, 
       GetSystemMetrics (SM_CXSCREEN), 
       GetSystemMetrics (SM_CYSCREEN), 
       SRCCOPY)) 
    { 
     MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK); 
     goto done; 
    } 

    // Create a compatible bitmap from the Window DC 
    hbmScreen = CreateCompatibleBitmap(hdcWindow, rcClient.right-rcClient.left, rcClient.bottom-rcClient.top); 

    if(!hbmScreen) 
    { 
     MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"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, 
       rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, 
       hdcWindow, 
       0,0, 
       SRCCOPY)) 
    { 
     MessageBox(hWnd, L"BitBlt has failed", L"Failed", MB_OK); 
     goto done; 
    } 

    // Get the BITMAP from the HBITMAP 
    GetObject(hbmScreen,sizeof(BITMAP),&bmpScreen); 

    BITMAPFILEHEADER bmfHeader;  
    BITMAPINFOHEADER bi; 

    bi.biSize = sizeof(BITMAPINFOHEADER);  
    bi.biWidth = bmpScreen.bmWidth;  
    bi.biHeight = bmpScreen.bmHeight; 
    bi.biPlanes = 1;  
    bi.biBitCount = 32;  
    bi.biCompression = BI_RGB;  
    bi.biSizeImage = 0; 
    bi.biXPelsPerMeter = 0;  
    bi.biYPelsPerMeter = 0;  
    bi.biClrUsed = 0;  
    bi.biClrImportant = 0; 

    DWORD dwBmpSize = ((bmpScreen.bmWidth * bi.biBitCount + 31)/32) * 4 * bmpScreen.bmHeight; 

    // 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. 
    HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize); 
    char *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)bmpScreen.bmHeight, 
     lpbitmap, 
     (BITMAPINFO *)&bi, DIB_RGB_COLORS); 

    // A file is created, this is where we will save the screen capture. 
    HANDLE hFile = CreateFile(L"captureqwsx.bmp", 
     GENERIC_WRITE, 
     0, 
     NULL, 
     CREATE_ALWAYS, 
     FILE_ATTRIBUTE_NORMAL, NULL); 

    // Add the size of the headers to the size of the bitmap to get the total file size 
    DWORD dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 

    //Offset to where the actual bitmap bits start. 
    bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER); 

    //Size of the file 
    bmfHeader.bfSize = dwSizeofDIB; 

    //bfType must always be BM for Bitmaps 
    bmfHeader.bfType = 0x4D42; //BM 

    DWORD dwBytesWritten = 0; 
    WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL); 
    WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL); 
    WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL); 

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

    //Close the handle for the file that was created 
    CloseHandle(hFile); 


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

    return 0; 
*/ 

//#if 0 

    HDC hdcScreen; 
    // HDC hdcWindow; 
    HDC hdcMemDC = NULL; 
    HBITMAP hbmScreen = NULL; 
    HRGN rgn = NULL; 

    BITMAP bmpScreen; 

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

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

     // Get the client area for size calculation 
     //RECT rcClient; 
     //GetClientRect(hWnd, &rcClient); 

     //This is the best stretch mode 
     SetStretchBltMode(hdcMemDC,HALFTONE); 
      // Create a compatible bitmap from the Window DC 
      hbmScreen = CreateCompatibleBitmap(hdcScreen, iRight - iLeft, iBottom - iTop); 

      if(!hbmScreen) 
      { 
       //MessageBox(hWnd, L"CreateCompatibleBitmap Failed",L"Failed", MB_OK); 
       goto done; 
      } 

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

    } 


    //The source DC is the entire screen and the destination DC is the current window (HWND) 
    /* if(!StretchBlt(hdcWindow, 
       0,0, 
       rcClient.right, rcClient.bottom, 
       hdcScreen, 
       0,0, 
       GetSystemMetrics (SM_CXSCREEN), 
       GetSystemMetrics (SM_CYSCREEN), 
       SRCCOPY)) 
    { 
     MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK); 
     goto done; 
    } 
    */ 


    // Bit block transfer into our compatible memory DC. 
    if(!StretchBlt(hdcMemDC, 
       0,0, 
       iRight - iLeft, 
       iBottom - iTop, 
       hdcScreen, 
       iLeft,iTop, 
       iRight - iLeft, 
       iBottom - iTop, 
       SRCCOPY)) 
    { 
     // MessageBox(hWnd, L"StretchBlt has failed",L"Failed", MB_OK); 
     goto done; 
    } 
    } 
*******************FUNCTION FOR GETTING THE BITMAP RAW DATA POINTER*********** 
BYTE* Get24BitPixels(HDC dcDesktop, HBITMAP pBitmap, WORD *pwWidth, WORD *pwHeight, WORD * pReminderWidth) 
{ 


    // a bitmap object just to get bitmap width and height 
    BITMAP bmpBmp; 

    // pointer to original bitmap info 
    LPBITMAPINFO pbmiInfo; 

    // bitmap info will hold the new 24bit bitmap info 
    BITMAPINFO bmiInfo; 

    // width and height of the bitmap 
    WORD wBmpWidth ; WORD wBmpHeight; 

    // --------------------------------------------------------- 
    // get some info from the bitmap 
    // --------------------------------------------------------- 
    GetObject(pBitmap, sizeof(bmpBmp),&bmpBmp); 
    pbmiInfo = (LPBITMAPINFO)&bmpBmp; 

    //get width and height 
    wBmpWidth = (WORD)pbmiInfo->bmiHeader.biWidth; 
    int iReminderWidth = (wBmpWidth%4);      
    //wBmpWidth -= (wBmpWidth%4);      // width is 4 byte boundary aligned. 
    wBmpHeight = (WORD)pbmiInfo->bmiHeader.biHeight; 

    // copy to caller width and height parms 
    *pwWidth = wBmpWidth; 
    *pwHeight = wBmpHeight; 

    wBmpWidth += (4 - iReminderWidth); // width is 4 byte boundary aligned, thereby increasing the width 
//so that it will be fully divible by four , it will cause some extra bytes to be filled in with garbage value 
//beyond the actual width of the bitmap, we will be discrading this extra padding pixels data while processign each pixel. 


*pReminderWidth = 4 - iReminderWidth; 
    // --------------------------------------------------------- 

    // allocate width * height * 24bits pixels 
    BYTE * pPixels = new BYTE[wBmpWidth*wBmpHeight*3]; 
    if (!pPixels) return NULL; 


    // get user desktop device context to get pixels from 
    //HDC hDC = GetWindowDC(NULL); 




    // fill desired structure 
    bmiInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    bmiInfo.bmiHeader.biWidth = wBmpWidth; 
    bmiInfo.bmiHeader.biHeight = -wBmpHeight; 
    bmiInfo.bmiHeader.biPlanes = 1; 
    bmiInfo.bmiHeader.biBitCount = 24; 
    bmiInfo.bmiHeader.biCompression = BI_RGB; 
    bmiInfo.bmiHeader.biSizeImage = wBmpWidth*wBmpHeight*3; 
    bmiInfo.bmiHeader.biXPelsPerMeter = 0; 
    bmiInfo.bmiHeader.biYPelsPerMeter = 0; 
    bmiInfo.bmiHeader.biClrUsed = 0; 
    bmiInfo.bmiHeader.biClrImportant = 0; 



    // get pixels from the original bitmap converted to 24bits 

    int iRes = GetDIBits(dcDesktop,pBitmap,0,wBmpHeight,(LPVOID)pPixels,&bmiInfo,DIB_RGB_COLORS); 

    // release the device context 
    //ReleaseDC(NULL,hDC); 

    // if failed, cancel the operation. 
    if (!iRes) 
    { 
    delete [] pPixels; 
    pPixels = NULL; 
    return NULL; 
    }; 

    // return the pixel array 
    return pPixels; 
} 
+0

你在讓我們看很多的代碼只有模糊的說法,由於預期這是行不通的。縮小問題範圍並提供更多有關錯誤的細節可能會獲得更好的結果。 –

回答