C语言实现bmp图片全彩转灰度,灰度转伪彩

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzw_ice/article/details/78643240
  • 话不多说,直接上代码
  • 全彩转灰度公式和灰度转伪彩色对应关系均可在代码里找到,有详细注释
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

#pragma pack(1)
typedef struct tagBITMAPFILEHEADER
{
    unsigned short bfType;//文件格式
    unsigned long bfSize;//文件大小
    unsigned short bfReserved1;//保留
    unsigned short bfReserved2;
    unsigned long bfOffBits; //DIB数据在文件中的偏移量
}fileHeader;
#pragma pack()
/*
位图数据信息结构
*/
#pragma pack(1)
typedef struct tagBITMAPINFOHEADER
{
    unsigned long biSize;//该结构的大小
    long biWidth;//文件宽度
    long biHeight;//文件高度
    unsigned short biPlanes;//平面数
    unsigned short biBitCount;//颜色位数
    unsigned long biCompression;//压缩类型
    unsigned long biSizeImage;//DIB数据区大小
    long biXPixPerMeter;
    long biYPixPerMeter;
    unsigned long biClrUsed;//多少颜色索引表
    unsigned long biClrImporant;//多少重要颜色
}fileInfo;
#pragma pack()
/*
调色板结构
*/
#pragma pack(1)
typedef struct tagRGBQUAD
{
    unsigned char rgbBlue; //蓝色分量亮度
    unsigned char rgbGreen;//绿色分量亮度
    unsigned char rgbRed;//红色分量亮度
    unsigned char rgbReserved;
}rgbq;
#pragma pack()

//其他数据  
typedef struct OtherData  
{  
    unsigned char extradata;  
    struct OtherData *next;  

}OtherData;

int colorToGray(FILE* fp1,FILE* fp2)
{
    fileHeader * fh;
    fileInfo * fi;
    fh = (fileHeader *)malloc(sizeof(fileHeader));
    fi = (fileInfo *)malloc(sizeof(fileInfo));

    //读取位图头结构和信息头
    fread(fh, sizeof(fileHeader), 1, fp1);
    fread(fi, sizeof(fileInfo), 1, fp1);

    //修改信息头
    fi->biBitCount = 8;
    //fi->biSizeImage = ((fi->biWidth * 3 + 3) / 4) * 4 * fi->biHeight;
    fi->biSizeImage = fi->biHeight*fi->biWidth;
    //修改文件头
    fh->bfOffBits = sizeof(fileHeader) + sizeof(fileInfo) + 256 * sizeof(rgbq);
    fh->bfSize = fh->bfOffBits + fi->biSizeImage;

    //创建调色板
    int i,j,k=0;
    rgbq *fq = (rgbq *)malloc(256 * sizeof(rgbq));
    for (i = 0; i<256; i++)
    {
        fq[i].rgbBlue = fq[i].rgbGreen = fq[i].rgbRed = i;
    }
    //写入文件头、信息头、调色板
    fwrite(fh, sizeof(fileHeader), 1, fp2);
    fwrite(fi, sizeof(fileInfo), 1, fp2);
    fwrite(fq, sizeof(rgbq), 256, fp2);

    //将位图信息转为灰度
    //存储bmp一行的像素点
    unsigned char ImgData[3000][3];
    //将灰度图像存到一维数组中
    unsigned char ImgData2[3000];


    //公式 
    for (i = 0; i<fi->biHeight; i++)
    {
        for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
        {
            for (k = 0; k<3; k++)
            fread(&ImgData[j][k], 1, 1, fp1);
        }
        for (j = 0; j<(fi->biWidth + 3) / 4 * 4; j++)
        {
            ImgData2[j] = int((float)ImgData[j][0] * 0.114 +
                (float)ImgData[j][1] * 0.587 +
                (float)ImgData[j][2] * 0.299);
        }
        //将灰度图信息写入
        fwrite(ImgData2, j, 1, fp2);
    }

    free(fh);
    free(fi);
    free(fq);
    fclose(fp1);
    fclose(fp2);
    return 1;
}

