網(wǎng)站首頁 編程語言 正文
1、BMP圖像編碼
BMP即bitmap,也就是位圖,一般由4部分組成:文件頭信息塊、圖像描述信息塊、顏色表(在真彩色模式無顏色表)和圖像數(shù)據(jù)區(qū)。
在圖像數(shù)據(jù)之前,如圖所示,共有54位數(shù)據(jù)
其中,0x424d在十進(jìn)制為19778,對應(yīng)的ASCII碼為BM,表示這是個bitmap
文件。
在C語言中,short類型為16位,即2字節(jié);int為4字節(jié)??紤]到BMP格式的文件頭中,每個信息基本都是2字節(jié)的倍數(shù),故而用int和short
便可描述出bmp格式的文件頭。
文件信息頭[14 bytes]存儲著文件類型,文件大小等信息
// 文件信息頭結(jié)構(gòu)體 typedef struct tagBITMAPFILEHEADER{ ? ? unsigned short bfType;?? ??? ?//必為'BM' ? ? unsigned int ? bfSize;?? ??? ?//文件字節(jié)數(shù)(2-5) ? ? unsigned int bfReserved; ? ?//位圖文件保留字,必為0(6-9) ? ? unsigned int ? bfOffBits; ? //像素數(shù)據(jù)偏移 (10-13) } bmpHeader;
接下來的40bytes存儲圖像的尺寸,顏色索引,位平面數(shù)等信息
#define uint unsigned int #define ushort unsigned short //圖像信息頭結(jié)構(gòu)體 typedef struct tagBITMAPINFOHEADER{ ? ? uint ? ?biSize; ? ? ? ? ?// 結(jié)構(gòu)體尺寸 (14-17) ? ? int ? ? biWidth; ? ? ? ? // 圖像寬度 ?(18-21) ? ? int ? ? biHeight; ? ? ? ?// 圖像高度 ?(22-25) ? ? ushort ?biPlanes; ? ? ? ?// 目標(biāo)設(shè)備的級別,為1(26-27) ? ? ushort ?biBitCount; ? ? ?// 像素位數(shù),為1、4、8或24(28-29) ? ? uint ? ?biCompression; ? // 位圖壓縮類型,0為不壓縮、1為BI_RLE8、2為BI_RLE4(30-33) ? ? uint ? ?biSizeImage; ? ? // 單像素數(shù)據(jù)大小,等于bfSize-bfOffBits (34-37) ? ? int ? ? biXPelsPerMeter; // 水平分辨率,一般為0 (38-41) ? ? int ? ? biYPelsPerMeter; // 垂直分辨率,一般為0 (42-45) ? ? uint ? ?biClrUsed; ? ? ? // 位圖顏色表中的顏色數(shù),0表示使用所有調(diào)色板項(46-49) ? ? uint ? ?biClrImportant; ?// 重要顏色索引的數(shù)目,0表示都重要(50-53) } infoHeader;
在54位的文件頭之后,如果需要的話,bmp文件可存放調(diào)色板信息,對于rgb圖像來說,可以如下
//24位圖像素信息結(jié)構(gòu)體,即調(diào)色板 typedef struct _PixelInfo { ? ? unsigned char rgbBlue; ? //藍(lán)色分量 ?(0-255) ? ? unsigned char rgbGreen; ?//綠色分量 ?(0-255) ? ? unsigned char rgbRed; ? ?//紅色分量 ?(0-255) ? ? unsigned char rgbReserved;// 保留,必須為0 } PixelInfo;
顏色表中RGBQUAD結(jié)構(gòu)數(shù)據(jù)的個數(shù)由biBitCount來確定:
- 當(dāng)biBitCount=1,4,8時,分別有2,16,256個表項;
- 當(dāng)biBitCount=24時,沒有顏色表項。
位圖信息頭和顏色表組成位圖信息,BITMAPINFO結(jié)構(gòu)定義如下:
typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 位圖信息頭 RGBQUAD bmiColors[1]; ? ? ? // 顏色表 } bmpInfo;
顏色表接下來為圖像數(shù)據(jù)區(qū),存儲每個像素對應(yīng)的顏色號,單像素點(diǎn)顏色號的位長度與圖像類型有關(guān)
圖像類型 | 2色圖像 | 16色圖像 | 256色圖像 | 真彩色圖像 |
---|---|---|---|---|
字節(jié)數(shù) | 1bit | 4bit | 1B(8bit) | 3B |
由此可知,理想情況下圖像數(shù)據(jù)區(qū)的字節(jié)數(shù)為:
但是,由于BMP以字節(jié)為單位,按行存儲圖片的數(shù)據(jù),也就是說每一行必須為字節(jié)數(shù)。而對于16色以及2色圖像而言,當(dāng)每行像素個數(shù)為奇數(shù)時,則必然導(dǎo)致出現(xiàn)空位,從而實際所占存儲空間要大于上述計算值。
2、讀取BMP文件
讀取文件之后第一件事即判斷我們讀取的是否為BMP圖像,即
//判斷是否是位圖,在0-1字節(jié)? int IsBitMap(FILE *fp){ ?? ?ushort s; ?? ?fread(&s,1,2,fp); ? ? return s==BM ? 1 : 0; }?
其中,fread命令表示讀取文件fp,并將讀取到的內(nèi)容存儲在s中。1表示要讀取的數(shù)據(jù)的大小,2表示將要讀取的元素的個數(shù)。由前文可知,位圖的文件類型必須是BM,十六進(jìn)制下0x4d42,十進(jìn)制為19778。
然后需要得到圖像的寬度和高度,從而確定數(shù)據(jù)區(qū)的范圍
//獲得圖片的寬度,在18-21字節(jié)? int getWidth(FILE *fp){ ?? ?int width; ?? ?fseek(fp,18,SEEK_SET); ?? ?fread(&width,1,4,fp); ?? ?return width;?? ? } ? //獲得圖片的高度 ,在22-25字節(jié)? int getHeight(FILE *fp){ ?? ?int height; ?? ?fseek(fp,22,SEEK_SET); ?? ?fread(&height,1,4,fp); ?? ?return height;?? ? } ?
其中,fseek
可以為fp提供一個偏移量,SEEK_SET表示從文件的開頭進(jìn)行移動。由上文可知,圖片高度所在位置是第22個字節(jié)。
若想讀取其他信息,以此類推即可。
//test.c #include<stdio.h> #include<malloc.h> #define BM 19778?? ??? ?// 位圖的標(biāo)志 #define PATH "1.bmp" ??? ?//打開的文件路徑? #define ushort unsigned short #define uint unsigned int #define uchar unsigned char //判斷是否是位圖,在0-1字節(jié)? int IsBitMap(FILE *fp){ ?? ?ushort s; ?? ?fread(&s,1,2,fp); ? ? return s==BM ? 1 : 0; }? ? //獲得圖片的寬度,在18-21字節(jié)? int getWidth(FILE *fp){ ?? ?int width; ?? ?fseek(fp,18,SEEK_SET); ?? ?fread(&width,1,4,fp); ?? ?return width;?? ? } ? //獲得圖片的高度 ,在22-25字節(jié)? int getHeight(FILE *fp){ ?? ?int height; ?? ?fseek(fp,22,SEEK_SET); ?? ?fread(&height,1,4,fp); ?? ?return height;?? ? } ? ? //獲得每個像素的位數(shù),在28-29字節(jié)? ushort getBit(FILE *fp) { ?? ?ushort bit; ?? ?fseek(fp,28,SEEK_SET); ?? ?fread(&bit,1,2,fp); ?? ?return bit; }? ? //獲得數(shù)據(jù)的起始位置,在10-13字節(jié) uint getOffSet(FILE *fp){ ?? ?uint OffSet; ?? ?fseek(fp,10L,SEEK_SET); ?? ?fread(&OffSet,1,4,fp); ?? ?return OffSet; } int main(){ ?? ?int width,height; ?? ?FILE *fp=fopen(PATH,"r"); ?? ?uchar *r,*g,*b; ?? ?int i,j; ?? ?r=(uchar *)malloc(4000); ?? ?b=(uchar *)malloc(4000); ?? ?g=(uchar *)malloc(4000); ?? ? ?? ?if(!IsBitMap(fp)){ ?? ??? ?printf("format error!\n"); ?? ??? ?fclose(fp); ?? ??? ?return 0;? ? ? } ? ? printf("this file is a bitmap picture\n"); ?? ?printf("width = %ld\nheight = %ld\n",getWidth(fp),getHeight(fp)); ?? ?printf("bit size = %d bit\n",getBit(fp)); ?? ?printf("OffSet = %d\n",getOffSet(fp)); ?? ? ?? ?return 0; }
驗證:
> gcc .\test.c
> .\a.exe ? ??
this file is a bitmap picture
width = 3840
height = 2160
bit size = 24 bit
OffSet = 138
原文鏈接:https://blog.csdn.net/m0_37816922/article/details/123717635
相關(guān)推薦
- 2022-11-14 python中的運(yùn)算符
- 2022-09-16 Go+Kafka實現(xiàn)延遲消息的實現(xiàn)示例_Golang
- 2022-03-05 Flutter基本組件Basics?Widget學(xué)習(xí)_Android
- 2022-09-13 Go語言中的數(shù)據(jù)競爭模式詳解_Golang
- 2022-11-16 C語言數(shù)據(jù)結(jié)構(gòu)不掛科指南之線性表詳解_C 語言
- 2022-03-22 C++運(yùn)算符重載詳情介紹_C 語言
- 2022-08-28 Centos解決顯卡驅(qū)動問題:NVIDIA-SMI has failed because it co
- 2022-07-07 通過Golang編寫一個AES加密解密工具_(dá)Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支