如果有个伪文青问你:“你能读懂这个世界吗?”作为技术男的你就要很淡定的说:“只要把它的协议给我,就有办法读懂它。”读,就是对信息的分析解释理解。世界是复杂的,可对于信息的有效传递,我认为,可以简单的概括为“理解——表达”的模式,而连接理解和表达的逻辑桥梁就是规则、协议。虽然是技术男,但你是不是也经常因为不理解心爱的人的心思而犯愁,她/他想要苹果,你却认为她/他想要的是香蕉,唉,没办法,网上没有这样的协议可供下载,或许有用的就是心理学规律了。而现在要讲的就是bmp的读取,我们要用电脑去理解bmp文件描述的画面,从某个角度来说,这要比用心理解那个ta要简单,因为计算机表达的都是确定的信息,是用一个个01串,一个一个字节去沟通的。
首先从bmp文件的协议入手,这是我在网上搜到的bmp解析文档:http://wenku.baidu.com/view/e9ed3ae39b89680203d8257d.html,我就不多说了,总而言之,bmp的协议主要由四个部分组成:1.文件头信息块。2.图像描述信息块。3.颜色表。4.图像数据区。我们先从简单的24位bmp图开始,而24位图是不用颜色表的。为了比较好的理解协议,一开始我是用UltraEdit十六进制的显示方式打开一张小图片,一个一个去对照理解的,如果有带有标记的红绿蓝三种颜色每种都有256色的笔,我们也可以参照协议画出那幅图,哈哈,当然只是假设。既然我的目标是用我编的程序显示bmp文件,那么我就抓住关键点得就行了——文件协议所对应的的有用信息:1.图片的长和宽。2.图片每个像素点的颜色值。3.基本规律:图像的扫描方式是自下而上,自左而右的;为了方便扫描,文件的行字节数是4的倍数,不够的用0补齐。代码实现如下:
因为在读取图片的长和宽时,字节需要逆置再读入一个整型
/** * 将读入的四个字节,按第一个字节为最低位,最后一个字节为最高位转为整数型 * @param dis 输入流 * @return 所需整数 */ public int changeInt(DataInputStream dis){ int ch1=0,ch2=0,ch3=0,ch4=0; try { ch1 = dis.read(); ch2 = dis.read(); ch3 = dis.read(); ch4 = dis.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); } catch (Exception e) { e.printStackTrace(); } return ((ch1 << 0) + (ch2 << 8) + (ch3 << 16) + (ch4 << 24)); }
解决了这个问题,我们就可以依次读取我们需要的数据了
/** * 读取文件 * @param f文件路径 */ public void readFile(File f){ try { fis = new FileInputStream(f); dis = new DataInputStream(fis); //读取文件头信息块,共14个字节 int firstLen = 14; byte[] bs1 = new byte[firstLen]; dis.read(bs1); //读取图像描述信息块,获得图片长宽,共40个字节 dis.readInt(); Wide = this.changeInt(dis); Height = this.changeInt(dis); int secondLen = 28; byte[] bs2 = new byte[secondLen]; dis.read(bs2); //读取图像数据区,将获取值存入二维坐标颜色数组 R = new int[Height][Wide]; G = new int[Height][Wide]; B = new int[Height][Wide]; if(!(Wide*3%4==0)){ skipWide= 4-Wide*3%4; }//记得哦,一次扫描四个字节,不够四个字节用0补齐,那么我们就要跳过读了 for(int h=Height-1;h>=0;h--){ for(int w=0;w<Wide;w++){ int blue=dis.read(); int green=dis.read(); int red=dis.read(); R[h][w]=red; G[h][w]=green; B[h][w]=blue; if(w==Wide-1){ dis.skipBytes(skipWide); } } } } catch (Exception e) { e.printStackTrace(); } }
这样就可以显示图片了
/** * 将图片显示 */ public void displayIma(){ Graphics g = jf.getGraphics(); for(int h=0;h<Height;h++){ for(int w=0;w<Wide;w++){ g.setColor(new Color(R[h][w],G[h][w],B[h][w])); g.drawLine(w+(BmpViewer.wide-Wide)/2, h+(BmpViewer.hight-Height)/2, w+(BmpViewer.wide-Wide)/2, h+(BmpViewer.hight-Height)/2); } } }
终于可以读懂bmp了!如果要用bmp的格式去表达一张图片呢?就是把图片保存下来。答案很简单:依照协议去表达。非图像数据区的写入具体代码就不show了。不过可以增加一个好玩的小功能,给图片上的美女化化妆再保存下来。下边是写入像素点颜色数据和在图片上画画并保存下来的方法的代码:
/** * 将图片和所画的图放入缓存图片中 */ public void changetoBuffer(){ bfi = new BufferedImage(BmpViewer.wide,BmpViewer.hight,BufferedImage.TYPE_3BYTE_BGR); Graphics g2 = bfi.getGraphics(); g2.setColor(jf.getBackground()); g2.fillRect(0, 0, BmpViewer.wide, BmpViewer.hight); for(int h=0;h<Height;h++){ for(int w=0;w<Wide;w++){ g2.setColor(new Color(R[h][w],G[h][w],B[h][w])); g2.drawLine(w+(BmpViewer.wide-Wide)/2, h+(BmpViewer.hight-Height)/2, w+(BmpViewer.wide-Wide)/2, h+(BmpViewer.hight-Height)/2); } } for(int i=0;i<DrawListener.list.size();i++){ int x = DrawListener.list.get(i).x; int y = DrawListener.list.get(i).y; g2.setColor(Color.red); g2.fillOval(x, y, 8, 8); } } /** * 获得每个点RGB值 */ public void getImageRgb(){ for(int h=jf.getHeight()-1;h>=0;h--){ for(int w=0;w<jf.getWidth();w++){ int rgb = bfi.getRGB(w, h); this.changRgb(rgb,h,w);//因为BufferedImage的getRGB方法只能获得改点的TYPE_INT_ARGB型值,所以要转换成我们想要的TYPE_3BYTE_BGR } } } /** * 将相应像素点的颜色值变为我们所需的TYPE_3BYTE_BGR值,并存储的坐标颜色数组中 * @param rgb TYPE_INT_ARGB型值 * @param h 纵坐标值 * @param w 横坐标值 */ public void changRgb(int rgb,int h,int w){ R1[h][w] =(int) ((rgb & 0xff0000 ) >> 16) ; G1[h][w]= (int) ((rgb & 0xff00 ) >> 8) ; B1[h][w]= (int) ( rgb & 0xff ); System.out.println(">>>>>>>>>>>>>>>>>>"); }
给美女涂上口红,保存下来,可以在Windows自带的图片查看器里显示了!
现在是不是漂亮多了!!!呵呵
程序做的很粗糙,望多多指教!不过这样我们就已经实现了bmp协议下的基于计算机的“理解——表达”,那么只要有物理介质,并且有在介质中传递的协议,是不是我们就能够通信了呢?未完待续~~
相关推荐
此函数可以读bmp格式图片。已经可以bmp24位bmp565格式的
读bmp图片,将rgb存入txt 并再输出bmp图片
读取bmp读取bmp读取bmp读取bmp读取bmp读取bmp图片读取bmp读取bmp读取bmp读取bmp读取bmp读取bmp图片 读取bmp读取bmp读取bmp读取bmp读取bmp读取bmp图片 读取bmp读取bmp读取bmp读取bmp读取bmp读取bmp图片 读取bmp读取...
一、BMP文件分析 1. 什么是BMP(位图)? 常见的图像文件格式有:BMP、JPG...BMP格式的图片,没有使用任何压缩算法,这种方式在以前使用的比较多,现在用的就比较少了,不过为了学习图像处理算法,所以先以该种格式的文
该工程,是用Eclipse开发Android2.1版本的bmp图片查看器。需要说明的是,要把你的.bmp图片放到res/drawable-mdpi目录下,且图片名要改为tu1.bmp,tu2.bmp,...,tuN.bmp。
获取BMP280气压计的温度、气压、海拔。内部自带驱动和用户移植接口,非常方便开发人员开发。
C语言对BMP图像的读和写和对像素的操作
DLL中封装BMP图像的读显程序
vc++ 读24位bmp灰度图 并将其转为8位灰度图 很好用
典型的BMP图像文件由四部分组成: A:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息; B:位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息; C:3:调色板,这个部分是可...
经典bmp小图标,编程用,可以美化你的程序。经典bmp小图标,编程用,可以美化你的程序。
资源为32位bmp转24位bmp图片的C++源码,适合C++开发者
利用读文件的方式直接读取BMP方式。比普通方式更加简单,明了。
BMP-2在人骨不连组织中的表达及其意义,王璐,刘傥,目的:通过对具有典型骨不连表现的患者进行实验研究,证实肥大性骨不连组织与萎缩性骨不连组织有相同的成骨潜能,为临床治疗骨不
支持通用格式的BMP文件读取 24比特格式的BMP文件写 比特 , 通用
bmp2h.exe是一个专门用来转换64K色bmp图片用的; 它可以把bmp格式(24位深度)的图片转换成64K色的数组数据(*.c文件); 点击按键“添加”将一个bmp图片添加进来,然后点击按键“转换”就会生成图片数组文件。 在S3...
可以实现jpg图片到256色bmp图片的转换,24位bmp图片到256色bmp图片的转换,含源代码,重新编译后即可
BMP文件格式BMP文件BMP文件格式格式
vc直接读文件方式显示BMP位图
24位BMP转32位BMP的c#代码测试可用,适用于linux开发板的LCD需要32位深度的BMP的场合,代码参看了网友彭军的代码,我将它实现了并上传....柏林