`
VIP庚
  • 浏览: 223347 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

BMP位图的读取与保存

 
阅读更多
在实现BMP位图的读取与保存之前 我们要了解BMP位图的文件结构


BMP位图文件结构分为4个部分:

  1 . 位图文件 头数据结构 ,它包含BMP 图像文件的类型、显示内容等信息; 
 2 .位图信息数据结构 ,它包含有BMP 图像的宽、高、压缩方法,以及定义颜色等信息;  
  3. 调色板 ,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24 位的 BMP )就不需要调色板; 
  4. 位图数据 ,这部分的内容根据BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB ,而其他的小于 24 位的使用调色板中颜色索引值。 




① BMP文件头 (14 字节 )

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


② 位图信息头(40 字节 )  
nt Size; // 本结构所占用字节数 (14-17 字节 )  
int image_width; // 位图的宽度,以像素为单位 (18-21 字节 )   
int image_heigh; // 位图的高度,以像素为单位 (22-25 字节 )  
short Planes; // 目标设备的级别,必须为 1(26-27 字节 )   
short biBitCount;// 每个像素所需的位数,必须是 1(双色), 4(16 色 ) , 8(256 色 ) 或 24(// 真彩色 ) 之一 (28-29 字节) 
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;// 保留,必须为 0   
}


由上面定义的RGBQUAD可知  每个表项占据4个字节

颜色表中RGBQUAD 结构数据的个数有 biBitCount 来确定。当biBitCount=1,4,8 时,分别有 2,16,256 个表项 ; 当biBitCount=24 时,没有颜色表项。、
所以当
biBitCount=1时  颜色表占8个字节
biBitCount=4时  颜色表占64个字节
biBitCount=8时  颜色表占1024个字节
biBitCount=24时  颜色表占0个字节

④ 位图数据   
位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右, 扫描行之间是从下到上。位图的一个像素值所占的字节数:   
当biBitCount=1 时, 8 个像素占 1 个字节 ;   
当biBitCount=4 时, 2 个像素占 1 个字节 ;   
当biBitCount=8 时, 1 个像素占 1 个字节 ;   
当biBitCount=24 时 ,1 个像素占 3 个字节 ;   
Windows规定一个扫描行所占的字节数必须是4 的倍数  不足的以 0 填充 

注:bmp储存数据 都是低位在前 高位在后  而java中是高位在前 低位在后 所以写入读取时要注意转换


// 定义一个内部方法 用来读取bmp整型
public int MyreadInt(BufferedInputStream bis) throws IOException {
		int a = bis.read();
		int b = bis.read();
		int c = bis.read();
		int d = bis.read();
		int e = (d << 24) + (c << 16) + (b << 8) + a;
		return e;
	}  



// ***********************读入24 位BMP文件***************************
public void ReadBMP(BufferedInputStream bis) throws IOException {
		char head[] = new char[2];
		head[0] = (char) bis.read();
		head[1] = (char) bis.read();
		String isbmp = new String(head);
		if ("BM".equals(isbmp)) {
			bis.skip(8);
			// 得到 位图数据的起始位置,
			int loction = MyreadInt(bis);
			bis.skip(4);
			// 得到位图hight width
			int width = MyreadInt(bis);
			int height = MyreadInt(bis);
			drawPanel.setPreferredSize(new Dimension(width, height));
			DrawListener.array = new int[height][width];
			bis.skip(loction - 26);
			int v = 0;
			if (width * 3 % 4 != 0)
				v = 4 - width * 3 % 4;
			for (int i = height - 1; i >= 0; i--) {
				for (int j = 0; j < width; j++) {
					int blue = bis.read();
					int green = bis.read();
					int red = bis.read();
					int rgb = (red << 16) + (green << 8) + blue;
					DrawListener.array[i][j] = rgb;
				}
				bis.skip(v);
			}

		}

		bis.close();
	}




// ***********************读入 16色BMP文件***************************
public void Read16BMP(BufferedInputStream bis) throws IOException {
char head[] = new char[2];
head[0] = (char) bis.read();
head[1] = (char) bis.read();
String isbmp = new String(head);
if ("BM".equals(isbmp)) {
bis.skip(8);
// 得到 位图数据的起始位置,
int loction = MyreadInt(bis);
bis.skip(4);
// 得到位图hight width
int width = MyreadInt(bis);
int height = MyreadInt(bis);
drawPanel.setPreferredSize(new Dimension(width, height));
DrawListener.array = new int[height][width];
bis.skip(loction - 26);

// *********************读位图数据******************************

int v = 0;
			if (width % 2 != 0)
				v = 4 - (width + 1) / 2 % 4;
			else
				v = 4 - width / 2 % 4;
			
			//当width为奇数时
			if (width % 2 != 0) {
				for (int i = height - 1; i >= 0; i--) {
					for (int j = 0; j < width; j++) {
						int a = bis.read();
						if (j == width - 1) {
							int c1 = (a >> 4) & 15;
							DrawListener.array[i][j] = colorArr[c1];
						} else {
							int c1 = (a >> 4) & 15;
							int c2 = a & 15;
							DrawListener.array[i][j] = colorArr[c1];
							j++;
							DrawListener.array[i][j] = colorArr[c2];
						}
					}
					bis.skip(v);
				}
			} else {
				//当width为偶数时
				for (int i = height - 1; i >= 0; i--) {
					for (int j = 0; j < width; j++) {
						int a = bis.read();
						int c1 = (a >> 4) & 15;
						int c2 = a & 15;
						DrawListener.array[i][j] = colorArr[c1];
						j++;
						DrawListener.array[i][j] = colorArr[c2];

					}
					bis.skip(v);
				}
			}

		}

		bis.close();
	}




// 创建16色位图颜色表
public void Creat16color() {
		colorArr[0] = new Color(0, 0, 0).getRGB();
		colorArr[1] = new Color(80, 0, 0).getRGB();
		colorArr[2] = new Color(0, 80, 0).getRGB();
		colorArr[3] = new Color(80, 80, 0).getRGB();
		colorArr[4] = new Color(0, 0, 80).getRGB();
		colorArr[5] = new Color(80, 0, 80).getRGB();
		colorArr[6] = new Color(0, 80, 80).getRGB();
		colorArr[7] = new Color(80, 80, 80).getRGB();
		colorArr[8] = new Color(192, 192, 192).getRGB();
		colorArr[9] = new Color(255, 0, 0).getRGB();
		colorArr[10] = new Color(0, 255, 0).getRGB();
		colorArr[11] = new Color(255, 255, 0).getRGB();
		colorArr[12] = new Color(0, 0, 255).getRGB();
		colorArr[13] = new Color(255, 0, 255).getRGB();
		colorArr[14] = new Color(0, 255, 255).getRGB();
		colorArr[15] = new Color(255, 255, 255).getRGB();

	}





// *******************得到位图文件大小********************
public int GetBMPSize(int type) {
		Dimension dim = drawPanel.getPreferredSize();
		int width = dim.width;
		int height = dim.height;

		int size = 0;
		size += 54;
		if (type == 24) {
			// 24位的时候

			// 计算每行要补充的字节数
			int v = 0;
			if (width * 3 % 4 != 0) {
				v = 4 - width * 3 % 4;
			}
			size += width * height * 3 + v * height;

		} else if (type == 4) {
			int v = 0;
			if ((width / 2) % 4 != 0)
				v = 4 - width / 2 % 4;
			size += width * height / 2 + v * height;
		}
		return size;
	}



// ********************写入int类型**********************
	public void MywriteInt(BufferedOutputStream bos, int data)
			throws IOException {
		int a = data >> 24 & 0xFF;
		byte b = (byte) (data >> 16 & 0xFF);
		byte c = (byte) (data >> 8 & 0xFF);
		byte d = (byte) (data & 0xFF);
		// System.out.println(a+" "+b+" "+c+" "+d);
		// 因为写入时值写入8个字节 所以 只写入 int的最低位 所以无需转型byte
		bos.write(d);
		bos.write(c);
		bos.write(b);
		bos.write(a);
	}

	// ********************写入short类型****************************
	public void MywriteShort(BufferedOutputStream bos, short data)
			throws IOException {
		int a = data >> 8 & 0xFF;
		int b = data & 0xFF;
		bos.write(b);
		bos.write(a);
	}

	// *******************写入BMP文件头 (14 字节 )********************
	public void WriteHead(BufferedOutputStream bos, int type)
			throws IOException {
		byte a = 'B';
		byte b = 'M';
		// 将'B' 'M'写入文件 2个字节
		bos.write(a);
		bos.write(b);
		// 写入位图文件大小 4个字节
		int size = this.GetBMPSize(type);
		this.MywriteInt(bos, size);

		// 位图文件保留字 4个字节 都为0
		bos.write(0);
		bos.write(0);
		bos.write(0);
		bos.write(0);
		// 位图数据的起始位置 4个字节 24位 颜色表为空
		if (type == 24) {
			this.MywriteInt(bos, 54);
		} else if (type == 4) {
			this.MywriteInt(bos, 54 + 64);
		}

	}

	// *******************写入位图信息头(40 字节 ) ********************
	public void WriteMessageHead(BufferedOutputStream bos, int type)
			throws IOException {
		// 本结构所占用字节数 (14-17 字节 )
		this.MywriteInt(bos, 40);
		// 位图的宽度,以像素为单位 (18-21 字节 )
		Dimension dim = drawPanel.getPreferredSize();
		int width = dim.width;
		int height = dim.height;
		// System.out.println(width+"  "+height);
		this.MywriteInt(bos, width);
		this.MywriteInt(bos, height);
		// 目标设备的级别,必须为 1(26-27 字节 )
		this.MywriteShort(bos, (short) 1);
		// 每个像素所需的位数
		this.MywriteShort(bos, (short) type);
		// 位图压缩类型
		this.MywriteInt(bos, 0);
		// 位图数据的大小
		if (type == 24) {
			int size = this.GetBMPSize(type) - 54;
			this.MywriteInt(bos, size);
		} else if (type == 4) {
			int size = this.GetBMPSize(type) - 54 - 64;
			this.MywriteInt(bos, size);
		}
		// 位图水平分辨率 4个字节 位图垂直分辨率 4个字节
		this.MywriteInt(bos, 0);
		this.MywriteInt(bos, 0);
		// 位图实际使用的颜色表中的颜色数
		this.MywriteInt(bos, 16);
		// 位图显示过程中重要的颜色数
		this.MywriteInt(bos, 0);

	}

	// *******************写入位图颜色表 ********************
	public void WriteColor(BufferedOutputStream bos, int type)
			throws IOException {
		if (type == 4) {
			for (int i = 0; i < 16; i++) {
				Color c = new Color(colorArr[i]);
				int red = c.getRed();
				int green = c.getGreen();
				int blue = c.getBlue();
				bos.write(blue);
				bos.write(green);
				bos.write(red);
				bos.write(0);
			}
		}
	}

	// *******************写入位图位图数据********************
	public void WriteData(BufferedOutputStream bos) throws IOException {
		Dimension dim = drawPanel.getPreferredSize();
		int width = dim.width;
		int height = dim.height;
		int v = 0;
		if (width * 3 % 4 != 0)
			v = 4 - width * 3 % 4;
		for (int i = DrawListener.array.length - 1; i >= 0; i--) {
			for (int j = 0; j < DrawListener.array[i].length; j++) {
				int RGB = DrawListener.array[i][j];
				bos.write(RGB & 0xFF);
				bos.write((RGB >> 8) & 0xFF);
				bos.write((RGB >> 16) & 0xFF);

			}
			for (int k = 0; k < v; k++)
				bos.write(0);
		}
	}
分享到:
评论

相关推荐

    Bmp位图读取与存储

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

    BMP位图的读取和显示

    "BMP位图的读取和显示" 本文将详细介绍 BMP 位图文件的基本格式,以及如何使用 VC++ 读取图像数据并将其显示在视图中。 BMP 位图文件格式 BMP 位图文件主要由四部分组成: 1. 文件头 BITMAPFILEHEADER 2. 位图...

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

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

    bmp位图文件的读取与保存

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

    bmp位图读取显示

    对bmp位图8位的灰度图像进行读取与显示,为后面的操作提供基础

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

    在本文中,我们将深入探讨BMP位图文件的结构、如何读取以及如何保存,旨在帮助读者更好地理解和操作这种图像格式。 1. BMP文件结构: BMP文件主要由三部分组成:文件头、信息头和像素数据。文件头包含了文件的基本...

    读取并显示BMP位图

    本教程主要讲解如何在VC6.0环境下读取并显示BMP位图,这对于初学者理解图像处理的基本原理非常有帮助。 首先,我们需要了解BMP文件的结构。BMP文件由文件头、位图信息头和实际像素数据三部分组成。文件头包含了文件...

    bmp位图读取并处理

    本文将深入解析BMP位图文件结构,并通过VC++编程语言演示如何读取、处理和显示BMP图像,包括反色、平滑、图像叠加和保存等操作。 首先,了解BMP文件的基本结构至关重要。一个BMP文件主要由两部分组成:文件头和图像...

    bmp位图的读取以及显示

    本篇将深入讲解如何读取和显示BMP位图文件,以及涉及的相关知识点。 首先,我们要了解BMP文件的基本结构。BMP文件分为文件头、信息头和像素数据三部分。文件头包含文件的基本信息,如文件大小、图像偏移量等;信息...

    VC6.0下bmp位图的读取与显示.doc

    通过以上步骤,你将在VC6.0环境中成功实现BMP位图的读取与显示。这不仅加深了对BMP文件格式的理解,还掌握了MFC库中处理图形的基本方法。在实际编程中,你可能需要根据具体需求调整代码,例如处理不同大小和位深度的...

    BMP位图读取并取反色

    ### BMP位图读取与取反色处理 #### 一、引言 在图像处理领域,位图(Bitmap)是一种常见的图像格式,其中BMP(Bitmap Image File Format)是无损压缩的一种图像存储格式,广泛应用于Windows操作系统。本文将详细...

    直接读取bmp位图

    本文将深入探讨如何直接通过读取文件的方式来显示BMP位图,这通常涉及到位图文件的结构理解、内存管理和图像渲染等技术。 BMP文件格式的基本结构: 1. 文件头(File Header):包含文件类型标识、文件大小和偏移量...

    按文件读取BMP位图

    本文将深入探讨如何按文件读取24位BMP位图,这是最常用的BMP位图深度,也是许多图像处理和编程任务的基础。 首先,我们要了解BMP文件的基本结构。BMP文件分为两个主要部分:文件头和位图数据。文件头包含关于图像的...

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

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

    Bitmap位图的读取、保存、显示

    "BMPTest"可能是一个包含示例代码的项目,用于演示如何读取、保存和显示BMP位图。这个项目可能包括了打开BMP文件、解析文件结构、创建并填充DIB对象、使用GDI或GDI+在窗口上显示图像等功能。通过学习和理解这个项目...

    VC++6.0 打开位图文件源代码 BMP图像数据的读取与显示

    在本文中,我们将深入探讨如何使用VC++ 6.0打开和显示位图(BMP)文件。位图文件是一种常见的图像格式,广泛应用于各种图形处理应用中。VC++ 6.0是一款经典的Microsoft Visual Studio集成开发环境,它提供了丰富的...

    数字水印程序,bmp位图读取

    本项目是一个针对初学者的实践教程,旨在介绍如何使用编程技术实现数字水印功能,并重点涉及BMP位图文件的读取与处理。 首先,我们来了解一下“数字水印”。数字水印是一种将特定信息嵌入到多媒体文件(如图像、...

    MFC-Bmp位图读取显示放大缩小程序

    在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC)库来开发一个Bmp位图读取、显示以及放大缩小的程序。MFC是微软为Windows操作系统提供的一套C++类库,它封装了Windows API,使得开发Windows应用...

    BMP格式图像的读取与保存

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

    BMP文件的读取与保存

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

Global site tag (gtag.js) - Google Analytics