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");
//申請位圖檔案頭結構變量,填寫檔案頭資訊
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);
//如果灰階圖像,有顔色表,寫入檔案
fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
//寫位圖資料進檔案
fwrite(imgBuf, height*lineByte, 1, fp);
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;
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;