Date621
任务:BMP真彩图像转为灰度图
一,算法及公式:
  1,什么叫灰度图?任何都有红、绿、蓝三原组成,假如原来某点的颜为RGB(RGB),那么,我们可以通过下面几种方法,将其转换为灰度:
      浮点算法:Gray=R*0.3+G*0.59+B*0.11
      整数方法:Gray=(R*30+G*59+B*11)/100
      移位方法:Gray =(R*28+G*151+B*77)>>8;
      平均值法:Gray=R+G+B/3;
      仅取绿:Gray=G
    通过上述任一种方法求得Gray后,将原来的RGB(R,G,B)中的R,G,B统一用Gray替换,形成新的颜RGB(Gray,Gray,Gray),用它替换原来的RGB(R,G,B)就是灰度图了。
2改变象素矩阵的RGB值,来达到彩图转变为灰度图
加权平均值算法:根据光的亮度特性,其实正确的灰度公式应当是
R=G=B=R*0.299+G*0.587+B0.144
为了提高速度我们做一个完全可以接受的近似,公式变形如下:R=G=B=(R*3+G*6+B)/10 
  3,真正的24位真彩图与8位的灰度图的区别就在于,真彩图文件中没有调板,灰度图有调板,真彩图中的象素矩阵是RGB值,灰度图中的象素矩阵是调板索引值。源代码1只简单的改变象素矩阵的RGB值,来达到彩图转为灰度图,并没有添加调板。源代码2添加了调板。

二,源代码
1
//可以输入文件名的源代码,有些变量定义进行了完善fread和fwrite的区别
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "windows.h"
#include "conio.h"
typedef struct{
    unsigned char b;
    unsigned char r;
    unsigned char g;
}pixel;
pixel a[640][480];
unsigned char aa[640][480];
void main()
{
    BITMAPFILEHEADER FILEH;
    BITMAPINFOHEADER INFOH;
    RGBQUAD RGBH[256];
    char name[11];
    char *fname[11];
    printf("输入需要转换的图片名:");
    scanf("%s",&name);
    *fname=name;
    strcat(*fname,".bmp");
    printf("%s",*fname);
    FILE *fp;
    if((fp=fopen(*fname,"rb"))==NULL)
    {
        //if((fp=fopen(*fname,"wb"))==NULL)//防止首次进入时初始化失败
        //{
            printf("打开文件%s失败!按任意键返回主菜单!",fname);   
            getch();
            exit(1);
        //}
    }
    printf("%s",*fname);
    int LEN1=sizeof(BITMAPFILEHEADER);
    int LEN2=sizeof(BITMAPINFOHEADER);
    int X,Y;
    printf("\nlen=%d,%d\n",LEN1,LEN2);
    fread(&FILEH,sizeof(BITMAPFILEHEADER),1,fp);
    fread(&INFOH,sizeof(BITMAPINFOHEADER),1,fp);
    X=INFOH.biWidth;
    Y=INFOH.biHeight;
    //printf("%d*%d",X,Y);
    if(FILEH.bfType!=0x4d42)
    {
        fclose(fp);
        printf("文件头不正确,不是bmp");
        exit(1);
    }
    if(INFOH.biBitCount!=24&&INFOH.biBitCount!=8)