BMP图像的读写(8位和24位)
8位、24位、32位图像数据转换

8位、24位、32位图像数据转换最近调⽤⼀个⼈体检测算法,算法要求输⼊的是图⽚的BGR数据,但是拿到的数据是32位Argb数据,算法⽆法正确进⾏⼈体检测,从⽹上百度⽂库中搜到⼀个C#代码,可以进⾏转换。
⽹上的代码有点乱,整理了⼀下,记录留存。
整理后的代码如下:1class BitmapConvertHelp2 {3struct BitmapFileHeader4 {5//位图⽂件头6public UInt16 bfType;7public UInt32 bfSize;8public UInt16 bfReserved1;9public UInt16 bfReserved2;10public UInt32 bfOffBits;11 }1213struct BitmapInfoHeader14 {15//位图信息头16public UInt32 biSize;17public UInt32 biWidth;18public UInt32 biHeight;19public UInt16 biPlanes;20public UInt16 biBitCount;21public UInt32 biCompression;22public UInt32 biSizeImage;23public UInt32 biXPelsPerMeter;24public UInt32 biYPelsPerMeter;25public UInt32 biClrUsed;26public UInt32 biClrImportant;27 }2829struct RGBQUAD30 {31//位图调⾊板项32public byte rgbBlue;33public byte rgbGreen;34public byte rgbRed;35public byte rgbReserved;36 }3738private string filepath = null;//需打开的位图的路径39private string savepath = null;//转换后位图的保存路径40private BitmapFileHeader bfh;41private BitmapInfoHeader bih;4243private void Save8Bits(Bitmap bmp)44 {45//为位图⽂件头赋值46 bfh.bfOffBits = 1078;47 bfh.bfReserved1 = 0;48 bfh.bfReserved2 = 0;49 bfh.bfSize = 14;50 bfh.bfType = 19778;51//为位图信息头赋值52 bih.biBitCount = 8;53 bih.biClrImportant = 0;54 bih.biClrUsed = 0;55 bih.biCompression = 0;56 bih.biHeight = (uint)bmp.Height;57 bih.biPlanes = 1;58 bih.biSize = 40;59 bih.biSizeImage = (uint)(bmp.Height * ((bmp.Width * 8 + 31) / 32 * 4));60 bih.biWidth = (uint)bmp.Width;61 bih.biXPelsPerMeter = 0;62 bih.biYPelsPerMeter = 0;63//构造256⾊的调⾊板,⾮索引图64 RGBQUAD[] pal = new RGBQUAD[256];65for (int i = 0; i < 256; i++)66 {67 pal[i].rgbBlue = (byte)i;68 pal[i].rgbGreen = (byte)i;69 pal[i].rgbRed = (byte)i;70 pal[i].rgbReserved = 0;71 }72 FileInfo f = new FileInfo(savepath);73using (BinaryWriter bw = new BinaryWriter(f.OpenWrite()))74 {75//写⼊⽂件头76 bw.Write(bfh.bfType);77 bw.Write(bfh.bfSize);78 bw.Write(bfh.bfReserved1);79 bw.Write(bfh.bfReserved2);80 bw.Write(bfh.bfOffBits);81//写⼊信息头82 bw.Write(bih.biSize);83 bw.Write(bih.biWidth);84 bw.Write(bih.biHeight);85 bw.Write(bih.biPlanes);86 bw.Write(bih.biBitCount);87 bw.Write(bih.biCompression);88 bw.Write(bih.biSizeImage);89 bw.Write(bih.biXPelsPerMeter);90 bw.Write(bih.biYPelsPerMeter);91 bw.Write(bih.biClrUsed);92 bw.Write(bih.biClrImportant);93//写⼊调⾊板94for (int i = 0; i < 256; i++)95 {96 bw.Write(pal[i].rgbBlue);97 bw.Write(pal[i].rgbGreen);98 bw.Write(pal[i].rgbRed);99 bw.Write(pal[i].rgbReserved);100 }101//位图上下翻转102 bmp.RotateFlip(RotateFlipType.Rotate180FlipX);103 BitmapData data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 104unsafe105 {106byte* ptr = (byte*)data.Scan0.ToPointer();107//位图的指针108109byte[] line = new byte[data.Stride];110//保存位图的⼀⾏111for (int i = 0; i < data.Stride; i++)112 line[i] = 0;113for (int i = 0; i < bmp.Height; i++)114 {115for (int j = 0; j < bmp.Width; j++)116 {117 line[j] = *ptr++;118 }119 ptr += data.Stride - bmp.Width;//指针跳过对齐的字节120 bw.Write(line, 0, line.Length);//写⼊位图的⼀⾏121 }122 }123 bw.Close();124 bmp.UnlockBits(data);125 }126 }127128public void Bit8To24()129 {130 Bitmap bmp8 = new Bitmap(filepath);131 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 132 Bitmap bmp24 = new Bitmap(bmp8.Width, bmp8.Height, PixelFormat.Format24bppRgb);133 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 134unsafe135 {136byte* ptr8 = (byte*)data8.Scan0.ToPointer();137byte* ptr24 = (byte*)data24.Scan0.ToPointer();138for (int i = 0; i < bmp8.Height; i++)139 {140for (int j = 0; j < bmp8.Width; j++)141 {142//⽤8位位图的灰度值填充24位位图的R、G、B值143 *ptr24++ = *ptr8;144 *ptr24++ = *ptr8;145 *ptr24++ = *ptr8++;146 }147 ptr8 += data8.Stride - bmp8.Width; //跳过对齐字节148 ptr24 += data24.Stride - bmp8.Width * 3; //跳过对齐字节149 }150 }151 bmp8.UnlockBits(data8);152 bmp24.UnlockBits(data24);153 bmp24.Save(savepath);154 }155156public void Bit8To32()157 {158 Bitmap bmp8 = new Bitmap(filepath);159 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 160 Bitmap bmp32 = new Bitmap(bmp8.Width, bmp8.Height, PixelFormat.Format32bppArgb);161 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 162163unsafe164 {165byte* ptr8 = (byte*)data8.Scan0.ToPointer();166byte* ptr32 = (byte*)data32.Scan0.ToPointer();167for (int i = 0; i < bmp8.Height; i++)168 {169for (int j = 0; j < bmp8.Width; j++)170 {171//⽤8位位图的灰度值,填充32位位图的RGB值,透明度为100%172 *ptr32++ = *ptr8;173 *ptr32++ = *ptr8;174 *ptr32++ = *ptr8++;175 *ptr32++ = 255;176 }177 ptr8 += data8.Stride - bmp8.Width;178 ptr32 += data32.Stride - bmp8.Width * 4;179 }180 }181 bmp8.UnlockBits(data8);182 bmp32.UnlockBits(data32);183 bmp32.Save(savepath);184 }185186public void Bit24To8()187 {188 Bitmap bmp24 = new Bitmap(filepath);189 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 190 Bitmap bmp8 = new Bitmap(bmp24.Width, bmp24.Height, PixelFormat.Format8bppIndexed);191 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 192193unsafe194 {195byte* ptr24 = (byte*)data24.Scan0.ToPointer();196byte* ptr8 = (byte*)data8.Scan0.ToPointer();197for (int i = 0; i < bmp8.Height; i++)198 {199for (int j = 0; j < bmp8.Width; j++)200 {201//⽤RGB值的均值作为8位位图的灰度值202 *ptr8++=(byte)(((int)(*ptr24++)+(int)(*ptr24++)+(int)(*ptr24++))/3);203 }204 ptr24 += data24.Stride - bmp8.Width * 3;205 ptr8 += data8.Stride - bmp8.Width;206 }207 }208 bmp8.UnlockBits(data8);209 bmp24.UnlockBits(data24);210 Save8Bits(bmp8);211 }212213public void Bit32To8()214 {215 Bitmap bmp32 = new Bitmap(filepath);216 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 217 Bitmap bmp8 = new Bitmap(bmp32.Width, bmp32.Height, PixelFormat.Format8bppIndexed);218 BitmapData data8 = bmp8.LockBits(new Rectangle(0, 0, bmp8.Width, bmp8.Height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 219unsafe220 {221byte* ptr32 = (byte*)data32.Scan0.ToPointer();222223byte* ptr8 = (byte*)data8.Scan0.ToPointer();224for (int i = 0; i < bmp8.Height; i++)225 {226for (int j = 0; j < bmp8.Width; j++)227 {228//⽤32位位图的RGB值的均值作为8位位图的灰度值229 *ptr8++ = (byte)(((int)(*ptr32++) + (int)(*ptr32++) + (int)(*ptr32++)) / 3);230 ptr32++;//跳过透明度字节231 }232 ptr32 += data32.Stride - bmp32.Width * 4;233 ptr8 += data8.Stride - bmp8.Width;234 }235 }236 bmp8.UnlockBits(data8);237 bmp32.UnlockBits(data32);238 Save8Bits(bmp8);239 }240241public void Bit32To24()242 {243 Bitmap bmp32 = new Bitmap(filepath);244 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 245 Bitmap bmp24 = new Bitmap(bmp32.Width, bmp32.Height, PixelFormat.Format24bppRgb);246 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 247unsafe248 {249byte* ptr32 = (byte*)data32.Scan0.ToPointer();250byte* ptr24 = (byte*)data24.Scan0.ToPointer();251for (int i = 0; i < bmp24.Height; i++)252 {253for (int j = 0; j < bmp24.Width; j++)254 {255//将32位位图的RGB值赋值给24位位图的RGB值256 *ptr24++ = *ptr32++;257 *ptr24++ = *ptr32++;258 *ptr24++ = *ptr32++;259 ptr32++;//跳过透明度字节260 }261 ptr24 += data24.Stride - bmp24.Width * 3;262 ptr32 += data32.Stride - bmp32.Width * 4;263 }264 }265 bmp32.UnlockBits(data32);266 bmp24.UnlockBits(data24);267 bmp24.Save(savepath);268 }269270public void Bit24To32()271 {272 Bitmap bmp24 = new Bitmap(filepath);273 BitmapData data24 = bmp24.LockBits(new Rectangle(0, 0, bmp24.Width, bmp24.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 274 Bitmap bmp32 = new Bitmap(bmp24.Width, bmp24.Height, PixelFormat.Format32bppArgb);275 BitmapData data32 = bmp32.LockBits(new Rectangle(0, 0, bmp32.Width, bmp32.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); 276unsafe277 {278byte* ptr24 = (byte*)data24.Scan0.ToPointer();279byte* ptr32 = (byte*)data32.Scan0.ToPointer();280for (int i = 0; i < bmp32.Height; i++)281 {282for (int j = 0; j < bmp32.Width; j++)283 {284//将24位位图的RGB值赋值给32位位图的RGB分量285 *ptr32++ = *ptr24++;286 *ptr32++ = *ptr24++;287 *ptr32++ = *ptr24++;288 *ptr32++ = 255;//设透明度为100%289 }290 ptr24 += data24.Stride - bmp24.Width * 3;291 ptr32 += data32.Stride - bmp32.Width * 4;292 }293 }294 bmp32.UnlockBits(data32);295 bmp24.UnlockBits(data24);296 bmp32.Save(savepath);297 }298 }。
完整程序_C语言对BMP图像的读和写和对像素的操作

#include <stdio.h>#include "Windows.h"BOOL readBmp(char *bmpName);BOOL saveBmp(char *bmpName, char *imgBuf, int width, int heigh, int biBitCount, RGBQUAD *pColorTable);char *pBmpBuf; //位图数据int bmpWidth; // 图像宽度int bmpHeight; //图像高度int biBiCount; //图像类型,每像素位数RGBQUAD *pColorTable; //位图颜色表指针int main(){char readName[] = "read.BMP";readBmp(readName);char writeName[] = "write.BMP";saveBmp(writeName, pBmpBuf, bmpWidth, bmpHeight, biBiCount, pColorTable);int lineByte = (bmpWidth*bmpHeight/8+3)/4*4;if (biBiCount == 8){for (int i = 0; i < bmpWidth/2; i++){for (int j = 0; j < bmpHeight/2; j++){*(pBmpBuf+i*lineByte+j) = 0;}}}else if (biBiCount == 24){/////对于24位真彩图,每个像素占三个字节分别存储R、G、B三个颜色分量的颜色值for (int i = 0; i < bmpWidth/2; i++){for (int j = 0; j < bmpHeight/2; j++){for (int k = 0; k < 3; k++)*(pBmpBuf+i*lineByte+j*3+k) = 0; //将rgb三个颜色分量设置成黑色}}}char Name[] = "copy.BMP";saveBmp(Name, pBmpBuf, bmpWidth, bmpHeight, biBiCount, pColorTable);delete []pBmpBuf;if (biBiCount == 8){delete []pColorTable;}return 0;}BOOL readBmp(char *bmpName ){FILE *pf = fopen(bmpName, "rb");if (pf == NULL) return FALSE;printf("read %s succeeded!\n", bmpName);fseek(pf, sizeof(BITMAPFILEHEADER), SEEK_SET);BITMAPINFOHEADER infoHeader;fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pf);bmpWidth = infoHeader.biWidth;bmpHeight = infoHeader.biHeight;biBiCount = infoHeader.biBitCount;//图像每行的字节数,一定要是4的倍数int lineByte = (bmpWidth*bmpHeight/8+3)/4*4;pBmpBuf = new char[lineByte*bmpHeight];//灰度图像有颜色表if (biBiCount == 8){pColorTable = new RGBQUAD[256];fread(pColorTable, sizeof(RGBQUAD), 1, pf);}fread(pBmpBuf, lineByte*bmpHeight, 1, pf);fclose(pf); //关闭文件return TRUE;}BOOL saveBmp(char *bmpName, char *imgBuf, int width, int heigh, int biBitCount, RGBQUAD *pColorTable ){FILE *pf = fopen(bmpName, "wb");if (pf == NULL) return FALSE;printf("write %s succeeded!\n", bmpName);//写头文件int colorTableSize = 0;if (biBitCount == 8){colorTableSize = 1024;}int lineByte = (width*heigh/8+3)/4*4;BITMAPFILEHEADER filehead;filehead.bfOffBits = 54+colorTableSize;filehead.bfType = 0x4D42;filehead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize+lineByte*heig h;filehead.bfReserved1 = 0;filehead.bfReserved2 = 0;fwrite(&filehead, sizeof(BITMAPFILEHEADER), 1, pf);BITMAPINFOHEADER infoHead;infoHead.biBitCount = biBitCount;infoHead.biWidth = width;infoHead.biHeight = heigh;infoHead.biSize = 40;infoHead.biClrImportant = 0;infoHead.biSizeImage = lineByte*heigh;infoHead.biClrUsed = 0;infoHead.biPlanes = 1;infoHead.biXPelsPerMeter = 0;infoHead.biYPelsPerMeter = 0;fwrite(&infoHead,sizeof(BITMAPINFOHEADER), 1, pf);if (biBitCount == 8){fwrite(pColorTable, sizeof(RGBQUAD), 256, pf);}fwrite(pBmpBuf, lineByte*heigh, 1, pf);fclose(pf);return TRUE;}。
读取并在屏幕上显示24位bmp图像

读取并在屏幕上显示24位bmp图像PS:本文非原创,code来自互联网。
代码如下:/*这里仅仅是一个简单的显示也可以写出适用于各种OpenGL使用例如设置我们甚至可以使用负的系数,使得整个图象进行水平方向或垂直方向的翻转(默认像素从左绘制到右,但翻转后将从右绘制到左。
默认像素从下绘制到上,但翻转后将从上绘制到下。
因此,*/ opengl#include <gl/#definestaticstaticstaticstaticstatic#include <stdio.h>#include <stdlib.h>void{////// glClear(GL_COLOR_BUFFER_BIT);//GL_glutSwapBuffers();}int{FILE* pFile = fopen(str,exit(fseek(pFile,fread(&ImageWidth,fread(&ImageHeight,PixelLength = ImageWidth *++PixelLength;PixelLength *= ImageHeight;exit(fseek(pFile,fread(fclose(pFile);glutInit(&argc, argv);glutInitDisplayMode(GLUT_glutInitWindowPosition(glutInitWindowSize(ImageWidth, ImageHeight);glutCreateWindow(FileName);glutDisplayFunc(&display);glutMainLoop();}显示结果截图如下:为方便理解程序,下面把网上找的关于部分bmp图像格式的说明也写在下面了,如果还想了解的更清楚,就自己再google下,很多相关资料的。
BMP文件是一种像素文件,它保存了一幅图象中所有的像素。
1 怎样读取BMP文件中的像素数据与显示位图

怎样读取BMP位图的数据与显示位图计算机与信息工程系管庶安一 BMP位图文件的结构以24位BMP位图文件为例说明。
BMP位图文件结构如下表所示:位图数据◇逐行逐列记录各像素点的三基色分量。
◇每一像素点占用三个字节,分别表示蓝色分量B、绿色分量G、红色分量R的值。
◇ 设图像有n行、m列像素,行顺序为从下向上分别为第1行、第2行……;列顺序为从左向右分别为第1列、第2列……。
按此顺序将各像素的三基色值记录于BYTE型的一维数组中,如下图所示:注意:当一行占用的字节数不是4的整数倍时,应补充1~3个无效字节,使一行占用的字节数能被4整除。
无效字节可为任意值,不会影响图像内容。
二读取BMP位图数据(1)在MFC工程中的 .H文件中定义如下全局成员变量:BITMAPFILEHEADER FileHead; // 定义存放 .BMP 文件头的结构BITMAPINFOHEADER BmpInfo; // 定义存放 .BMP 信息头的结构LPBYTE lpImage; // 定义存放 .BMP文件中的位图数据的BYTE型指针typedef struct CCC{ // 定义能存放一个像素的3个基色值的结构类型BYTE B;BYTE G;BYTE R;};CCC C3 [480] [640];// 定义能存放一幅480行、640列像素的二维数组,以便图像处理与识别时运算(2)在.CPP文件中的类构造函数中,为lpImage指针申请内存:lpImage=(LPBYTE)new BYTE[640*480*3];在.CPP文件中的类析构函数中,为lpImage指针释放内存:delete[ ] lpImage;(3)在.CPP文件中的适当函数中打开.BMP文件,读取信息头和位图数据。
CFile f;BOOL OK;OK=f.Open( Bmp.PathName,CFile::modeRead|CFile::typeBinary|CFile::shareExcl usive,NULL);if(!OK) return(-1); //不能打开文件,返回失败标志-1f.Read(&FileHead,sizeof(FileHead)); //读文件头if(FileHead.bfType!=0x4d42) {f.Close();return -2; //不是BMP文件,返回失败标志-2 }short x,y,z;z=(BmpInfo.biWidth*3/4)*4+(BmpInfo.biWidth*3%4==0 ? 0 : 4);f.Read(&BmpInfo,sizeof(BmpInfo)); //读信息头f.Seek(FileHead.bfOffBits,0);f.Read(lpImage,BmpInfo.biHeight*z); //读全部位图数据f.Close();for(y=BmpInfo.biHeight-1;y>=0;y--){memcpy(C3[y],lpImage+(BmpInfo.biHeight-1-y)*z,z); //逐行将位图数据填写到C3数组中}return 1; //最后,返回成功标志1三显示位图1 先按上述方法读取位图数据,再将读取数据予以显示。
BMP24位位图格式总结

图像BMP24位位图格式总结1、创建图片创建一张只有六个像素的图片(两行三列),每个像素的颜色RGB组合值如图1(示意图)所示:图12、windows系统下存储格式(使用WinHex打开)3、文件结构3.1 文件头(bmp file header),提供文件的格式、大小等信息,共14个字节,如图2所示。
图23.1.1 0-1字节(2个字节)0x42 0x4d = "BM",表示这是Windows支持的位图格式,如图3所示。
图33.1.2 2-5字节(4个字节),表示该bmp文件的大小,存储形式为图4所示,因为小端对齐形式存储,实际存储的16进制数为0x4e,转换为十进制为78,与我们直接查看此图片的属性所看到的文件大小一致。
注:对于arm,intel这种x86架构的复杂指令CPU,整数在内存中是倒着存放的,低地址放低位,高地址放高位,小端对齐,但对于unix服务器的CPU,更多是采用大端对齐的情况图43.1.3 6-9字节这是两个保留段,为0如图5所示。
图53.1.4 A-D字节如图6所示,存储数据为0x36,十进制为54,表示的意义为从文件头到位图数据需偏移54字节。
图63.2 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息,40个字节,如图7所示。
图73.2.1 0E-11字节,如图8所示,存储数据为0x28,十进制为40,表示意义为:位图信息头的大小为40个字节。
图83.2.2 12-15字节,如图9所示,存储数据为0x03,十进制为3,表示意义为:图像宽为3个像素,与我们创建的图像一致。
图93.2.3 16-19字节,如图10所示,存储数据为0x02,十进制为2,表示意义为:图像高为2个像素,与我们创建的图像一致。
图103.2.4 1A-1B字节,如图11所示,存储数据为0x01,该值总为1,表示意义为位元面数。
BMP图像存储格式

维基百科的BMP定义BMP取自位图BitMaP的缩写,也称为DIB(与设备无关的位图),是微软视窗图形子系统(Graphics Device Interface)内部使用的一种位图图形格式,它是微软视窗平台上的一个简单的图形文件格式。
图像通常保存的颜色深度有2(1位)、16(4位)、256(8位)、65536(16位)和1670万(24位)种颜色(其中位是表示每点所用的数据位)。
8位图像可以是索引彩色图像外,也可以是灰阶图像。
表示透明的alpha通道也可以保存在一个类似于灰阶图像的独立文件中。
带有集成的alpha通道的32位版本已经随着Windows XP出现,它在视窗的登录和主题系统中都有使用。
文件大小计算BMP文件通常是不压缩的,所需存储空间比较大。
一个像素所占的字节数为n∕8字节,n是位深。
文件大小可以根据以下公式近似计算:BMP文件大小≈54+4*2n+(width*height*n)∕8;54是位图文件的文件头,4*2n是调色板的大小(对于没有调色板的位图文件,则不存在这一项),最后一项是像素数据。
由于存储算法决定的因素,实际文件大小和计算值可能有细微差别;因此使用的≈符号而不是等于号。
文件存储格式BMP图像自推出以后,几经演进,存储格式也有所变化。
下表详细描述了位图文件可能包含的数据。
结构体名称可选大小用途备注位图文件头否14字节存储位图文件通用信息仅在读取文件时有用DIB头否固定(存在7种不同版本)存储位图详细信息及像素格式紧接在位图文件头后附加位掩码是3或4 DWORD(12或16字节)定义像素格式仅在DIB头是BITMAPINFOHEADER时存在调色板见备注可变定义图像数据(像素数组)所用颜色色深≤ 8时不能省略填充区A是可变结构体对齐位图文件头中像素数组偏移量的产物像素数组否可变定义实际的像素数值像素数据在DIB头和附加位掩码中定义。
像素数组中每行均以4字节对齐填充区B 是可变结构体对齐DIB头中ICC色彩特性数据偏移量的产物ICC色彩特性数据是可变定义色彩特性可以包含外部文件路径,由该文件来定义色彩特性Remark:像素数组每行均以4字节对齐,这会影响我们怎么读取像素数据。
图像处理Bmp文件存储顺序

读写Bmp文件的方法步骤:读:1.读方式打开文件2.读入BITMAPFILEHEADER结构3.读入BITMAPINFOHEADER结构4.读入颜色表RGBQUAD结构5.读入位图数据6.关闭文件写:1.写方式打开文件2.填写BITMAPFILEHEADER结构并写入文件3.写入BITMAPINFHEADER结构并写入文件4.写颜色表进文件5.写位图数据进文件6.关闭文件①:位图文件头BITMAPFILEHEADER: (14字节)bfType :位图文件类型(0x4D42)bfSize :位图文件大小bfReserved1: Windows保留字1bfReserved2: Windows保留字2bfOffBits: 从文件头到实际位图数据的偏移字节数=文件头+ 信息头+调色板长度。
②:位图信息头(40字节)biSize: 本结构长度为40字节biWidth: 位图宽度,(像素为单位)biHeight: 位图的高度,(像素为单位)biPlanes: 设为1biCount: 位深度biCompression: 为0:不压缩;1:8位压缩;2:4位压缩。
biSizeImage:实际的位图数据占用的字节数biXPelsPerMeter:水平分辨率(像素/米)biYPelPerMeter: 垂直分辨率(像素/米)biClrCount:位图实际用到的颜色数(为0时,颜色数为2的biBitCount次幂)biClrImportant:位图显示过程中重要的颜色数(0:都是重要的)③:颜色表(4字节)rgbBlue:蓝色分量rgbGreen:绿色分量rgbRed: 红色分量rgbReserved:保留字节颜色表的大小:二值图像:大小=2*sizeof(RGBQUAD)=88位灰度图像:大小= 256*sizeof(RGBQUAD)= 102424位真彩色图像无颜色表④位图数据8位灰度图像ColorTablesize = 1024;lineByte =(bmpWidth * biBitCount / 8 + 3)/4 *4;1.申请位图文件头结构变量,并填写文件头信息BITMAPFILEHEADER fileHeader;fileHead.bfType = 0x4D42; //bmp类型//bfSize是图像文件4个组成部分之和fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAOINFOHEADER) + ColorTablesize + lineByte*Height;fileHeader.bfReserved1 = 0;fileHeader.bfReserved2 = 0;//bfOffBits是图像文件前3部分所需空间之和fileHead.bfOffBits = 54 + ColorTablesize;2.申请位图信息头结构变量,填写信息头信息BITMAPINFOHEADER head;head.biBitCount = biBitCount;head.biClrImportant = 0;head.biClrUsed = 0;head.biCompression = 0;head.biHeight = height;head.biSize = 40;head.biSizeImage = lineByte * height;head.biWidth = width;head.biXPelsPerMeter = 0;head.biYPelsPerMete = 0;3.写灰度图像的颜色表4.写位图数据进文件调色板句柄HPALETTE文件头指针LPBITMAFILEHEADER : m_lpDib信息头指针LPBITMAPINFOHEADER :m_lpBmpInfoHead 颜色表LPRGBQUAD : m_lpColorTable 信息指针LPBITMAPINFO :m_lpBmpInfo图像数据指针:m_pImgData (包括:信息头指针和颜色表)1读入一幅图像(即打开操作):将四部分都考虑进去(1,2,3,4);2写入一幅图像(即保存操作):将四部分都考虑进去(1,2,3,4)3显示一幅图像:只需将3部分考虑进去(2,3,4)4 处理一幅图像:只需将3部分考虑进去(2,3,4)位图显示和数据处理:将(位图信息头、颜色表)即:信息指针内容,位图数据指针依次写入,并进行操作。
BMP图片格式

BMP图片格式简介:BMP是一种与硬件设备无关的图像文件格式,使用非常广。
它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。
BMP文件的图像深度可选lbit、4bit、8bit及24bit。
BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。
由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
文件结构:典型的BMP图像文件由四部分组成:1:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;2:位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;3:调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;4:位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
位图的类型:位图一共有两种类型,即:设备相关位图(DDB)和设备无关位图(DIB)。
DDB位图在早期的Windows系统(Windows 3.0以前)中是很普遍的,事实上它也是唯一的。
然而,随着显示器制造技术的进步,以及显示设备的多样化,DDB位图的一些固有的问题开始浮现出来了。
比如,它不能够存储(或者说获取)创建这张图片的原始设备的分辨率,这样,应用程序就不能快速的判断客户机的显示设备是否适合显示这张图片。
为了解决这一难题,微软创建了DIB位图格式。
设备无关位图 (Device-Independent Bitmap)DIB位图包含下列的颜色和尺寸信息:*原始设备(即创建图片的设备)的颜色格式。
*原始设备的分辨率。
*原始设备的调色板*一个位数组,由红、绿、蓝(RGB)三个值代表一个像素。
*一个数组压缩标志,用于表明数据的压缩方案(如果需要的话)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
南通大学计算机科学与技术学院
《数字图像处理》课程实验
报告书
实验名 BMP文件的读写(8位和24位)
班级计 121
姓名张进
学号 1213022016
2014年6月 16 日
一、实验内容
1、了解BMP文件的结构
2、8位位图和24位位图的读取
二、BMP图形文件简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。
Windows系统内部各图像绘制操作都是以BMP为基础的。
Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP 图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。
Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。
BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。
位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节阵列,它具有如下所示的形式。
位图文件结构内容摘要
三、读写涉及的原理
1、图像的二值化的基本原理
图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。
即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。
在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。
为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。
所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。
如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阀值法就可以得到比较的分割效果。
如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阀值选取技术来分割该图像。
动态调节阀值实现图像的二值化可动态观察其分割图像的具体结果。
2、图像的反色原理
对于彩色图像的R、G、B各彩色分量取反的技术就是图像的反色处理,这在处理二值化图像的连通区域选取的时候非常重要。
如物体连通域用黑色表示,而二值化后的物体连通域图像可那是白色的,而背景是黑色的,这时应手动选取图像的反色处理或有程序根据背景和物体连通域两种颜色的数量所占比例而自动选择是否选择选取图像的反色处理
四、读写转换代码
五、运行结果
24位位图24dog.bmp如下:
原图像的属性:
读取结果:
生成的新图片:
8位位图读取8dog.bmp如下
图片属性:
读取的结果:
生成的新图片:
六、心得体会
大一学的c++,现在却发现忘得差不多了,在程序实现上遇到了困难。
但是本次实验确实又再一次的让我接触了c语言。
这次实验掌握了BMP文件的读取,第一次对图像有这么深的认识了解。
对图像的组成不再是以前那种错误的认识,有收获。