java解析bmp文件
2013-07-04 17:38
155 查看
最近想做一个图片查看器,因为bmp的图片简单些,也就从这个入手。
运用的基本知识还是IO的,关键是在于对于“协议”的理解。
一直觉得这些个协议是个很帅气的东西。感觉就像密码一样,你读到了一个文件,你只有知道对方的“加密”方式,你才能正确的解读,否则你拿着也没用。就像你无法用记事本正确地打开一张图片一样,里面只会全是乱码。
言归正传,根据以上的说法,我们首先应该去了解的是BMP文件时如何写的。
BMP文件分为四个部分:文件头信息块,图像描述信息块,颜色表,图像信息区。
文件头信息块
这个部分主要是一些基本的信息,比如,开头两个字节最终读出来是BM,是标识BMP文件的,所以如果以后想要读多种文件分类,可以用开头的标识来分类。
因为此部分的信息后面读取图片意义不大,所以直接读出来,跳过。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
//读取前面14个字节
int bflen=14;
byte bf[]=new byte[bflen];
dis.read(bf);
图像描述信息块
此部分包含图像的一些基本信息,包括图像大小,宽,高,压缩方式等等。
宽高是一个非常重要的数据,因此在此我们要获取到宽和高。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
//读取后面40个字节,并且获取到图像的宽和高
int bilen=40;
byte bi[]=new byte[bilen];
dis.read(bi,0,bilen);
image_width=ChangeInt(bi,7);
image_height=ChangeInt(bi,11);
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
/**
* byte转变为int数据的方法
* @param bi传入的数组
* @param end四个byte型数的最后的一个
* @return
*/
public int ChangeInt(byte[] bi,int end){
return(((int)bi[end]&0xff)<<24)
|(((int)bi[end-1]&0xff)<<16)
|(((int)bi[end-2]&0xff)<<8)
|(int)bi[end-3]&0xff;
}
颜色表
此区域大小由颜色模式而定,在后面读取中基本不怎么用到,所以在此就不详解了。
图像数据区
BMP格式的图像分为2色图,16色图,256色图以及真彩图。
除了真彩色以外,其它三种形式均要用00补齐行字节数,使之成为4的整数倍。
也因此,我们在处理图像的时候,要注意这个问题,跳过是用来补齐4的整数倍的数据。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
/**
* 显示颜色的方法
* 对颜色的处理
* @param dis数据流
*/
public void showRGB24(DataInputStream dis){
if(!(image_width*3%4==0)){
skip_width=4-image_width*3%4;
}
//申请数组空间
imageG=new int[image_height][image_width];
imageB=new int[image_height][image_width];
imageR=new int[image_height][image_width];
for(int h=image_height-1;h>=0;h--){
for(int w=0;w<image_width;w++){
try {
int blue= dis.read();
int green=dis.read();
int red=dis.read();
imageB[h][w]=blue;
imageG[h][w]=green;
imageR[h][w]=red;
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
if(w==0){
try {
System.out.println(dis.skipBytes(skip_width));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
存储好颜色之后,后面再重绘出图片就OK 啦。
![](http://dl2.iteye.com/upload/attachment/0086/3834/496a63f5-32df-37d6-aecd-5675cc474429.jpg)
一点小结:
包括后面要做的通信项目,个人觉得关键仍然是协议。不是一种看看就可以的状态,要深入去了解,包括一些特殊的情况。透过现象看本质吧~
运用的基本知识还是IO的,关键是在于对于“协议”的理解。
一直觉得这些个协议是个很帅气的东西。感觉就像密码一样,你读到了一个文件,你只有知道对方的“加密”方式,你才能正确的解读,否则你拿着也没用。就像你无法用记事本正确地打开一张图片一样,里面只会全是乱码。
言归正传,根据以上的说法,我们首先应该去了解的是BMP文件时如何写的。
BMP文件分为四个部分:文件头信息块,图像描述信息块,颜色表,图像信息区。
文件头信息块
这个部分主要是一些基本的信息,比如,开头两个字节最终读出来是BM,是标识BMP文件的,所以如果以后想要读多种文件分类,可以用开头的标识来分类。
因为此部分的信息后面读取图片意义不大,所以直接读出来,跳过。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
//读取前面14个字节
int bflen=14;
byte bf[]=new byte[bflen];
dis.read(bf);
//读取前面14个字节 int bflen=14; byte bf[]=new byte[bflen]; dis.read(bf);
图像描述信息块
此部分包含图像的一些基本信息,包括图像大小,宽,高,压缩方式等等。
宽高是一个非常重要的数据,因此在此我们要获取到宽和高。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
//读取后面40个字节,并且获取到图像的宽和高
int bilen=40;
byte bi[]=new byte[bilen];
dis.read(bi,0,bilen);
image_width=ChangeInt(bi,7);
image_height=ChangeInt(bi,11);
//读取后面40个字节,并且获取到图像的宽和高 int bilen=40; byte bi[]=new byte[bilen]; dis.read(bi,0,bilen); image_width=ChangeInt(bi,7); image_height=ChangeInt(bi,11);
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
/**
* byte转变为int数据的方法
* @param bi传入的数组
* @param end四个byte型数的最后的一个
* @return
*/
public int ChangeInt(byte[] bi,int end){
return(((int)bi[end]&0xff)<<24)
|(((int)bi[end-1]&0xff)<<16)
|(((int)bi[end-2]&0xff)<<8)
|(int)bi[end-3]&0xff;
}
/** * byte转变为int数据的方法 * @param bi传入的数组 * @param end四个byte型数的最后的一个 * @return */ public int ChangeInt(byte[] bi,int end){ return(((int)bi[end]&0xff)<<24) |(((int)bi[end-1]&0xff)<<16) |(((int)bi[end-2]&0xff)<<8) |(int)bi[end-3]&0xff; }
颜色表
此区域大小由颜色模式而定,在后面读取中基本不怎么用到,所以在此就不详解了。
图像数据区
BMP格式的图像分为2色图,16色图,256色图以及真彩图。
除了真彩色以外,其它三种形式均要用00补齐行字节数,使之成为4的整数倍。
也因此,我们在处理图像的时候,要注意这个问题,跳过是用来补齐4的整数倍的数据。
Java代码
![](http://lwangkangrui.iteye.com/images/icon_copy.gif)
![](http://lwangkangrui.iteye.com/images/icon_star.png)
![](http://lwangkangrui.iteye.com/images/spinner.gif)
/**
* 显示颜色的方法
* 对颜色的处理
* @param dis数据流
*/
public void showRGB24(DataInputStream dis){
if(!(image_width*3%4==0)){
skip_width=4-image_width*3%4;
}
//申请数组空间
imageG=new int[image_height][image_width];
imageB=new int[image_height][image_width];
imageR=new int[image_height][image_width];
for(int h=image_height-1;h>=0;h--){
for(int w=0;w<image_width;w++){
try {
int blue= dis.read();
int green=dis.read();
int red=dis.read();
imageB[h][w]=blue;
imageG[h][w]=green;
imageR[h][w]=red;
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
if(w==0){
try {
System.out.println(dis.skipBytes(skip_width));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/** * 显示颜色的方法 * 对颜色的处理 * @param dis数据流 */ public void showRGB24(DataInputStream dis){ if(!(image_width*3%4==0)){ skip_width=4-image_width*3%4; } //申请数组空间 imageG=new int[image_height][image_width]; imageB=new int[image_height][image_width]; imageR=new int[image_height][image_width]; for(int h=image_height-1;h>=0;h--){ for(int w=0;w<image_width;w++){ try { int blue= dis.read(); int green=dis.read(); int red=dis.read(); imageB[h][w]=blue; imageG[h][w]=green; imageR[h][w]=red; } catch (IOException e) { e.printStackTrace(); System.exit(0); } if(w==0){ try { System.out.println(dis.skipBytes(skip_width)); } catch (IOException e) { e.printStackTrace(); } } } } }
存储好颜色之后,后面再重绘出图片就OK 啦。
![](http://dl2.iteye.com/upload/attachment/0086/3834/496a63f5-32df-37d6-aecd-5675cc474429.jpg)
一点小结:
包括后面要做的通信项目,个人觉得关键仍然是协议。不是一种看看就可以的状态,要深入去了解,包括一些特殊的情况。透过现象看本质吧~
相关文章推荐
- java解析bmp文件
- 解析Java的Hibernate框架中的持久化类和映射文件
- Java+Flex+POI 解析Excel文件(读取文件中想要的内容)
- java jar包解析:打包文件,引入文件
- java常用类解析五:IO系统File类及文件搜索工具类
- java通过解析文件获取apk版本等信息
- java常用类——java web接受文件表单时常用文件解析方法
- Java Class文件结构解析 及 实例分析验证
- 分别用js和java解析xml文件
- Java解析Excel文件
- java 加载解析properties 文件
- java通过ftp方式读取文件,并解析入库
- Java解析JSON文件的方法
- java解析XML配置文件及log4j开源日志系统
- java通过jxl解析Excel文件
- java解析TXT格式文件
- JAVA SAX解析XML文件
- java Excel 文件解析存入数据库 整型数据被整成科学记数法
- 如何用C语言解析BMP文件的结构
- Java 的 Class 文件格式——解析魔数和版本号