自制BMP文件的格式打开和保存

以前做项目自制了一个画板,但是始终没实现以BMP格式保存和打开图片功能,今天把BMP格式的保存和打开的方式给大家讲一下。

附件如下:

点击这里

先了解一下

【BMP文件结构】

典型的BMP图像文件由四部分构成1.位图文件头(14字节):包含BMP的类型,文件头偏移量等2.位图信息头(40字节):包含位图尺寸,宽高等3.颜色表:由若干表项组成。每个表项是一个RGBQUAD类型的结构,结构由R值、G值、B值和一个数值为0的保留字节组成。RGBQUAD个数由biBitCount(每个像素所需位数)决定,biBitCount=24时,没有颜色表项4.位图数据:位图数据记录了位图的每个像素值,记录顺序的在扫描行内从左到右,从下到上。当biBitCount = 24时,一个像素占三个字节,即R、G、B三个颜色值(0-255)。

【位图文件头】

int bfType;//(0-1字节)位图文件的类型,为’B’、’M’两个字母int bfSize;//(2-5字节)位图文件大小int usignedshort bfReserved1;//(6-7字节)位图文件保留字,为0int usignedshort bfReserved2;//(8-9字节)位图文件保留字,为0int bfOffBits;//(10-13字节)文件头的偏移量【位图信息头】

int Size;//(14-17字节)本结构所占用的字节数int image_width;//(18-21字节)位图的宽度,单位为像素int image_height;//(22-25字节)位图的高度,单位为像素int Planes;//(26-27字节)目标设备的级别,为1intbiBitCount;//(28-29字节)//每个像素所需的位数,必须为1、4、8、24其中一个,分别代表双色、16色,256色和真彩色

int biCompression;//(30-33字节)位图压缩类型,为0int SizeImage;//(34-37字节)位图大小int biXPelsPerMeter;//(38-41字节)位图水平分辨率int biYPelsPerMeter;//(42-45字节)位图垂直分辨率int biClrUsed;//(46-49字节)位图实际使用的颜色表中的颜色数int biClrImportant;//(50-53字节)位图显示过程中重要的颜色数

由于我们选择的是24位的BMP图片,所以今天不讨论颜色表的问题。

【BMP格式文件读取的步骤】

1.利用DataInputStream流将文件中的信息按一定次序读入2.获取文件中的重要信息3.根据信息绘制图像按一定次序:因为我们在文件中读入的是一个一个的字节,而实际操作需要的最少也是一个int(即四个字节),因此我们需要将byte数组转化成int型

重要信息:虽然BMP格式文件中有很多信息,,但是打开和保存一个BMP文件只需要几个简单的信息。例如image_width文件宽度和image_height文件高度

【BMP格式文件的读取】代码如下:

/*** 读取BMP格式文件*/public void BMPOpen(String path, int[][] imageR, int[][] imageG,int[][] imageB) {try {// 创建intputStream对象InputStream is = new FileInputStream(path);// 创建DataInputStream对象DataInputStream dis = new DataInputStream(is);// 读入BMP头文件int bflen = 14;byte bf[] = new byte[bflen];dis.read(bf, 0, bflen);// 读入位图信息头int bilen = 40;byte[] bi = new byte[bilen];dis.read(bi, 0, bilen);// 获取一些重要信息image_width = changeInt(bi, 7);// 源图宽度image_height = changeInt(bi, 11);// 源图高度int nbitcount = ((int) bi[15] & 0xff) << 8 | (int) bi[14] & 0xff;// 位数int nsizeimage = changeInt(bi, 23);// 源图大小int skip_width = 0;// 需要跳过的字节数if (!(image_width * 3 % 4 == 0)) {//判断后面是否需要补0skip_width = 4 – image_width * 3 % 4;}for (int h = image_height – 1; h >= 0; h–) {for (int w = 0; w < image_width; w++) {// 分别读入B、G、R,并放入数组int blue = dis.read();int green = dis.read();int red = dis.read();imageR[h][w] = red;imageG[h][w] = green;imageB[h][w] = blue;if (w == 0) {// 跳过每一行的补0的项System.out.println(dis.skipBytes(skip_width));}}}// 清空数据流dis.close();is.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}其中调用的changeInt()函数定义如下:

/** * 转成Int方法 */public int changeInt(byte[] bi, int start) {return (((int) bi[start] & 0xff) << 24)| (((int) bi[start – 1] & 0xff) << 16)| (((int) bi[start – 2] & 0xff) << 8)| ((int) bi[start – 3] & 0xff);}

在解释之前,先给大家补一点关于Java的位运算符的知识

【Java位运算符】

按位与 & 两位同时为1,结果才为1,否则为0

0000 1111 & 1111 0000 = 0000 0000

按位或 | 两位中至少一位为1,结果为1,否则为0

0000 1111 | 1111 0000 =1111 1111

感受不同地域不一样的节奏与表象。

自制BMP文件的格式打开和保存

相关文章:

你感兴趣的文章:

标签云: