×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!
  • Students Click Here

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

screen capture: 24bit color Vs 256 color

screen capture: 24bit color Vs 256 color

screen capture: 24bit color Vs 256 color

(OP)
Hi all:
 I have a piece of code which captures the screen and saves it as a bitmap file. When i use 32 and 24 bit color it works fine, however..when i set the display to 256 colors, it gives me a blank screen...why?????
Appriciate the help.
Thanks,
Preetham.

RE: screen capture: 24bit color Vs 256 color

Almost certainly related to palettes. 32 and 24-bit desktops are easily captured because the code doesn't need to worry about palettes. 256 colors and less can, oddly, be a little more complex

RE: screen capture: 24bit color Vs 256 color

(OP)
Is there any piece of code that i could get that would help solve my problem.
And true, i am not handling any kinda paletts in my code.

RE: screen capture: 24bit color Vs 256 color

please: would you post the piece of code for me? ive been searching for a while that functionality...

thanks anyway

RE: screen capture: 24bit color Vs 256 color

(OP)
The method GetScreenBitmap() is used to capture the screen.
There are some redundant operations performed in the method, which u can ignore or modify....



#define DibWidth(pDib)    (((BITMAPINFOHEADER *)pDib)->biWidth)
#define DibHeight(pDib)   (((BITMAPINFOHEADER *)pDib)->biHeight)
#define DibBitCount(pDib) (((BITMAPINFOHEADER *)pDib)->biBitCount)
#define DibClrUsed(pDib)  (((BITMAPINFOHEADER *)pDib)->biClrUsed)
#define DibNumColors(pDib) (DibClrUsed(pDib) ? DibClrUsed (pDib) :         \
               (DibBitCount(pDib) <= 8 ? 1 << DibBitCount(pDib) : 0))

#define DibClrTablePtr(pDib) ((RGBQUAD *) (pDib + sizeof (BITMAPINFOHEADER)))

#define DibBitsPtr(pDib) (pDib + sizeof (BITMAPINFOHEADER) +               \
                                 sizeof (RGBQUAD) * DibNumColors(pDib))

#define DibRowLength(pDib) (((DibWidth(pDib) *                             \
                                        DibBitCount(pDib) + 31) & ~31) >> 3)

#define DibRowPtr(pDib,iRow) (DibBitsPtr(pDib) +                           \
                         DibRowLength(pDib) * (DibHeight(pDib) - (iRow) - 1))

#define DibPixelPtr(pDib,iRow,iCol) (DibRowPtr(pDib,iRow) +                \
                                   (iCol) * DibBitCount(pDib) / 8)

#define DibBitsSize(pDib)  (DibHeight(pDib) * DibRowLength(pDib))

#define DibTotalSize(pDib) (sizeof (BITMAPINFOHEADER) +                    \
                            sizeof (RGBQUAD) * DibNumColors(pDib) +        \
                            DibBitsSize(pDib))
#define DibGetColor(pDib,i) (* (DibClrTablePtr(pDib) + (i)))
#define DibSetColor(pDib,i,rgb) (* (DibClrTablePtr(pDib) + (i)) = (rgb))

//Get the Screen Bitmap and return a global handle to the memory containing the bmp
BOOL GetScreenBitmap(HDC appDC);


HPALETTE GetCurrentPalette (HWND hwnd);

BYTE * ConvertDDBtoDIB (HWND hwnd, HBITMAP hBitmap, HPALETTE hPalette);

int Compare1 (const void * p1, const void * p2) ;
int Compare2 (const void * p1, const void * p2) ;

typedef struct
{
     int     indexOld ;       // The original palette index
     int     indexNew ;       // The new palette index
     DWORD   dwCount ;        // The number of pixels of that color
     RGBQUAD rgb ;            // The RGB value for that index
}
COLORCOUNT ;
BYTE * DibSortColorTable (BYTE * pDib);

DWORD DibGetPixel (PBYTE pDib, int iRow, int iCol) ;
void  DibSetPixel (PBYTE pDib, int iRow, int iCol, DWORD dwPixel) ;


