C語言編寫的bmp讀寫程序
C語言編寫的bmp讀寫程序 建議先把bmp的數據存儲格式了解下
- <span style="font-size:16px;">#include "Windows.h"
- #include "stdio.h"
- #include "string.h"
- #include "malloc.h"
- unsigned char *pBmpBuf;//讀入圖像數據的指針
- int bmpWidth;//圖像的寬
- int bmpHeight;//圖像的高
- RGBQUAD *pColorTable;//顏色表指針
- int biBitCount;//圖像類型,每像素位數
- bool readBmp(char *bmpName)
- {
- //二進制讀方式打開指定的圖像文件
- FILE *fp=fopen(bmpName,"rb");
- if(fp==0) return 0;
- //跳過位圖文件頭結構BITMAPFILEHEADER
- fseek(fp, sizeof(BITMAPFILEHEADER),0);
- //定義位圖信息頭結構變量,讀取位圖信息頭進內存,存放在變量head中
- BITMAPINFOHEADER head;
- fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
- //獲取圖像寬、高、每像素所占位數等信息
- bmpWidth = head.biWidth;
- bmpHeight = head.biHeight;
- biBitCount = head.biBitCount;
- //定義變量,計算圖像每行像素所占的字節數(必須是4的倍數)
- int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
- //灰度圖像有顏色表,且顏色表表項為256
- if(biBitCount==8){
- //申請顏色表所需要的空間,讀顏色表進內存
- pColorTable=new RGBQUAD[256];
- fread(pColorTable,sizeof(RGBQUAD),256,fp);
- }
- //申請位圖數據所需要的空間,讀位圖數據進內存
- pBmpBuf=new unsigned char[lineByte * bmpHeight];
- fread(pBmpBuf,1,lineByte * bmpHeight,fp);
- //關閉文件
- fclose(fp);
- return 1;
- }
- bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,
- int biBitCount, RGBQUAD *pColorTable)
- {
- //如果位圖數據指針為0,則沒有數據傳入,函數返回
- if(!imgBuf)
- return 0;
- //顏色表大小,以字節為單位,灰度圖像顏色表為1024字節,彩色圖像顏色表大小為0
- int colorTablesize=0;
- if(biBitCount==8)
- colorTablesize=1024;
- //待存儲圖像數據每行字節數為4的倍數
- int lineByte=(width * biBitCount/8+3)/4*4;
- //以二進制寫的方式打開文件
- FILE *fp=fopen(bmpName,"wb");
- if(fp==0) return 0;
- //申請位圖文件頭結構變量,填寫文件頭信息
- BITMAPFILEHEADER fileHead;
- fileHead.bfType = 0x4D42;//bmp類型
- //bfSize是圖像文件4個組成部分之和
- fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
- + colorTablesize + lineByte*height;
- fileHead.bfReserved1 = 0;
- fileHead.bfReserved2 = 0;
- //bfOffBits是圖像文件前3個部分所需空間之和
- fileHead.bfOffBits=54+colorTablesize;
- //寫文件頭進文件
- fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
- //申請位圖信息頭結構變量,填寫信息頭信息
- BITMAPINFOHEADER head;
- head.biBitCount=biBitCount;
- head.biClrImportant=0;
- head.biClrUsed=0;
- head.biCompression=0;
- head.biHeight=height;
- head.biPlanes=1;
- head.biSize=40;
- head.biSizeImage=lineByte*height;
- head.biWidth=width;
- head.biXPelsPerMeter=0;
- head.biYPelsPerMeter=0;
- //寫位圖信息頭進內存
- fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
- //如果灰度圖像,有顏色表,寫入文件
- if(biBitCount==8)
- fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
- //寫位圖數據進文件
- fwrite(imgBuf, height*lineByte, 1, fp);
- //關閉文件
- fclose(fp);
- return 1;
- }
- void main()
- {
- char inFileName[90],outFileName[90];
- printf("請輸入原始位圖文件的文件名:");
- scanf("%s",inFileName);
- printf("請輸入加密程序產生的新位圖文件的文件名:");
- scanf("%s",outFileName);
- //讀入指定BMP文件進內存
- readBmp(inFileName);
- //輸出圖像的信息
- printf("width=%d,height=%d, biBitCount=%d\n",bmpWidth,bmpHeight, biBitCount);
- //將圖像數據存盤
- saveBmp(outFileName, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
- //清除緩沖區,pBmpBuf和pColorTable是全局變量,在文件讀入時申請的空間
- delete []pBmpBuf;
- if(biBitCount==8)
- delete []pColorTable;
- }
- </span>
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
一、BMP文件結構
BMP文件組成
BMP文件由文件頭、位圖信息頭、顏色信息和圖形數據四部分組成。
BMP文件頭
BMP文件頭數據結構含有BMP文件的類型、文件大小和位圖起始位置等信息。
其結構定義如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbfType; // 位圖文件的類型,必須為BM
DWORD bfSize; // 位圖文件的大小,以字節為單位
WORDbfReserved1; // 位圖文件保留字,必須為0
WORDbfReserved2; // 位圖文件保留字,必須為0
DWORD bfOffBits; // 位圖數據的起始位置,以相對于位圖
// 文件頭的偏移量表示,以字節為單位
} BITMAPFILEHEADER;
3. 位圖信息頭
BMP位圖信息頭數據用于說明位圖的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本結構所占用字節數
LONGbiWidth; // 位圖的寬度,以像素為單位
LONGbiHeight; // 位圖的高度,以像素為單位
WORD biPlanes; // 目標設備的級別,必須為1
WORD biBitCount// 每個像素所需的位數,必須是1(雙色),
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),
// 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一
DWORD biSizeImage; // 位圖的大小,以字節為單位
LONGbiXPelsPerMeter; // 位圖水平分辨率,每米像素數
LONGbiYPelsPerMeter; // 位圖垂直分辨率,每米像素數
DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數
DWORD biClrImportant;// 位圖顯示過程中重要的顏色數
} BITMAPINFOHEADER;
4. 顏色表
顏色表用于說明位圖中的顏色,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下:
typedef struct tagRGBQUAD {
BYTErgbBlue;// 藍色的亮度(值范圍為0-255)
BYTErgbGreen; // 綠色的亮度(值范圍為0-255)
BYTErgbRed; // 紅色的亮度(值范圍為0-255)
BYTErgbReserved;// 保留,必須為0
} RGBQUAD;
顏色表中RGBQUAD結構數據的個數有biBitCount來確定:
當biBitCount=1,4,8時,分別有2,16,256個表項;
當biBitCount=24時,沒有顏色表項。
位圖信息頭和顏色表組成位圖信息,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位圖信息頭
RGBQUAD bmiColors[1]; // 顏色表
} BITMAPINFO;
5. 位圖數據
位圖數據記錄了位圖的每一個像素值,記錄順序是在掃描行內是從左到右,掃描行之間是從下到上。位圖的一個像素值所占的字節數:
當biBitCount=1時,8個像素占1個字節;
當biBitCount=4時,2個像素占1個字節;
當biBitCount=8時,1個像素占1個字節;
當biBitCount=24時,1個像素占3個字節;
Windows規定一個掃描行所占的字節數必須是
4的倍數(即以long為單位),不足的以0填充,
一個掃描行所占的字節數計算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
// 一個掃描行所占的字節數
DataSizePerLine= DataSizePerLine/4*4; // 字節數必須是4的倍數
位圖數據的大小(不壓縮情況下):
DataSize= DataSizePerLine* biHeight;