java bmp_java解析bmp文件

本文介绍了使用Java解析BMP文件的过程,从文件头信息块、图像描述信息块、颜色表到图像信息区,详细讲解了每个部分的作用和读取方法,特别是如何获取图像的宽和高。通过理解BMP文件的协议,实现对图像数据的处理和显示。
摘要由CSDN通过智能技术生成

最近想做一个图片查看器,因为bmp的图片简单些,也就从这个入手。

运用的基本知识还是IO的,关键是在于对于“协议”的理解。

一直觉得这些个协议是个很帅气的东西。感觉就像密码一样,你读到了一个文件,你只有知道对方的“加密”方式,你才能正确的解读,否则你拿着也没用。就像你无法用记事本正确地打开一张图片一样,里面只会全是乱码。

言归正传,根据以上的说法,我们首先应该去了解的是BMP文件时如何写的。

BMP文件分为四个部分:文件头信息块,图像描述信息块,颜色表,图像信息区。

文件头信息块

这个部分主要是一些基本的信息,比如,开头两个字节最终读出来是BM,是标识BMP文件的,所以如果以后想要读多种文件分类,可以用开头的标识来分类。

因为此部分的信息后面读取图片意义不大,所以直接读出来,跳过。

Java代码 de88fc7bde64c316e905f45ba8945776.gif 47fa6dadf02837df2d843942312e19c6.png

b124fadd4d523207aa81e40b90da4a0a.gif

//读取前面14个字节

intbflen=14;

bytebf[]=newbyte[bflen];

dis.read(bf);

//读取前面14个字节

int bflen=14;

byte bf[]=new byte[bflen];

dis.read(bf);

图像描述信息块

此部分包含图像的一些基本信息,包括图像大小,宽,高,压缩方式等等。

宽高是一个非常重要的数据,因此在此我们要获取到宽和高。

Java代码 de88fc7bde64c316e905f45ba8945776.gif 47fa6dadf02837df2d843942312e19c6.png

b124fadd4d523207aa81e40b90da4a0a.gif

//读取后面40个字节,并且获取到图像的宽和高

intbilen=40;

bytebi[]=newbyte[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代码 de88fc7bde64c316e905f45ba8945776.gif 47fa6dadf02837df2d843942312e19c6.png

b124fadd4d523207aa81e40b90da4a0a.gif

/**

* byte转变为int数据的方法

* @param bi传入的数组

* @param end四个byte型数的最后的一个

* @return

*/

publicintChangeInt(byte[] bi,intend){

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代码 de88fc7bde64c316e905f45ba8945776.gif 47fa6dadf02837df2d843942312e19c6.png

b124fadd4d523207aa81e40b90da4a0a.gif

/**

* 显示颜色的方法

* 对颜色的处理

* @param dis数据流

*/

publicvoidshowRGB24(DataInputStream dis){

if(!(image_width*3%4==0)){

skip_width=4-image_width*3%4;

}

//申请数组空间

imageG=newint[image_height][image_width];

imageB=newint[image_height][image_width];

imageR=newint[image_height][image_width];

for(inth=image_height-1;h>=0;h--){

for(intw=0;w

try{

intblue= dis.read();

intgreen=dis.read();

intred=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

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 啦。

dd89ae8956712950a76628be928be13e.png

一点小结:

包括后面要做的通信项目,个人觉得关键仍然是协议。不是一种看看就可以的状态,要深入去了解,包括一些特殊的情况。透过现象看本质吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值