BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种Windows应用程序所支持。因为几乎不进行压缩,所以BMP格式是最简单的通用格式之一。
本篇文章主要介绍BMP文件的格式规范,解析及其保存。
BMP文件结构(本段代码由小组成员卿雯童鞋呈现)
位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节(位图数据,即图像数据,Data Bits 或Data Body)阵列,它具有如下所示的形式。
位图文件头 (bitmap-file header) BITMAPFILEHEADER bmfh
/** * bitmap-file header(14 byte) * */ class BITMAPFILEHEADER { short bfType;// the type of BMP file,value of 'B' or 'M' only.(1-2 byte) int bfSize;// the size of BMP file.(3-6 byte) short bfReserved1;// reserved word of bmp file,value of 0 only.(7-8 byte) short bfReserved2;// reserved word of bmp file,value of 0 only.(9-10byte) int bfOffBits;// the offset of file header(11-14 byte) }
位图信息头 (bitmap-information header) BITMAPINFOHEADER bmih
/** * bitmap-information header(40 byte) * */ class BITMAPINFOHEADER { int biSize;// the size of this part.(15-18 byte) int biWidth;// the width of bmp file.(19-22 byte) int biHeight;// the height of bmp file.(23-26 byte) byte biPlanes;// the rank of target device.value of q only(27-28 byte) byte biBitCount;// the bit of per pixel,value of 1,4 8 or 24 only.(29-30byte) int biCompression;// the type of compression,value of 0(BI_RGB)(non-compression),1(BI_RLE8) or 2(BI_RLE4) only.(31-34 byte) int biSizeImage;// the size of image.(35-38 byte) int biXPelsPerMeter;// horizontal resolution, Pixels per meter.(39-42 byte) int biYPelsPerMeter;// vertical resolution,Pixels per meter.(43-46 byte) int biClrUsed;// the number of all used color.(47-50 byte) int biClrImportant;// the number of key color.(51-54 byte) }
彩色表 (color table) RGBQUAD aColors[]
/** * color table * */ class RGBQUAD { byte rgbRed;// the red channel byte rgbGreen;// the Green channel byte rgbBlue;// the blue channel byte rgbReserved;// reserved,value of 0 only }
图象数据阵列字节 BYTE aBitmapBits[]
/** * Data Bits * */ class BITMAPINFO { BITMAPINFOHEADER bmiHeader; RGBQUAD bmiColors; }
BMP文件解析(本段代码由小组成员阳超群童鞋呈现)
要点:先读取位图文件头的信息(14 byte)
然后读取位图信息头为的信息(40 byte)
注意:此段要获取信息头的2个重要的参数,位图的宽度和高度
最后读取位图的图像信息。
其中要注意数据类型的匹配。
读取位图文件头和信息头
/** * read the image from the bitmap file * * @param path * the path of bitmap file * @throws IOException */ public void readBMP(String path) throws IOException { // creat a FileInputStream object; fis = new java.io.FileInputStream(path); // creat a DataInputStream object; dins = new java.io.DataInputStream(fis); // read the bitmap loader of bitmap file int bmploaderLen = 14; byte[] bmploader = new byte[bmploaderLen]; dins.read(bmploader, 0, bmploaderLen); // read the info header of bitmap file int bmpheaderLen = 40; byte[] bmpheader = new byte[bmpheaderLen]; dins.read(bmpheader, 0, bmpheaderLen); biWidth = convert2Int(bmpheader, 7); biHeight = convert2Int(bmpheader, 11); }
将byte数组转换为int类型的数据
/** * 4 byte convert to 1 int * @param bytes the source byte array * @return the converted int */ private int convert2Int(byte[] bytes, int index) { return (((int) bytes[index] & 0xff) << 24) | (((int) bytes[index - 1] & 0xff) << 16) | (((int) bytes[index - 2] & 0xff) << 8) | ((int) bytes[index - 3] & 0xff); }
计算补零的长度
// calculate the length of zero-padding if (!(biHeight * 3 % 4 == 0)) { skip_width = 4 - biWidth * 3 % 4; }
读取RGB信息
for (int h = biHeight - 1; h >= 0; h--) { for (int w = 0; w < biWidth; w++) { // 分别按照协议顺序读出字节 int blue = dins.read(); int green = dins.read(); int red = dins.read(); // 由于颜色值范围超出byte正值范围,可能存储为负值,进行位运算 int blue_temp = (blue & 0xff); int green_temp = (green & 0xff); int red_temp = (red & 0xff); imageB[h][w] = blue_temp; imageG[h][w] = green_temp; imageR[h][w] = red_temp; // zero-padding if (w == 0) { byte bytes[] = new byte[skip_width]; dins.read(bytes); } } } dins.close(); fis.close(); }
绘出位图图像
/** * paint the image on the frame */ public void paint(Graphics g) { super.paint(g); // g = this.getGraphics(); for (int h = 0; h < biHeight; h++) { for (int w = 0; w < biWidth; w++) { g.setColor(new Color(imageR[h][w], imageG[h][w], imageB[h][w])); g.fillRect(w, h, 1, 1); } } }
BMP文件的保存(本段代码有小组成员曹睿超童鞋呈现)
要点:按BMP文件结构依次写入位图文件头,位图信息图,RGB颜色表,和图象数据阵列字节
注意:数据类型的匹配。
/** * 写入bmp文件 * @param image * @param file */ public void writeBMP(BufferedImage image, File file) { try { // 创建输入流 FileOutputStream fos = new FileOutputStream(file); DataOutputStream dos = new DataOutputStream(fos); //位图文件类型,2个字节,必须为'B'和'M' dos.writeByte((int)'B'); dos.writeByte((int)'M'); //BMP头文件 biWidth = image.getWidth(); biHeight = image.getHeight(); //位图文件大小,4个字节 int skip_width = 0; //一个扫描行所占的字节数必须为4的倍数,不足的补上0 if(skip_width * 3 % 4 != 0) skip_width = 4 - skip_width * 3 % 4; //得到文件的大小 bfSize = 54 + (biWidth + skip_width) * 3 * biHeight; dos.write(changeIntToByte(bfSize, 4) , 0, 4); //起始位置4个字节 dos.write(changeIntToByte(bfReserved1, 2), 0, 2); dos.write(changeIntToByte(bfReserved2, 2), 0, 2); //写入位图文件的起始位置 dos.write(changeIntToByte(bfOffBits, 4), 0, 4); //位图信息图 biSize = (biWidth + skip_width) * 3 * biHeight; dos.write(changeIntToByte(biSize, 4), 0, 4); //宽度,高度 dos.write(changeIntToByte(biWidth, 4), 0, 4); dos.write(changeIntToByte(biHeight, 4), 0, 4); //目标设备 dos.write(changeIntToByte(biPlanes, 2), 0, 2); //像素所需位数,24 biBitCount = 24; dos.write(changeIntToByte(biBitCount, 2), 0 ,2); //压缩类型 dos.write(changeIntToByte(biCompression, 4), 0 ,4); //位图大小 dos.write(changeIntToByte(biSizeImage, 4), 0, 4); //写入水平,垂直分辨率(150ppm) dos.write(changeIntToByte(biXPelsPreMeter, 4), 0, 4); dos.write(changeIntToByte(biYPelsPreMeter, 4), 0, 4); //写入位图中实际使用的颜色表的颜色数 dos.write(changeIntToByte(biClrUsed, 4), 0, 4); //写入重要的颜色 dos.write(changeIntToByte(biClrImportant, 4), 0, 4); //位图数据 int color [][] = new int [biWidth][biHeight]; byte colorR[][] = new byte [biWidth][biHeight]; byte colorG[][] = new byte [biWidth][biHeight]; byte colorB[][] = new byte [biWidth][biHeight]; for(int i = 0;i < biHeight;i ++) { for(int j = 0;j < biWidth;j ++) { int temp = image.getRGB(j, i); color[i][j] = temp; colorR[i][j] = (byte)(temp >> 16); colorG[i][j] = (byte)(temp >> 8); colorB[i][j] = (byte)(temp >> 0); } } for(int i = biHeight - 1;i >= 0;i ++) { for(int j = biWidth - 1;j >= 0;j --){ dos.write(colorB[i][j]); dos.write(colorG[i][j]); dos.write(colorR[i][j]); if(skip_width != 0 && j == 0) dos.write(changeIntToByte(0, skip_width), 0, skip_width); } } fos.flush(); fos.close(); dos.flush(); dos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }
将int类型转换为Byte数组
/** * 将int类型转换为byte数组 * @param num int类型的对象 * @param size 数组的长度 * @return byte类型数组 */ private byte[] changeIntToByte(int num, int size) { //定义一个byte类型数组 byte[] count = new byte[size]; //循环进行位运算 for(int i = 0;i < size;i ++) { count[i] = (byte) (num >> (i * 8)); } return count; }
相关推荐
### BMP文件格式解析 BMP(Bitmap)文件格式是一种设备无关...通过深入解析BMP文件格式,不仅可以更好地理解图像文件的内部结构,还能掌握如何编写程序来处理和操作这类文件,为图像处理、格式转换等任务奠定基础。
#### 二、BMP文件结构解析 BMP文件的数据组织形式由以下几个主要部分构成: 1. **BMP文件头** (BMP File Header): 包含文件格式、大小等基本信息。 2. **位图信息头** (Bitmap Information): 提供图像数据的尺寸、...
BMP文件通常由图像数据、颜色表和文件头等部分组成,这些组成部分对于理解BMP格式至关重要。 1. **BMP文件结构** BMP文件以文件头开始,包括两个主要部分:BITMAPFILEHEADER(位图文件头)和BITMAPINFOHEADER...
这个项目似乎涉及使用C++编程语言来实现对BMP文件的读取和保存功能。接下来,我们将深入探讨BMP文件格式以及如何使用C++进行处理。 1. **BMP文件格式** BMP文件是一种位图格式,它存储了图像的颜色信息和像素数据...
本主题将深入探讨如何在C语言环境下读取和保存BMP文件。 BMP文件结构主要由三个部分组成:文件头、信息头和像素数据。文件头包括文件类型标识、文件大小、保留字段和偏移量,用于指示图像数据在文件中的位置。信息...
在开发工具方面,Visual Studio等IDE提供了调试和预览BMP文件的功能,帮助开发者直观地检查文件解析和保存的结果。同时,可以使用Hex Editor等十六进制编辑器查看BMP文件的二进制数据,以验证文件头和图像数据是否...
这个程序或许包含了一些基本的图像编辑功能,如画刷、填充、裁剪等,用于展示如何在实际应用中读取和保存BMP文件。 在深入学习BMP文件的读取与保存时,我们需要了解以下几个关键知识点: 1. BMP文件结构:BMP文件...
总的来说,自制画板打开和保存BMP格式文件涉及到的知识点包括:BMP文件格式的理解与解析,二进制文件操作,图像处理基础,GUI编程,以及事件驱动编程。这个项目既能够加深对图像文件格式的理解,也能锻炼实际编程...
BMP文件主要由三部分组成:文件头、信息头和像素数据。文件头包含了文件的基本信息,如文件类型、文件大小等;信息头则提供了更具体的图像信息,如宽度、高度、颜色深度等;像素数据是实际的图像内容,按照从左到右...
1. **读取BMP文件**:首先,我们需要解析BMP文件头,获取图像的宽度、高度、位深度等信息。BMP文件的头部包含了这些元数据,解析后可以确定图像的实际像素数据在文件中的位置。 2. **处理色彩信息**:BMP文件中的每...
BMP 图像格式是与硬件设备无关的图像文件格式,使用非常广泛。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大。BMP 文件的图像深度可选 1bit、4bit、8bit 及 24...
【BMP文件格式详解】 BMP文件格式,全称Bitmap或Device-...对于编程工作,正确理解和处理这些数据结构是至关重要的,因为不同的位图格式和数据排列方式可能导致解析错误,尤其是在处理不同平台或不同版本的BMP文件时。
理解和解析BMP文件格式对于图像处理程序的编写至关重要。开发者需要知道如何读取和解析文件头以获取图像的基本信息,以及如何根据颜色位深度和像素数据的排列方式来还原图像的原始色彩。此外,了解BMP文件格式也有助...
当我们将BMP文件转换为TXT时,我们需要解析这些二进制数据并将其转化为人类可读的文本格式。这通常包括: 1. 文件头:BMP文件以一个固定长度的文件头开始,包括文件大小、创建时间等信息。例如,DOS头(2字节)和...
BMP文件格式有特定的头部结构,包括文件头、信息头和颜色数据。你需要按照BMP格式的规范构造这些头部信息,并将解析后的framebuffer数据写入文件。在Android上,你可以使用Java或者C/C++代码来完成这个过程。 5. *...
5. 保存 BMP 文件:最后,将生成的 BMP 文件头和像素数据写入到一个新文件中,完成转换。 代码实现: 在 `RAW_to_BMP.c` 文件中,你可以找到上述步骤的具体实现。代码通常会包含以下几个函数: - `read_RAW_file()...
在VC++环境下,开发人员经常需要处理BMP文件的读取和写入操作,以便在应用程序中显示或保存图像。以下是一些关于如何在VC++中进行这些操作的关键知识点: 1. **BMP文件结构**: - BMP文件由一个文件头(File ...
要将预览的图像保存为BMP文件,我们需要理解BMP文件格式,它是一个未经压缩的位图格式,包含图像的宽度、高度、色彩深度和像素数据。可以使用GDI+或者Windows API函数来创建BMP文件。首先,截取屏幕或MDI子窗口的...
5. 如果要保存修改后的BMP文件,按照原格式重新构建文件头和数据,然后写入文件。 在实际编程中,可以使用各种编程语言实现BMP文件的读取和写入,例如C++、C#、Python等。通过熟悉BMP文件格式,我们可以创建自定义...
总之,理解和解析BMP文件结构是图像处理领域的一个基础技能。通过学习和掌握,我们可以更好地进行图像读取、修改和保存,进一步应用于图像分析、图像合成等高级任务。对于开发者来说,熟悉BMP文件结构能够增强处理...