將24位BMP真彩圖轉換成BMP灰度圖

pamxy發表於2013-03-20

轉自:http://blog.csdn.net/xiakq/article/details/2956902

       真正的24位真彩圖與8位的灰度圖的區別就在於,真彩圖檔案中沒有調色盤,灰度圖有調色盤,真彩圖中的象素矩陣是RGB值,灰度圖中的象素矩陣是調色盤索引值。

        我在這裡用C語言只簡單的改變象素矩陣的RGB值,來達到彩色圖轉變為灰度圖,並沒有新增調色盤。

         主要步驟:    選擇演算法把R,G,B三原色轉換成灰度顏色。

         演算法選取

        (1)平均值演算法:   
          顧名思意,就是取某點R、G、B三原色的平均值作為該點轉換之後的灰度顏色,可用公式表示如下:   
          R=G=B=(R+G+B)/3   
        (2)快速演算法:   
          由於平均值演算法的公式當中有除3的步驟,所以如果用在遊戲中的話實時效果一定會大打折扣,所以有必要將其改造一下,首先想到的是用移位來代替除法,我們使用/4(也就是>>2)來實現。但是/3和/4之間的誤差太大,有必要將其公式改造一下,設改造後的公式為(R+G+B+a)>>2,解出a的值是(R+G+B)/3,我們暫時取a為128(0~255的中間值)。公式如下:   
  R=G=B=(R+G+B+128)/4>>2   
  (3).加權平均值演算法:   
          根據光的亮度特性,其實正確的灰度公式應當是R=G=B=R*0.299+G*0.587+B0.144,為了提高速度我們做一個完全可以接受的近似,公式變形如下:   
  R=G=B=(R*3+G*6+B)/10   
  (4).精確加權平均值演算法:   
          如果你的程式不是用於遊戲,而只是想得到灰度圖,那麼就老老實實的使用帶浮點數的公式吧:   
  R=G=B=R*0.299+G*0.587+B0.144

 

 

原始碼

 

 

 

#include <stdio.h>  
#include <windows.h> 


int main()
{
 BITMAPFILEHEADER bmpfileheader;     //檔案頭
 BITMAPINFOHEADER bmpinfoheader;     //資訊頭
    
 BYTE *matrix1;                      //象素矩陣
 FILE *fp;                           //讀取操作流
 FILE *store;                        //讀出操作流

 


 fp=fopen("picture.bmp","r+b");
 if (fp == NULL) 
 {  
  printf("Open failed/n");
  
  return 1;  
 } 
 else  
  printf("Open Successsfully/n");

    
 fread(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,fp);//讀取檔案頭
 fread(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,fp);//讀取資訊頭
 if (bmpinfoheader.biBitCount != 24)
 {
  printf("The error picture!");
  return 1;
 }
 
   
  
    matrix1 = new BYTE[bmpinfoheader.biSizeImage];
 memset(matrix1,0,bmpinfoheader.biSizeImage);
 

 fread(matrix1,1,bmpinfoheader.biSizeImage,fp);//讀取象素矩陣

 fclose(fp);


 for(unsigned long k=0;k<bmpinfoheader.biSizeImage;k=k+3)
 {
  
  *(matrix1+k)=*(matrix1+k+1)=*(matrix1+k+2)=(*(matrix1+k)+*(matrix1+k+1)+*(matrix1+k+2))/3;
 
 }

 

    //建立新的灰度圖
 
 store=fopen("test.bmp","w+b");
 fwrite(&bmpfileheader,sizeof(BITMAPFILEHEADER),1,store);
 fwrite(&bmpinfoheader,sizeof(BITMAPINFOHEADER),1,store);

 fwrite(matrix1,1,bmpinfoheader.biSizeImage,store);
 fclose(store);

 int a;
 scanf("%d",&a);

 return 0;
}

 

 

 

        


相關文章