BMP图像的读写(8位和24位)
南通大学计算机科学与技术学院《数字图像处理》课程实验
报告书
实验名BMP文件的读写(8位和24位)
班级计121
姓名张进
学号**********
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文件的读取,第一次对图像有这么深的认识了解。
对图像的组成不再是以前那种错误的认识,有收获。
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文件结构与读写
/luosha828/blog/item/032d0747bb9d74029313c6f8.html【转】 BMP文件结构与读写2011-02-12 10:43转载自qinshaoq最终编辑qinshaoqBMP文件结构1. BMP文件组成BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。
文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息.位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。
颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。
文件中的数据块表示图像的相应的像素值,需要注意的是:图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的;另外一个需要关注的细节是:文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,否则,需要在后端补0,凑足4的倍数。
2. BMP文件头BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。
其结构定义如下:typedef struct tagBITMAPFILEHEADER{WORD bfType; // 位图文件的类型,必须为BMDWORD bfSize; // 位图文件的大小,以字节为单位WORD bfReserved1; // 位图文件保留字,必须为0WORD bfReserved2; // 位图文件保留字,必须为0DWORD bfOffBits; // 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位} BITMAPFILEHEADER;该结构占据14个字节。
图像处理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文件的读写
• lpszFilter是一个包含有通配符的以“|”字符分隔的字符 串。要注意的是, 在第一个“|”字符之前是将要显示在 文件对话框的“文件类型”列表框中的信息, 第二个
“ | ”字符和第一个“ | ”字符之间的内容为对话框的过
滤器内容。在字符串szFilter的尾部, 使用两个“|”字符
而不是一个, 表示过滤器内容结束。
StretchDIBits函数简介
• • • • • • • • • • • • hdc:指向目标设备环境的句柄。 XDest:指定目标矩形左上角位置的X轴坐标,按逻辑单位来表示坐标。 YDest:指定目标矩形左上角的Y轴坐标,按逻辑单位表示坐标。 nDestWidth:指定目标矩形的宽度。 nDestHeight:指定目标矩形的高度。 XSrc:指定DIB中源矩形(左上角)的X轴坐标,坐标以像素点表示。 YSrc:指定DIB中源矩形(左上角)的Y轴坐标,坐标以像素点表示。 nSrcWidth:按像素点指定DIB中源矩形的宽度。 nSrcHeight:按像素点指定DIB中源矩形的高度。 lpBits:指向DIB位的指针,这些位的值按字节类型数组存储。 lpBitsInfo:指向BITMAPINFO结构的指针,该结构包含有关DIB方面的信息。 iUsage:表示是否提供了BITMAPINFO结构中的成员bmiColors,如果提供了, 那么该bmiColors是否包含了明确的RGB值或索引。参数iUsage必须取下列值, 这些值的含义如下: DIB_PAL_COLOR:表示该数组包含对源设备环境的 逻辑调色板进行索引的16位索引值。 DIB_RGB_COLORS:表示该颜色表 包含原义的KGB值。 dwRop:指定源像素点、目标设备环境的当前刷子和目标像素点是如何组合形成 新的图像。 返回值:如果函数执行成功,那么返回值是拷贝的扫描线数目,如果函数执行失 败,那么返回值是GDI_ERROR。 备注:。参数iUsage一般设为DIB_RGB_COLORS。dwRop一般设为SRCCOPY 。
数字图像处理实验报告
《数字图像处理》实验报告专业:软件工程*名:***学号: S********* 指导老师:***2019年 12 月 28 日信息学部软件学院目录实验一、BMP文件的读写 (1)1 实验目的与实验内容 (1)2 实验原理 (1)3 实验关键代码 (1)4 实验运行结果 (3)5 总结 (4)实验二、图像缩放 (4)1 实验目的及内容 (4)2 实验原理 (5)3 实验关键代码和运行结果 (6)4 结果分析 (8)实验三、直方图均衡 (9)1 实验目的及内容 (9)2 实验原理 (9)3 实验关键代码和实验结果 (10)4 思考题 (11)5结果分析 (12)实验四、图像滤波 (12)1 实验目的及内容 (12)2 图像滤波的原理 (12)3 实验关键代码及结果 (13)实验五、图像的灰度映射 (17)1 实验目的及内容 (17)2 实验关键代码及结果 (17)3 不同参数的变换结果 (20)附录一 (17)实验要求:用 c/c++语言编程实现以下功能实验环境:Windows10开发工具:CodeBlocks实验一、BMP文件的读写1 实验目的与实验内容1.1灰度 BMP 图像的读写:(1) 读入 lena.bmp 文件;(2) 通过文件内容得出文件大小,位图数据起始字节,图像长、宽以及每像素的位数等信息;(3) 提取出原图像中的位图数据,另存为 lena.raw, 并通过 photoshop 打开该文件,查看所读取的数据。
(4)仅取原始图像左上角 1/4 的数据,另存一个 lenas.bmp 图像,在photoshop 中打开查看效果。
1.2 彩色 BMP 图像读写(1) 读入文件 lena_C.bmp 文件;(2) 通过文件内容得出文件大小,位图数据起始字节,图像长、宽以及每像素的位数等信息;(3) 提取出原图像中的位图数据,另存为 lena_C.raw, 并通过 photoshop 打开该文件,查看所读取的数据。
