`
什么世道
  • 浏览: 219281 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

BMP文件格式的解析和保存

阅读更多

 

  BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。因为几乎不进行压缩,所以BMP格式是最简单的通用格式之一。

  本篇文章主要介绍BMP文件的格式规范,解析及其保存。

 

 

   BMP文件结构(本段代码由小组成员卿雯童鞋呈现)

  位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节(位图数据,即图像数据,Data Bits 或Data Body)阵列,它具有如下所示的形式。

 

位图文件头 (bitmap-file header) BITMAPFILEHEADER bmfh
/**
	 * bitmap-file header(14 byte)
	 * 
	 */
	class BITMAPFILEHEADER {
		short bfType;// the type of BMP file,value of 'B' or 'M' only.(1-2 byte)
		int bfSize;// the size of BMP file.(3-6 byte)
		short bfReserved1;// reserved word of bmp file,value of 0 only.(7-8 byte)
		short bfReserved2;// reserved word of bmp file,value of 0 only.(9-10byte)
		int bfOffBits;// the offset of file header(11-14 byte)
	}

 

 

 

位图信息头 (bitmap-information header) BITMAPINFOHEADER bmih
/**
	 * bitmap-information header(40 byte)
	 * 
	 */
	class BITMAPINFOHEADER {
		int biSize;// the size of this part.(15-18 byte)
		int biWidth;// the width of bmp file.(19-22 byte)
		int biHeight;// the height of bmp file.(23-26 byte)
		byte biPlanes;// the rank of target device.value of q only(27-28 byte)
		byte biBitCount;// the bit of per pixel,value of 1,4 8 or 24 only.(29-30byte)
		int biCompression;// the type of compression,value of 0(BI_RGB)(non-compression),1(BI_RLE8) or 2(BI_RLE4) only.(31-34 byte)
		int biSizeImage;// the size of image.(35-38 byte)
		int biXPelsPerMeter;// horizontal resolution, Pixels per meter.(39-42 byte)
		int biYPelsPerMeter;// vertical resolution,Pixels per meter.(43-46 byte)
		int biClrUsed;// the number of all used color.(47-50 byte)
		int biClrImportant;// the number of key color.(51-54 byte)
	}
彩色表  (color table) RGBQUAD aColors[]
	/**
	 * color table
	 * 
	 */
	class RGBQUAD {
		byte rgbRed;// the red channel
		byte rgbGreen;// the Green channel
		byte rgbBlue;// the blue channel
		byte rgbReserved;// reserved,value of 0 only
	}
 
图象数据阵列字节 BYTE aBitmapBits[]
/**
	 * Data Bits
	 * 
	 */
	class BITMAPINFO {
		BITMAPINFOHEADER bmiHeader;
		RGBQUAD bmiColors;

	}
 
BMP文件解析(本段代码由小组成员阳超群童鞋呈现)
要点:先读取位图文件头的信息(14 byte)
然后读取位图信息头为的信息(40 byte)
注意:此段要获取信息头的2个重要的参数,位图的宽度和高度
最后读取位图的图像信息。
其中要注意数据类型的匹配。
 
读取位图文件头和信息头
	/**
	 * read the image from the bitmap file
	 * 
	 * @param path
	 *            the path of bitmap file
	 * @throws IOException
	 */
	public void readBMP(String path) throws IOException {
		// creat a FileInputStream object;
		fis = new java.io.FileInputStream(path);
		// creat a DataInputStream object;
		dins = new java.io.DataInputStream(fis);

		// read the bitmap loader of bitmap file
		int bmploaderLen = 14;
		byte[] bmploader = new byte[bmploaderLen];
		dins.read(bmploader, 0, bmploaderLen);

		// read the info header of bitmap file
		int bmpheaderLen = 40;
		byte[] bmpheader = new byte[bmpheaderLen];
		dins.read(bmpheader, 0, bmpheaderLen);

		biWidth = convert2Int(bmpheader, 7);
		biHeight = convert2Int(bmpheader, 11);

	}
将byte数组转换为int类型的数据
/**
	 * 4 byte convert to 1 int
	 * @param bytes the source byte array
	 * @return the converted int
	 */
	private int convert2Int(byte[] bytes, int index) {
		return (((int) bytes[index] & 0xff) << 24)
				| (((int) bytes[index - 1] & 0xff) << 16)
				| (((int) bytes[index - 2] & 0xff) << 8)
				| ((int) bytes[index - 3] & 0xff);
	}
计算补零的长度
// calculate the length of zero-padding
		if (!(biHeight * 3 % 4 == 0)) {
			skip_width = 4 - biWidth * 3 % 4;
		}
 
读取RGB信息
for (int h = biHeight - 1; h >= 0; h--) {
			for (int w = 0; w < biWidth; w++) {
				// 分别按照协议顺序读出字节
				int blue = dins.read();
				int green = dins.read();
				int red = dins.read();
				// 由于颜色值范围超出byte正值范围,可能存储为负值,进行位运算
				int blue_temp = (blue & 0xff);
				int green_temp = (green & 0xff);
				int red_temp = (red & 0xff);
				imageB[h][w] = blue_temp;
				imageG[h][w] = green_temp;
				imageR[h][w] = red_temp;

				// zero-padding
				if (w == 0) {
					byte bytes[] = new byte[skip_width];
					dins.read(bytes);
				}
			}
		}
		dins.close();
		fis.close();

	}
 
绘出位图图像
    /**
	 * paint the image on the frame
	 */
	public void paint(Graphics g) {
		super.paint(g);
		// g = this.getGraphics();
		for (int h = 0; h < biHeight; h++) {
			for (int w = 0; w < biWidth; w++) {
				g.setColor(new Color(imageR[h][w], imageG[h][w], imageB[h][w]));
				g.fillRect(w, h, 1, 1);
			}
		}
	}
 
BMP文件的保存(本段代码有小组成员曹睿超童鞋呈现)
要点:按BMP文件结构依次写入位图文件头,位图信息图,RGB颜色表,和图象数据阵列字节 
注意:数据类型的匹配。
/**
	 * 写入bmp文件
	 * @param image
	 * @param file
	 */
	public void writeBMP(BufferedImage image, File file) {

		try {
			// 创建输入流
			FileOutputStream fos = new FileOutputStream(file);
			DataOutputStream dos = new DataOutputStream(fos);
			
			
			//位图文件类型,2个字节,必须为'B'和'M'
			dos.writeByte((int)'B');
			dos.writeByte((int)'M');
			
			
			
			//BMP头文件
			biWidth = image.getWidth();
			biHeight = image.getHeight();
			
			//位图文件大小,4个字节
			int skip_width = 0;
			//一个扫描行所占的字节数必须为4的倍数,不足的补上0
			if(skip_width * 3 % 4 != 0)
				skip_width = 4 - skip_width * 3 % 4;
			
			//得到文件的大小
			bfSize = 54 + (biWidth + skip_width) * 3 * biHeight;
			dos.write(changeIntToByte(bfSize, 4) , 0, 4);
			
			//起始位置4个字节
			dos.write(changeIntToByte(bfReserved1, 2), 0, 2);
			dos.write(changeIntToByte(bfReserved2, 2), 0, 2);
			
			//写入位图文件的起始位置
			dos.write(changeIntToByte(bfOffBits, 4), 0, 4);
			
			//位图信息图
			biSize = (biWidth + skip_width) * 3 * biHeight;
			dos.write(changeIntToByte(biSize, 4), 0, 4);
			
			//宽度,高度
			dos.write(changeIntToByte(biWidth, 4), 0, 4);
			dos.write(changeIntToByte(biHeight, 4), 0, 4);
			
			//目标设备
			dos.write(changeIntToByte(biPlanes, 2), 0, 2);
			
			//像素所需位数,24
			biBitCount = 24;
			dos.write(changeIntToByte(biBitCount, 2), 0 ,2);
			
			//压缩类型
			dos.write(changeIntToByte(biCompression, 4), 0 ,4);
			
			//位图大小
			dos.write(changeIntToByte(biSizeImage,  4), 0, 4);
			
			//写入水平,垂直分辨率(150ppm)
			dos.write(changeIntToByte(biXPelsPreMeter, 4), 0, 4);
			dos.write(changeIntToByte(biYPelsPreMeter, 4), 0, 4);
			
			//写入位图中实际使用的颜色表的颜色数
			dos.write(changeIntToByte(biClrUsed, 4), 0, 4);
			
			//写入重要的颜色
			dos.write(changeIntToByte(biClrImportant, 4), 0, 4);
			
			//位图数据
			int color [][] = new int [biWidth][biHeight];
			byte colorR[][] = new byte [biWidth][biHeight];
			byte colorG[][] = new byte [biWidth][biHeight];
			byte colorB[][] = new byte [biWidth][biHeight];
			
			for(int i = 0;i < biHeight;i ++) {
				for(int j = 0;j < biWidth;j ++) {
					int temp = image.getRGB(j, i);
					color[i][j] = temp;
					colorR[i][j] = (byte)(temp >> 16);
					colorG[i][j] = (byte)(temp >> 8);
					colorB[i][j] = (byte)(temp >> 0);
				}
			}
			
			for(int i = biHeight - 1;i >= 0;i ++) {
				for(int j = biWidth - 1;j >= 0;j --){
					dos.write(colorB[i][j]);
					dos.write(colorG[i][j]);
					dos.write(colorR[i][j]);
					
					if(skip_width != 0 && j == 0)
						dos.write(changeIntToByte(0, skip_width), 0, skip_width);
					
				}
			}
			fos.flush();
			fos.close();
			dos.flush();
			dos.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
将int类型转换为Byte数组
         /**
	 * 将int类型转换为byte数组
	 * @param num int类型的对象
	 * @param size 数组的长度
	 * @return byte类型数组
	 */
	private byte[] changeIntToByte(int num, int size) {
		
		//定义一个byte类型数组
		byte[] count = new byte[size];
		
		//循环进行位运算
		for(int i = 0;i < size;i ++) {
			count[i] = (byte) (num >> (i * 8));
		}
		
		return count;
	}
 

 

分享到:
评论
1 楼 刘凯宁 2013-10-07  
  

相关推荐

    BMP 图片解析及数据提取 成C文件

    软件解析BMP文件,并做出相应的指示,提取有效数据,保存成*.C便 于下位机编程使用。

    read and save bmp

    解析bmp文件、读取bmp文件、保存bmp文件,获取bmp文件中图片的图像的高宽。

    MNIST_BMP_图片库.7z

    在官网http://yann.lecun.com/exdb/mnist/下载的图片数据集,用python 解析为原图后保存为BMP格式,亲测可用。非常适合深度学习入门训练。祝大家学习愉快

    医学图像格式转换器DcmTransform.rar

    转化的文件格式可设为BMP格式和JPG格式。用户亦可以根据自己的需要设置转化图像的属性信息,如图像的质量,大小。对于CT,MRI断层图像来说,通常拍摄得到的是一系列DICOM文件,该系列文件通常在同一个文件夹目录下。...

    AVI文件的软件解析及 自动单帧捕获

    系统地解析了 AVI文件的结构,实现了从 AVI视频流中自动捕获单帧图像 ,并保存为 BMP文件 该算法的实现为对 AVI视频文件进行自动地运动分析及相应的图像处理奠定了基础.

    c++basic&mfc operate bmp&image format introduction&libtiff leaflet&image transform ppt&region grow code grey &threshold selection for image segmentation

    this assorted file includes:1,bmp文件MFC中翻转、保存和解析代码;2,c++programming shows some basic concepts in c++;3,imageformatdepict depicts six image format;4,libtiff how to use, demostrates use of ...

    Gprinter光栅位图数据解析软件v1.0中文绿色免费版

    Gprinter打印机光栅位图数据解析软件(Gprinter光栅位图点阵数据解析器)是一款最新...可直观显示解析后的图像和相关信息,并保存成bmp和png格式的图片可设定光栅位图模式,Bitmpa DIB扫描方向,生成的文件,欢迎有需要的

    利用VC++实现AVI文件的合成和分解

    本文详细的解析了AVI文件的存储结构,介绍了微软提供的用来操作AVI文件的一组API使用方法,并通过例子代码,演示了如何将一组静态Bmp图片合成一个avi视频文件以及如何将一个avi视频文件解析保存为一系列的bmp图像...

    动态规划的思想压缩位图

    有一个参数为输入位图文件名(*.bmp),它能解析8、16、24位位图文件格式,获取位图BITMAPINFOHEADER信息和每个像素的数据信息,放入内存中。 (2)对8、16、24位位图数据的写功能 有一个参数为输出位图文件名(*.bmp)...

    bmptool:基于Kaitai Struct的简单工具,用于读取BMP图像

    加载BMP文件时,可以使用另一种压缩方法,位深度或标头类型将其保存为另一种图像格式(例如PNG),以使其更加可移植等。入门要启动并运行本地副本,请遵循以下简单步骤。先决条件Node.js(JavaScript运行时环境)+ ...

    JSOCR捷速OCR文字识别软件免费版.rar

    读取后纸面解析当前的文件,识别后可提取文字到WORD中,或保存图片为BMP格式。支持以多种倍率查看 文档。就是将从图片中提取可直接编辑复制的文字,一键智能OCR识别,速度快识别率高,能够对当前的图片或PDF文档...

    算宝

    可以解高中范围的各种不定形式的一元,二元,参数方程的解,绘制各种函数曲线,可以保存为BMP文件 对平面解析几何也有帮助,提供复杂的函数计算,可以保存结果 函授计算中可以输入文本,可以保存为TXT文件,可以...

    Swift Axe MX(SWF分解工具) v1.2.021012

    同时还可以获得各组件的详细属性信息内置预览功能,不需要调用任何外部程序,特有的 COC 技术使得预览过程更加流畅清晰批量提取所有组件为独立SWF影片,还可以将音频和位图保存为 MP3、WAV BMP、JPG 文件支持彩色...

    C#开发实例大全(基础卷).软件开发技术联盟(带详细书签) PDF 下载

    主要内容有C#开发环境的使用、C#语言基础应用、字符串处理技术、数组和集合的使用、面向对象编程技术、数据结构与算法、Windows窗体基础、特色窗体界面、窗体控制技术、MDI窗体和继承窗体、Windows常用控件的使用、...

    Crimm Imageshop数码图片处理系统 v2.2.zip

    自行完美解析BMP格式,支持一些GDI和GDI 都无法打开的BMP文件。在保存为16位图像时,增加了PS未提供的抖动选项,让用户在真彩色和高彩色之间的转换信息损失降低到最少。能完美支持各种格式的PCX\TGA\PNM等格式的转换...

    浩辰CAD2008标准版part1(1/2)

    当程序异常退出,图形文件没有被保存时,程序再次启动,将显示图形恢复管理器,列出没有保存文件的最近保存版本和自动备份文件,以供用户从最近保存的备份文件中恢复。  新的图形修复管理器界面和ACAD兼容,对未...

Global site tag (gtag.js) - Google Analytics