日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

C語言如何讀取bmp圖像_C 語言

作者:微小冷 ? 更新時間: 2022-06-02 編程語言

1、BMP圖像編碼

BMP即bitmap,也就是位圖,一般由4部分組成:文件頭信息塊、圖像描述信息塊、顏色表(在真彩色模式無顏色表)和圖像數據區。

在圖像數據之前,如圖所示,共有54位數據

其中,0x424d在十進制為19778,對應的ASCII碼為BM,表示這是個bitmap文件。

在C語言中,short類型為16位,即2字節;int為4字節。考慮到BMP格式的文件頭中,每個信息基本都是2字節的倍數,故而用int和short便可描述出bmp格式的文件頭。

文件信息頭[14 bytes]存儲著文件類型,文件大小等信息

// 文件信息頭結構體
typedef struct tagBITMAPFILEHEADER{
? ? unsigned short bfType;?? ??? ?//必為'BM'
? ? unsigned int ? bfSize;?? ??? ?//文件字節數(2-5)
? ? unsigned int bfReserved; ? ?//位圖文件保留字,必為0(6-9)
? ? unsigned int ? bfOffBits; ? //像素數據偏移 (10-13)
} bmpHeader;

接下來的40bytes存儲圖像的尺寸,顏色索引,位平面數等信息

#define uint unsigned int
#define ushort unsigned short
//圖像信息頭結構體
typedef struct tagBITMAPINFOHEADER{
? ? uint ? ?biSize; ? ? ? ? ?// 結構體尺寸 (14-17)
? ? int ? ? biWidth; ? ? ? ? // 圖像寬度 ?(18-21)
? ? int ? ? biHeight; ? ? ? ?// 圖像高度 ?(22-25)
? ? ushort ?biPlanes; ? ? ? ?// 目標設備的級別,為1(26-27)
? ? ushort ?biBitCount; ? ? ?// 像素位數,為1、4、8或24(28-29)
? ? uint ? ?biCompression; ? // 位圖壓縮類型,0為不壓縮、1為BI_RLE8、2為BI_RLE4(30-33)
? ? uint ? ?biSizeImage; ? ? // 單像素數據大小,等于bfSize-bfOffBits (34-37)
? ? int ? ? biXPelsPerMeter; // 水平分辨率,一般為0 (38-41)
? ? int ? ? biYPelsPerMeter; // 垂直分辨率,一般為0 (42-45)
? ? uint ? ?biClrUsed; ? ? ? // 位圖顏色表中的顏色數,0表示使用所有調色板項(46-49)
? ? uint ? ?biClrImportant; ?// 重要顏色索引的數目,0表示都重要(50-53)
} infoHeader;

在54位的文件頭之后,如果需要的話,bmp文件可存放調色板信息,對于rgb圖像來說,可以如下

//24位圖像素信息結構體,即調色板
typedef struct _PixelInfo {
? ? unsigned char rgbBlue; ? //藍色分量 ?(0-255)
? ? unsigned char rgbGreen; ?//綠色分量 ?(0-255)
? ? unsigned char rgbRed; ? ?//紅色分量 ?(0-255)
? ? unsigned char rgbReserved;// 保留,必須為0
} PixelInfo;

顏色表中RGBQUAD結構數據的個數由biBitCount來確定:

  • 當biBitCount=1,4,8時,分別有2,16,256個表項;
  • 當biBitCount=24時,沒有顏色表項。

位圖信息頭和顏色表組成位圖信息,BITMAPINFO結構定義如下:

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位圖信息頭
RGBQUAD bmiColors[1]; ? ? ? // 顏色表
} bmpInfo;

顏色表接下來為圖像數據區,存儲每個像素對應的顏色號,單像素點顏色號的位長度與圖像類型有關

圖像類型 2色圖像 16色圖像 256色圖像 真彩色圖像
字節數 1bit 4bit 1B(8bit) 3B

由此可知,理想情況下圖像數據區的字節數為:

但是,由于BMP以字節為單位,按行存儲圖片的數據,也就是說每一行必須為字節數。而對于16色以及2色圖像而言,當每行像素個數為奇數時,則必然導致出現空位,從而實際所占存儲空間要大于上述計算值。

2、讀取BMP文件

讀取文件之后第一件事即判斷我們讀取的是否為BMP圖像,即

//判斷是否是位圖,在0-1字節?
int IsBitMap(FILE *fp){
?? ?ushort s;
?? ?fread(&s,1,2,fp);
? ? return s==BM ? 1 : 0;
}?

其中,fread命令表示讀取文件fp,并將讀取到的內容存儲在s中。1表示要讀取的數據的大小,2表示將要讀取的元素的個數。由前文可知,位圖的文件類型必須是BM,十六進制下0x4d42,十進制為19778。

然后需要得到圖像的寬度和高度,從而確定數據區的范圍

//獲得圖片的寬度,在18-21字節?
int getWidth(FILE *fp){
?? ?int width;
?? ?fseek(fp,18,SEEK_SET);
?? ?fread(&width,1,4,fp);
?? ?return width;?? ?
}
?
//獲得圖片的高度 ,在22-25字節?
int getHeight(FILE *fp){
?? ?int height;
?? ?fseek(fp,22,SEEK_SET);
?? ?fread(&height,1,4,fp);
?? ?return height;?? ?
} ?

其中,fseek可以為fp提供一個偏移量,SEEK_SET表示從文件的開頭進行移動。由上文可知,圖片高度所在位置是第22個字節。

若想讀取其他信息,以此類推即可。

//test.c
#include<stdio.h>
#include<malloc.h>

#define BM 19778?? ??? ?// 位圖的標志
#define PATH "1.bmp" ??? ?//打開的文件路徑?
#define ushort unsigned short
#define uint unsigned int
#define uchar unsigned char

//判斷是否是位圖,在0-1字節?
int IsBitMap(FILE *fp){
?? ?ushort s;
?? ?fread(&s,1,2,fp);
? ? return s==BM ? 1 : 0;
}?
?
//獲得圖片的寬度,在18-21字節?
int getWidth(FILE *fp){
?? ?int width;
?? ?fseek(fp,18,SEEK_SET);
?? ?fread(&width,1,4,fp);
?? ?return width;?? ?
}
?
//獲得圖片的高度 ,在22-25字節?
int getHeight(FILE *fp){
?? ?int height;
?? ?fseek(fp,22,SEEK_SET);
?? ?fread(&height,1,4,fp);
?? ?return height;?? ?
} ?
?
//獲得每個像素的位數,在28-29字節?
ushort getBit(FILE *fp)
{
?? ?ushort bit;
?? ?fseek(fp,28,SEEK_SET);
?? ?fread(&bit,1,2,fp);
?? ?return bit;
}?
?
//獲得數據的起始位置,在10-13字節
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

欄目分類
最近更新