24位BMP文件读取、BMP文件转灰度图(附c/c++代码+详细注释)

1.BMP文件的格式介绍

BMP图像文件由四部分组成:

  • 位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;
  • 位图信息头数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
  • 调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;
  • 位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。
    BMP文件内容分以上三部分,一个BMP文件在存储上是按照如下图存储的。
    这里写图片描述

首先存储的是BMP文件的文件头,接着是信息头,调色板是根据位图类型可以选择有无的,24位及32位的BMP图像是没有调色板的。目前使用最多的也都是24位的位图文件。接着存储的是各个位置上的像素值。所以24位(真彩色)bmp文件只有文件头、信息头、像素值数据这三部分。
给出完整的读取BMP文件的源代码:

#include <iostream>
#include <fstream>
#pragma pack(1)//可以自定义结构体对齐方式
using namespace std;

typedef unsigned char BYTE;//一个字节
typedef unsigned short WORD;//两个字节
typedef unsigned int DWORD;//4个字节
//位图文件头 14个字节
typedef struct tagBITMAPFILEHEADER {
    WORD bfType; /* 说明文件的类型 必须是0x424D,即字符串“BM”,也就是说所有.bmp文件的头两个字节都是“BM”*/
    DWORD bfSize; /* 说明文件的大小,包括这14个字节,以字节为单位 */
    WORD bfReserved1; /* 保留,设置为0 */
    WORD bfReserved2; /* 保留,设置为0 */
    DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量,以字节为单位 */
} BITMAPFILEHEADER;
//位图信息头 固定大小为40个字节
typedef struct tagBITMAPINFOHEADER {
    DWORD biSize;//信息头大小
    DWORD biWidth;//图像宽度
    DWORD biHeight;//图像高度
    WORD biPlanes;//位平面数,必须为1
    WORD biBitCount;//每像素位数。常用的值为1(黑白二色图), 4(16色图), 8(256色), 24(真彩色图)或32(新的.bmp格式支持32位色)
    DWORD  biCompression; //压缩类型:有效的值为BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS(都是一些Windows定义好的常量)
    DWORD  biSizeImage;  //压缩图像大小字节数 biSizeImage=biWidth’ × biHeight,biWidth’必须是4的整倍数,(所以不是biWidth,而是biWidth’,表示大于或等于biWidth的,最接近4的整倍数)
    DWORD  biXPelsPerMeter; //水平分辨率,单位是每米的象素个数
    DWORD  biYPelsPerMeter; //垂直分辨率,单位是每米的象素个数
    DWORD  biClrUsed; //位图实际用到的色彩数,如果该值为零,则用到的颜色数为2^biBitCount
    DWORD  biClrImportant; //本位图中重要的色彩数,如果该值为零,则认为所有的颜色都是重要的。
} BITMAPINFOHEADER;  //位图信息头定义
//调色板的定义 4个字节
/*真彩色是无调色板部分的
如真彩色图是不需要调色板的,BITMAPINFOHEADER后直接是位图数据。
调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2^biBitCount个元素),数组中每个元素的类型是一个RGBQUAD结构,共占4个字节*/
typedef struct tagRGBQUAD{
    BYTE rgbBlue; //该颜色的蓝色分量
    BYTE rgbGreen; //该颜色的绿色分量
    BYTE rgbRed; //该颜色的红色分量
    BYTE rgbReserved; //保留值
}RGBQUAD;//调色板定义
/*
要注意一下几点:
(1)每一行的字节数必须是4的整倍数,如果不是,则需要补齐。如241补齐为244.
(2)一般来说,.bMP文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的是图象最下面一行的左边第一个象素,
然后是左边第二个象素……接下来是倒数第二行左边第一个象素,左边第二个象素……依次类推 ,最后得到的是最上面一行的最右一个象素。
(3)图像是24位或是32位数据的位图的话,位图数据区就不是索引而是实际的像素值了。
(4)24位RGB按照BGR的顺序来存储每个像素的各颜色通道的值,一个像素的所有颜色分量值都存完后才存下一个像素,不进行交织存储。
(5)32位数据按照BGRA的顺序存储,其余与24位位图的方式一样。
*/

int main()
{
    BITMAPFILEHEADER bmpFlieHead;
    BITMAPINFOHEADER bmpInfHead;

    //int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;//灰度图像有颜色表,且颜色表表项为256
    FILE *fpbmp = fopen("baboon.bmp", "rb");//二进制读 打开
    FILE *fpGray = fopen("Graybaboon.bmp", "wb");//二进制写 打开
    fread(&bmpFlieHead, 14, 1, fpbmp);
    fread(&bmpInfHead, 40, 1, fpbmp);
    char* buffer = new char[bmpFlieHead.bfSize - 54]();
    int bmpWidth = bmpInfHead.biWidth;
    int bmpHeight = bmpInfHead.biHeight;
    fread(buffer, bmpFlieHead.bfSize - 54, 1, fpbmp);
    int lineByte = (bmpWidth*bmpInfHead.biBitCount / 8 + 3) / 4 * 4;
    for (int i = 0; i < bmpHeight;i++)
    {
        int n = 0;
        for (int j = 0; j < lineByte-2;j++)
        {
            char color = buffer[i*lineByte + j];
            buffer[i*lineByte + j + 1] = color;
            buffer[i*lineByte + j + 2] = color;
            j += 2;
        }
    }
    //memset(buffer, 100,(bmpFlieHead.bfSize - 54));
    fwrite(&bmpFlieHead, 14, 1, fpGray);
    fwrite(&bmpInfHead, 40, 1, fpGray);
    fwrite(buffer, bmpFlieHead.bfSize - 54, 1, fpGray);
        fclose(fpGray);
        delete[] buffer;
    return 0;
}
  • 11
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要编写一个C/C++程序来读取一个24真彩BMP文件并将其转换灰度图像并存储为8,可以按照以下步骤进行操作: 1. 打开BMP文件:使用C/C++中的文件操作函数打开一个24BMP文件。确保该文件存在且可以被读取。 2. 读取BMP文件头信息:通过读取文件的前54个字节,获取BMP文件头信息,包括图像宽度、高度以及文件的大小等。 3. 读取像素数据:根据BMP文件头信息中的图像宽度和高度,确定像素数据的大小。使用文件操作函数读取数据,存储到一个数组中。 4. 转换灰度图像:遍历像素数组,将每个像素的RGB值转换灰度值。可以使用下面的公式将RGB值转换灰度值: 灰度值 = 0.299 * 红色值 + 0.587 * 绿色值 + 0.114 * 蓝色值 确保将每个像素的RGB值转换为整数值,并将结果存储到另一个矩阵中。 5. 减小深度:对于灰度图像,每个像素灰度值通常使用8存储。将每个像素灰度值右移3,使其只占用8。 6. 存储为8BMP文件:将转换后的灰度图像数据存储到一个新的文件中,格式为8BMP文件。确保在文件头信息中更新图像深度为8,并将图像的宽度、高度以及像素数据写入文件。 7. 关闭文件:在完成图像转换并保存后,使用文件操作函数关闭打开的BMP文件和新存储的8BMP文件。 以上是一个大致的程序框架,您可以根据具体的需求和编程语言进行调整和实现,以达到将24真彩BMP文件转换为8灰度图像并存储的目的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值