`

BMP文件的读取及保存

    博客分类:
  • Java
阅读更多

Bmp

 

BMP是一种与硬件设备无关的图像文件格式,使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此, BMP 文件所占用的空间很大。 BMP 文件的图像深度可选 lbit 4bit 8bit 24bit BMP 文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。 由于 BMP 文件格式是 Windows 环境中交换与图有关的数据的一种标准,因此在 Windows 环境中运行的图形图像软件都支持 BMP 图像格式。

 

是在之前的画图板基础上添加的功能.

 

现在的界面很简单:



 



 

之前的画图板简介:

1.创建JFrame窗口,添加三个JPanel,在左边加上单选按钮选择形状

2.在DrawListener中是想抽象的鼠标适配器.

3.在正中间添加画布,添加监听器

4.画直线,矩形,椭圆,画笔功能.

5.重写paint方法

6.创建Shape类,Line,Rect等类继承Shape类,单独实现绘制功能,用ArrayList<Shape> 存放绘制形状的列表.顺便加入撤销功能.

7.保存读取文件(实际是保存List对象.)

 

 

24位BMP格式特点:包括BMP文件头 (14 字节 ),位图信息头(40 字节 ),颜色表(24位没有),数据. 四个部分

 

//BMP文件头

int bfType1= 0x42; // 位图文件的类型,必须为 ' B '' M '两个字母 (0-1字节 )   

int bfType2= 0x4d; 

int bfSize=14; // 位图文件的大小,以字节为单位 (2-5 字节 )   *********

int bfReserved1=0; // 位图文件保留字,必须为 0(6-7 字节 )    

int  bfReserved2=0; // 位图文件保留字,必须为 0(8-9 字节 )   

int  bfOffBits=54; // 位图数据的起始位置,以相对于位图 (10-13 字节 ) 

 

//Bmp信息头

int Size=40; // 本结构所占用字节数 (14-17 字节 )  

int image_width=DrawListener.colors[0].length; // 位图的宽度,以像素为单位 (18-21 字节 )   

int image_height=DrawListener.colors.length; // 位图的高度,以像素为单位 (22-25 字节 )  

int Planes=1; // 目标设备的级别,必须为 1(26-27 字节 )   

int biBitCount=24;// 每个像素所需的位数,必须是 1(双色),(28-29 字节) 4(16 色 ) , 8(256 色 ) 或 24(// 真彩色 ) 之一  

int biCompression=0; // 位图压缩类型,必须是 0( 不压缩 ),(30-33 字节 ) 1(BI_RLE8 压缩类型 ) 或// 2(BI_RLE4 压缩类型 ) 之一  

int SizeImage=height*width; // 位图的大小,以字节为单位 (34-37 字节 ) 

int biXPelsPerMeter=0; // 位图水平分辨率,每米像素数 (38-41 字节 )  0是默认值 

int biYPelsPerMeter=0; // 位图垂直分辨率,每米像素数 (42-45 字节 )  0是默认值

int biClrUsed=0;// 位图实际使用的颜色表中的颜色数 (46-49 字节 )        0说明全部用了

int biClrImportant=0;// 位图显示过程中重要的颜色数 (50-53 字节 )    0说明全部重要

 

保存bmp文件就是先将这些数据保存在文件中,从第54字节开始保存位图数据.每个像素点都按照bgr的顺序(与red green blue相反)保存在文件中.每三个字节合成一个像素点的颜色.

 

注意:由于获得像素点颜色是用java提供的getRGB方法,返回的是一个int整数,需要拆分成4个byte.从低到高位依次是bgra.也就是说,bytes[0]是蓝色,bytes[1]是绿色,bytes[2]是红色.

	public byte[] int2byte(int data){
		byte[] bytes = {(byte)(((data)<<24)>>24),(byte)(((data)<<16)>>24),(byte)(((data)<<8)>>24),(byte)((data)>>24)};
		return bytes; 
	}

 将bytes[]合成int的方法(读取文件的时候用到)

	public static int byte2int(byte b[]) {
		int b3 = b[3] & 0xff;
		int b2 = b[2] & 0xff;
		int b1 = b[1] & 0xff;
		int b0 = b[0] & 0xff;
		int i = b3 << 24 | b2 << 16 | b1 << 8 | b0;
		return i;
	}

 

完整的FileSave代码:

public class FileSave {
	static int height,width;
	static int size;
	static JFileChooser jfc = new JFileChooser("D:\\");
	
	/**
	 * 保存hb格式图片
	 * @param f 文件
	 * @param b 形状对象
	 */
	public static void saveHb(File f,ArrayList<Shape> b){
		try{
			FileOutputStream fos = new FileOutputStream(f);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			size=b.size();
			oos.writeInt(size);//保存size,避免重新打开程序后不知道要读多少个对象,导致无法读取数据
			for(int i=0;i<size;i++){
				oos.writeObject(b.get(i));
			}
			
			oos.flush();
			oos.close();
			fos.close();
			
			
		}catch(IOException e){
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 保存成bmp的方法
	 * @param f bmp文件地址
	 */
	public void write24bmp(File f){
		

		//BMP文件头
		int bfType1= 0x42; // 位图文件的类型,必须为 ' B '' M '两个字母 (0-1字节 )   
		int bfType2= 0x4d; 
		int bfSize=14; // 位图文件的大小,以字节为单位 (2-5 字节 )   *********
		int bfReserved1=0; // 位图文件保留字,必须为 0(6-7 字节 )    
		int  bfReserved2=0; // 位图文件保留字,必须为 0(8-9 字节 )   
		int  bfOffBits=54; // 位图数据的起始位置,以相对于位图 (10-13 字节 ) 

		//Bmp信息头
		int Size=40; // 本结构所占用字节数 (14-17 字节 )  
		int image_width=DrawListener.colors[0].length; // 位图的宽度,以像素为单位 (18-21 字节 )   
		int image_height=DrawListener.colors.length; // 位图的高度,以像素为单位 (22-25 字节 )  
		int Planes=1; // 目标设备的级别,必须为 1(26-27 字节 )   
		int biBitCount=24;// 每个像素所需的位数,必须是 1(双色),(28-29 字节) 4(16 色 ) , 8(256 色 ) 或 24(// 真彩色 ) 之一  
		int biCompression=0; // 位图压缩类型,必须是 0( 不压缩 ),(30-33 字节 ) 1(BI_RLE8 压缩类型 ) 或// 2(BI_RLE4 压缩类型 ) 之一  
		
		int SizeImage=height*width; // 位图的大小,以字节为单位 (34-37 字节 ) 
		int biXPelsPerMeter=0; // 位图水平分辨率,每米像素数 (38-41 字节 )  0是默认值 
		int biYPelsPerMeter=0; // 位图垂直分辨率,每米像素数 (42-45 字节 )  0是默认值
		int biClrUsed=0;// 位图实际使用的颜色表中的颜色数 (46-49 字节 )        0说明全部用了
		int biClrImportant=0;// 位图显示过程中重要的颜色数 (50-53 字节 )    0说明全部重要

		//个人理解,用byte定义这些属性的话虽然不一定超出范围,但是写数据出去的时候不方便控制字节数,例如size占4字节,Planes占2字节,如果用byte定义还要判断填0
		//不如直接用int然后再转为byte[4],再用write(byte[],开始位置,长度)这一个方法直接写出去.
		
		//写出去文件头信息头
		
		try {
			 FileOutputStream fos = new FileOutputStream(f);
			 BufferedOutputStream bos = new BufferedOutputStream(fos); 

			 bos.write(bfType1);
			 bos.write(bfType2);
			 bos.write(int2byte(bfSize),0,4);
			 bos.write(int2byte(bfReserved1),0,2);
			 bos.write(int2byte(bfReserved2),0,2);
			 bos.write(int2byte(bfOffBits),0,4);
			 bos.write(int2byte(Size),0,4);// 输入信息头数据的总字节数  
			 bos.write(int2byte(image_width),0,4);// 输入位图的宽  
			 bos.write(int2byte(image_height),0,4);// 输入位图的高
			 bos.write(int2byte(Planes),0,2);// 输入位图的目标设备级别
			 bos.write(int2byte(biBitCount),0,2);// 输入每个像素占据的字节数
			 bos.write(int2byte(biCompression),0,4);// 输入位图的压缩类型
			 bos.write(int2byte(SizeImage),0,4);// 输入位图的实际大小  
			 bos.write(int2byte(biXPelsPerMeter),0,4);// 输入位图的水平分辨率  
			 bos.write(int2byte(biYPelsPerMeter),0,4);// 输入位图的垂直分辨率  
			 bos.write(int2byte(biClrUsed),0,4);// 输入位图使用的总颜色数
			 bos.write(int2byte(biClrImportant),0,4);// 输入位图使用过程中重要的颜色数  
			 //24位没有颜色表,所以接下来输出颜色信息.将我们的int数组变成byte[4]后将b[0] b[1] b[2] 依次作为blue green red输出去
			 // 这里遍历的时候注意,在计算机内存中位图数据是从左到右,从下到上来保存的,  
			 // 也就是说实际图像的第一行的点在内存是最后一行 
			 for (int h = image_height - 1; h >= 0; h--) { 
				 for (int w = 0; w < image_width; w++) { 
					 // 这里还需要注意的是,每个像素是有三个RGB颜色分量组成的,
					 // 而数据在windows操作系统下是小端存储,对多字节数据有用。
					 byte b[]=new byte[4];
					 b= int2byte(DrawListener.colors[h][w]);
					 byte red = b[2];// 得到红色分量  
					 byte green = b[1];// 得到绿色分量
					 byte blue = b[0];// 得到蓝色分量 
					 
					 bos.write(blue);
					 bos.write(green);  
					 bos.write(red); 
				 } 
			 } 
			 //关闭数据的传输  
			 bos.flush(); 
			 bos.close(); 
			 fos.close(); 
			 System.out.println("写入成功!!!");
			 
			 
		} catch (IOException e) {
			e.printStackTrace();
		} 
		 
		
		
		
	}
	
	public byte[] int2byte(int data){
		byte[] bytes = {(byte)(((data)<<24)>>24),(byte)(((data)<<16)>>24),(byte)(((data)<<8)>>24),(byte)((data)>>24)};
		//{BGRA}
		return bytes; 
	}
	
	public static int byte2int(byte b[]) {
		int b3 = b[3] & 0xff;
		int b2 = b[2] & 0xff;
		int b1 = b[1] & 0xff;
		int b0 = b[0] & 0xff;
		int i = b3 << 24 | b2 << 16 | b1 << 8 | b0;
		return i;
	}
  

	
	/**
	 * 读取bmp的方法
	 * @param f
	 */
	public static void read24bmp(File f,Graphics g) {

		try {
			FileInputStream fis = new FileInputStream(f);
			BufferedInputStream bis = new BufferedInputStream(fis);
			try {
				int [][]data = null;
				if (bis.read() == 66 && bis.read() == 77) {
					bis.skip(16);// 先去除才开始18个,再取出4个byte拼成一个int型的宽度
					byte wi[] = new byte[4];
					bis.read(wi);
					width = byte2int(wi);
					byte he[] = new byte[4];
					bis.read(he);
					height = byte2int(he);
					data = new int[height][width];
					bis.skip(28);
					int skipNum=4-width*3%4;
					for (int h = height - 1; h >= 0; h--) {
						for (int w = 0; w < width; w++) {
							
							//
							int b = bis.read();
							int green = bis.read();
							int r = bis.read();
							Color c = new Color(r,green,b);
							data[h][w] = c.getRGB();
						}
						if (skipNum != 4) {
							bis.skip(skipNum);
						}


						
					}
					bis.close();
					fis.close();
					DrawUI.center.setPreferredSize(new Dimension(width,height));  
		            javax.swing.SwingUtilities.updateComponentTreeUI(DrawUI.center);
					
				}

				if (data != null) {
					for (int i = 0; i < data.length; i++) {
						for (int j = 0; j < data[i].length; j++) {
							Color c = new Color(data[i][j]);
							Line line = new Line(j, i, j, i, c);
							line.draw(g);
							if(data[i][j]!=-1){
								DrawListener.list.add(line);
							}
							
						}
					}

				}
				
			} catch (IOException e) {
				e.printStackTrace();
			}

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * 读取hb格式图片
	 * @param f 文件
	 * @param b 形状对象
	 */
	public static ArrayList readHb(File f){
		ArrayList<Shape> b=new ArrayList<Shape>();
		try{
			FileInputStream fis = new FileInputStream(f);
			ObjectInputStream ois = new ObjectInputStream(fis);
			size = ois.readInt();
			for(int i=0;i<size;i++){
					try {
						b.add((Shape) ois.readObject());
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
				
		
			}	
			ois.close();
			fis.close();
			return b;
		}catch(EOFException e){
			System.out.println("读取上次自动保存的文件发生错误.");
		}
		catch(IOException e){
			e.printStackTrace();
		}
		return null;
	}
	
	public static void read(Graphics g){
		int state = jfc.showOpenDialog(null);
		if (state == 0) {// 点击了打开按钮
			File f = new File(jfc.getSelectedFile().getAbsolutePath());
			try {
				FileInputStream fis = new FileInputStream(f);
				BufferedInputStream bis = new BufferedInputStream(fis);
				if (bis.read() == 66 && bis.read() == 77) {
					bis.close();
					fis.close();
					read24bmp(f,g);
				}else{
					bis.close();
					fis.close();
					
					DrawListener.list =readHb(f);
					
				}
			}catch(IOException e){
				e.printStackTrace();
			}
			
		}
		
	}
	
}

 

 

 

其余类代码参考:

 

 

 

  • 大小: 8.1 KB
  • 大小: 38.8 KB
0
0
分享到:
评论

相关推荐

    vs2005 BMP文件读取保存

    在VS2005中,我们可以使用C++语言来实现BMP文件的读取和保存。首先,我们需要定义一个结构体来对应BMP文件的头信息,例如`BITMAPFILEHEADER`和`BITMAPINFOHEADER`。接着,使用`ifstream`类打开BMP文件进行读取,通过...

    bmp位图文件的读取与保存.rar_bmp_bmp save_c bmp_保存 bmp_文件保存bmp

    本主题将深入探讨如何在C语言环境下读取和保存BMP文件。 BMP文件结构主要由三个部分组成:文件头、信息头和像素数据。文件头包括文件类型标识、文件大小、保留字段和偏移量,用于指示图像数据在文件中的位置。信息...

    BMP文件的读取与保存

    这个项目似乎涉及使用C++编程语言来实现对BMP文件的读取和保存功能。接下来,我们将深入探讨BMP文件格式以及如何使用C++进行处理。 1. **BMP文件格式** BMP文件是一种位图格式,它存储了图像的颜色信息和像素数据...

    BMP格式图像的读取与保存

    根据提供的文件信息,本文将详细解释BMP格式图像的读取与保存的相关知识点,包括BMP文件的基本结构、如何读取BMP文件以及如何保存BMP文件等内容。 ### BMP文件基本结构 BMP(Bitmap Image File Format)是一种常见...

    bmp位图文件的读取与保存

    本篇文章将深入探讨如何使用C++来读取和保存BMP位图文件,特别是通过二进制方式获取BMP文件的像素信息。 首先,我们要了解BMP文件的结构。BMP文件由文件头、信息头和像素数据三部分组成。文件头包含文件类型标识、...

    C++读取保存BMP图像

    首先,我们需要打开BMP文件并读取其头部信息,以获取图像的尺寸和色彩深度。然后,我们可以逐行读取像素数据,根据色彩深度转换成相应的颜色值。如果是灰度图转换,只需将红、绿、蓝三个分量取平均即可。 保存BMP...

    bmp文件的读取

    - 定义`BITMAPFILEHEADER`和`BITMAPINFOHEADER`类型的结构体变量`bf`和`bi`,用于保存BMP文件的文件头和信息头。 2. **打开文件**: - 使用`fopen`函数打开指定路径的BMP文件,模式为`"rb"`(二进制读)。 3. **...

    BMP.rar_bmp_bmp位图_bmp保存_bmp文件保存_保存bmp

    BMP位图文件是一种常见的图像文件格式,广泛应用于各种操作系统和应用程序中。它的全称是Bitmap,源自Microsoft Windows...实践操作中的文件"**BMP位图文件读取保存**"将提供一个很好的起点,帮助你亲手实践这些概念。

    VC读取BMP文件

    本篇文章将深入探讨如何在VC++6.0中实现BMP文件的读取和保存。 首先,我们需要了解BMP文件的基本结构。BMP文件由文件头、位图信息头和像素数据三部分组成。文件头包含文件类型标识、文件大小等基本信息;位图信息头...

    Bmp位图读取与存储

    本文将深入探讨如何使用C语言来读取和保存BMP文件,主要涉及`ReadBmp`和`SaveBmp`两个关键函数。 首先,我们需要了解BMP文件的结构。BMP文件通常由文件头、位图信息头和像素数据三部分组成。文件头...

    bmp.rar_BMP读取_C 读取bmp_C++ 保存位图_bmp_读取bmp

    本文将深入探讨如何使用C和C++语言读取与保存BMP文件,帮助你理解其背后的原理和操作步骤。 首先,我们要了解BMP文件的基本结构。BMP是一种未经压缩的图像文件格式,包含图像的宽度、高度、颜色深度以及实际的像素...

    读取BMP文件并显示_C#读取BMP文件并显示_tropicalvsr_

    Bitmap类是表示位图图像的核心类,可以用来加载、创建和保存BMP文件。我们首先需要创建一个Bitmap对象,将BMP文件加载到内存中。 3. **加载BMP文件** 要加载BMP文件,我们可以使用Bitmap类的构造函数,传入文件...

    C++读取、旋转和保存.bmp文件 代码

    本文件中有三份C++程序的代码,均可以读取.bmp文件的图像。其中包括彩色的.bmp文件和黑白的.bmp文件的代码。并且可以实现对文件图像的任意角度的旋转,以及旋转后的图像保存,为广大朋友提供诸多便利。并且也可以在...

    C语言读取BMP文件

    7. **保存或处理图像**:你可以选择将读取的像素数据保存到另一个BMP文件,或者进行图像处理,比如调整亮度、对比度等。 8. **释放内存**:完成操作后,记得使用`free()`释放分配的内存,并关闭文件。 在提供的`1_...

    bmp.rar_BMP图片_C 读取图片_保存bmp_打开BMP_读取bmp c#

    C 和 C# 都提供了处理BMP文件的方法,让我们深入了解一下如何在这些编程语言中读取、保存和打开BMP图片,以及如何解析BMP文件的头部信息。 1. BMP文件结构 BMP文件由三部分组成:位图文件头(Bitmap File Header)...

    BMP图片读取并保存成文本C程序

    BMP图片读取并保存成文本C程序,加了保存到文本的功能

    bmp文件读出为txt文件, txt文件写入为bmp文件

    本文将详细讨论如何从BMP文件读取数据并将其转换为TXT文本文件,以及如何将TXT文件的数据重新写入为BMP文件。这两个过程涉及到二进制与文本之间的转换,这对于理解计算机数据处理和文件格式至关重要。 首先,我们来...

    BMP文件读取器

    BMP文件读取器是一种软件工具或程序,专门设计用于打开和显示位图(Bitmap)图像文件。位图图像文件格式,通常简称为BMP,是Windows操作系统中的一个标准图像文件格式,它存储未经压缩的像素数据,因此可以精确地...

    bmp文件访问文件头信息头指导书

    读取24位BMP文件的位图数据并保存到TXT文件** - **输入**: BMP文件的文件名和TXT文件的文件名。 - **输出**: 将位图数据以十进制形式保存到TXT文件中。 - **实现思路**: 继续读取BMP文件中的位图数据部分,并...

Global site tag (gtag.js) - Google Analytics