BMP图像文件小结

  • Post author:
  • Post category:其他




一.




BMP




图像文件






BMP


是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式。通常我们看到的


bmp


图像文件一般都比较大,占用很大的空间。因为除了位像深度可选以外,其他不采用任何压缩。


Bmp


文件存储数据时,图像的扫描方式是按从左到右,从下到上的顺序。所以读取时,我们也要注意这个问题。


BMP





Windows


环境中交换与图有关的数据的一种标准,在


Windows


环境中运行的图形图像软件都支持


BMP


图像格式。





典型的


BMP


图像文件由四部分组成:文件头,图像参数,调色板,位图数据。


简单介绍下这四个部分。




1


:文件头,占


14


个字节。它包含


BMP


图像文件的类型、内容尺寸和起始偏移量等信息。


位图文件类型


,


占两个字节,第一个字节为字母


‘B’


,第二个字节为字母


‘M'(1-2


字节


)





位图文件的大小


,


以字节为单位


(3-6


字节


)


。还有四个字节的保留字


位图数据部分相对于文件首的起始偏移量,如果知道文件头了,这样就可以直接知道图像的颜色保存在那个位置了。




2


:图像参数,它包含图像的宽、高、压缩方法,以及颜色定义等信息




3


:调色板(可选部分)




bpp:


表示图像像素值的位数叫做图像的像素深度,又称为位


/


像素(


BPP


)。




bpp


较小的位图需要调色板;有些位图,比如


24bpp


(真彩色)图就不需要调色板;




4





1.


位图数据(一般为


40


个字节)


这部分的内容因位图实际像素位数和编码格式而不同,在真彩位图中直接使用


RGB


真彩色值;而有调色板的位图则使用调色板中颜色索引值。


每个像素所需的位数,必须是


1(


双色


)





4(16





)





8(256





)





24(


真彩色


)


之一,


(29-30


字节


)



位图数据包括:位图的大小,水平分辨率和垂直分辨率。以及位图实际使用的颜色表中的颜色数和位图显示过程中重要的颜色数。







2.


位图数据的读取(读取的方法有点特别)




.


每行的字节数必须是


4


的倍数,如果不是,则需要后面用


0


补齐。




BMP


位图数据的存放是从下到上,从左到右的。故我们也需要先读最后一行,读完后在读倒数第二行。


虽然说,bmp图像文件一般有四个部分,但在实际过程中,我们如果知道图像的长和高,以及每一点的颜色也可以将文件中的图片重绘出来。


如图:




package bmp;

import java.awt.Color;
import java.awt.Graphics;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;

import javax.swing.JFrame;

public class bmpTest extends JFrame{
	private int image_width;//图片的长和高
	private int image_heigh;
	Graphics  g;      //画布对象
    int blue,green,red;  
	int skip_width;   //跳过的项数
	
	int[][] imageR,imageG,imageB; //RGB的三个分值
	static String path="D:\\1000\\西北风光.bmp";
	/**
	 * 程序入口
	 * @param args
	 */
	public  static void  main(String [] args){
		 bmpTest BT=new bmpTest();
		 BT.read(path);
	}
	public void read(String path){
		try{
			//创建文件读取流
			FileInputStream  fis=new FileInputStream(path);
			BufferedInputStream  bis=new BufferedInputStream(fis);//将文件包装成一个普通数据类型的缓冲输出流
			
			 int bflen = 14;
			 byte[] bf = new byte[bflen];
			 bis.read(bf, 0, bflen);// 读取14字节的BMP文件头
			 
			 int bilen=40;
			 byte[]  bi=new byte[bilen];
			 bis.read(bi,0,bilen);   //读取40个字节的位图信息
			 image_width=ChangeInt(bi,7);  //原图宽度
			 image_heigh=ChangeInt(bi,11);   //原图高度

			 showRGB24(bis);    //读取位图数据
			
			 fis.close();  //关闭流
		     bis.close();
		     showUI();//调用窗口实现的方法
     	}
		
		catch(Exception e){
			e.printStackTrace();
		} 
	}
	/**
	 * 数据转换的方法
	 * @param bi 需要转换的数据存放的数组
	 * @param start 从数组的哪个位置开始转换
	 * @return  用一个int型返回转换好的数据
	 */
	public int ChangeInt(byte[] bi,int start){//将四个byte型的数据从低到高转成一个int型的数据
		return   (((int)bi[start]&0xff)<<24)|(((int)bi[start-1]&0xff)<<16)|(((int)bi[start-2]&0xff)<<8)|(int)bi[start-3]&0xff;
		
	}
	public void showRGB24(BufferedInputStream  dis)throws IOException{
		  if(!(image_width*3%4==0)){
			  skip_width=4-image_width*3%4;
		   }
		imageR=new int[image_heigh][image_width];//创建三个二维数组分别用来存放 颜色的R,G,B值
		imageG=new int[image_heigh][image_width];
		imageB=new int[image_heigh][image_width];
		 for (int h = image_heigh - 1; h >= 0; h--) {
			   for (int w = 0; w < image_width; w++) {
			     blue = dis.read();// 先读取出蓝色
			     green = dis.read();// 读取出绿色
			     red = dis.read();   // 读取的是红色
			     imageR[h][w] = red;
			     imageG[h][w] = green;
			     imageB[h][w] = blue;
			  
			     if (w ==image_width-1) {
			     // 跳过补0项
			      dis.skip(skip_width);
			    }
			   }
		 }
	}
	public void showUI(){
		//设置窗体的一些属性
		this.setTitle("(bmp)西北风光图片");//标题
		this.setSize(image_width,image_heigh); //大小
		this.setDefaultCloseOperation(3);  //当点击关闭按钮时,使程序退出
		this.setResizable(false);  //不能改变大小
		this.setVisible(true);    //使窗体实现
		g=this.getGraphics();    //获得窗体的画布对象
		repaint();               //重绘图片
	}
	/**
	 * 重写paint方法
	 */
	public void paint(Graphics g){
		super.paint(g);
		for(int h=0;h<image_heigh;h++){
			for(int w=0;w<image_width;w++){
				g.setColor(new Color(imageR[h][w],imageG[h][w],imageB[h][w]));//设置每个像素点的颜色
				g.drawLine(w,h,w,h);                        //重画每一个点
			}
		}
	}
}



