none
How to develop a code to find lowest rgb on bitmap image in certain area in mfc RRS feed

  • Question

  • Dear Sir,

    How to find lowest RGB value over bitmap image using vc++

    Thanks

    Shyamsunder Reddi

    • Moved by Amanda Zhu Sunday, August 4, 2013 3:36 AM
    Friday, August 2, 2013 10:37 AM

Answers

  • Hi Shyamsunder Reddi,

    You can try the following steps:

    First,use the CBitmap Class and LoadImage function to load the bitmap image.

    second,use the CDC Class   and SetPixel Method to get the information of this bitmap.

    Then,use the Min Function to find lowest RGB value.

    Here is the code you can refer to:

    void CCreateRandomBMPDlg::OnBtnTest() 
    { 
     // TODO: Add your control notification handler code here 
     HBITMAP hBmp; 
     CFileDialog dlg(TRUE,"bmp",NULL,0,"bitmapfile (*.bmp)|*.bmp||",this);
     if(dlg.DoModal() != IDOK) 
     {  
      return; 
     }
    
    HBITMAP hBmp = (HBITMAP)LoadImage(NULL,dlg.GetPathName(),IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); 
     if(hBmp == NULL) 
     { 
      return; 
     }
    
     BITMAP bm; 
     PBITMAPINFO bmpInf; 
     if(GetObject(hBmp,sizeof(bm),&bm)==0) 
      return ; 
    
     int nPaletteSize=0; 
     if(bm.bmBitsPixel<16) 
      nPaletteSize=(int)pow(2,bm.bmBitsPixel); 
     bmpInf=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+ sizeof(RGBQUAD)*nPaletteSize); 
    
     //----------------------------------------------- 
     bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
     bmpInf->bmiHeader.biWidth = bm.bmWidth; 
     bmpInf->bmiHeader.biHeight = bm.bmHeight; 
     bmpInf->bmiHeader.biPlanes = bm.bmPlanes; 
     bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel; 
     bmpInf->bmiHeader.biCompression = BI_RGB; 
     bmpInf->bmiHeader.biSizeImage = (bm.bmWidth+7)/8*bm.bmHeight*bm.bmBitsPixel; 
     bmpInf->bmiHeader.biXPelsPerMeter = 0; 
     bmpInf->bmiHeader.biYPelsPerMeter = 0; 
     bmpInf->bmiHeader.biClrUsed = 0; 
     bmpInf->bmiHeader.biClrImportant = 0; 
     //----------------------------------------------- 
    
     HDC hDC = ::GetWindowDC(NULL); 
     if(!::GetDIBits(hDC,hBmp,0,(WORD)bm.bmHeight,NULL,bmpInf,DIB_RGB_COLORS)) 
     { 
      LocalFree(bmpInf); 
      ::ReleaseDC(NULL,hDC); 
      return ; 
     }
     void* buf=(void*) new char[bmpInf->bmiHeader.biSizeImage]; 
     if(buf==NULL) 
     { 
      ::ReleaseDC(NULL,hDC); 
      LocalFree(bmpInf); 
      return ; 
     }
     if(!::GetDIBits(hDC,hBmp,0,(UINT)bm.bmHeight,buf,bmpInf,DIB_RGB_COLORS)) 
     { 
      ::ReleaseDC(NULL,hDC); 
      delete []buf; 
      LocalFree(bmpInf); 
      return ; 
     } 
     ::ReleaseDC(NULL,hDC);
    
     CString sMsg; 
     sMsg.Format("BitsPixel:%d,width:%d,height:%d", bm.bmBitsPixel,bm.bmWidth,bm.bmHeight); 
     AfxMessageBox(sMsg);
    
     CClientDC dc(this); 
     if(bm.bmBitsPixel == 8) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth; 
      while(nWidth %4 != 0) 
      {
       nWidth++; 
      } 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        RGBQUAD rgbQ; 
        rgbQ = bmpInf->bmiColors[pData[i*nWidth+j]]; 
        dc.SetPixel(j,bm.bmHeight-i,RGB(rgbQ.rgbRed,rgbQ.rgbGreen,rgbQ.rgbBlue)); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 16) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*2; 
      while(nWidth %4 != 0) 
      { 
       nWidth++; 
      } 
      BYTE red,green,blue; 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        blue = pData[i*nWidth+j*2]&0x1F; 
        green = pData[i*nWidth+j*2]>>5; 
        green |= (pData[i*nWidth+j*2+1]&0x03)<<3; 
        red = (pData[i*nWidth+j*2+1]>>2)&0x1F; 
        WORD wRed = red*8; 
        WORD wBlue = blue*8; 
        WORD wGreen = green*8; 
        red = min(255,wRed); 
        blue = min(255,wBlue); 
        green = min(255,wGreen); 
        dc.SetPixel(j,bm.bmHeight-i,RGB(red,green,blue)); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 24) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*3; 
      while(nWidth %4 != 0) 
      { 
       nWidth++; 
      } 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        dc.SetPixel(j,bm.bmHeight-i, 
         RGB(pData[i*nWidth+j*3+2], 
         pData[i*nWidth+j*3+1], 
         pData[i*nWidth+j*3])); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 32) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*4; 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j< bm.bmWidth; j++) 
       { 
         dc.SetPixel(j,bm.bmHeight-i, 
         RGB(pData[i*nWidth+j*4+2], 
         pData[i*nWidth+j*4+1], 
         pData[i*nWidth+j*4])); 
       } 
      } 
     }
    
     delete []buf; 
     DeleteObject(hBmp); 
     LocalFree(bmpInf); 
    }
    
    

    Best Regards.


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Sunday, August 4, 2013 6:44 AM

