使用GetPixel要注意

来源:互联网 发布:淘宝光威鱼竿有假的吗 编辑:程序博客网 时间:2024/06/04 20:08
今天遇到一个问题,调试了一天都没有搞明白。任务是这样的:将一个bitmap图片放到一个DC里,然后获取这个DC里的某一点的RGB值。情况正如下:
  1.     CFile file;         //用于读取BMP文件
  2.     
  3.     BITMAPFILEHEADER bfhHeader;     //bmp文件头
  4.     BITMAPINFOHEADER bmiHeader;     //bmp格式头
  5.     LPBITMAPINFO lpBitmapInfo;      //bmp格式具体信息
  6.     int bmpWidth=0;                 //图片宽度
  7.     int bmpHeight = 0;              //图片高度
  8.     
  9.     if( !file.Open( filePath, CFile::modeRead ) )
  10.         return ;                              //打开文件
  11.     
  12.     //读取文件头
  13.     file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));
  14.     if(bfhHeader.bfType!=((WORD) ('M'<<8)|'B'))   //判断是否是"BM"
  15.         return ;
  16.     if(bfhHeader.bfSize!=file.GetLength())
  17.         return ;
  18.     
  19.     //读取位图信息
  20.     if (file.Read((LPSTR)&bmiHeader, sizeof(bmiHeader)) != sizeof(bmiHeader))
  21.         return ;
  22.     bmpHeight = bmiHeader.biHeight; //得到高度和宽度
  23.     bmpWidth = bmiHeader.biWidth;
  24.     
  25.     file.SeekToBegin(); //指针移动到文件的开头
  26.     file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER)); 
  27.     UINT uBmpInfoLen=(UINT) bfhHeader.bfOffBits-sizeof(BITMAPFILEHEADER);//File Size
  28.     
  29.     lpBitmapInfo=(LPBITMAPINFO) new BYTE[uBmpInfoLen]; //具体信息分配内存
  30.     
  31.     file.Read((LPVOID) lpBitmapInfo,uBmpInfoLen);
  32.     if((* (LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))
  33.         return ;
  34.     DWORD dwBitlen = bfhHeader.bfSize - bfhHeader.bfOffBits;//图像数据的字节大小
  35.     unsigned char *lpSrcBits=new BYTE[dwBitlen];
  36.     file.ReadHuge(lpSrcBits,dwBitlen);
  37.     file.Close();       //关闭文件
  38.     
  39.     //将文件数据加到DC里
  40.     CClientDC  pDC(this);
  41.     //CClientDC  pDC(&m_blackWhiteImage);
  42.     //CDC* pDC  = NULL;
  43.     //HDC   pDC = ::CreateCompatibleDC( NULL );
  44.     //::CreateCompatibleDC(pDC); 
  45.     int ret = StretchDIBits(pDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,
  46.                             lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);

调试的时候,上面执行都没有问题,问题是:

int a = pDC.GetPixel(currentBit, currentLine);

a的返回值是-1,无论怎么改,都是这个值。然后没有办法,只能google,有人说调试的时候调用GetPixel会出错。我试了一下正常模式下运行,竟然通过了。真是的,都怪平时太依赖调试模式了。


几天后的更新:
原来GetPixel调用时也是可以获取正确的值的,但是要使用CompatibleDC,代码如下:
  1.     if ( m_hBmp != NULL)
  2.     {
  3.         DeleteObject(m_hBmp);
  4.     }
  5.     m_hBmp = (HBITMAP)LoadImage(AfxGetInstanceHandle(), 
  6.                                 imagePath,
  7.                                 IMAGE_BITMAP,
  8.                                 0,
  9.                                 0,
  10.                                 LR_LOADFROMFILE);
  11.     if ( m_hBmp == NULL )
  12.     {
  13.         AfxMessageBox("无法打开指定的黑底白框图!");
  14.         return;
  15.     }else
  16.     {
  17.         BITMAP bmp;
  18.         GetObject(m_hBmp, sizeof(BITMAP), &bmp);
  19.         m_bmHeight = bmp.bmHeight; //得到高度和宽度
  20.         m_bmWidth = bmp.bmWidth;    
  21.     }
  22.     selectBlock = -1;
  23.     //将文件数据加到DC里
  24.     //CClientDC  pDC(this);
  25.     CDC dc;
  26.     dc.CreateCompatibleDC( NULL );
  27.     if ( dc == NULL )
  28.     {
  29.         AfxMessageBox("无法创建兼容DC");
  30.         return;
  31.     }
  32.     HBITMAP hOldBmp = (HBITMAP)SelectObject(dc, m_hBmp);
  33.     blocksCount = 0;
  34.     //遍历各行找矩形框左上角的坐标
  35.     for(int currentLine = 1; currentLine < m_bmHeight - 1; currentLine++)
  36.     {
  37.         for(int currentBit = 1; currentBit < m_bmWidth - 1; currentBit++)
  38.         {
  39.             //优化(不是必须的),提高执行效率
  40.             for ( int i = 0; i < blocksCount; i++ )
  41.             {
  42.                 if (currentLine >= blocks[i].pos.top &&
  43.                     currentLine <= blocks[i].pos.bottom &&
  44.                     currentBit >= blocks[i].pos.left &&
  45.                     currentBit <= blocks[i].pos.right)
  46.                 {
  47.                     currentBit = blocks[i].pos.right + 1;
  48.                 }
  49.             }
  50.             if ( 0x00ffffff == dc.GetPixel(currentBit, currentLine) &&        //自己是白点
  51.                  0x00ffffff != dc.GetPixel(currentBit, (currentLine - 1)) &&  //上面是不是白点
  52.                  0x00ffffff == dc.GetPixel(currentBit, (currentLine + 1)) &&  //下面是白点
  53.                  0x00ffffff != dc.GetPixel((currentBit - 1), currentLine) &&  //左边是不是白点
  54.                  0x00ffffff == dc.GetPixel((currentBit + 1), currentLine) )   //右边是白点
  55.             //找到一个左上角
  56.             {
  57.                 blocks[blocksCount].pos.top = currentLine;
  58.                 blocks[blocksCount].pos.left = currentBit;
  59.                 //计算按钮的高和宽
  60.                 UINT bottom = currentLine;
  61.                 for(;;bottom++)
  62.                 {
  63.                     if (0x00ffffff != dc.GetPixel(currentBit, bottom))
  64.                         break;
  65.                 }
  66.                 blocks[blocksCount].pos.bottom = bottom;
  67.                 UINT right = currentBit;
  68.                 for(;;right++)
  69.                 {
  70.                     if (0x00ffffff != dc.GetPixel(right, currentLine))
  71.                         break;
  72.                 } 
  73.                 blocks[blocksCount].pos.right = right;
  74.                 blocks[blocksCount].id = -1;
  75.                 blocksCount++;
  76.             }
  77.         }
  78.     }
  79.     if ( blocksCount == 0 )
  80.     {
  81.         AfxMessageBox("无法检测到白框");
  82.     }
  83.     (HBITMAP)SelectObject(dc, hOldBmp);
  84.     dc.DeleteDC();
这种情况下将断点设置在GetPixel上就没有问题了,原因是使用CreateCompatibleDC生成的DC是设备无关的,只是放在内存里,使用GetPixel获取RGB值只是读内存,而不是读界面的颜色。
原创粉丝点击