zoukankan      html  css  js  c++  java
  • 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
    ");
    127         return 0;
    128 }

    结果:

  • 相关阅读:
    JavaScript中需要注意的几个问题
    前端编码规范之JavaScript
    那些年,我们一起玩过的响应式布局
    前端编码规范之CSS
    一个不陌生的JS效果-marquee,用css3来实现
    解读jQuery中extend函数
    字体大小自适应纯css解决方案
    浅谈叶小钗面试的几个问题
    【Python开发】C和Python之间的接口实现
    【Python开发】【编程开发】各种系统的清屏操作命令
  • 原文地址:https://www.cnblogs.com/wd1001/p/4571163.html
Copyright © 2011-2022 走看看