Bmp图片格式介绍
Bmp圖片格式介紹
介紹
BMP是英文Bitmap(位圖)的簡寫,它是Windows操作系統中的標準圖像文件格式,能夠被多種Windows應用程序所支持。隨著Windows操作系統的流行與豐富的Windows應用程序的開發,BMP位圖格式理所當然地被廣泛應用。這種格式的特點是包含的圖像信息較豐富,幾乎不進行壓縮,但由此導致了它與生俱來的缺點–占用磁盤空間過大
文件數據結構
bmp 格式圖片的文件頭長度絕大多數都是 54 字節,其中包括 14 字節的 位圖文件頭(head)以及 40 字節的 DIB (Device Independent Bitmap) 位圖信息數據頭(BItmap Information Header)。
位圖文件頭(14 bytes)
| 00 | 2 | 固定頭文件字段,內容為0x424D |
| 02 | 4 | bmp文件大小(little endian) |
| 06 | 2 | 預留字段 |
| 08 | 2 | 預留字段 |
| 0A | 4 | 圖片信息的開始位置 |
位圖信息數據頭(40bytes)
| 0E | 4 | 位圖信息數據頭的大小 40bytes |
| 12 | 4 | 圖像寬度(little endian) |
| 16 | 4 | 圖像高度(little endian) |
| 1A | 2 | 色彩平面的數量,默認為1 |
| 1C | 2 | 每像素用多少bit表示 |
| 1E | 4 | 圖片采用的壓縮方式,通常不壓縮即BL_RGB,對應值0 |
| 22 | 4 | 圖片大小(原始位圖數據大小)對于不壓縮的圖片,默認為0 |
| 26 | 4 | 橫向分辨率(像素/米) |
| 2A | 4 | 縱向分辨率(像素/米) |
| 2E | 4 | 調試板中顏色數量,默認為0 |
| 32 | 4 | 重要顏色的數量,默認為0 |
原始位圖數據 Raw Bitmap Data
拿最常見的 24BPP RGB (24 比特每像素,紅綠藍三通道) 位圖來說,每種顏色需要 8 比特,或者說 1 字節,來存儲。在二進制文件中,通常情況下,RGB 按照藍、綠、紅的順序依次表示圖片中的像素點,而 RGBA 則按照藍、綠、紅、透明的順序(從左下開始,橫向逐行向上掃描)。特殊時候,也會出現順序與上述情況不同的特例,這時色彩順序會寫在 DIB Header 的 Bit Fields 中,以不同色彩通道的 Mask 的形式進行規定。由于 BI_BITFIELDS 也是一種壓縮方式,而通常 BMP 不采用任何壓縮方式,所以絕大多數時候,我們都是按照前面說的順序進行排序。
| 36 | 4 | 00 00 FF 00 | Red Channel bit mask |
| 3A | 4 | 00 FF 00 00 | Green Channel bit mask |
| 3E | 4 | FF 00 00 00 | Blue Channel bit mask |
| 42 | 4 | 00 00 00 FF | Alpha Channel bit mask |
主流的 CPU 每次從內存中讀取并處理數據塊(chunk),且通常為 32 比特(4 字節)。因此,為了提升讀取效率,位圖每行的數據(字節)都需要是 4 的倍數,字節對齊
Row_Size = (BitPerPixel * Image_Width + 31) / 32 * 4
每行的字節數等于:每像素比特數乘以圖片寬度加 31 的和除以 32,并向下取整,最后乘以 4。
Pix_Array_Size = Row_Size * Image_Height
原始位圖數據大小等于:每行的字節數乘以圖像高度(也就是總行數)
文件大小 = 原始位圖數據大小 + 文件頭大小
代碼表示bitmap數據
BitMap Head
#pragma pack(1) typedef struct {unsigned short bfType; // "BM"unsigned int bfSize; // 文件大小unsigned short bfReserved1; // 保留,必須設置為0unsigned short bfReserved2; // 保留,必須設置為0unsigned int bfOffBits; // 從文件頭到像素數據的偏移 } BitMapFileHeader;BitMap Info Header
typedef struct{unsigned int biSize; // 此結構體的大小int biWidth; // 圖像的寬int biHeight; // 圖像的高unsigned short biPlanes; // 表示bmp圖片的平面屬,顯然顯示器只有一個平面,所以恒等于1unsigned short biBitCount; // 一像素所占的位數,一般為24unsigned int biCompression; // 說明圖象數據壓縮的類型,0為不壓縮。unsigned int biSizeImage; // 像素數據所占大小, 這個值應該等于上面文件頭結構中bfSize-bfOffBitsint biXPelsPerMeter; // 說明水平分辨率,用象素/米表示。一般為0int biYPelsPerMeter; // 說明垂直分辨率,用象素/米表示。一般為0unsigned int biClrUsed; // 說明位圖實際使用的彩色表中的顏色索引數(設為0的話,則說明使用所有調色板項)。unsigned int biClrImportant;// 說明對圖象顯示有重要影響的顏色索引的數目,如果是0,表示都重要。 } BitMapInfoHeader;rgb
// 24bit typedef struct {unsigned char rgblue;unsigned char rgbgreen; unsigned char rgbred;unsigned char rgbreserved; } PixelInfo;代碼demo
讀取bmp文件數據頭
#ifndef _BMP_H_ #define _BMP_H_#pragma pack(1)typedef struct {unsigned short bfType; // "BM"unsigned int bfSize; // 文件大小unsigned short bfReserved1; // 保留,必須設置為0unsigned short bfReserved2; // 保留,必須設置為0unsigned int bfOffBits; // 從文件頭到像素數據的偏移 } BitMapFileHeader;typedef struct{unsigned int biSize; // 此結構體的大小int biWidth; // 圖像的寬int biHeight; // 圖像的高unsigned short biPlanes; // 表示bmp圖片的平面屬,顯然顯示器只有一個平面,所以恒等于1unsigned short biBitCount; // 一像素所占的位數,一般為24unsigned int biCompression; // 說明圖象數據壓縮的類型,0為不壓縮。unsigned int biSizeImage; // 像素數據所占大小, 這個值應該等于上面文件頭結構中bfSize-bfOffBitsint biXPelsPerMeter; // 說明水平分辨率,用象素/米表示。一般為0int biYPelsPerMeter; // 說明垂直分辨率,用象素/米表示。一般為0unsigned int biClrUsed; // 說明位圖實際使用的彩色表中的顏色索引數(設為0的話,則說明使用所有調色板項)。unsigned int biClrImportant;// 說明對圖象顯示有重要影響的顏色索引的數目,如果是0,表示都重要。 } BitMapInfoHeader;// 24bit typedef struct {unsigned char rgblue;unsigned char rgbgreen; unsigned char rgbred;unsigned char rgbreserved; } PixelInfo;#endif #include <stdio.h> #include "bmp.h"void show_bmp_file_head(BitMapFileHeader *data) {printf("#########################################\n");printf("bfType %x\n", data->bfType);printf("bfSize %d\n", data->bfSize/1024);printf("bfOffBits %d\n", data->bfOffBits); }void show_bmp_info_head(BitMapInfoHeader *data) {printf("#########################################\n");printf("biSize %d\n", data->biSize);printf("biWidth %d\n", data->biWidth);printf("biHeight %d\n", data->biHeight);printf("biPlanes %d\n", data->biPlanes);printf("biBitCount %d\n", data->biBitCount);printf("biCompression %d\n", data->biCompression);printf("biXPelsPerMeter %d\n", data->biXPelsPerMeter);printf("biYPelsPerMeter %d\n", data->biYPelsPerMeter);printf("biClrUsed %d\n", data->biClrUsed);printf("biClrImportant %d\n", data->biClrImportant); }void show_bmp_rgb(PixelInfo *data) {printf("#########################################\n");printf("rgblue %2x\n", data->rgblue);printf("rgbgreen %2x\n", data->rgbgreen);printf("rgbred %2x\n", data->rgbred); }int main(int argc, char *argv[]) {FILE *fp = NULL;BitMapFileHeader FileHead;BitMapInfoHeader InfoHead;PixelInfo rgbinfo;char *ptr = NULL;int i, j;fp = fopen(argv[1], "rb");if(fp == NULL){perror("open bmp file error");return -1;}fread(&FileHead, sizeof(BitMapFileHeader), 1, fp);fread(&InfoHead, sizeof(BitMapInfoHeader), 1, fp);show_bmp_file_head(&FileHead);show_bmp_info_head(&InfoHead);show_bmp_rgb(&rgbinfo);ptr = (unsigned char *)malloc(FileHead.bfSize);if(ptr == NULL){perror("malloc ptr fail\n");return 0;}for(i = 0; i <= InfoHead.biHeight; i++){for(j = 0; j <= InfoHead.biWidth; j++){fread(&rgbinfo, sizeof(PixelInfo), 1, fp);*ptr = 0xff << 24 | rgbinfo.rgbred << 16 | rgbinfo.rgbgreen << 8 | rgbinfo.rgblue;memset(&rgbinfo, 0, sizeof(PixelInfo));ptr++;if((rgbinfo.rgbred == 255) && (rgbinfo.rgbgreen == 255) && (rgbinfo.rgblue == 255))printf(" ");elseprintf("#");}printf("\n");} fclose(fp);return 0; } lin@u-android:~/lin/workspace/demo_project/bmp$ gcc -o bmp_test show_bmp_head.c lin@u-android:~/lin/workspace/demo_project/bmp$ ./bmp_test ./test.bmp ######################################### bfType 4d42 bfSize 459 bfOffBits 54 ######################################### biSize 40 biWidth 507 biHeight 309 biPlanes 1 biBitCount 24 biCompression 0 biXPelsPerMeter 0 biYPelsPerMeter 0 biClrUsed 0 biClrImportant 0總結
- 上一篇: java批量修改指定目录下的文件名
- 下一篇: openwrt网络管理工具网络管理工具: