图像的 BGR 灰度转换给出损坏的图像

问题描述 投票:0回答:1

我正在尝试使用代码将 BGR 位图图像转换为灰度,

int main()
{
    FILE* fIn;
    FILE* fOut;
    if (fopen_s(&fIn, "D:\\VBox\\Shared\\images\\sample01.bmp", "rb") != 0) {
        return 1;
    }

    if (fopen_s(&fOut, "D:\\VBox\\Shared\\images\\sample01_gs1.bmp", "wb") != 0) {
        return 1;
    }

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, fIn); // read the 54-byte header


    int32_t width, height;
    uint16_t bitperpixl;
    memcpy(&width, info + 18, sizeof(int32_t));
    memcpy(&height, info + 22, sizeof(int32_t));
    memcpy(&bitperpixl, info + 28, sizeof(uint16_t));

    int padding = ((width * bitperpixl) / 8) % 4; // which Is 0 for the image which I am using. 

    fwrite(info, sizeof(unsigned char), 54, fOut);

    unsigned char pixel[3]; //bgr
    for (int y = 0; y < height; ++y)
    {
        for (int x = 0; x < width; ++x)
        {
            fread(pixel, 3, 1, fIn);
            unsigned char gray = pixel[2] * 0.3 + pixel[1] * 0.58 + pixel[0] * 0.11;
            memset(pixel, gray, sizeof(pixel));
            fwrite(&pixel, 3, 1, fOut);
        }
        fread(pixel, padding, 1, fIn);
        fwrite(pixel, padding, 1, fOut);
    }
    fclose(fOut);
    fclose(fIn);
}

创建的文件与输入图像的大小相同。当我尝试使用 Windows 图像查看器打开文件时,它显示图像不受支持或已损坏。

c++ bitmap grayscale bitmapimage
1个回答
0
投票

您的代码存在几个主要问题。首先,您不应该假设位图图像数据始终从字节 54 开始。如维基百科“BMP 文件格式”文章的文件结构部分所示,开头为

位图图像文件由固定大小的结构(标题)以及按预定顺序出现的可变大小的结构组成。由于这种文件格式的长期演变,其中一些结构的许多不同版本可以出现在文件中。

还有一个图表显示出现在实际像素阵列之前的可选或半可选部分。相反,要获取它们的起始位置,如位图文件头部分所示,位置从偏移量 10 开始,因此您应该有几行,例如

uint32_t pixelData;
memcpy(&pixelData, info + 10, sizeof(int32_t));

当然,您应该确保在处理像素时从该位置开始读取。

另外,关于处理像素数据本身,请注意,您不能假设它们都是 4 字节块,每个块的前 3 个字节是 RGB 值,然后是填充字节。相反,可能会使用一个颜色表(例如,其中的值是该表的偏移量)。另外,如果使用 Windows BITMAPINFOHEADER,则在偏移量 30 处有一个 4 字节值,指示所使用的压缩方法。维基百科文章描述了各个位的含义。

如果您可以确定输入的 .bmp 文件属于一组特定的有限格式,则可以编写代码来处理这些类型的文件。否则,您应该处理所有这些不同的附加细节。请注意,虽然 BMP 文件格式实际上基本上是最简单的图像格式,但在一般情况下仍然有很多事情需要检查和处理。

© www.soinside.com 2019 - 2024. All rights reserved.