c語言實現BMP圖像轉換為灰度圖


當初是自己要裝X,非要用c來寫信息隱藏作業,裝了X,就得付出實踐。查了好久資料,到期末才把作業交了,這里總結一下。

這道題是將真彩圖轉換為灰度圖

  • 關於BMP文件結構,這是困擾了我好久的問題,上網查了很久圖片的知識才弄明白
  • BMP文件包括以下幾部分(具體結構在程序中說明):
    • 位圖文件頭
    • 位圖信息頭
    • 調色板
    • 位圖數據
  • 結構體內存對齊原則對於pragma pack(n)
    • 當成員大小小於n時,每個成員存儲的起始位置要從該成員大小的整數倍開始,否則從n的整數倍開始
    • 成員是結構體時相對於起始偏移是以其內部最大成員為准
    • 當n大於內部最大成員時,結構體的總大小是其內部最大成員的整數倍反之為n的整數倍
    • 32位默認n為4,64位默認為8
  • 因此在定義頭結構的時候要加上#pragma pack(1),設置以1字節為對齊方式,不然后面數據會錯位
  1 /*
  2 真彩圖轉換成灰度圖的改進版
  3 (不把真彩圖的每個像素點放入二維矩陣,而是讀一行寫一行)
  4 blog:http://www.cnblogs.com/wd1001/
  5 2015年6月2日19:04:09
  6 */
  7 #include<stdio.h>
  8 #include<malloc.h>
  9 #include<stdlib.h>
 10 /*
 11 位圖頭結構
 12 */
 13 #pragma pack(1)
 14 typedef struct tagBITMAPFILEHEADER
 15 {
 16     unsigned char bfType[2];//文件格式
 17     unsigned long bfSize;//文件大小
 18     unsigned short bfReserved1;//保留
 19     unsigned short bfReserved2;
 20     unsigned long bfOffBits; //DIB數據在文件中的偏移量
 21 }fileHeader;
 22 #pragma pack()
 23 /*
 24 位圖數據信息結構
 25 */
 26 #pragma pack(1)
 27 typedef struct tagBITMAPINFOHEADER
 28 {
 29     unsigned long biSize;//該結構的大小
 30     long biWidth;//文件寬度
 31     long biHeight;//文件高度
 32     unsigned short biPlanes;//平面數
 33     unsigned short biBitCount;//顏色位數
 34     unsigned long biCompression;//壓縮類型
 35     unsigned long biSizeImage;//DIB數據區大小
 36     long biXPixPerMeter;
 37     long biYPixPerMeter;
 38     unsigned long biClrUsed;//多少顏色索引表
 39     unsigned long biClrImporant;//多少重要顏色
 40 }fileInfo;
 41 #pragma pack()
 42 /*
 43 調色板結構
 44 */
 45 #pragma pack(1)
 46 typedef struct tagRGBQUAD
 47 {
 48     unsigned char rgbBlue; //藍色分量亮度
 49     unsigned char rgbGreen;//綠色分量亮度
 50     unsigned char rgbRed;//紅色分量亮度
 51     unsigned char rgbReserved;
 52 }rgbq;
 53 #pragma pack()
 54 
 55 int main()
 56 {
 57     /*存儲RGB圖像的一行像素點*/
 58     unsigned char ImgData[3000][3];
 59     /*將灰度圖的像素存到一個一維數組中*/
 60     unsigned char ImgData2[3000];
 61     int i,j,k;
 62     FILE * fpBMP,* fpGray;
 63     fileHeader * fh;
 64     fileInfo * fi;
 65     rgbq * fq;
 66     
 67     if((fpBMP=fopen("G:/vc6.0/work/21.bmp","rb"))==NULL)
 68     {
 69         printf("打開文件失敗");
 70         exit(0);
 71     }
 72     
 73     if((fpGray=fopen("G:/vc6.0/work/22.bmp","wb"))==NULL)
 74     {
 75         printf("創建文件失敗");
 76         exit(0);
 77     }
 78     
 79     fh=(fileHeader *)malloc(sizeof(fileHeader));
 80     fi=(fileInfo *)malloc(sizeof(fileInfo));
 81     //讀取位圖頭結構和信息頭
 82     fread(fh,sizeof(fileHeader),1,fpBMP);
 83     fread(fi,sizeof(fileInfo),1,fpBMP);
 84     //修改頭信息
 85     fi->biBitCount=8;
 86     fi->biSizeImage=( (fi->biWidth*3+3)/4 ) * 4*fi->biHeight;
 87     //fi->biClrUsed=256;
 88     
 89     fh->bfOffBits = sizeof(fileHeader)+sizeof(fileInfo)+256*sizeof(rgbq);
 90     fh->bfSize = fh->bfOffBits + fi->biSizeImage;
 91     
 92     //創建調色版
 93     fq=(rgbq *)malloc(256*sizeof(rgbq));
 94     for(i=0;i<256;i++)
 95     {
 96         fq[i].rgbBlue=fq[i].rgbGreen=fq[i].rgbRed=i;
 97         //fq[i].rgbReserved=0;
 98     }
 99     //將頭信息寫入
100     fwrite(fh,sizeof(fileHeader),1,fpGray);  
101     fwrite(fi,sizeof(fileInfo),1,fpGray); 
102     fwrite(fq,sizeof(rgbq),256,fpGray);
103     //讀取RGB圖像素並轉換為灰度值
104     for ( i=0;i<fi->biHeight;i++ )
105     {
106         for(j=0;j<(fi->biWidth+3)/4*4;j++)
107         {
108             for(k=0;k<3;k++)
109                 fread(&ImgData[j][k],1,1,fpBMP);
110         }
111         for(j=0;j<(fi->biWidth+3)/4*4;j++)
112         {
113             ImgData2[j]=int( (float)ImgData[j][0] * 0.114 +
114                         (float)ImgData[j][1] * 0.587 +
115                         (float)ImgData[j][2] * 0.299 );
116         }
117         //將灰度圖信息寫入
118         fwrite(ImgData2,j,1,fpGray);
119     }   
120         
121         free(fh);
122         free(fi);
123         free(fq);
124         fclose(fpBMP);
125         fclose(fpGray);
126         printf("success\n");
127         return 0;
128 }

結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM