BMP格式文件解析

BMP是一种与硬件无关的图像文件格式,使用非常广泛。

它采用位映射存储格式,除了图像深度可选外,不采用其他任何压缩。因此,BMP文件所占的空间很大。

BMP文件的图像深度可选1 bit、4bit、8bit及 24bit。

BMP的文件存储时,图像的扫描方式是按从左到右、从上到下的顺序。      

BMP图像文件由4部分组成:

1、位图文件  头数据结构  它包含BMP图像文件的类型、显示内容等信息;

2、位图信息数据结构  它包含BMP图像的宽、高、压缩方法,以及定义颜色等信息;

3、调色板  这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;

4、位图数据   这部分的内容根据BMP位图使用是位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。

 int image_width;// 位图的宽度,以像素为单位(19-22字节)
	 int image_height;// 位图的高度,以像素为单位(23-26字节)
	 int biBitCount;// 每个像素所需的位数,必须是1(双色)、4(16色)、8(256色)、24(真彩色)之一,(29-30字节)
	 int sizeImage;// 位图的大小,以字节为单位(35-38字节)
	 // 跳过补0项
	 int skip_width;
	 // 用于存储RGB颜色数据的数组
	 int[][] imageR, imageB, imageG;

 读取BMP图像文件数据:

try{
			//创建文件输入流
			FileInputStream fis=new FileInputStream(path);
			//把文件输入流包装成输入缓冲流
			BufferedInputStream bu=new BufferedInputStream(fis);
			//读入BMP头文件的基本信息
			int bflen=14;//头文件的长度
			byte[] bf=new byte[bflen];//定义一个存入头文件事件数据的数组
			//读取14字节的BMP文件头
			bu.read(bf,0,bflen);
			int bilen=40;		//读入位图信息头
			byte[] bi=new byte[bilen];
			//读取40字节的BMP位图信息头
			bu.read(bi,0,bilen);
			//获取:位图文件的宽度、高度、每个像素点所需的位数(即图像的深度)、源图的大小(测试时值为0)
			image_width = changeInt(bi,7);//源文件宽度
			image_height=changeInt(bi,11);//源文件的高度
			//每个像素点所需的位数,必须是1(双色)、4(16色)、8(256色)、24(真彩色)之一,(29-30字节)
			biBitCount=(((int)bi[15]&0xff)<<8)|((int)bi[14]&0xff);
			sizeImage=changeInt(bi,23);//位图的大小,以字节为单位(35-38字节),测试结果为sizeImage=0;
			//调用读取位图数据的方法,将数据存入imageR.imageG,imageB三个二维数组中
			readRGB(bu);
			bu.close();//关闭缓冲流
			fis.close();//关闭输入流
			showi(path);
		}
		catch(Exception e){
			e.printStackTrace();
		}

 读取BMP图像文件时,要读取位图数据:

public void readRGB(BufferedInputStream bis){
		if(!(image_width*3%4==0)){//图片的宽度不为0
			skip_width=4-image_width*3%4;
		}//判断是否后面有补0 的情况
		//装载RGB颜色的数据数组
		imageR=new int[image_height][image_width];
		imageG=new int[image_height][image_width];
		imageB=new int[image_height][image_width];
		//按行读取,如果H,W为正,则倒着来
		for(int h=image_height-1;h>=0;h--){
			for(int w=0;w<image_width;w++){
				try{
					//读取三种颜色
					int blue=bis.read();
					int green=bis.read();
					int red=bis.read();
					imageR[h][w]=red;
					imageG[h][w]=green;
					imageB[h][w]=blue;
				}catch(IOException ef){
					ef.printStackTrace();
				}
				if(w==0){  //跳过补0项
					try{
						bis.skip(skip_width);
					}catch(IOException e){
						e.printStackTrace();
					}
				}
			}
		}
	}

 存在数组中是是字节,要将它转化成int类型。因为的出来的顺序是倒序,所以第i个位置要左移24位才能到高8位,要得到int值,只需将他们每8个字节先进行逻辑与,再左移,在进行逻辑或运算,即可。

public int changeInt(byte[] bu,int i){
		return ((((int) bu[i] & 0xff) << 24) | (((int) bu[i - 1] & 0xff) << 16)
	    | (((int) bu[i - 2] & 0xff) << 8) | (((int) bu[i - 3] & 0xff)));
	}
  显示界面,将读取的数据显示出来。

	public void showi(String path){
		this.setTitle(path);
		this.setSize(image_width, image_height);
		this.setDefaultCloseOperation(3);
		this.setVisible(true);
		Graphics g=this.getGraphics();//得到画布
		repaint();//调用重绘方法
		this.validate();
	}

 显示界面时要调用paint()方法,才能够显示BMP图像

public void paint(Graphics g){
		super.paint(g);//调用父类的重绘方法
		for(int h=0;h<image_height;h++){
			for(int w=0;w<image_width;w++){
				g.setColor(new java.awt.Color(imageR[h][w],imageG[h][w],imageB[h][w]));
				g.drawLine(w,h,w,h);//画点
			}
		}
	}

结果如下图所示:

注意: 保存类型应为24位位图


BMP格式文件解析

你可能感兴趣的:(数据结构)