int grayToColor(FILE* fp1,FILE* fp2)  
{   
    unsigned char * * ImgData;//二维数组 
    unsigned int j, k,i;  
    fileHeader fh;  
    fileInfo fi;  
    rgbq *IpRGBQuad;           
    OtherData  *Otherdata, *temp,*SavePreCursor;  


    /*图像的读取顺序是从下到上,从左到右*/  

    IpRGBQuad = (rgbq *)malloc(256*sizeof(rgbq));//灰度图为8位的调色板数据为256个结构,1024个字节  
    Otherdata = (OtherData*)malloc(sizeof(OtherData));  
    SavePreCursor = Otherdata;//保存当前指针游标,目的就是保存链表头结点  
    Otherdata->extradata = NULL;  
    Otherdata->next = NULL;  

    //拥有1024个调色板数据   
    fread(&fh, sizeof(fileHeader), 1, fp1);  

    if (fh.bfType == 0x4D42)  
    {
        //读取位图信息头 
        fread(&fi, sizeof(fileInfo), 1, fp1);  
        //读取调色板数据   
        fread(IpRGBQuad, sizeof(rgbq), 256, fp1); 
        fi.biBitCount = 24;
        fi.biSizeImage = fi.biHeight*fi.biWidth;
        fh.bfOffBits = sizeof(fileHeader)+sizeof(fileInfo)+256*sizeof(rgbq);
        fh.bfSize = fh.bfOffBits + fi.biSizeImage;
        fwrite(&fh, sizeof(fileHeader), 1, fp2);
        fwrite(&fi, sizeof(fileInfo), 1, fp2);
        fwrite(IpRGBQuad, sizeof(rgbq), 256, fp2);

        //读取像素数据  

        fi.biHeight++;  
        fi.biWidth += 2;  
        ImgData = new unsigned char *[fi.biHeight];  

        for (j = 0; j < fi.biHeight; j++)  
        {  
            ImgData[j] = new unsigned char [fi.biWidth];//定义像素数组ImgData[InfoHeader.biHeight][InfoHeader.biWidth]  
        }  

        for ( j = 0; j < fi.biHeight; j++)  
        {  

            for ( k = 0; k < fi.biWidth; k++)  
            {  
                fread(&ImgData[j][k], sizeof(unsigned char), 1, fp1);
                //fwrite(&ImgData[j][k], sizeof(unsigned char), 1, fp2);
            }  
        }  

    unsigned char ImgData2[3000][3];//伪彩色数据     

    for (i = 0; i<fi.biHeight; i++)
    {
        for (j = 0; j<fi.biWidth; j++)
        {
            //蓝色
            if(ImgData[i][j] >=0 && ImgData[i][j]<=31)
            {
                ImgData2[j][2] = 0;
                ImgData2[j][1] = 0;
                ImgData2[j][0] = 255;
            }
            //绿色
            if(ImgData[i][j] >=32 && ImgData[i][j]<=63)
            {
                ImgData2[j][2] = 0;
                ImgData2[j][1] = 255;
                ImgData2[j][0] = 0;
            }
            //淡蓝色
            if(ImgData[i][j] >=64 && ImgData[i][j]<=95)
            {
                ImgData2[j][2] = 173;
                ImgData2[j][1] = 216;
                ImgData2[j][0] = 230;
            }
            //紫色
            if(ImgData[i][j] >=96 && ImgData[i][j]<=127)
            {
                ImgData2[j][2] = 155;
                ImgData2[j][1] = 48;
                ImgData2[j][0] = 255;
            }
            //红色
            if(ImgData[i][j] >=128 && ImgData[i][j]<=159)
            {
                ImgData2[j][2] = 255;
                ImgData2[j][1] = 0;
                ImgData2[j][0] = 0;
            }
            //橙色
            if(ImgData[i][j] >=160 && ImgData[i][j]<=191)
            {
                ImgData2[j][2] = 255;
                ImgData2[j][1] = 165;
                ImgData2[j][0] = 0;
            }
            //黄色
            if(ImgData[i][j] >=192 && ImgData[i][j]<=223)
            {
                ImgData2[j][2] = 255;
                ImgData2[j][1] = 255;
                ImgData2[j][0] = 0;
            }
            //淡黄色
            if(ImgData[i][j] >=224 && ImgData[i][j]<=255)
            {
                ImgData2[j][2] = 255;
                ImgData2[j][1] = 255;
                ImgData2[j][0] = 254;
            }
        }
        fwrite(ImgData2, sizeof(unsigned char)*3, j, fp2);
    }


        //读取其他数据  

        temp = (OtherData*)malloc(sizeof(OtherData));  
        while (!feof(fp1))  
        {  
            temp = (OtherData*)malloc(sizeof(OtherData));  

            fread(&temp->extradata, sizeof(unsigned char), 1, fp1);  
            fwrite(&temp->extradata, sizeof(unsigned char), 1, fp2);  
            Otherdata->next = temp;  
            Otherdata = Otherdata->next;  
        }  
        Otherdata->next = NULL;//置末尾为空,判断条件  
        Otherdata = SavePreCursor;//使Otherdata重新指向头部  
    }  


    fclose(fp1);  
    fclose(fp2);   
    return 1;  
}
int main(){
    int colorToGray(FILE* fp1,FILE* fp2);
    int grayToColor(FILE* fp1,FILE* fp2);
    int n;
    char inPath[100],outPath[100];
    printf("功能:\n");
    printf("1 : 彩色转灰色\n");
    printf("2 : 灰色转伪彩色\n");
    printf("输入功能编号:\n");
    scanf("%d",&n);
    printf("输入源文件绝对地址(含文件名):\n");
    scanf("%s",inPath);
    printf("输入目标文件绝对地址(含文件名):\n");
    scanf("%s",outPath);


    FILE *fp1 = fopen(inPath, "rb+");
    if (fp1 == NULL)
    {
        printf("打开文件fp1失败");
        return 0;
    }
    FILE *fp2 = fopen(outPath, "wb");
    if (fp1 == NULL)
    {
        printf("打开文件fp2失败");
        return 0;
    }

    switch(n)
    {
        case 1:
        {
            if(colorToGray(fp1,fp2) == 1)
            {
                printf("success\n");
            }
            break;
        };
        case 2:
        {
            if(grayToColor(fp1,fp2) == 1)
            {
                printf("success\n");
            }
            break;
        }
        default: break;
    }
}

  • 测试结果
    彩色

转换后的灰度图

灰度转伪彩

猜你喜欢

转载自blog.csdn.net/wzw_ice/article/details/78643240