All replies

  • Hello,

    I have moved this thread to Visual C++ forum for better response.

    Best regards,


    Amanda Zhu
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Sunday, August 4, 2013 3:36 AM
  • There is no shortcut.  You have to write code to iterate through every pixel.  However, before you do that, you have to figure out what you mean by "lowest RGB value".  An RGB pixel is a vector of 3 values, so you can't just do a simple integer comparison, because that you have (1,255,255) compute as less than (2,0,0).  One reasonable approach is to use the black-and-white brightness of the pixel, and you can get a close approximation by using 2xR + 4xG + B.

    So, if I have a byte pointer pointing to the bits of a 24-bit DIB, I could use something like this:

        unsigned char *pj = PointerToBytes;
        int minX = -1;
        int minY = -1;
        int minBright = 99999;
        for( int y = 0; y < Height; y++ )
            for( int x = 0; x < Width; x++, pj += 3 )
            {
                int bright = pj[0] + 4*pj[1] + 2*pj[2];
                if( bright < minBright )
                {
                    minX = x;
                    minY = y;
                    minBright = bright;
                }
            }
    

    I'm assuming there's no scanline padding here. 


    Tim Roberts, VC++ MVP Providenza & Boekelheide, Inc.

    Sunday, August 4, 2013 6:09 AM
  • Hi Shyamsunder Reddi,

    You can try the following steps:

    First,use the CBitmap Class and LoadImage function to load the bitmap image.

    second,use the CDC Class   and SetPixel Method to get the information of this bitmap.

    Then,use the Min Function to find lowest RGB value.

    Here is the code you can refer to:

    void CCreateRandomBMPDlg::OnBtnTest() 
    { 
     // TODO: Add your control notification handler code here 
     HBITMAP hBmp; 
     CFileDialog dlg(TRUE,"bmp",NULL,0,"bitmapfile (*.bmp)|*.bmp||",this);
     if(dlg.DoModal() != IDOK) 
     {  
      return; 
     }
    
    HBITMAP hBmp = (HBITMAP)LoadImage(NULL,dlg.GetPathName(),IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION); 
     if(hBmp == NULL) 
     { 
      return; 
     }
    
     BITMAP bm; 
     PBITMAPINFO bmpInf; 
     if(GetObject(hBmp,sizeof(bm),&bm)==0) 
      return ; 
    
     int nPaletteSize=0; 
     if(bm.bmBitsPixel<16) 
      nPaletteSize=(int)pow(2,bm.bmBitsPixel); 
     bmpInf=(PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)+ sizeof(RGBQUAD)*nPaletteSize); 
    
     //----------------------------------------------- 
     bmpInf->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
     bmpInf->bmiHeader.biWidth = bm.bmWidth; 
     bmpInf->bmiHeader.biHeight = bm.bmHeight; 
     bmpInf->bmiHeader.biPlanes = bm.bmPlanes; 
     bmpInf->bmiHeader.biBitCount = bm.bmBitsPixel; 
     bmpInf->bmiHeader.biCompression = BI_RGB; 
     bmpInf->bmiHeader.biSizeImage = (bm.bmWidth+7)/8*bm.bmHeight*bm.bmBitsPixel; 
     bmpInf->bmiHeader.biXPelsPerMeter = 0; 
     bmpInf->bmiHeader.biYPelsPerMeter = 0; 
     bmpInf->bmiHeader.biClrUsed = 0; 
     bmpInf->bmiHeader.biClrImportant = 0; 
     //----------------------------------------------- 
    
     HDC hDC = ::GetWindowDC(NULL); 
     if(!::GetDIBits(hDC,hBmp,0,(WORD)bm.bmHeight,NULL,bmpInf,DIB_RGB_COLORS)) 
     { 
      LocalFree(bmpInf); 
      ::ReleaseDC(NULL,hDC); 
      return ; 
     }
     void* buf=(void*) new char[bmpInf->bmiHeader.biSizeImage]; 
     if(buf==NULL) 
     { 
      ::ReleaseDC(NULL,hDC); 
      LocalFree(bmpInf); 
      return ; 
     }
     if(!::GetDIBits(hDC,hBmp,0,(UINT)bm.bmHeight,buf,bmpInf,DIB_RGB_COLORS)) 
     { 
      ::ReleaseDC(NULL,hDC); 
      delete []buf; 
      LocalFree(bmpInf); 
      return ; 
     } 
     ::ReleaseDC(NULL,hDC);
    
     CString sMsg; 
     sMsg.Format("BitsPixel:%d,width:%d,height:%d", bm.bmBitsPixel,bm.bmWidth,bm.bmHeight); 
     AfxMessageBox(sMsg);
    
     CClientDC dc(this); 
     if(bm.bmBitsPixel == 8) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth; 
      while(nWidth %4 != 0) 
      {
       nWidth++; 
      } 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        RGBQUAD rgbQ; 
        rgbQ = bmpInf->bmiColors[pData[i*nWidth+j]]; 
        dc.SetPixel(j,bm.bmHeight-i,RGB(rgbQ.rgbRed,rgbQ.rgbGreen,rgbQ.rgbBlue)); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 16) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*2; 
      while(nWidth %4 != 0) 
      { 
       nWidth++; 
      } 
      BYTE red,green,blue; 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        blue = pData[i*nWidth+j*2]&0x1F; 
        green = pData[i*nWidth+j*2]>>5; 
        green |= (pData[i*nWidth+j*2+1]&0x03)<<3; 
        red = (pData[i*nWidth+j*2+1]>>2)&0x1F; 
        WORD wRed = red*8; 
        WORD wBlue = blue*8; 
        WORD wGreen = green*8; 
        red = min(255,wRed); 
        blue = min(255,wBlue); 
        green = min(255,wGreen); 
        dc.SetPixel(j,bm.bmHeight-i,RGB(red,green,blue)); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 24) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*3; 
      while(nWidth %4 != 0) 
      { 
       nWidth++; 
      } 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j<bm.bmWidth; j++) 
       { 
        dc.SetPixel(j,bm.bmHeight-i, 
         RGB(pData[i*nWidth+j*3+2], 
         pData[i*nWidth+j*3+1], 
         pData[i*nWidth+j*3])); 
       } 
      } 
     } 
     else if(bm.bmBitsPixel == 32) 
     { 
      BYTE *pData = (BYTE*)buf; 
      int nWidth = bm.bmWidth*4; 
      for(int i=0; i<bm.bmHeight; i++) 
      { 
       for(int j=0; j< bm.bmWidth; j++) 
       { 
         dc.SetPixel(j,bm.bmHeight-i, 
         RGB(pData[i*nWidth+j*4+2], 
         pData[i*nWidth+j*4+1], 
         pData[i*nWidth+j*4])); 
       } 
      } 
     }
    
     delete []buf; 
     DeleteObject(hBmp); 
     LocalFree(bmpInf); 
    }
    
    

    Best Regards.


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Sunday, August 4, 2013 6:44 AM
  • We have verified the above code, which i reply back from Mr.Jane wang, But the above code is getting the No.Bits per pixel , Image Width and Image Height, But we want to get the lowest RGB value on bitmap image on certain area, So kindly help us out from the following issue

    Thanks

    Shyamsunder Reddi


    Monday, August 5, 2013 12:27 PM
  • Hi Shyamsunder Reddi,

    Thank you for your feedback.

    I want to clarify that I have not tested the code above yet.I put it here is just as a referance to what I have suggested.

    If you want to get the lowest RGB value on bitmap image on certain area in MFC,while the comparision function does not help,please try to find other ways to realize your program.

    Best Regards.


    Jane Wang
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, August 6, 2013 1:02 PM