第三章:BMP文件的读取与显示

BMP文件的读取与显示

常见的图像文件格式

BMP(Bitmap位图)

是一种与设备无关(DIB)的图像文件格式,是Windows环境中经常使用的一种位图格式。其特点是不进行压缩,包含的图像信息丰富,但由此导致了占用磁盘空间过大的缺点。

BMP在单机上非常流行,不受Internet网络欢迎。

采用的是RGB色彩系统。

GIF(.gif)文件

GIF(Graphics Interchange Format)是美国联机服务商CompuServe针对当时网络传输带宽的限制开发的图像格式。其特点是压缩比高,磁盘空间占用较少,但不能存储超过256色的图像。

在Internet上广泛应用:

①它不仅可以存储单幅静止图像,也可以同时存储若干静止图像进而形成连续的动画;

②指定透明区域;

③渐显方式。

采用的是RGB色彩系统。

JPEG(.jpg)文件

JPEG(Joint Photographic Experts Group)是利用JPEG方法压缩的图像格式,有损压缩、压缩比非常高,但压缩/解压缩算法复杂、存储和显示速度慢。可以处理24位真彩色,适用于处理大幅的图像。

JPEG是Internet中 最受欢迎 的图像格式。

采用的是YCbCr色彩系统。

TIFF(.tif)文件

TIFF(Tag Image File Format)是一种独立于操作系统和文件系统的格式,便于在软件间进行图像数据交换。文件格式复杂,记录的相关信息多(图层、通道信息、多幅图像)。

该格式支持压缩;支持单色、256色、24位真彩色、32位色、48位色等多种色彩位;同时支持RGB、CMYK、YCbCr等多种色彩系统。

BMP图像文件结构

BITMAPFILEHEADER结构---14字节

1
2
3
4
5
6
7
typedef struct tagBITMAPFILEHEADER {
WORD bfType; //2个字节
DWORD bfSize; //4个字节
WORD bfReserved1; //2个字节
WORD bfReserved2; //2个字节
DWORD bfOffBits; //4个字节
} BITMAPFILEHEADER;

这个结构的长度是固定的,为14个字节(WORD为无符号16位整数,DWORD为无符号32位整数),各个成员的说明如下:

  1. bfType:文件类型,为BM,即0x4D42,表示BMP文件。

  2. bfSize:文件大小,以字节为单位。

  3. bfReserved1:保留字,为0。

  4. bfReserved2:保留字,为0。

  5. bfOffBits:图像数据相对于文件头的偏移量,即位图数据的起始位置。即结构示意图中前三个部分的长度之和。

BITMAPINFOHEADER结构---40字节

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

这个结构的长度是固定的,为40个字节,各个成员的说明如下:

  1. biSize:指定结构大小,为40。

  2. biWidth:指定图像的宽度,单位是像素。

  3. biHeight:指定图像的高度,单位是像素。

  4. biPlanes:必须是1,不用考虑。

  5. biBitCount:指定表示颜色时要用到的位数,常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)。

biBitCount在实验中会经常使用到!!!

  1. biCompression 指定位图是否压缩。Windows位图可以采用压缩格式,但用的不多。我们只讨论的不压缩的情况,biCompression为BI_RGB(Windows定义好的常量) 。

  2. biSizeImage 位图数据占用的字节数,可以通过图像的高度、宽度、颜色深度计算出来。如果biCompression为BI_RGB,则该项可以为零。

  3. biXPelsPerMeter 指定目标设备的水平分辨率,单位是每米的像素个数。

  4. biYPelsPerMeter 指定目标设备的垂直分辨率,单位同上。

  5. biClrUsed 指定本图象实际用到的颜色数(决定调色板数组元素的个数),如果该值为零,则用到的颜色数为2的biBitCount次方。

biClrUsed在实验中也会经常使用到!!!

11。 biClrImportant 指定本图象中重要的颜色数,该值通常为零,即认为所有的颜色都是重要的。

Palette结构

调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次方个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节,其定义如下:

1
2
3
4
5
6
typedef struct tagRGBQUAD { 
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值,不考虑
} RGBQUAD;

真彩色图,不需要调色板的,BITMAPINFOHEADER 后直接是位图数据

关于灰度图像的调色板

BMP格式的文件中并没有灰度图这个概念,但可以很容易地用BMP文件来表示灰度图。方法是用256色的调色板,不过这个调色板有些特殊,每一项的RGB都相同。RGB值从(0,0,0)、(1,1,1)一直到(255,255,255)。 (0,0,0)是全黑色, (255,255,255)是全白色。

对于R=G=B的色彩,带入HSI色彩系统转换公式中可以看到只有亮度信息,饱和度分量都是0,即没有色彩信息。

实际的位图数据 ImageData

对于用到调色板的位图,图象数据就是该像素颜色在调色板中的索引值,对于真彩色图,图像数据就是实际的R,G,B值。下面就2色,16色,256色位图和真彩色位图分别介绍

2色位图,用1位就可以表示该像素的颜色(一般0表示黑,1表示白),一个字节可以表示8个像素

16色位图,用4位可以表示一个像素的颜色,所以一个字节可以表示2个像素,分为前4位和后4位

256色位图,一个字节表示1个像素

真彩色图,三个字节表示1个像素,RGB分别占用一个字节

位图数据——需要注意的两点

① 每一行的字节数必须是4的整倍数,如果不是,则需要补齐。

② BMP文件的数据是从下到上,从左到右的。也就是说,从文件中最先读到的是图像最下面一行的左边第一个像素,然后是左边第二个像素。。。接下来是倒数第二行左边第一个像素,左边第二个像素。。。依次类推 ,最后得到的是最上面一行的最右一个像素。

这个指针2怎么得到的没搞懂

计算方法:

1
2
3
4
int w = lpBitsInfo->bmiHeader.biWidth;
int h = lpBitsInfo->bmiHeader.biHeight;
int LineBytes = (w * lpBitsInfo->bmiHeader.biBitCount + 31) / 32 * 4;
BYTE* lpBits = (BYTE*)&lpBitsInfo->bmiColors[lpBitsInfo->bmiHeader.biClrUsed];
注意:每一行的字节数LineBytes必须是4的整倍数

遍历灰度图像数据的方法:

1
2
3
4
5
6
7
8
9
10
int i, j;
BYTE* pixel;
for (i = 0; i < h; i ++)
{
for (j = 0; j < w; j ++)
{
// 指向像素点(i,j)的指针
pixel = lpBits + LineBytes * (h - 1 - i) + j;
}
}

BMP图像文件读写与显示


第三章:BMP文件的读取与显示
http://jrhu0048.github.io/2024/10/25/shu-zi-tu-xiang-chu-li/di-san-zhang-bmp-wen-jian-de-du-qu-yu-xian-shi/
作者
JR.HU
发布于
2024年10月25日
更新于
2024年12月28日
许可协议