遇到的问题:



在测试的时候,开始总是出现


OutOfMemoryError

异常,完全崩溃,看不懂啊!后来不知道怎么搞的,就将图片的格式换了换。才知道,是我只是将开始的jpg图片的后缀改了,但是它并不是bmp格式的图像。才终于解决这个问题。




其次,就是,在将文件包装成一个普通数据类型的输出流时,我使用的是DataInputStream流,以致图片重绘的时候,出现图像扭曲闪屏现象。在这里,使用缓冲流好些,不会出现这种情况。



其实,这次的学习给我留下了深刻的印象。因为这次的学习是由我们班的同学组织学习的。哎。。。一定要好好像他学习啊!!!









二.下面是几种常见的图像文件格式:






1.JPEG


格式




JPEG


是常见的一种图像格式,


JPEG


文件的扩展名为


.jpg





.jpeg










JPEG


是与平台无关的格式,支持最高级别的压缩,其压缩技术十分先进,它用有损压缩方式去除冗余的图像和彩色数据,获取得极高的压缩率的同时能展现十分丰富生动的图像,所以说


JPEG


是一种很灵活的格式,但这种压缩是有损耗的。文件大小是以图像质量为代价的。


JPEG


不适用于所含颜色很少、具有大块颜色相近的区域或亮度差异十分明显的较简单的图片。








2.TIFF


:标记图像文件格式




TIFF


以任何颜色深度存储单个光栅图像。由于


TIFF


格式结构较为复杂,兼容性较差,因此有时你的软件可能不能正确识别


TIFF


文件(现在绝大部分软件都已解决了这个问题)。目前在


Mac





PC


机上移植


TIFF


文件也十分便捷,因而


TIFF


现在也是微机上使用最广泛的图像文件格式之一。




TIFF


支持可选压缩,但不适用于在


Web


浏览器中查看。





3.GIF


格式




GIF


格式的特点是压缩比高,磁盘空间占用较少,被广泛应用。









GIF


的缺点,即不能存储超过


256


色的图像。尽管如此,这种格式仍在网络上大行其道应用,这和


GIF


图像文件短小、下载速度快、可用许多具有同样大小的图像文件组成动画等优势是分不开的。





4.PNG


格式




PNG





PortableNetworkGraphics


)是一种新兴的网络图像格式。




PNG


是目前保证最不失真的格式,它汲取了


GIF





JPG


二者的优点,存贮形式丰富,兼有


GIF





JPG


的色彩模式;它能把图像文件压缩到极限以利于网络传输,但又能保留所有与图像品质有关的信息,因为


PNG


是采用无损压缩方式来减少文件的大小,这一点与牺牲图像品质以换取高压缩率的


JPG


有所不同;它的另一特点是显示速度很快,只需下载


1/64


的图像信息就可以显示出低分辨率的预览图像。而且


PNG


同样支持透明图像的制作,透明图像在制作网页图像的时候很有用,我们可以把图象背景设为透明,用网页本身的颜色信息来代替设为透明的色彩,这样可让图像和网页背景很和谐地融合在一起。




PNG


的缺点是不支持动画应用效果






版权声明:本文为iteye_18620原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。