BMP文件格式分析
第0--1字节:必须是‘B’'M'两个字母
2--5字节:位图文件的大小,以字节为单位
6--7字节:位图文件保留字必须为0
8--9字节:位图文件保留字,必须为0
10--13字节:位图数据的其实位置,以相对于位图,文件头的偏移量,以字节
为单位
其次是位图信息头信息(一般40个字节),用于说明位图尺寸等信息
第0--3字节:本结构所占字节数(一般40个字节)
4--7字节:位图的宽度,以字节为单位
8--11字节:位图的高度,以字节为单位
12--13字节:目标设备的级别,必须为1
14--15字节:每个像素所需要的位数,必须是1(双色),4(16色),8(256
色)24()真彩色之一
16--19字节:位图压缩类型,如果是0(不压缩)
20--13字节:位图的大小,以字节为单位
24--27字节:位图水平分辨率,每米像素数
28--31字节:位图垂直分辨率,每米像素数
32--35字节:位图实际使用的颜色表中的颜色数
36--39字节:位图显示过程中重要的颜色数
第三部分是调色板,这个我不是很了解,因为当你保存的每个像素所需要的位数为
24时,就可以不需要它。
最后一部分是每个像素点的颜色值的保存,它是用三个字节来表示一个像素的颜色
情况,而且每个字节分别保存的是(B、G、R)三基色。
下面是我用代码来实现的bmp图片格式的保存
1、bmp文件的保存
//创建文件保存对象 try{ javax.swing.JFileChooser jfc=new javax.swing.JFileChooser(); int num=jfc.showSaveDialog(null); if(num==0){ //获得文件的;路径 String strg=jfc.getSelectedFile().getAbsolutePath()+".bmp"; //创建文件输出流对象 java.io.FileOutputStream ops=new java.io.FileOutputStream(strg); //先写头信息,定义长度为14的字节数组 byte byh[]=new byte[14]; //依次给数组赋值 byh[0]='B'; byh[1]='M'; //文件的大小,转化为字节 int size=40; byh[2]=(byte)size; size=size>>8; byh[3]=(byte)size; size=size>>8; byh[4]=(byte)size; size=size>>8; byh[5]=(byte)size; //两个保留字,必须为零 byh[6]=(byte)0; byh[7]=(byte)0; byh[8]=(byte)0; byh[9]=(byte)0; //同样的将位图偏移量按照同样的方式存入数组 int count=54; byh[10]=(byte)count; count=count>>8; byh[11]=(byte)count; count=count>>8; byh[12]=(byte)count; count=count>>8; byh[13]=(byte)count; //写入头信息 ops.write(byh); //位图信息头信息,用于说明位图尺寸等信息 byte byb[]=new byte[40]; //用4个字节存储位图头信息的大小 byb[0]=40; byb[1]=0; byb[2]=0; byb[3]=0; //存储的位图宽度信息 int width=moslistener.data[0].length; byb[4]=(byte)width; width=width>>8; byb[5]=(byte)width; width=width>>8; byb[6]=(byte)width; width=width>>8; byb[7]=(byte)width; //存储的位图高度信息 int height=moslistener.data.length; byb[8]=(byte)height; height=height>>8; byb[9]=(byte)height; height=height>>8; byb[10]=(byte)height; height=height>>8; byb[11]=(byte)height; //目标设备级别的存储,必须为1 byb[12]=1; byb[13]=0; //每个像素所需要的位数的存储 byb[14]=24; byb[15]=0; //说明数据压缩的类型,4个字节,0表示不压缩 byb[16]=0; byb[17]=0; byb[18]=0; byb[19]=0; //存放图片大小的信息 int image=moslistener.data.length*moslistener.data[0].length*3; byb[20]=(byte)image; image=height>>8; byb[21]=(byte)image; image=image>>8; byb[22]=(byte)image; image=image>>8; byb[23]=(byte)image; //剩下的不重要,可以全部赋0 for(int y=24;y<byb.length;y++){ byb[y]=0; } //写入信息 ops.write(byb); //定义一个字节数组,要来写入B、G、R byte []color=new byte[3]; int RGB=0; //开始写入位图信息,图像的全部 for(int i=moslistener.data.length-1;i>=0;i--){ for(int j=0;j<moslistener.data[i].length;j++){ //取得每个点的颜色 RGB=moslistener.data[i][j]; //将像素值转换成字节,存取到color数组中 color[0]=(byte)RGB; RGB=RGB>>8; color[1]=(byte)RGB; RGB=RGB>>8; color[2]=(byte)RGB; //写入文件中 ops.write(color); } //如果宽度不是4的倍数,则补零 for(int h=0;h<(moslistener.data[i].length*3)%4;h++){ ops.write((byte)0); } } //强制写出,关闭输出流 ops.flush(); ops.close(); } }catch(Exception ef){ ef.printStackTrace(); }
2、bmp文件的打开
//打开bmp的处理过程 try{ //创建一个文件打开器 javax.swing.JFileChooser jfc=new javax.swing.JFileChooser(); int num=jfc.showOpenDialog(null); if(num==0){ //获得文件的路径 String str1=jfc.getSelectedFile().getAbsolutePath(); //创建文件输入流对象 java.io.FileInputStream ips=new java.io.FileInputStream(str1); //跳过10个字节 ips.skip(10); //读取位图文件的起始位置 byte[] by1=new byte[4]; ips.read(by1); //转化为一个整数 int sta=changeInt(by1); //跳过一些字节 ips.read(by1); //读取位图的宽度,以字节为单位 ips.read(by1); int width=changeInt(by1); //读取位图的高度,以字节为单位 ips.read(by1); int height=changeInt(by1); //设置画布的大小 dr.mb3.setPreferredSize(new Dimension(width,height)); //刷新一下 dr.mb3.updateUI(); //跳过一些字节 ips.skip((sta-26)); //定义一个三个int的数组,又来保存B、G、R int []by2=new int[3]; //定义一个二维数组,用来保存颜色值 int [][]date=new int[height][width]; for(int i=date.length-1;i>=0;i--){ for(int j=0;j<date[i].length;j++){ //读取颜色,用数组保存 for(int k=0;k<3;k++){ by2[k]=ips.read(); } //转化为颜色对象 Color color=new Color(by2[2],by2[1],by2[0]); date[i][j]=color.getRGB(); } //如果宽度不是4的倍数,则取出零 for(int h=0;h<(date[i].length*3)%4;h++){ ips.read(); } } moslistener.data=date; //关闭输入流 ips.close(); //刷新面板 dr.mb3.updateUI(); } }catch(Exception ef){ ef.printStackTrace(); }