`
人生难得糊涂
  • 浏览: 117695 次
社区版块
存档分类
最新评论

JAVA如何自己写方法读取BMP文件

 
阅读更多

BMP图像解析

 

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

 

要解析文件,就必须知道他的文件结构:

6.3.1 BMP文件结构 

典型的BMP 图像文件由四部分组成:   

 . 位图文件 头数据结构 ,它包含BMP 图像文件的类型、显示内容等信息;  

 .位图信息数据结构 ,它包含有BMP 图像的宽、高、压缩方法,以及定义颜色等信息;   

  3. 调色板 ,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24 位的 BMP )就不需要调色板;  

     4. 位图数据 ,这部分的内容根据BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB ,而其他的小于 24 位的使用调色板中颜色索引值。  

 

6.3.2对应的数据结构

① BMP文件头 (14 字节     

   BMP文件头数据结构含有 BMP 文件的类型、文件大小和位图起始位置等信息其结构定义如下   

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

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

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

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

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

 

② 位图信息头(40 字节   

  BMP 位图信息头数据用于说明位图的尺寸等信息。  

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

int image_width// 位图的宽度,以像素为单位 (18-21 字节   

int image_heigh// 位图的高度,以像素为单位 (22-25 字节  

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

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

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

int SizeImage// 位图的大小,以字节为单位 (34-37 字节   

int biXPelsPerMeter// 位图水平分辨率,每米像素数 (38-41 字节   

int biYPelsPerMeter// 位图垂直分辨率,每米像素数 (42-45 字节   

int biClrUsed;// 位图实际使用的颜色表中的颜色数 (46-49 字节   

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

  

 

③ 颜色表    

颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD 类型的结构定义一种颜色。 

class  RGBQUAD {   

byte  rgbBlue;// 蓝色的亮度 值范围为 0-255)    

byte  rgbGreen; // 绿色的亮度 值范围为 0-255)   

byte  rgbRed; // 红色的亮度 值范围为 0-255)    

byte  rgbReserved;// 保留,必须为    

}

颜色表中RGBQUAD 结构数据的个数有 biBitCount 来确定biBitCount=1,4,8 时,分别有 2,16,256 个表项 biBitCount=24 时,没有颜色表项。   

位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下    

class  BITMAPINFO {   

BITMAPINFOHEADER bmiHeader; // 位图信息头   

RGBQUAD bmiColors[1]; // 颜色表   

}  

 

④ 位图数据    

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右扫描行之间是从下到上。位图的一个像素值所占的字节数   

biBitCount=1 时, 个像素占 个字节    

biBitCount=4 时, 个像素占 个字节    

biBitCount=8 时, 个像素占 个字节    

biBitCount=24 时 ,1 个像素占 个字节    

Windows规定一个扫描行所占的字节数必须是的倍数 即以 long 为单位 ), 不足的以 填充,具体数据举例:如某BMP 文件开头:   424D 4690 0000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 

 0090 0000 A00F 0000 A00F 0000 0000 0000 0000 0000*00F8 E007 1F00 0000*02F1 84F1  

04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 .... ....    

BMP 文件可分为四个部分:位图文件头、位图信息头、彩色板、图像数据阵列,在上图中已用 分隔。 比方说,我们就可以做一个BMP图片的查看器 (暂时只做24位BMP图像解析器,大多数BMP图像也是2位)



 

 

package data0605_bmp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileNameExtensionFilter;

/*
 * bmp文件读取保存
 */
public class Projiect  extends JFrame{
	int map[][];//保存像素颜色的数组
	MyPanel center;//绘图面板
	File selectFile;//读取的文件
	int width;//图像宽度
	int height;//图像高度
	byte temp1[];//读取BMP文件的前18个字节信息
	byte temp2[];//读取BMP文件的后28个字节信息
	JScrollPane scrollpane;//滚动面板
	public Projiect() {
		//观感必须为main方法的第一个操作,否则可能不起作用
		try {
			UIManager
				.setLookAndFeel(new com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel());
		} catch (Exception e) {
			e.printStackTrace();
		}
		this.setLayout(new BorderLayout());//最好先设置布局再添加组件
		//初始化画图面板
		center=new MyPanel();
		center.setBackground(Color.WHITE);
		center.setPreferredSize(new Dimension(400,200));
		scrollpane=new JScrollPane(center);//用center初始化滚动面板
		scrollpane.setPreferredSize(new Dimension(500,300));
		MyListener lis=new MyListener();
		
		//初始化菜单栏
		JMenuBar menuBar=new JMenuBar();
		JMenu fileMenu=new JMenu("file");
		JMenuItem open=new JMenuItem("open");
		JMenuItem save=new JMenuItem("save");
		open.addActionListener(lis);
		save.addActionListener(lis);
		fileMenu.add(open);
		fileMenu.add(save);
		menuBar.add(fileMenu);
		//
		JPanel left=new JPanel();
		left.setBackground(Color.DARK_GRAY);
		left.setPreferredSize(new Dimension(50,0));
		this.add(left,BorderLayout.WEST);
		this.setJMenuBar(menuBar);
		this.add(scrollpane,BorderLayout.CENTER);//加入的是滚动面板
		this.setTitle("bmp");
		this.setLocation(300, 150);
		this.setSize(800, 500);
		this.setDefaultCloseOperation(3);
		this.setVisible(true);
		
	}
	/**
	 * 读取bmp文件
	 */
	public void readBMP()
	{
		try {
			FileInputStream fis=new FileInputStream(selectFile);
			BufferedInputStream bis=new BufferedInputStream(fis);
			byte[] wb=new byte[4];//读取宽度的字节数组
			 byte[] hb=new byte[4];//读取高度的字节数组
			 temp1=new byte[18];
			bis.read(temp1);//bis.skip(18);//跳过前18个byte
			bis.read(wb);//读取宽度
			bis.read(hb);//读取高度
			width=byteToint(wb);
			height=byteToint(hb);
			System.out.println(width+"<>"+height);
			map=new int[height][width];
			int skip=4-width*3%4;//得到每行要跳过的数字(与windows 系统机制有关)
			temp2=new byte[28];
			bis.read(temp2);//bis.skip(28);
			for(int i=0;i<height;i++)
			{
				for(int j=0;j<width;j++)
				{
					int blue=bis.read();
					int green=bis.read();
					int red=bis.read();
					Color c=new Color(red,green,blue);
					map[i][j]=c.getRGB();
				}
				if(skip!=4)
				bis.skip(skip);
			}
			bis.close();
			center.setPreferredSize(new Dimension(width,height));
			javax.swing.SwingUtilities.updateComponentTreeUI(center);//这里必须要用updateComponentTreeUI(center)函数
		//不能用repaint()函数

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public void writeBMP()
	{
		try {
			FileOutputStream fos=new FileOutputStream(selectFile);
			BufferedOutputStream bos=new BufferedOutputStream(fos);
			bos.write(temp1);//
			bos.write(intTobyte(width,4));//写入宽度
			bos.write(intTobyte(height,4));//写入高度
			bos.write(temp2);
			int skip=0;
			if(width*3/4!=0)
			{
				skip=4-width*3%4;
			}
			for(int i=0;i<height;i++)
			{
				for(int j=0;j<width;j++)
				{
					Color c=new Color(map[i][j]);
					int blue=c.getBlue();
					int green=c.getGreen();
					int red=c.getRed();
					bos.write(blue);
					bos.write(green);
					bos.write(red);
				}
				if(skip!=0)
					bos.write(new byte[skip]);
			}
			bos.flush();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	//字节转int
	public static  int byteToint(byte b[])
	{
		int t1=(b[3]&0xff)<<24;
		int t2=(b[2]&0xff)<<16;
		int t3=(b[1]&0xff)<<8;
		int t4=b[0]&0xff;
		//System.out.println(b[1]&0xff);//输出的是一个整形数据
		//在java中,设计int和比int位数来的小的类型b,如byte,char等,都是先把小类型扩展成int再来运算,
		//return( t1<<24)+(t2<<16)+(t3<<8)+t4;//必须加括号
		return t1+t2+t3+t4;
	}
	//int 转byte
	public static byte[] intTobyte(int a,int len)
	{
		byte []t=new byte[len];
			t[0]=(byte) ((a&0xff));
			if(len>1)
			t[1]=(byte)((a&0xff00)>>8);
			if(len>2)
			t[2]=(byte)((a&0xff0000)>>16);
			if(len>3)
			t[3]=(byte)((a&0xff000000)>>24);
		return t;
	}
	/**
	 * 绘图面板
	 * @author ZhangZunC
	 *
	 */
	class MyPanel extends JPanel{
		public void paint(Graphics g) {
			super.paint(g);
			if(map!=null)
			{
				for(int i=0;i<map.length;i++)
				{
					for(int j=0;j<map[i].length;j++)
					{
						g.setColor(new Color(map[i][j]));
						g.drawLine(j, height-i, j,height- i);
					}
				}
			}
		}
	}
	
	class MyListener implements ActionListener{
		JFileChooser fileChosser;
		MyListener()
		{
			FileNameExtensionFilter filter=new FileNameExtensionFilter("24位位图(*.bmp)", "bmp");
			fileChosser=new JFileChooser();
			fileChosser.setFileFilter(filter);
			fileChosser.setCurrentDirectory(new File("\\"));
		}
		public void actionPerformed(ActionEvent e) {
			if(e.getActionCommand().equals("open"))//选择的是打开
			{
				int choose=fileChosser.showOpenDialog(null);
				if(choose==JFileChooser.APPROVE_OPTION)//点击的是确定按钮
				{
					selectFile=fileChosser.getSelectedFile();
					readBMP();
				}
			}
			if(e.getActionCommand().equals("save"))//选择的是打开
			{
				int choose=fileChosser.showSaveDialog(null);
				if(choose==JFileChooser.APPROVE_OPTION)
				{
					selectFile=fileChosser.getSelectedFile();
					writeBMP();
					System.out.println("save ");
				}
			}
		}
		
	}
	
	
	public static void main(String[] args) {
		new Projiect();
//		byte[] b=new byte[4];
//		b[0]=0;
//		b[1]=(byte) 0xaf;
//		b[2]=0;
//		b[3]=0;
	//	System.out.println(byteToint(b));	
//		byte b1[]=intTobyte(byteToint(b),4);
//		System.out.println(b1[0]+"<>"+b1[1]+"<>"+b1[2]+"<>"+b1[3]);
	}
}

 

 

  • 大小: 62 KB
  • 大小: 37.2 KB
3
0
分享到:
评论
1 楼 jun4997 2015-01-10  
                 

相关推荐

    java语言读取bmp文件

    ### Java语言读取BMP文件的关键知识点 #### 1. BMP文件格式理解 BMP(Bitmap)是一种位图文件格式,主要用于Windows操作系统中存储图像数据。它由文件头、信息头、颜色表以及实际的像素数据四部分组成。在处理BMP...

    用java读取bmp格式图片文件

    通过读取bmp格式文件的数据格式,用数组合理的读取后,重新画出该图片

    Java读取所有色bmp图片格式

    1. **文件读取**:使用Java的`java.io`包中的`FileInputStream`或`BufferedInputStream`读取BMP文件的二进制流。 2. **解析文件头**:根据BMP文件格式定义,解析文件头以获取文件的整体信息。 3. **解析信息头**:...

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

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

    按文件读取BMP位图

    读取BMP文件通常涉及以下步骤: 1. **打开文件**:使用编程语言(如C++、Python或Java)的文件操作函数打开BMP文件。 2. **读取文件头**:BMP文件头包含两个部分:BITMAPFILEHEADER(BFH)和BITMAPINFOHEADER(BIH...

    读取bmp图片输出RGB值

    本话题将深入探讨如何读取BMP格式的图片,并从中提取RGB(Red, Green, Blue)颜色信息,然后将这些信息输出到TXT文件中。 RGB色彩模型是计算机图形学中广泛使用的颜色模型,它通过红、绿、蓝三种基本颜色的不同强度...

    BMP文件采样读取缩略图.rar

    这个压缩包“BMP文件采样读取缩略图.rar”显然包含了与BMP文件处理相关的代码或教程,特别是关于如何采样读取BMP文件以生成缩略图的内容。以下是对这个主题的详细讲解: 首先,BMP文件结构主要包括以下几个部分: ...

    读取并显示bmp文件的制作流程

    3. **读取BMP文件** 使用编程语言(例如C++、Python或Java)打开文件,读取文件头数据以获取图像的基本信息。然后跳过可能存在的色彩表,直接定位到图像数据部分。 4. **处理色彩信息** BMP文件通常支持24位色彩...

    利用java实现画图板和保存读取BMP格式的图片(一)

    在本篇博文中,我们将探讨如何使用Java编程语言来实现一个简单的画图板应用程序,并学习如何保存和读取BMP(Bitmap)格式的图片。BMP是一种无损图像格式,通常用于存储像素数据,便于程序处理。以下是实现这一功能所...

    一个读取BMP图像的程序

    下面将详细介绍如何读取BMP图像以及相关知识点。 1. BMP文件结构: BMP文件由两部分组成:位图头信息和位图数据。位图头信息包含了图像的宽度、高度、颜色深度等元数据,而位图数据则存储实际的像素颜色值。常见的...

    java 实现 bmp 转 jpg

    1. **读取BMP文件**:使用Java的`java.awt.image.BufferedImage`类来读取BMP文件。BMP文件的图像数据是按行存放的,每行数据可能需要填充以保持字节对齐。 ```java FileInputStream fis = new FileInputStream(...

    java关于BMP位图文件解析的分析与实现[源码][附图]

    实现这个过程,我们可以创建一个Java类,包含解析和显示BMP文件的方法。首先,使用`java.io.RandomAccessFile`来读取文件的各个部分。然后,将读取到的数据转化为图像的像素数组。最后,可以利用Java的`java.awt....

    bmp格式图片转换为raw格式

    转换过程中,我们首先读取BMP文件的头部信息,获取图像的宽度和高度,然后逐行读取像素数据。对于24位BMP(每像素有8位红、绿、蓝分量),我们可以直接将RGB值存入RAW文件。由于RAW格式通常不包含元数据,所以我们...

    bmp格式文件图象读取

    读取BMP文件时,首先需要解析文件头以确定数据的布局,然后根据位图信息头解析图像尺寸和颜色信息,最后读取像素数据。这个过程通常涉及文件I/O操作,如打开、读取和关闭文件。 写入BMP文件则需要逆向进行,先创建...

    BMP_RGB.rar_BGR BMP_BMP rgb bgr_bmp RGB_rgb 存储 bmp_读取bmp

    这个主题主要涉及如何读取BMP文件以及理解BMP文件的内部结构,特别是颜色通道——红色、绿色和蓝色(RGB)之间的转换,尤其是BGR(Blue-Green-Red)顺序的处理。 首先,我们需要理解BMP文件的基本结构。BMP文件通常...

    bmp文件格式分析及其编程

    C++中可以利用文件流操作直接读取BMP文件,Python则可以借助PIL(Pillow)库轻松处理图像,Java则有Java AWT和Swing库提供支持。编写代码时,需要注意内存管理和数据类型的选择,确保正确地处理不同平台和字节序的...

    java准确读取flash以及jpg,gif,bmp等格式文件源码.rar

    Java编程语言在处理各种文件类型,如Flash(SWF)、JPEG(JPG)、GIF和BMP等图像格式时,提供了强大的支持。本压缩包文件包含的源码着重于如何在Java环境中准确地读取这些文件,从而实现对它们内容的解析、显示或...

    Java提取压缩包中的文件.rar

    Java提取压缩包中的文件,文件操作的范畴,操作对象为ZIP格式的压缩文件,将从ZIP中提取出BMP图像文件,要将从压缩包中提取文件,必须先解压压缩包,然后将指定文件拷贝出来,代码中先实现了对zip文件的解压,然后...

    Java应用程序读取图片内容.zip

    `ImageIO`类是这个API的核心,提供了`read()`方法来读取图像文件。 2. **使用ImageIO.read()**: 要读取图片,首先需要导入`javax.imageio.ImageIO`和`java.awt.image.BufferedImage`。然后,你可以使用`ImageIO....

    DCM文件转为bmp文件

    这些库提供了读取和操作DCM文件,以及创建和写入BMP文件的功能。 7. **错误处理与兼容性**:转换过程中可能会遇到各种问题,如文件格式不正确、元数据错误等,需要有适当的错误处理机制。此外,考虑不同版本的DCM...

Global site tag (gtag.js) - Google Analytics