java读取bitmap文件
来源:互联网 发布:2017seo新手教程 编辑:程序博客网 时间:2024/04/28 23:05
读取24位bitmap(bmp)格式图片文件
//读取bmp图片文件
package pcm24; import java.awt.Color; import java.awt.Graphics; import java.io.IOException; public class BmpRead24 extends javax.swing.JFrame { /** * */ private static final long serialVersionUID = 1L; /** * 位图的宽 */ private static int width; /** * 位图的高 */ private static int height; /** * 位图数据数组,即一个像素的三个分量的数据数组 */ private static int[][] red, green, blue; Graphics g; public static void main(String args[]) { BmpRead24 bmp = new BmpRead24(); bmp.init(); } public void init() { try { // 通过bmp文件地址创建文件输入流对象 java.io.FileInputStream fin = new java.io.FileInputStream( "C:\\Documents and Settings\\专属于我\\桌面\\未命名1.bmp"); // 根据文件输入流对象创建原始数据输入对象 // 这里既可以用原始数据输入流来读取数据,也可以用缓冲输入流来读取,后者速度相比较快点。 // java.io.DataInputStream bis = new java.io.DataInputStream(fin); java.io.BufferedInputStream bis = new java.io.BufferedInputStream( fin); // 建立两个字节数组来得到文件头和信息头的数据 byte[] array1 = new byte[14]; bis.read(array1, 0, 14); byte[] array2 = new byte[40]; bis.read(array2, 0, 40); // 翻译bmp文件的数据,即将字节数据转化为int数据 // 通过翻译得到位图数据的宽和高 width = ChangeInt(array2, 7); height = ChangeInt(array2, 11); // 调用可以将整个位图数据读取成byte数组的方法 getInf(bis); fin.close(); bis.close(); // 创建BMP对象来显示图画 showUI(); } catch (Exception e) { e.printStackTrace(); } } /** * 实现可将四个字节翻译int数据的方法 * * @param array2 * 存储字节的字节数组 * @param start * 起始字节 * @return 返回翻译后的int数据 */ public int ChangeInt(byte[] array2, int start) { // 因为char,byte,short这些数据类型经过运算符后会自动转为成int数据类, // 所以array2[start]&0xff的实际意思就是通过&0xff将字符数据转化为正int数据,然后在进行位运算。 // 这里需要注意的是<<的优先级别比&高,所以必须加上括号。 int i = (int) ((array2[start] & 0xff) << 24) | ((array2[start - 1] & 0xff) << 16) | ((array2[start - 2] & 0xff) << 8) | (array2[start - 3] & 0xff); return i; } /** * 得到位图数据的int数组 * * @param dis * 数据输入流对象 */ public void getInf(java.io.BufferedInputStream bis) { // 给数组开辟空间 red = new int[height][width]; green = new int[height][width]; blue = new int[height][width]; // 通过计算得到每行计算机需要填充的字符数。 // 为什么要填充?这是因为windows系统在扫描数据的时候,每行都是按照4个字节的倍数来读取的。 // 因为图片是由每个像素点组成。而每个像素点都是由3个颜色分量来构成的,而每个分量占据1个字节。 // 因此在内存存储中实际图片数据每行的长度是width*3。 int skip_width = 0; int m = width * 3 % 4; if (m != 0) { skip_width = 4 - m; } // 通过遍历给数组填值 // 这里需要注意,因为根据bmp的保存格式。 // 位图数据中height的值如果是正数的话: // 那么数据就是按从下到上,从左到右的顺序来保存。这个称之为倒向位图。 // 反之就是按从上到下,从左到右的顺序来保存。这个则称之为正向位图。 for (int i = height - 1; i >= 0; i--) { for (int j = 0; j < width; j++) { try { // 这里遍历的时候,一定要注意本来像素是有RGB来表示, // 但是在存储的时候由于windows是小段存储,所以在内存中是BGR顺序。 blue[i][j] = bis.read(); green[i][j] = bis.read(); red[i][j] = bis.read(); // 这里一定要知道,其实系统在给位图数据中添加填充0的时候,都是加在每行的最后。 // 但是我们在使用dis.skipBytes()这个方法的时候,却不一定要在最后一列。 // 系统在填充数据的时候,在数据上加了标记。 // 所以dis.skipBytes()这个方法只要调用了,那么系统就会自动不读取填充数据。 if (j == 0) { bis.skip(skip_width); } } catch (IOException e) { e.printStackTrace(); } } } } public void showUI() { // 对窗体的属性进行设置 this.setTitle("BMP解析");//设置标题 this.setSize(width, height);//设置窗体大小 this.setDefaultCloseOperation(3);//点击关闭,程序自动退出。 this.setResizable(false);//设置窗体大小不可以调节 this.setLocationRelativeTo(null);//设置窗体出现在屏幕中间 //创建自己的panel,用其来显示图形。 //因为如果将图片设置到窗体上显示时,因为jframe是一个复合组件,上面的组件有多个paint方法,所以在paint的时候会画两次, //而panel是只需画一次。 MyPanel panel = new MyPanel(); java.awt.Dimension di = new java.awt.Dimension(width, height);//设置panel大小 panel.setPreferredSize(di); this.add(panel);//窗体添加panel this.setVisible(true);//使窗体可见。 } public class MyPanel extends javax.swing.JPanel { /** * */ private static final long serialVersionUID = 1L; /** * 重写paint方法 */ public void paint(Graphics g) { // 这句话可写可不写,因为这句话是用来画jframe的contentPane的。 // 而这里我们已经在下面定义了contentPane的方法了 super.paint(g); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { g.setColor(new Color(red[i][j], green[i][j], blue[i][j])); // 如果这里画点的话,是不能使用下面注释掉的方法的,不行的话,亲,自己试试吧 // 因为系统在画椭圆的时候,是先画出椭圆的外切矩形。而矩形的边框刚好是占据一个像素点。 // 因此也就出现了,jdk api中说g.drawOval的像素点是width+1,height+1。 // 如果亲,你有更好的理解,请告诉我们。欢迎交流!!! // g.fillOval(j, i, 1, 1); g.fillRect(j, i, 1, 1);// 这里可以使用画点的任何方法,除了上面那种特例。 } } } } }
编写bmp
package pcm24; import java.awt.Color; /** * * 类说明:实现BMP文件格式的保存 * * @author 彭晨明 E-mail:2294552925@qq.com * * @version 创建时间:2012-2-5下午9:06:28 * */ public class BmpWrite24 { /** * 图形数据数组 */ private Color[][] pointArray; /** * 图形的宽 */ int width; /** * 图形的高 */ int height; /** * BMPWrite构造器的重载,传入图形数据数组 * * @param pointArray */ public BmpWrite24(Color[][] pointArray) { this.pointArray = pointArray; this.width = pointArray.length; this.height = pointArray[0].length; this.write(); } /** * 将数据传入内存 */ public void write() { try { // 创建输出流文件对象 java.io.FileOutputStream fos = new java.io.FileOutputStream( "C:\\Documents and Settings\\专属于我\\桌面\\未命名1.bmp"); // 创建原始数据输出流对象 java.io.DataOutputStream dos = new java.io.DataOutputStream(fos); // 给文件头的变量赋值 int bfType = 0x424d; // 位图文件类型(0—1字节) int bfSize = 54 + width * height * 3;// bmp文件的大小(2—5字节) int bfReserved1 = 0;// 位图文件保留字,必须为0(6-7字节) int bfReserved2 = 0;// 位图文件保留字,必须为0(8-9字节) int bfOffBits = 54;// 文件头开始到位图实际数据之间的字节的偏移量(10-13字节) // 输入数据的时候要注意输入的数据在内存中要占几个字节, // 然后再选择相应的写入方法,而不是它自己本身的数据类型 // 输入文件头数据 dos.writeShort(bfType); // 输入位图文件类型'BM' dos.write(changeByte(bfSize),0,4); // 输入位图文件大小 dos.write(changeByte(bfReserved1),0,2);// 输入位图文件保留字 dos.write(changeByte(bfReserved2),0,2);// 输入位图文件保留字 dos.write(changeByte(bfOffBits),0,4);// 输入位图文件偏移量 // 给信息头的变量赋值 int biSize = 40;// 信息头所需的字节数(14-17字节) int biWidth = width;// 位图的宽(18-21字节) int biHeight = height;// 位图的高(22-25字节) int biPlanes = 1; // 目标设备的级别,必须是1(26-27字节) int biBitcount = 24;// 每个像素所需的位数(28-29字节),必须是1位(双色)、4位(16色)、8位(256色)或者24位(真彩色)之一。 int biCompression = 0;// 位图压缩类型,必须是0(不压缩)(30-33字节)、1(BI_RLEB压缩类型)或2(BI_RLE4压缩类型)之一。 int biSizeImage = width * height;// 实际位图图像的大小,即整个实际绘制的图像大小(34-37字节) int biXPelsPerMeter = 0;// 位图水平分辨率,每米像素数(38-41字节)这个数是系统默认值 int biYPelsPerMeter = 0;// 位图垂直分辨率,每米像素数(42-45字节)这个数是系统默认值 int biClrUsed = 0;// 位图实际使用的颜色表中的颜色数(46-49字节),如果为0的话,说明全部使用了 int biClrImportant = 0;// 位图显示过程中重要的颜色数(50-53字节),如果为0的话,说明全部重要 // 因为java是大端存储,那么也就是说同样会大端输出。 // 但计算机是按小端读取,如果我们不改变多字节数据的顺序的话,那么机器就不能正常读取。 // 所以首先调用方法将int数据转变为多个byte数据,并且按小端存储的顺序。 // 输入信息头数据 dos.write(changeByte(biSize),0,4);// 输入信息头数据的总字节数 dos.write(changeByte(biWidth),0,4);// 输入位图的宽 dos.write(changeByte(biHeight),0,4);// 输入位图的高 dos.write(changeByte(biPlanes),0,2);// 输入位图的目标设备级别 dos.write(changeByte(biBitcount),0,2);// 输入每个像素占据的字节数 dos.write(changeByte(biCompression),0,4);// 输入位图的压缩类型 dos.write(changeByte(biSizeImage),0,4);// 输入位图的实际大小 dos.write(changeByte(biXPelsPerMeter),0,4);// 输入位图的水平分辨率 dos.write(changeByte(biYPelsPerMeter),0,4);// 输入位图的垂直分辨率 dos.write(changeByte(biClrUsed),0,4);// 输入位图使用的总颜色数 dos.write(changeByte(biClrImportant),0,4);// 输入位图使用过程中重要的颜色数 // 因为是24位图,所以没有颜色表 // 通过遍历输入位图数据 // 这里遍历的时候注意,在计算机内存中位图数据是从左到右,从下到上来保存的, // 也就是说实际图像的第一行的点在内存是最后一行 for (int i = height - 1; i >= 0; i--) { for (int j = 0; j < width; j++) { // 这里还需要注意的是,每个像素是有三个RGB颜色分量组成的, // 而数据在windows操作系统下是小端存储,对多字节数据有用。 int red = pointArray[i][j].getRed();// 得到位图点的红色分量 int green = pointArray[i][j].getGreen();// 得到位图点的绿色分量 int blue = pointArray[i][j].getBlue();// 得到位图点的蓝色分量 byte[] red1 = changeByte(red); byte[] green1 = changeByte(green); byte[] blue1 = changeByte(blue); dos.write(blue1,0,1); dos.write(green1,0,1); dos.write(red1,0,1); } } //关闭数据的传输 dos.flush(); dos.close(); fos.close(); System.out.println("success!!!"); } catch (Exception e) { e.printStackTrace(); } } /** * 将一个int数据转为按小端顺序排列的字节数组 * @param data int数据 * @return 按小端顺序排列的字节数组 */ public byte[] changeByte(int data){ byte b4 = (byte)((data)>>24); byte b3 = (byte)(((data)<<8)>>24); byte b2= (byte)(((data)<<16)>>24); byte b1 = (byte)(((data)<<24)>>24); byte[] bytes = {b1,b2,b3,b4}; return bytes; } }
阅读全文
0 0
- java读取bitmap文件
- 从文件中读取Bitmap
- Bitmap位图文件读取、保存、屏幕截图
- Bitmap位图文件读取、保存、屏幕截图
- android bitmap保存为文件及读取
- C#读取Win32标准DLL文件中的Bitmap(位图)
- android 读取文件生成Bitmap的几种方式
- CCS+C6678LE开发记录04:编写CMD文件+读取Bitmap
- Linux C++读取RGB24格式的bitmap文件(24-bit Bitmap)
- java读取ini文件
- JAVA读取XML文件
- java读取中文文件
- Java读取文件
- JAVA读取XML文件
- java读取中文文件
- java读取pdf文件
- JAVA读取word文件
- JAVA读取PDF文件
- HTML xmlns 属性
- 比特币小算力分支币比特现金(BCC)事件的起因
- 网络请求篇---Volley框架
- Atmel Studio-SAM单片机开发 ---新建工程
- 剑指offer:从尾到头打印链表
- java读取bitmap文件
- Alternative Thinking
- nyoj-195 飞翔【动态规划】
- (一) docker简介及组成-------学习笔记
- get和post的区别
- 反射---第十九天
- 单链表的基本操作(第一篇)
- 【Linux】【Docker】CentOs 6.x升级内核到3.10, 安装并升级docker1.9.1
- codeforces 832D Misha, Grisha and Underground