最近正在學習數字圖像處理,研究了bmp圖像的相關知識,下面是用c語言實作的将真彩圖轉化為灰階圖。可能寫的比較亂,但運作結果還是正确的。
程式區分了灰階圖與真彩圖,如果打開的檔案1本身是灰階圖,則直接檔案存儲在2中,若檔案1是真彩圖,則轉化為灰階圖後存在2中
#include "stdafx.h"
#include<stdio.h>
#include<windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
int bmpHeight;
int bmpWidth;
unsigned char *pBmpBuf;
RGBQUAD *pColorTable;
int biBitCount;
//讀取bmp檔案
FILE *fp=fopen("dog1.bmp","rb");
if(fp==0)
return 0;
fseek(fp,sizeof(BITMAPFILEHEADER),0);
BITMAPINFOHEADER head;
fread(&head,40,1,fp);
bmpHeight=head.biHeight;
bmpWidth=head.biWidth;
biBitCount=head.biBitCount;
if(biBitCount==8)
{
pColorTable=new RGBQUAD[256];
fread(pColorTable,sizeof(RGBQUAD),256,fp);
}
int LineByte=(bmpWidth*biBitCount/8+3)/4*4;//保證每一行位元組數都為4的整數倍
pBmpBuf=new unsigned char[LineByte*bmpHeight];
fread(pBmpBuf,LineByte*bmpHeight,1,fp);
fclose(fp);
測試讀取功能子產品
printf("bmpWidth:%d ,bmpHeight: %d,biBitCount:%d \n",bmpWidth,bmpHeight,biBitCount);
//将24位真彩圖灰階化并儲存
FILE *fp1=fopen("dog2.bmp","wb");
if(fp1==0)
return 0;
int LineByte1=(bmpWidth*8/8+3)/4*4;
//修改檔案頭,其中有兩項需要修改,分别為bfSize和bfOffBits
BITMAPFILEHEADER bfhead;
bfhead.bfType=0x4D42;
bfhead.bfSize=14+40+256*sizeof(RGBQUAD)+LineByte1*bmpHeight;//修改檔案大小
bfhead.bfReserved1=0;
bfhead.bfReserved2=0;
bfhead.bfOffBits=14+40+256*sizeof(RGBQUAD);//修改偏移位元組數
fwrite(&bfhead,14,1,fp1); //将修改後的檔案頭存入fp1;
//修改資訊頭,其中有兩項需要修改,1個位biBitCount:真彩圖為24 ,應改成8;另一個是biSizeImage:由于每像素所占位數的變化,是以位圖資料的大小發生變化
BITMAPINFOHEADER head1;
head1.biBitCount=8; //将每像素的位數改為8
head1.biClrImportant=0;
head1.biCompression=0;
head1.biClrUsed=0;
head1.biHeight=bmpHeight;
head1.biWidth=bmpWidth;
head1.biPlanes=1;
head1.biSize=40;
head1.biSizeImage=LineByte1*bmpHeight;//修改位圖資料的大小
head1.biXPelsPerMeter=0;
head1.biYPelsPerMeter=0;
fwrite(&head1,40,1,fp1); //将修改後的資訊頭存入fp1;
if(biBitCount==24)//判斷是否是真彩圖,若是,由于真彩圖沒有顔色表,是以在變為灰階圖後要加上顔色表
{
pColorTable=new RGBQUAD[256];
for (int i = 0; i < 256; i++ )
pColorTable[i].rgbRed = pColorTable[i].rgbGreen = pColorTable[i].rgbBlue = i; //是顔色表裡的B、G、R分量都相等,且等于索引值
}
fwrite(pColorTable,sizeof(RGBQUAD),256,fp1); //将顔色表寫入fp1;
//寫位圖資料
unsigned char *pBmpBuf1;
pBmpBuf1= new unsigned char[LineByte1*bmpHeight];
for(int i=0;i<bmpHeight;i++)
for(int j=0;j<bmpWidth;j++)
{
unsigned char *pb1,*pb2;
pb1=pBmpBuf+i*LineByte+j*3;
int y=*(pb1)*0.299+*(pb1+1)*0.587+*(pb1+2)*0.114; //将每一個像素都按公式y=B*0.299+G*0.587+R*0.114進行轉化
pb2=pBmpBuf1+i*LineByte1+j;
*pb2=y;
}
if(biBitCount==8)
fwrite(pBmpBuf,LineByte*bmpHeight,1,fp1);
else
fwrite(pBmpBuf1,LineByte1*bmpHeight,1,fp1);
fclose(fp1);
system("pause");
return 0;
}