//Get the Screen Bitmap and return a global handle to the memory containing the bmp
BOOL
GetScreenBitmap(HDC hdcscr)
{
    HPALETTE hPalette;
    BYTE    * pdib;
    RECT    appRectNew;
    BITMAPFILEHEADER   bmfh ;
    DWORD              dwTotalSize, dwBitsSize ;

    GetClientRect(hWndApp, &appRectNew);   
    if(appRectNew.bottom + 48 != appRect.bottom    ||
        appRectNew.right + 8  != appRect.right    ||
        appRectNew.top    != appRect.top            ||
        appRectNew.left    != appRect.left)
    {
        appRect.bottom    = appRectNew.bottom + 48;
        appRect.right    = appRectNew.right  + 8;
        appRect.top        = appRectNew.top;
        appRect.left    = appRectNew.left;
        //
        hbitmap = CreateCompatibleBitmap(hdcscr,
                                        int (appRect.right - appRect.left),
                                        int (appRect.bottom - appRect.top));

        SelectObject(hdcmem, hbitmap);
        if(hbitmap == NULL)
        {
            //error
            //err1 = GetLastError();
        }
    }


    BitBlt(hdcmem,  0, 0,
                    abs(appRect.right - appRect.left),
                    abs(appRect.bottom - appRect.top),
                    hdcscr, appRect.left, appRect.top, SRCCOPY );

    hPalette = GetCurrentPalette(hWndApp);
    //if(hPalette == NULL)



    if(hbitmap)
    {
        pdib = ConvertDDBtoDIB(hWndApp, hbitmap, hPalette);
        if(pdib == NULL)
        {
            return 0;
        }
        pdib = DibSortColorTable(pdib);
    }

     // Get the size of the DIB and the bits
     dwBitsSize  = DibBitsSize (pdib) ;
     dwTotalSize = DibTotalSize (pdib) ;

     // Now we're ready to define the BITMAPFILEHEADER
     bmfh.bfType      = * (WORD *) "BM" ;
     bmfh.bfSize      = sizeof (BITMAPFILEHEADER) + dwTotalSize ;
     bmfh.bfReserved1 = 0 ;
     bmfh.bfReserved2 = 0 ;
     bmfh.bfOffBits   = bmfh.bfSize - dwBitsSize ;

    //Allocate memory and move the bitmap data to the memory
    if(prevMemScreenDataSize == 0  || prevMemScreenDataSize != bmfh.bfSize
                                                        || memScreenData == 0)
        memScreenData = (LPBYTE) GlobalAlloc(GMEM_FIXED, bmfh.bfSize);

    memcpy((void *)memScreenData,(LPVOID)&bmfh, sizeof (bmfh));
    memcpy((void *)(memScreenData + sizeof(bmfh)),(LPVOID)pdib, dwTotalSize);

    //DeleteObject(hPalette);
    //set the buffer size and the Buffer pointer
    memScreenDataSize = bmfh.bfSize;
    screenInfoCard->bufSize = bmfh.bfSize;
    screenInfoCard->hSize = appRect.right - appRect.left;
    screenInfoCard->vSize = appRect.bottom - appRect.top;
    prevMemScreenDataSize = bmfh.bfSize;

     // Open the output file
    //write the bmp into the memory
    DWORD dwTemp =0;
    HANDLE hf = CreateFile("testCaptureBitmap.bmp",
                   GENERIC_READ | GENERIC_WRITE,
                   (DWORD) 0,
                    NULL,
                   CREATE_ALWAYS,
                   FILE_ATTRIBUTE_NORMAL,
                   (HANDLE) NULL);
    WriteFile(hf, memScreenData, bmfh.bfSize,
        (LPDWORD) &dwTemp,  NULL);
    CloseHandle(hf);
    
    free(pdib);

    return true;
}







/*-------------------------------------------------------
   GetCurrentPalette: Obtains the current system palette.
  -------------------------------------------------------*/

HPALETTE GetCurrentPalette (HWND hwnd)
{
     HDC          hdc ;
     HPALETTE     hPalette ;
     int          iSize ;
     LOGPALETTE * plogpal ;

          // Get a video device context

     hdc = GetDC (hwnd) ;

          // If the video device supports palettes, get palette size
          //   (Betcha a hundred to one it'll be 256!)

     if (RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS))
     {
          iSize = GetDeviceCaps (hdc, SIZEPALETTE) ;

               // Allocate memory for the palette and get it.

          plogpal = (LOGPALETTE*)malloc (sizeof (LOGPALETTE) +
                            sizeof (PALETTEENTRY) * (iSize - 1)) ;

          plogpal->palVersion    = 0x0300 ;
          plogpal->palNumEntries = iSize ;

          GetSystemPaletteEntries (hdc, 0, iSize, plogpal->palPalEntry) ;

               // Now create a palette based on the system palette entries

          hPalette = CreatePalette (plogpal) ;

               // free the memory
     
          free (plogpal) ;
     }
          // If the device doesn't support palettes, hPalette is NULL.

     else
          hPalette = NULL ;

     // Release the DC
     ReleaseDC (hwnd, hdc) ;

     return hPalette ;
}



/*-------------------------------------------------------------------------
   ConvertDDBtoDIB: Converts a GDI bitmap object to a DIB using a palette.
                    Function based on Knowledge Base article Q80080.
  -------------------------------------------------------------------------*/

