Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to screenshot as a single color bitmap file?

How to screenshot as a single color bitmap file?

Scheduled Pinned Locked Moved C / C++ / MFC
graphicsperformancetutorialquestion
5 Posts 2 Posters 6 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wangningyu
    wrote on last edited by
    #1

    Hello everybody ! I wan't to save the bitmap to convert to a single color bitmap (8 pixel / Byte). I use this way to save to 16 color bitmap. how to convert it to single bitmap ,or how to save it from the device context first ?

    /************************************************************************
    Function : Screenshot
    Parameter: hwnd the window handle.
    lpRect the window rect.
    return : HBITMAP
    other : NULL
    ************************************************************************/
    HBITMAP GetWindowBitmap(HWND hwnd, LPRECT lpRect)
    {

     if( !lpRect )
          return NULL;
    
     HDC	hDC;
     HDC	hMemDC;
     HBITMAP	hBitmap = NULL;
     HBITMAP	hOldBitmap;
    
     if( hwnd == NULL )
         hDC = ::GetDC(HWND\_DESKTOP);
     else
         hDC = ::GetWindowDC(hwnd);
    
     if( hDC == NULL )
         return NULL;
    
     hMemDC  = CreateCompatibleDC(hDC);
     hBitmap = CreateCompatibleBitmap(hDC, lpRect->right - lpRect->left, 
     lpRect->bottom - lpRect->top);
    
     if( hBitmap == NULL)
         return NULL;
    
     hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
     BitBlt(hMemDC, 0, 0, lpRect->right - lpRect->left, 
     lpRect->bottom - lpRect->top, hDC, lpRect->left, lpRect->top, SRCCOPY);
    
     SelectObject(hMemDC, hOldBitmap);
     DeleteDC(hMemDC);
     ::ReleaseDC(hwnd, hDC);
    
     return hBitmap;
    

    }

    /************************************************************************
    Function : Write to file
    Parameter: strFilePath the whole file path.
    hBitmap the bitmap memory
    return : if success return TRUE, otherwise return FALSE.
    ************************************************************************/
    BOOL SaveBitmapToFile(CString strFilePath,HBITMAP hBitmap)
    {
    HDC hdc = NULL;
    FILE* fp = NULL;
    LPVOID pBuf = NULL;
    BITMAPINFO bmpInfo;
    BITMAPFILEHEADER bmpFileHeader;

    do{
    	
    	hdc = ::GetDC(NULL);
    	ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
    	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);				
    	GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB\_RGB\_COLORS);
    	//bmpInfo.bmiHeader.biBitCount = 0x08;		// 8bit,when I use it ,bmp is invalid.
    	bmpInfo.bmiHeader.biBitCount = 0x10;		// 16
    
    	if(bmpInfo.bmiHeader.biSizeImage <= 0)
    		bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth\*abs(bmpInfo.bmiHeader.biHeight)\*(bmpInfo.bmiHeader.biBitCount+7)/8;
    	
    	if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL)
    	{
    		::MessageBox(NULL,\_T("Unable to Alloca
    
    O 1 Reply Last reply
    0
    • W wangningyu

      Hello everybody ! I wan't to save the bitmap to convert to a single color bitmap (8 pixel / Byte). I use this way to save to 16 color bitmap. how to convert it to single bitmap ,or how to save it from the device context first ?

      /************************************************************************
      Function : Screenshot
      Parameter: hwnd the window handle.
      lpRect the window rect.
      return : HBITMAP
      other : NULL
      ************************************************************************/
      HBITMAP GetWindowBitmap(HWND hwnd, LPRECT lpRect)
      {

       if( !lpRect )
            return NULL;
      
       HDC	hDC;
       HDC	hMemDC;
       HBITMAP	hBitmap = NULL;
       HBITMAP	hOldBitmap;
      
       if( hwnd == NULL )
           hDC = ::GetDC(HWND\_DESKTOP);
       else
           hDC = ::GetWindowDC(hwnd);
      
       if( hDC == NULL )
           return NULL;
      
       hMemDC  = CreateCompatibleDC(hDC);
       hBitmap = CreateCompatibleBitmap(hDC, lpRect->right - lpRect->left, 
       lpRect->bottom - lpRect->top);
      
       if( hBitmap == NULL)
           return NULL;
      
       hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
       BitBlt(hMemDC, 0, 0, lpRect->right - lpRect->left, 
       lpRect->bottom - lpRect->top, hDC, lpRect->left, lpRect->top, SRCCOPY);
      
       SelectObject(hMemDC, hOldBitmap);
       DeleteDC(hMemDC);
       ::ReleaseDC(hwnd, hDC);
      
       return hBitmap;
      

      }

      /************************************************************************
      Function : Write to file
      Parameter: strFilePath the whole file path.
      hBitmap the bitmap memory
      return : if success return TRUE, otherwise return FALSE.
      ************************************************************************/
      BOOL SaveBitmapToFile(CString strFilePath,HBITMAP hBitmap)
      {
      HDC hdc = NULL;
      FILE* fp = NULL;
      LPVOID pBuf = NULL;
      BITMAPINFO bmpInfo;
      BITMAPFILEHEADER bmpFileHeader;

      do{
      	
      	hdc = ::GetDC(NULL);
      	ZeroMemory(&bmpInfo,sizeof(BITMAPINFO));
      	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);				
      	GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB\_RGB\_COLORS);
      	//bmpInfo.bmiHeader.biBitCount = 0x08;		// 8bit,when I use it ,bmp is invalid.
      	bmpInfo.bmiHeader.biBitCount = 0x10;		// 16
      
      	if(bmpInfo.bmiHeader.biSizeImage <= 0)
      		bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth\*abs(bmpInfo.bmiHeader.biHeight)\*(bmpInfo.bmiHeader.biBitCount+7)/8;
      	
      	if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL)
      	{
      		::MessageBox(NULL,\_T("Unable to Alloca
      
      O Offline
      O Offline
      Ozer Karaagac
      wrote on last edited by
      #2

      You can do it by following way. First, you need storage space for color table as being palette entries.

      typedef struct tagBITMAPINFO_8BPP
      {
      BITMAPINFOHEADER bmiHeader;
      RGBQUAD bmiColors[256];
      } BITMAPINFO_8BPP;

      I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.

      ...
      LPVOID pBuf = NULL;
      BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
      BITMAPFILEHEADER bmpFileHeader;

      ...

      bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.

      ...

      bmpInfo.bmiHeader.biCompression = BI_RGB;
      GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
      pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);

      ...

      bmpFileHeader.bfReserved1 = 0;
      bmpFileHeader.bfReserved2 = 0;
      bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
      bmpInfo.bmiHeader.biSizeImage;
      bmpFileHeader.bfType = 'MB';
      bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);

      fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
      fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
      fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);

      ...

      W 2 Replies Last reply
      0
      • O Ozer Karaagac

        You can do it by following way. First, you need storage space for color table as being palette entries.

        typedef struct tagBITMAPINFO_8BPP
        {
        BITMAPINFOHEADER bmiHeader;
        RGBQUAD bmiColors[256];
        } BITMAPINFO_8BPP;

        I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.

        ...
        LPVOID pBuf = NULL;
        BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
        BITMAPFILEHEADER bmpFileHeader;

        ...

        bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.

        ...

        bmpInfo.bmiHeader.biCompression = BI_RGB;
        GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
        pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);

        ...

        bmpFileHeader.bfReserved1 = 0;
        bmpFileHeader.bfReserved2 = 0;
        bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
        bmpInfo.bmiHeader.biSizeImage;
        bmpFileHeader.bfType = 'MB';
        bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);

        fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
        fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
        fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);

        ...

        W Offline
        W Offline
        wangningyu
        wrote on last edited by
        #3

        thanks ! ;)

        1 Reply Last reply
        0
        • O Ozer Karaagac

          You can do it by following way. First, you need storage space for color table as being palette entries.

          typedef struct tagBITMAPINFO_8BPP
          {
          BITMAPINFOHEADER bmiHeader;
          RGBQUAD bmiColors[256];
          } BITMAPINFO_8BPP;

          I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.

          ...
          LPVOID pBuf = NULL;
          BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
          BITMAPFILEHEADER bmpFileHeader;

          ...

          bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.

          ...

          bmpInfo.bmiHeader.biCompression = BI_RGB;
          GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
          pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);

          ...

          bmpFileHeader.bfReserved1 = 0;
          bmpFileHeader.bfReserved2 = 0;
          bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
          bmpInfo.bmiHeader.biSizeImage;
          bmpFileHeader.bfType = 'MB';
          bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);

          fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
          fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
          fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);

          ...

          W Offline
          W Offline
          wangningyu
          wrote on last edited by
          #4

          There is two different with me: 1、RGBQUAD color table it used 256 count, but is "[1]" before. // why is it? 2、bmpInfo.bmiHeader.biBitCount = 0x01; // here is used 0x01 , means than is a single bitmap . I use the default RGBQUAD [1], and then set the biBitCount is 0x01, at last use the sam way to write to the file, but the bitmap is invalid. and then, you used RGBQUAD[256], the bitmap is right , why ? or this question may said: what's the color table in the bitmap file format ? (I google this ,but still don't quite understand.)

          O 1 Reply Last reply
          0
          • W wangningyu

            There is two different with me: 1、RGBQUAD color table it used 256 count, but is "[1]" before. // why is it? 2、bmpInfo.bmiHeader.biBitCount = 0x01; // here is used 0x01 , means than is a single bitmap . I use the default RGBQUAD [1], and then set the biBitCount is 0x01, at last use the sam way to write to the file, but the bitmap is invalid. and then, you used RGBQUAD[256], the bitmap is right , why ? or this question may said: what's the color table in the bitmap file format ? (I google this ,but still don't quite understand.)

            O Offline
            O Offline
            Ozer Karaagac
            wrote on last edited by
            #5

            bmiColors member of BITMAPINFO is variable sized array. Its size can be zero or more depending on other attributes such as biClrUsed, biBitCount and last parameter of GetDIBits() which can be DIB_PAL_COLORS or DIB_RGB_COLORS. BITMAPINFOHEADER[^] Excerpt from above link. If biCompression equals BI_RGB and the bitmap uses 8 bpp or less, the bitmap has a color table immediatelly following the BITMAPINFOHEADER structure. The color table consists of an array of RGBQUAD values. The size of the array is given by the biClrUsed member. If biClrUsed is zero, the array contains the maximum number of colors for the given bitdepth; that is, 2^biBitCount colors. In our case, 2 ^ 8 = 256 color table entries exist. You may also want to look at BITMAPINFO[^]. If bmpInfo.bmiHeader.biBitCount = 0x01; then it is a monochrome bitmap and color table will have two entries (e.g. RGB(0, 0, 0) and RGB(255, 255, 255)). Color table is array of colors used in the bitmap.

            1 Reply Last reply
            0
            Reply
            • Reply as topic
            Log in to reply
            • Oldest to Newest
            • Newest to Oldest
            • Most Votes


            • Login

            • Don't have an account? Register

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • World
            • Users
            • Groups