在实现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);
}
}
分享到:
相关推荐
本文将深入探讨如何使用C语言来读取和保存BMP文件,主要涉及`ReadBmp`和`SaveBmp`两个关键函数。 首先,我们需要了解BMP文件的结构。BMP文件通常由文件头、位图信息头和像素数据三部分组成。文件头...
"BMP位图的读取和显示" 本文将详细介绍 BMP 位图文件的基本格式,以及如何使用 VC++ 读取图像数据并将其显示在视图中。 BMP 位图文件格式 BMP 位图文件主要由四部分组成: 1. 文件头 BITMAPFILEHEADER 2. 位图...
本主题将深入探讨如何在C语言环境下读取和保存BMP文件。 BMP文件结构主要由三个部分组成:文件头、信息头和像素数据。文件头包括文件类型标识、文件大小、保留字段和偏移量,用于指示图像数据在文件中的位置。信息...
本篇文章将深入探讨如何使用C++来读取和保存BMP位图文件,特别是通过二进制方式获取BMP文件的像素信息。 首先,我们要了解BMP文件的结构。BMP文件由文件头、信息头和像素数据三部分组成。文件头包含文件类型标识、...
对bmp位图8位的灰度图像进行读取与显示,为后面的操作提供基础
在本文中,我们将深入探讨BMP位图文件的结构、如何读取以及如何保存,旨在帮助读者更好地理解和操作这种图像格式。 1. BMP文件结构: BMP文件主要由三部分组成:文件头、信息头和像素数据。文件头包含了文件的基本...
本教程主要讲解如何在VC6.0环境下读取并显示BMP位图,这对于初学者理解图像处理的基本原理非常有帮助。 首先,我们需要了解BMP文件的结构。BMP文件由文件头、位图信息头和实际像素数据三部分组成。文件头包含了文件...
本文将深入解析BMP位图文件结构,并通过VC++编程语言演示如何读取、处理和显示BMP图像,包括反色、平滑、图像叠加和保存等操作。 首先,了解BMP文件的基本结构至关重要。一个BMP文件主要由两部分组成:文件头和图像...
本篇将深入讲解如何读取和显示BMP位图文件,以及涉及的相关知识点。 首先,我们要了解BMP文件的基本结构。BMP文件分为文件头、信息头和像素数据三部分。文件头包含文件的基本信息,如文件大小、图像偏移量等;信息...
通过以上步骤,你将在VC6.0环境中成功实现BMP位图的读取与显示。这不仅加深了对BMP文件格式的理解,还掌握了MFC库中处理图形的基本方法。在实际编程中,你可能需要根据具体需求调整代码,例如处理不同大小和位深度的...
### BMP位图读取与取反色处理 #### 一、引言 在图像处理领域,位图(Bitmap)是一种常见的图像格式,其中BMP(Bitmap Image File Format)是无损压缩的一种图像存储格式,广泛应用于Windows操作系统。本文将详细...
本文将深入探讨如何直接通过读取文件的方式来显示BMP位图,这通常涉及到位图文件的结构理解、内存管理和图像渲染等技术。 BMP文件格式的基本结构: 1. 文件头(File Header):包含文件类型标识、文件大小和偏移量...
本文将深入探讨如何按文件读取24位BMP位图,这是最常用的BMP位图深度,也是许多图像处理和编程任务的基础。 首先,我们要了解BMP文件的基本结构。BMP文件分为两个主要部分:文件头和位图数据。文件头包含关于图像的...
本文将深入探讨如何使用C和C++语言读取与保存BMP文件,帮助你理解其背后的原理和操作步骤。 首先,我们要了解BMP文件的基本结构。BMP是一种未经压缩的图像文件格式,包含图像的宽度、高度、颜色深度以及实际的像素...
"BMPTest"可能是一个包含示例代码的项目,用于演示如何读取、保存和显示BMP位图。这个项目可能包括了打开BMP文件、解析文件结构、创建并填充DIB对象、使用GDI或GDI+在窗口上显示图像等功能。通过学习和理解这个项目...
在本文中,我们将深入探讨如何使用VC++ 6.0打开和显示位图(BMP)文件。位图文件是一种常见的图像格式,广泛应用于各种图形处理应用中。VC++ 6.0是一款经典的Microsoft Visual Studio集成开发环境,它提供了丰富的...
本项目是一个针对初学者的实践教程,旨在介绍如何使用编程技术实现数字水印功能,并重点涉及BMP位图文件的读取与处理。 首先,我们来了解一下“数字水印”。数字水印是一种将特定信息嵌入到多媒体文件(如图像、...
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC)库来开发一个Bmp位图读取、显示以及放大缩小的程序。MFC是微软为Windows操作系统提供的一套C++类库,它封装了Windows API,使得开发Windows应用...
根据提供的文件信息,本文将详细解释BMP格式图像的读取与保存的相关知识点,包括BMP文件的基本结构、如何读取BMP文件以及如何保存BMP文件等内容。 ### BMP文件基本结构 BMP(Bitmap Image File Format)是一种常见...
这个项目似乎涉及使用C++编程语言来实现对BMP文件的读取和保存功能。接下来,我们将深入探讨BMP文件格式以及如何使用C++进行处理。 1. **BMP文件格式** BMP文件是一种位图格式,它存储了图像的颜色信息和像素数据...