bmp文件显示、翻转、灰化等操作 | 您所在的位置:网站首页 › bmp格式文件不可以使用什么 › bmp文件显示、翻转、灰化等操作 |
一 BMP文件格式
BMP(Bitmap)是Windows操作系统中的标准图像文件格式。 Windows的发布时机远早于Linux、Android、IOS等操作系统,Windows中相当多的标准数据格式和算法也是当今所有OS绕不开、必须兼容的数据结构和算法。 BMP是当前计算机中图像文件的标准文件格式,它是计算机图像学这门课程的必修课,研究BMP的意义也在于此。 BMP文件类型可以分成两类:设备相关位图(DDB)和设备无关位图(DIB)。 BMP相较于其他图像格式的特点: BMP文件不采用任何压缩。BMP是原始的像素数据的集合,文件格式简单易懂。图像的扫描方式是按从左到右、从下到上的顺序。兼容1、2、4、8、16、32位颜色模式。BMP文件从头到尾结构如下: 1. bmp文件头(BITMAPFILEHEADER结构) typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER, FAR*LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;bfType:’BM’两个可打印字符,用于标识BMP文件。 bfSize:文件大小 bfReserved1:保留,必须设置为0 bfReserved2:保留,必须设置为0 bfOffBits:从文件头到位图数据的偏移。一般来说,24位和32位的值是54(BITMAPINFOHEADER的大小+ BITMAPINFOHEADER的大小),而8位位图的值为1078(BITMAPINFOHEADER的大小+ BITMAPINFOHEADER的大小+颜色表的大小) 2 位图信息头(即BITMAPINFOHEADER结构) typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;biSize:信息头大小,即40字节 biWidth:以像素为单位图像的宽度 biHeight:以像素为单位图像的高度。如果为正,说明位图倒立(即数据表示从图像的左下角到右上角),如果为负说明正向 biPlanes:为目标设备说明颜色平面数,总被设置为1 biBitCount:bit/pixel,1、2、4、8、16、24、32 biCompression:图像的压缩类型,最常用的就是0(BI_RGB),表示不压缩 biSizeImages:4字节,说明位图数据的大小,当用BI_RGB格式时,可以设置为0 biXPelsPerMeter:表示水平分辨率,单位是像素/米,有符号整数 biYPelsPerMeter:表示垂直分辨率,单位是像素/米,有符号整数 biClrUsed:位图使用的调色板中的颜色索引数,为0说明使用所有 biClrImportant:对图像显示有重要影响的颜色索引数,为0说明都重要 另外需要注意的是,位图的每显示一行的扫描线长度总是4字节对齐的,计算方法是: (width* biBitCount&31+ width* biBitCount)/4,不足的要补0,否则会导致文件格式解析错误。 3. 调色板(只存在于8位位图, 即RGBQUAD[256]数组) typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGBQUAD;当位图是8bit时,像素值代表调色板的索引值。显示器很早就可以支持24位色,此模式主要用于减小文件大小和历史兼容性。显示8位位图的像素值时,在调色板中按照索引值找到调色板中索引对应的红黄蓝三颜色的值,在显示器上显示对应的该24位颜色值。 4.位图数据 即像素值。24位像素值按照red,green,blue顺序排列。32位色按照ALPHA,red,green,blue顺序排列,alpha值代表透明度。16位比较特殊,一般是按照5:6:5的顺序表示red,green,blue这3种颜色的值。 二 BMP位图像素操作 将24位位图转换为8位创建并在调色板中构造合适的24位颜色值,然后将24位(或者32位)位图的颜色值修改为调色板中的索引值。为了简单,代码中将颜色值修改为依此递增的白色。因为纯白色的颜色值为0xffffff(红绿蓝三色的值必须相等,否则将会呈现三者之中值较大的那种颜色,而且三者的值越大,越加趋向于纯白色),所以调色板中的24位色是从010101,020202,030303,…,ffffff依次递增的256种、从灰色到纯白色的颜色值。 原始图片如下: 结果示例: 涉及到的gamma矫正算法如下: 即将上述灰度颜色值取反后的结果。 若是颜色表中不是这种排序,将会导致的结果如下(以绿色蓝色分量为0为例子): 使用代码实现区域像素的平移、在bmp图像中画白色矩形的操作。 因为一般的bmp文件是倒序存放的,即显示时的第一行位于位图数据文件的最后一行,最后一行位于位图文件的第一行中。为了操作和计算方便,需要将位图中扫描线翻转,操作之后,再将像素的扫描线翻转回去。具体实现看代码。 区域平移效果示例: 使用的矩阵乘法,旋转15度。仅仅出于图形学演示效果,未做优化,所以效果不佳。 使用了如下矩阵实现像素旋转: ∣ n e w x n e w y ∣ = ∣ cos β − sin β sin β cos β ∣ ∣ x y ∣ \begin {vmatrix} new_x \\ new_y \end {vmatrix} = \begin {vmatrix} \cos \beta & -\sin \beta \\ \sin \beta& \cos \beta \end {vmatrix} \begin {vmatrix} x \\ y \end {vmatrix} newxnewy = cosβsinβ−sinβcosβ xy 图片合成:背景图: 使用如下算法: c o l o r = c o l o r ∗ a l p h a + c o l o r 2 ∗ ( 1 − a l p h a ) 0 < a l p h a < 1 color = color* alpha + color2*(1-alpha) \quad \quad 0biWidth*( bi->biBitCount/8); for (int j = 0;j biWidth;j++) { if (bi->biBitCount == 8) { } else if (bi->biBitCount == 16) { } else if (bi->biBitCount == 24) { ULONG v = line[j*3] + line[j*3 + 1] + line[j * 3 + 2]; nd[nd_size++] = v/3; } else if (bi->biBitCount == 32) { ULONG v = line[j * 4] + line[j * 4 + 1] + line[j * 4 + 2] + line[j * 4 + 3]; nd[nd_size++] =v/4; } } } nd_bi->biBitCount = 8; nd_bi->biSizeImage = bi->biHeight*bi->biWidth; nd_bf->bfSize = nd_size; nd_bf->bfOffBits += 1024; ret = FileHelper::fileWriter("mandrill_new.bmp", nd, nd_bf->bfSize,TRUE); char* framedata = new char[nd_bf->bfSize + 1024]; memcpy(framedata, nd, nd_bf->bfSize); reverseBmp(nd + nd_bf->bfOffBits, nd_bi->biHeight, nd_bi->biWidth); ret = FileHelper::fileWriter("mandrill_new_2.bmp", nd, nd_bf->bfSize, TRUE); frame(framedata + nd_bf->bfOffBits, nd_bi->biHeight, nd_bi->biWidth,100,50); ret = FileHelper::fileWriter("mandrill_new_3.bmp", framedata, nd_bf->bfSize, TRUE); char* rotatesrc = new char[bf->bfSize + 1024]; char* rotatedata = new char[bf->bfSize + 1024]; memcpy(rotatesrc, file, bf->bfSize); rotate(rotatesrc + bf->bfOffBits, bi->biHeight, bi->biWidth,bi->biBitCount/8, rotatedata); memcpy(rotatesrc + bf->bfOffBits, rotatedata, bi->biSizeImage); ret = FileHelper::fileWriter("mandrill_new_4.bmp", rotatesrc, bf->bfSize, TRUE); } } return 0; } int main() { int ret = 0; ret = mainproc(); return 0; } 工程代码如下: https://download.csdn.net/download/m0_37567738/88571695 注意:为防止某些版本的VS编译错误,编译时在“设置”->“c++”->“预处理器”->“预处理器定义”中添加” _CRT_SECURE_NO_WARNINGS” 三 参考链接 c++将24位bmp转8位bmp灰度, 8位bmp灰度反色,24位转3张8位bmp灰度图bmp文件结构 |
CopyRight 2018-2019 实验室设备网 版权所有 |