今天遇到一个问题,调试了一天都没有搞明白。任务是这样的:将一个bitmap图片放到一个DC里,然后获取这个DC里的某一点的RGB值。情况正如下:
调试的时候,上面执行都没有问题,问题是:
int a = pDC.GetPixel(currentBit, currentLine);
a的返回值是-1,无论怎么改,都是这个值。然后没有办法,只能google,有人说调试的时候调用GetPixel会出错。我试了一下正常模式下运行,竟然通过了。真是的,都怪平时太依赖调试模式了。
几天后的更新:
原来GetPixel调用时也是可以获取正确的值的,但是要使用CompatibleDC,代码如下:
这种情况下将断点设置在
GetPixel上就没有问题了,原因是使用CreateCompatibleDC生成的DC是设备无关的,只是放在内存里,使用GetPixel获取RGB值只是读内存,而不是读界面的颜色。
- CFilefile;//用于读取BMP文件
- BITMAPFILEHEADERbfhHeader;//bmp文件头
- BITMAPINFOHEADERbmiHeader;//bmp格式头
- LPBITMAPINFOlpBitmapInfo;//bmp格式具体信息
- intbmpWidth=0;//图片宽度
- intbmpHeight=0;//图片高度
- if(!file.Open(filePath,CFile::modeRead))
- return;//打开文件
- //读取文件头
- file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));
- if(bfhHeader.bfType!=((WORD)('M'<<8)|'B'))//判断是否是"BM"
- return;
- if(bfhHeader.bfSize!=file.GetLength())
- return;
- //读取位图信息
- if(file.Read((LPSTR)&bmiHeader,sizeof(bmiHeader))!=sizeof(bmiHeader))
- return;
- bmpHeight=bmiHeader.biHeight;//得到高度和宽度
- bmpWidth=bmiHeader.biWidth;
- file.SeekToBegin();//指针移动到文件的开头
- file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));
- UINTuBmpInfoLen=(UINT)bfhHeader.bfOffBits-sizeof(BITMAPFILEHEADER);//FileSize
- lpBitmapInfo=(LPBITMAPINFO)newBYTE[uBmpInfoLen];//具体信息分配内存
- file.Read((LPVOID)lpBitmapInfo,uBmpInfoLen);
- if((*(LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))
- return;
- DWORDdwBitlen=bfhHeader.bfSize-bfhHeader.bfOffBits;//图像数据的字节大小
- unsignedchar*lpSrcBits=newBYTE[dwBitlen];
- file.ReadHuge(lpSrcBits,dwBitlen);
- file.Close();//关闭文件
- //将文件数据加到DC里
- CClientDCpDC(this);
- //CClientDCpDC(&m_blackWhiteImage);
- //CDC*pDC=NULL;
- //HDCpDC=::CreateCompatibleDC(NULL);
- //::CreateCompatibleDC(pDC);
- intret=StretchDIBits(pDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,
- lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
调试的时候,上面执行都没有问题,问题是:
int a = pDC.GetPixel(currentBit, currentLine);
a的返回值是-1,无论怎么改,都是这个值。然后没有办法,只能google,有人说调试的时候调用GetPixel会出错。我试了一下正常模式下运行,竟然通过了。真是的,都怪平时太依赖调试模式了。
几天后的更新:
原来GetPixel调用时也是可以获取正确的值的,但是要使用CompatibleDC,代码如下:
- if(m_hBmp!=NULL)
- {
- DeleteObject(m_hBmp);
- }
- m_hBmp=(HBITMAP)LoadImage(AfxGetInstanceHandle(),
- imagePath,
- IMAGE_BITMAP,
- 0,
- 0,
- LR_LOADFROMFILE);
- if(m_hBmp==NULL)
- {
- AfxMessageBox("无法打开指定的黑底白框图!");
- return;
- }else
- {
- BITMAPbmp;
- GetObject(m_hBmp,sizeof(BITMAP),&bmp);
- m_bmHeight=bmp.bmHeight;//得到高度和宽度
- m_bmWidth=bmp.bmWidth;
- }
- selectBlock=-1;
- //将文件数据加到DC里
- //CClientDCpDC(this);
- CDCdc;
- dc.CreateCompatibleDC(NULL);
- if(dc==NULL)
- {
- AfxMessageBox("无法创建兼容DC");
- return;
- }
- HBITMAPhOldBmp=(HBITMAP)SelectObject(dc,m_hBmp);
- blocksCount=0;
- //遍历各行找矩形框左上角的坐标
- for(intcurrentLine=1;currentLine<m_bmHeight-1;currentLine++)
- {
- for(intcurrentBit=1;currentBit<m_bmWidth-1;currentBit++)
- {
- //优化(不是必须的),提高执行效率
- for(inti=0;i<blocksCount;i++)
- {
- if(currentLine>=blocks[i].pos.top&&
- currentLine<=blocks[i].pos.bottom&&
- currentBit>=blocks[i].pos.left&&
- currentBit<=blocks[i].pos.right)
- {
- currentBit=blocks[i].pos.right+1;
- }
- }
- if(0x00ffffff==dc.GetPixel(currentBit,currentLine)&&//自己是白点
- 0x00ffffff!=dc.GetPixel(currentBit,(currentLine-1))&&//上面是不是白点
- 0x00ffffff==dc.GetPixel(currentBit,(currentLine+1))&&//下面是白点
- 0x00ffffff!=dc.GetPixel((currentBit-1),currentLine)&&//左边是不是白点
- 0x00ffffff==dc.GetPixel((currentBit+1),currentLine))//右边是白点
- //找到一个左上角
- {
- blocks[blocksCount].pos.top=currentLine;
- blocks[blocksCount].pos.left=currentBit;
- //计算按钮的高和宽
- UINTbottom=currentLine;
- for(;;bottom++)
- {
- if(0x00ffffff!=dc.GetPixel(currentBit,bottom))
- break;
- }
- blocks[blocksCount].pos.bottom=bottom;
- UINTright=currentBit;
- for(;;right++)
- {
- if(0x00ffffff!=dc.GetPixel(right,currentLine))
- break;
- }
- blocks[blocksCount].pos.right=right;
- blocks[blocksCount].id=-1;
- blocksCount++;
- }
- }
- }
- if(blocksCount==0)
- {
- AfxMessageBox("无法检测到白框");
- }
- (HBITMAP)SelectObject(dc,hOldBmp);
- dc.DeleteDC();