两类DIB图片需要辨析的地方

来源:互联网 发布:地狱之歌ova知乎 编辑:程序博客网 时间:2024/06/05 20:25

在做通过鼠标设置ROI并对其进行阈值化功能的时候,发现处理的图像区域总是与我用鼠标设置的区域上下颠倒,源代码如下:

for (UINT i=rc.bottom; i<rc.top; i++){for (UINT j=3*rc.left; j<3*rc.right; j=j+3){//在BMP图片中颜色顺序为BGR//color=red*0.299+green*0.587+blue*0.144;  *(pImgData + i*lineByte + j) = (*(pImgData + i*lineByte + j))*0.114 +(*(pImgData + i*lineByte + j + 1))*0.587 + (*(pImgData + i*lineByte + j + 2))*0.299;int blue = *(pImgData + i*lineByte + j);if (blue < thresholValue){*(pImgData + i*lineByte + j) = 0;}else{*(pImgData + i*lineByte + j) = 255;}*(pImgData + i*lineByte + j + 1) = (*(pImgData + i*lineByte + j));int green = *(pImgData + i*lineByte + j + 1);if (green < thresholValue){*(pImgData + i*lineByte + j + 1) = 0;}else{*(pImgData + i*lineByte + j + 1) = 255;}*(pImgData + i*lineByte + j + 2) = (*(pImgData + i*lineByte + j));int red = *(pImgData + i*lineByte + j + 2);if (red < thresholValue){*(pImgData + i*lineByte + j + 2) = 0;}else{*(pImgData + i*lineByte + j + 2) = 255;}}}
其中rc为是我在MFC定义的一个CRect的类,其矩形的始末点由鼠标左键按下和左键抬起的位置的坐标点,这个鼠标的坐标点实际上是使用了MFC中的CPoint类的坐标,该坐标的坐标系原点在窗口的左上角。正在当我百思不得其解的时候,我在foreverhuylee《位图结构解析》博文中看出了点端倪,原因如下:

DIB位图也有两种形式,即:底到上型DIB(bottom-up),和顶到下型DIB(top-down)。底到上型DIB的原点(origin)在图像的左下角,而顶到下型DIB的原点在图像的左上角。如果DIB的高度值(由BITMAPINFOHEADER结构中的biHeight成员标识)是一个正值,那么就表明这个DIB是一个底到上型DIB,如果高度值是一个负值,那么它就是一个顶到下型DIB。注意:顶到下型的DIB位图是不能被压缩的。

由上可知,其实我使用到的BMP图片都是属于“底到上型”的,即其数据读取都是从下到上,由左至右的,说白了就是其坐标原点在左下角和我们用CRect截取的矩形坐标(原点在左上角)是不同的,即X轴坐标相同,而Y轴不同,用图片的高度减去矩形的高度就能让两者的坐标同步,故修改后的代码如下:

for (UINT i=(bmpInfo.biHeight-rc.bottom); i<(bmpInfo.biHeight-rc.top); i++){for (UINT j=3*rc.left; j<3*rc.right; j=j+3){//在BMP图片中颜色顺序为BGR//color=red*0.299+green*0.587+blue*0.144;  *(pImgData + i*lineByte + j) = (*(pImgData + i*lineByte + j))*0.114 +(*(pImgData + i*lineByte + j + 1))*0.587 + (*(pImgData + i*lineByte + j + 2))*0.299;int blue = *(pImgData + i*lineByte + j);if (blue < thresholValue){*(pImgData + i*lineByte + j) = 0;}else{*(pImgData + i*lineByte + j) = 255;}*(pImgData + i*lineByte + j + 1) = (*(pImgData + i*lineByte + j));int green = *(pImgData + i*lineByte + j + 1);if (green < thresholValue){*(pImgData + i*lineByte + j + 1) = 0;}else{*(pImgData + i*lineByte + j + 1) = 255;}*(pImgData + i*lineByte + j + 2) = (*(pImgData + i*lineByte + j));int red = *(pImgData + i*lineByte + j + 2);if (red < thresholValue){*(pImgData + i*lineByte + j + 2) = 0;}else{*(pImgData + i*lineByte + j + 2) = 255;}}}
此时,已经完成我最初对程序的设想,即使用鼠标设置ROI并对该区域进行阈值化。