前军教程网

中小站长与DIV+CSS网页布局开发技术人员的首选CSS学习平台

Windows API操作BMP图像(4)对像素进行访问和修改

对BMP图像的操作,主要是对图像像素的访问。若图像信息头中的biHeight值大于0,则图像像素是从下到上,从左到右,按行顺序存储的,如图1.16 a)所示;若图像信息头中的biHeight值小于0,则图像像素是从上到下,从左到右,按行顺序存储的,如图1.16 b)所示。在存储的时候,必须保证每行的字节数为4的倍数,若每行的字节数不为4的倍数,则每行末尾补0。

大多数BMP图像的内存存储顺序是从第N行开始逆序存储的,即按照图1的顺序来存储图像像素。但是大多数OpenCV读取的视频图像内存存储顺序是从第一行开始顺序存储的,即按照图2的顺序存储图像;这时候在显示视频时候需要将位图信息头的biHeight值赋值为负数(如果赋值为正数,则显示的视频刚好上下颠倒),这一点在显示视频的时候需要特别注意。

在访问图像像素的时候,可以用一维指针来访问,指针的首地址指向图像像素的起始位置;也可以用二维指针来访问,二维指针的大小是图像的行数,二维指针里的每个元素指向的是图像一行数据的首地址。由于一维指针更容易分配和维护,因此下面用一维指针来访问图像数据。

以下以在24位真彩色图像中画矩形为例,来说明如何访问BMP图像数据。

BMP图像上绘制矩形

//功能:在24位真彩色BMP图像上画一个矩形线框
//输入:bmpHeader,BMP头;pBmpBits,图像像素指针
//输入:矩形左上角坐标(x1,y1)
//输入:矩形右下角坐标(x2,y2)
//输出:参数无误返回TRUE,否则返回FALSE
//输入:   r, g,b 矩形线框的RGB颜色值
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
bool DrawRectangle(const BITMAPINFO *bmpHeader,
       unsigned char *pBmpBits, int x1, int y1, int x2, int y2, int r, int g, int b)
{
  BITMAPINFOHEADER infoHdr = bmpHeader->bmiHeader;
  //每行像素个数
  int nWidth = infoHdr.biWidth;
  //像素行数,注意infoHdr.biHeight的值有可能为负数
  int nHeight = abs(infoHdr.biHeight);
  //每行字节数
  long nLineBytes = WIDTHBYTES(infoHdr.biWidth*infoHdr.biBitCount);
  if (x1 >= nWidth || x2 >= nWidth || x1 < 0 || x2 < 0)
 	 return false;
  if (y1 >= nHeight || y2 >= nHeight || y1 < 0 || y2 < 0)
  	return false;
  if (x1 > x2) return false;
  if (y1 > y2) return false;
  int nLeft = x1, nRight = x2;
  int nTop = 0, nBot = 0;
  //Y坐标要根据情况进行转换
  if (infoHdr.biHeight > 0) {
  	nTop = nHeight - y2; nBot = nHeight - y1;
  }
  else {
  	nTop = y1; nBot = y2;
  }
  int nIndex = 0;
  //垂直线
  for (int i = nTop; i < nBot; i++) {
    //左边
    nIndex = nLineBytes * i + nLeft * 3;
    pBmpBits[nIndex + 0] = b;
    pBmpBits[nIndex + 1] = g;
    pBmpBits[nIndex + 2] = r;
    //右边
    nIndex = nLineBytes * i + nRight * 3;
    pBmpBits[nIndex + 0] = b;
    pBmpBits[nIndex + 1] = g;
    pBmpBits[nIndex + 2] = r;
  }
  //水平线
  for (int i = nLeft; i <= nRight; i++) {
    //上边
    nIndex = nLineBytes * nTop + i * 3;
    pBmpBits[nIndex + 0] = b;
    pBmpBits[nIndex + 1] = g;
    pBmpBits[nIndex + 2] = r;
    //下边
    nIndex = nLineBytes * nBot + i * 3;
    pBmpBits[nIndex + 0] = b;
    pBmpBits[nIndex + 1] = g;
    pBmpBits[nIndex + 2] = r;
  }
  return true;
}

这里定义了一个宏WIDTHBYTES,用来确定BMP文件每行字节数。WIDTHBYTES宏输入的参数是每行像素所占用比特数,返回的是每行对应的字节数。

在Visual C++ 2017基于对话框的应用程序中,先调用ReadBMPFromFile()函数读取真彩色图像,然后调用DrawRectangle()函数绘制矩形,最后DisplayBMPImg()函数显示图像,其结果如下图3所示:

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言