• C++实现彩色bmp图片转灰度图


    简介

    BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。BMP位图文件默认的文件扩展名是BMP或者bmp。

    BMP图片格式

    BMP文件总体上由4部分组成,分别是位图文件头、位图信息头、调色板和图像数据

    位图文件头(bitmap-file header)

    BMP文件头数据结构共14个字节,包含以下信息:

    typedef struct{
        unsigned short bfType;                            //文件类型,具体值为0x4D42
        int bfSize;                                        //文件大小,以字节为单位
        unsigned short bfReserved1;                       //保留值,必须为0
        unsigned short bfReserved2;                       //保留值,必须为0
        int bfOffBits;                                     //从文件开头到具体图像数据的字节偏移量(具体文件头(14byte)+位图信息头(40byte)+调色板)
    }BITMAPFILEHEADER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    位图信息头(bitmap-information header)

    图片信息头(40字节)存储着图像的尺寸,颜色索引,位平面数等信息,其结构体包括:

    
    typedef struct{
       unsigned int biSize;                           //位图信息头的大小,均为40字节
       int biWidth;                                    //位图宽度,单位为像素
       int biHeight;                                   //位图高度,单位为像素
       unsigned short biPlanes;                      //位图的平面数,设置为1
       unsigned short biBitCount;                    //像素位数,有1,4,8,16,24,32等
       unsigned int biCompression;                   //位图压缩类型,0为不压缩、1为BI_RLE8、2为BI_RLE4(30-33)
       unsigned int    biSizeImage;                  //图像数据部分大小,等于bfSize-bfOffBits (34-37)
       int     biXPelsPerMeter;                       // 用像素/米表示的水平分辨率
       int     biYPelsPerMeter;                       // 用像素/米表示的垂直分辨率
       unsigned int    biClrUsed;                    // 调色板中的颜色索引数,0为图片有调色板
       unsigned int    biClrImportant;               // 重要颜色索引的数目,0表示都重要(50-53)
    }BITMAPINFOHEADER;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    彩色表/调色板(color table)

    调色板,由颜色索引数决定【可以没有该项数据结构】

    typedef struct
    {
        unsigned char rgbBlue;  //蓝色分量亮度
        unsigned char rgbGreen; //绿色分量亮度
        unsigned char rgbRed;   //红色分量亮度
        unsigned char rgbReserved;
    }RGBQUAD;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    位图数据(bitmap-data)

    位图数据记录了位图的每一个像素值。
    像素是从下到上、从左到右保存的
    每个像素使用一个或者多个字节表示。
    如果一个图像水平线的字节数不是4的倍数,这行就使用空字节补齐,通常是ASCII码0。
    如果图片是24位的彩色图,则RGB的顺序为B0G0R0B1G1R1…。

    代码编写

    本代码实现彩色图转灰度图的功能。

    #include
    #pragma pack(1)
    typedef struct{
        unsigned short bfType;                            //文件类型,具体值为0x4D42
        int bfSize;                                        //文件大小,以字节为单位
        unsigned short bfReserved1;                       //保留值,必须为0
        unsigned short bfReserved2;                       //保留值,必须为0
        int bfOffBits;                                     //从文件开头到具体图像数据的字节偏移量(具体文件头(14byte)+位图信息头(40byte)+调色板)
    }BITMAPFILEHEADER;
    
    typedef struct{
       unsigned int biSize;                           //位图信息头的大小,均为40字节
       int biWidth;                                    //位图宽度,单位为像素
       int biHeight;                                   //位图高度,单位为像素
       unsigned short biPlanes;                      //位图的平面数,设置为1
       unsigned short biBitCount;                    //像素位数,有1,4,8,16,24,32等
       unsigned int biCompression;                   //位图压缩类型,0为不压缩、1为BI_RLE8、2为BI_RLE4(30-33)
       unsigned int    biSizeImage;                  //图像数据部分大小,等于bfSize-bfOffBits (34-37)
       int     biXPelsPerMeter;                       // 用像素/米表示的水平分辨率
       int     biYPelsPerMeter;                       // 用像素/米表示的垂直分辨率
       unsigned int    biClrUsed;                    // 调色板中的颜色索引数,0为图片有调色板
       unsigned int    biClrImportant;               // 重要颜色索引的数目,0表示都重要(50-53)
    }BITMAPINFOHEADER;
    
    typedef struct
    {
        unsigned char rgbBlue;  //蓝色分量亮度
        unsigned char rgbGreen; //绿色分量亮度
        unsigned char rgbRed;   //红色分量亮度
        unsigned char rgbReserved;
    }RGBQUAD;
    
    void showbmp(BITMAPFILEHEADER bmp){
       printf("****************************************文件头信息打印*******************************************************\n");
       printf("文件类型:%x\n",bmp.bfType);
       printf("文件大小=%d\n",bmp.bfSize);
       printf("文件保留值1=%d\n",bmp.bfReserved1);
       printf("文件保留值2=%d\n",bmp.bfReserved2);
       printf("文件信息区的大小=%d\n",bmp.bfOffBits);
    }
    
    void showbmpinfo(BITMAPINFOHEADER info){
       printf("结构体大小=%d\n",info.biSize);
       printf("图像宽=%d\n",info.biWidth);
       printf("图像高=%d\n",info.biHeight);
       printf("图像位面数=%d\n",info.biPlanes);
       printf("像素位数=%d\n",info.biBitCount);
       printf("位图压缩类型:%d\n",info.biCompression);
       printf("图像数据部分大小:%d\n",info.biSizeImage);
       printf("水平分辨率:%d\n",info.biXPelsPerMeter);
       printf("垂直分辨率:%d\n",info.biYPelsPerMeter);
       printf("位图颜色表中的颜色数:%d\n",info.biClrUsed);
       printf("重要颜色索引的数目:%d\n",info.biClrImportant);
    }
    
    int main(){
        BITMAPFILEHEADER bmp;
        BITMAPINFOHEADER bmp_info;
        //
        FILE* fp1;
        FILE* fp2;
        fp1=fopen("C:\\Users\\qjm\\Desktop\\test.bmp","rb");
        fread(&bmp,14,1,fp1);
        fread(&bmp_info,40,1,fp1);
        //show infomation
        showbmp(bmp);
        showbmpinfo(bmp_info);
        //
        int lineByte=(bmp_info.biWidth*3+3)/4*4;                 //4字节对齐后一行的字节数,单位字节
        int lineByte_gray=(bmp_info.biWidth+3)/4*4;
        printf("lineByte=%d\n",lineByte);
        printf("lineByte_gray=%d\n",lineByte_gray);
        //
        unsigned char* src_img=new unsigned char[bmp_info.biSizeImage];
        unsigned char* dest_img=new unsigned char[bmp_info.biSizeImage/3];
        fread(src_img,1,bmp_info.biSizeImage,fp1);
        for(int i=0;i<bmp_info.biHeight;i++)
            for(int j=0;j<bmp_info.biWidth;j++){
                unsigned char b=src_img[i*lineByte+j*3+0];
                unsigned char g=src_img[i*lineByte+j*3+1];
                unsigned char r=src_img[i*lineByte+j*3+2];
                unsigned char gray=((unsigned int)r+(unsigned int)g+(unsigned int)b)/3;
                dest_img[i*lineByte_gray+j]=gray;
        }
        fclose(fp1);
        //
        printf("****************************************************************\n");
        RGBQUAD* pRgbQuards=new RGBQUAD[256];
    	for(int i=0;i<256;i++)
    	{
    		pRgbQuards[i].rgbBlue=i;
    		pRgbQuards[i].rgbRed=i;
    		pRgbQuards[i].rgbGreen=i;
    
    	}
        fp2=fopen("C:\\Users\\qjm\\Desktop\\test_out.bmp","wb");
        bmp_info.biBitCount=24/3;
        bmp_info.biSizeImage=bmp_info.biSizeImage/3;
        bmp.bfOffBits=14+40+256*sizeof(RGBQUAD);                         //增加了颜色表
        bmp.bfSize=bmp.bfOffBits+bmp_info.biSizeImage;
        //
        showbmp(bmp);
        showbmpinfo(bmp_info);
        //
        fwrite(&bmp,1,14,fp2);
        fwrite(&bmp_info,1,40,fp2);
        fwrite(pRgbQuards,1,256*sizeof(RGBQUAD),fp2);
        fwrite(dest_img,1,bmp_info.biSizeImage,fp2);
        fclose(fp2);
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112

    待测试图片:
    在这里插入图片描述
    转灰度图后的效果:
    在这里插入图片描述

  • 相关阅读:
    Java+JSP+MySQL基于SSM的会议交接平台的设计与实现-计算机毕业设计
    WSL Ubuntu 22.04.2 LTS 安装paddlepaddle-gpu==2.5.1踩坑日记
    【尚硅谷】IDEA2022快速上手开发利器
    VC编译器编译命令cl、rc、link
    c++ 基础知识(一)
    软考高级系统架构设计师系列论文二:论软件的性能优化设计
    Python面向对象特性——多继承(概念、语法、代码演练、使用注意事项)
    C语言进阶——程序环境和预处理
    [工具推荐]截图工具 -- snipaste
    【冰糖R语言】实现贝叶斯优化 rBayesianOptimization
  • 原文地址:https://blog.csdn.net/qq_40268672/article/details/128147475