龙空技术网

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

klogin 67

前言:

目前姐妹们对“c语言读取bmp像素”大概比较看重,兄弟们都想要剖析一些“c语言读取bmp像素”的相关资讯。那么小编同时在网络上搜集了一些有关“c语言读取bmp像素””的相关资讯,希望姐妹们能喜欢,同学们一起来了解一下吧!

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

图1. biHeight>0时BMP图像在内存中的存储顺序

图2. biHeight<0时BMP图像在内存中的存储顺序

大多数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所示:

图像显示结果

标签: #c语言读取bmp像素