BYTE * ConvertDDBtoDIB (HWND hwnd, HBITMAP hBitmap, HPALETTE hPalette)
{
     BITMAP       bm ;
     BITMAPINFO * pbmi ;
     BYTE       * pBits ;
     HDC          hdc ;
     WORD         wBitCount, wNumColor, wColorEntries, wRowLength ;

          // Get information about the DDB & calculate bits per pixel

     GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm) ;
     wBitCount = bm.bmPlanes * bm.bmBitsPixel ;

          // Figure out the DIB bit count and number of colors.
          //   (Probably more generalized than it needs to be)

     if (wBitCount > 16)
     {
          wNumColor = 0 ;
          wBitCount = 24 ;
     }
     else if (wBitCount > 8)
     {
          wNumColor = 0 ;
          wBitCount = 16 ;
     }
     else if (wBitCount > 4)
     {
          wNumColor = 1 << wBitCount ;
          wBitCount = 8 ;
     }
     else if (wBitCount > 2)
     {
          wNumColor = 1 << wBitCount ;
          wBitCount = 4 ;
     }
     else if (wBitCount == 1)
     {
          wNumColor = 2 ;
     }

          // Determine the number of entries in the DIB color table

     wColorEntries = wNumColor ;

     if (wColorEntries == 0 && wBitCount <= 8)
          wColorEntries = 1 << wBitCount ;

          // DIB rows are always multiple of 4 bytes long.

     wRowLength = ((bm.bmWidth * wBitCount + 31) & ~31) >> 3 ;

          // Allocate memory for the entire DIB.

     DWORD size = sizeof (BITMAPINFOHEADER) +
                    sizeof (RGBQUAD) * wColorEntries +
                    wRowLength * bm.bmHeight;
     pbmi = (BITMAPINFO*)malloc (size) ;

     if (pbmi == NULL)
     {
         cout << "ERROR:" << GetLastError() << endl;
          return NULL ;
     }

          // Initialize the BITMAPINFOHEADER

     pbmi->bmiHeader.biSize          = sizeof (BITMAPINFOHEADER) ;
     pbmi->bmiHeader.biWidth         = bm.bmWidth ;
     pbmi->bmiHeader.biHeight        = bm.bmHeight ;
     pbmi->bmiHeader.biPlanes        = 1 ;
     pbmi->bmiHeader.biBitCount      = wBitCount ;
     pbmi->bmiHeader.biCompression   = BI_RGB ;
     pbmi->bmiHeader.biSizeImage     = 0 ;
     pbmi->bmiHeader.biXPelsPerMeter = 0 ;
     pbmi->bmiHeader.biYPelsPerMeter = 0 ;
     pbmi->bmiHeader.biClrUsed       = wNumColor ;
     pbmi->bmiHeader.biClrImportant  = 0 ;

          // Determine the address of the pixel bits in the DIB

     pBits = (BYTE *) pbmi + sizeof (BITMAPINFOHEADER) +
                             sizeof (RGBQUAD) * wColorEntries ;

          // Get a video device context and select the palette into it

     hdc = GetDC (hwnd) ;
     SelectPalette (hdc, hPalette, FALSE) ;
     RealizePalette (hdc) ;

          // Here's the function we've all been waiting for.

     GetDIBits (hdc, hBitmap, 0, bm.bmHeight, pBits, pbmi, DIB_RGB_COLORS) ;
          
          // Clean up and get out.

     ReleaseDC (hwnd, hdc) ;

     return (BYTE *) pbmi ;
}



     // Sorts the array of COLORCOUNT structures to put the highest
     //   counts at the beginning.

int Compare1 (const void * p1, const void * p2)
{
     COLORCOUNT * pcc1 = (COLORCOUNT *) p1 ;
     COLORCOUNT * pcc2 = (COLORCOUNT *) p2 ;

     if (pcc1->dwCount > pcc2->dwCount)
          return -1 ;

     return (pcc1->dwCount < pcc2->dwCount) ;
}

     // Sorts the array of COLORCOUNT structures to put the lowest
     //   old index at the beginning.

int Compare2 (const void * p1, const void * p2)
{
     COLORCOUNT * pcc1 = (COLORCOUNT *) p1 ;
     COLORCOUNT * pcc2 = (COLORCOUNT *) p2 ;

     if (pcc1->indexOld < pcc2->indexOld)
          return -1 ;

     return (pcc1->indexOld > pcc2->indexOld) ;
}



/*----------------------------------------------------------------------
   DibSortColorTable: Sorts a DIB color table to put most-used colors
                      at the beginning. Possibly reduces size of DIB
                      for unused colors, so returns pointer to new DIB.
  ----------------------------------------------------------------------*/
