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();
}