BYTE * DibSortColorTable (BYTE * pDib)
{
     COLORCOUNT cc[256] ;
     int        cRows, cCols, cClrs, iRow, iCol, i, cClrsNew ;

          // This function is only applicable for palette DIBs

     if (DibBitCount(pDib) > 8)
          return pDib ;

          // Get some useful information about the DIB using macros
          //   defined in ScreenSeizeDib.h

     cRows = DibHeight (pDib) ;
     cCols = DibWidth  (pDib) ;
     cClrs = DibNumColors (pDib) ;

          // Initialize the structure with DIB color table

     for (i = 0 ; i < cClrs ; i++)
     {
          cc.indexOld = i ;
          cc.indexNew = 0 ;
          cc.dwCount  = 0 ;
          cc.rgb      = DibGetColor (pDib, i) ;
     }

          // Now accumulate the pixel counts in the structure

     for (iRow = 0 ; iRow < cRows ; iRow++)
     for (iCol = 0 ; iCol < cCols ; iCol++)
          cc[DibGetPixel (pDib, iRow, iCol)].dwCount ++ ;

          // Sort the structure by the pixel counts

     qsort (&cc, cClrs, sizeof (COLORCOUNT), Compare1) ;

          // Transfer the sorted colors into the DIB, but
          //   don't transfer those that aren't used at all.

     for (i = 0 ; i < cClrs && cc.dwCount ; i++)
          DibSetColor (pDib, i, cc.rgb) ;

          // The new number of colors is now available

     cClrsNew = i ;

          // Put the new color indices into the structure

     for (i = 0 ; i < cClrs ; i++)
          cc.indexNew = i ;

          // Sort the structure by the old indices

     qsort (&cc, cClrs, sizeof (COLORCOUNT), Compare2) ;

          // Now we can easily change each color index

     for (iRow = 0 ; iRow < cRows ; iRow++)
     for (iCol = 0 ; iCol < cCols ; iCol++)
          DibSetPixel (pDib, iRow, iCol,
               cc[DibGetPixel (pDib, iRow, iCol)].indexNew) ;

          // Now the file can be tightened up to get rid of unused colors

     if (cClrsNew < cClrs)
     {
          BYTE * pBitsOld, * pBitsNew ;
          int    iBitsSize ;
          
          pBitsOld = DibBitsPtr (pDib) ;
          ((BITMAPINFOHEADER *) pDib)->biClrUsed = cClrsNew ;
          pBitsNew = DibBitsPtr (pDib) ;
          iBitsSize = DibBitsSize (pDib) ;

          for (i = 0 ; i < iBitsSize ; i++)
               *pBitsNew++ = *pBitsOld++ ;

          pDib = (BYTE*)realloc (pDib, DibTotalSize (pDib)) ;
     }

     return pDib ;
}


/*--------------------------------------------------------------------------
   DibGetPixel: Gets a pixel value for a particular row and column address.
                NOTE: No bounds check on row and column!
  --------------------------------------------------------------------------*/

DWORD DibGetPixel (PBYTE pDib, int iRow, int iCol)
{
          // Handy macro in ScreenSeizeDib.h

     BYTE * pPixel = DibPixelPtr (pDib, iRow, iCol) ;

          // Another macro and gritty bit work
     
     switch (DibBitCount (pDib))
     {
     case  1:  return 0x01 & (* pPixel >> (7 - (iCol & 7))) ;  
     case  4:  return 0x0F & (* pPixel >> (iCol & 1 ? 0 : 4)) ;
     case  8:  return * pPixel ;
     case 16:  return * (WORD *) pPixel ;
     case 24:  return 0x00FFFFFF & * (DWORD *) pPixel ;
     case 32:  return * (DWORD *) pPixel ;
     }
     return 0 ;
}

/*--------------------------------------------------------------------------
   DibSetPixel: Sets a pixel value for a particular row and column address.
                NOTE: No bounds check on row and column!
  --------------------------------------------------------------------------*/

void DibSetPixel (PBYTE pDib, int iRow, int iCol, DWORD dwPixel)
{
          // Ditto

     BYTE * pPixel = DibPixelPtr (pDib, iRow, iCol) ;

     switch (DibBitCount (pDib))
     {
     case  1:  * pPixel &= ~(1     << (7 - (iCol & 7))) ;
               * pPixel |= dwPixel << (7 - (iCol & 7)) ;
               break ;

     case  4:  * pPixel &= 0x0F    << (iCol & 1 ? 4 : 0) ;
               * pPixel |= dwPixel << (iCol & 1 ? 0 : 4) ;
               break ;

     case  8:  * pPixel = (BYTE) dwPixel ;
               break ;

     case 16:  * (WORD *) pPixel = (WORD) dwPixel ;
               break ;

     case 24:  * (RGBTRIPLE *) pPixel = * (RGBTRIPLE *) &dwPixel ;
               break ;

     case 32:  * (DWORD *) pPixel = dwPixel ;
               break ;
     }
}

RE: screen capture: 24bit color Vs 256 color

thanks !!!!

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close