使用 BMP - 加载和保存

Working with BMP - loading and saving

我们正在与朋友一起尝试编写应用程序来处理 BMP 文件,我们将使其尽可能简单,因为我们才刚刚开始学习 C 和 C++。使用新的实际尺寸的线条复制效果很好,但现在我想添加灰度效果并遇到另一个问题:图片的右侧移动到左侧 - 检查图片。是什么导致了这个问题?

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <unistd.h>


using namespace std;

void ReadBMP()
{
    FILE* f = fopen("test2.bmp", "rb");
    FILE* w = fopen("zapis.bmp", "wb");

    if(f == NULL)
        throw "Argument Exception";

    unsigned char info[54];
    fread(info, sizeof(unsigned char), 54, f);
    fwrite(info, sizeof(unsigned char), 54, w);

    int width = *(int*)&info[18];
    int height = *(int*)&info[22];

    cout << endl;
    cout << "Width: " << width << endl;
    cout << "Height: " << height << endl;



    int realwidth = 3*width+(4 - ((3*width)%4))%4;
    int volume = height * realwidth;
    unsigned char* data = new unsigned char[volume];

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

    fread(data, sizeof(unsigned char), volume, f);
    unsigned char color = 0;

    for(int i = 0; i < volume; i+=3)
    {
        color = 0;
        color+=data[i]*0.114;
        color+=data[i+1]*0.587;
        color+=data[i+2]*0.299;
        data[i] = color;
        data[i+1] = color;
        data[i+2] = color;
    }


    fwrite(data, sizeof(unsigned char), volume, w);



    fclose(f);
    fclose(w);
    delete(data);
}

int main()
{
    ReadBMP();
    return 0;
}

Input image

Output image

您的图像数据大小公式有误。首先,您需要找到间距,方法是将宽度乘以每个像素的字节数(24 位图像为 3),然后四舍五入到最接近的 4 的倍数。然后将间距乘以高度;

int byte_width = width * 3;
int pitch = byte_width + (4 - byte_width % 4) % 4;
int volume = pitch * height;

正如我在自己的代码(大约 20 年前编写的)中看到的那样,图像的每一行都由 0 个或更多空字节补充以对齐起始字节。看来,你的对齐计算错误。

只需复制并粘贴到此处:

unsigned short paddingSize;
unsigned short bitsPerLine = width * bitsPerPixel;

if(1 == bitsPerPixel || 4 == bitsPerPixel)
{
  if(bitsPerLine % 8)
    bitsPerLine += 8;

  paddingSize = (bitsPerLine/8) % 2;
}
else if(8 == bitsPerPixel)
  paddingSize = 0x0003 & ~((bitsPerLine/8) % 4 - 1);
else
  paddingSize = (bitsPerLine/8) % 2;

每行的实际大小是 calculatedSize + paddingSize,其中 calculatedSize 是以字节为单位的行的确切大小,即 ceil(bitsPerLine/8)(bitsPerLine + 7)/8 ic C/C++。

关于代码,我能说的是它已经过调试并且可以正常工作。但是我不记得为什么要在这里进行所有这些检查。

unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
// fwrite(info, sizeof(unsigned char), 54, w); --- comment this line !!!!!!! 

int width = *(int*)&info[18];
int height = *(int*)&info[22];

您正在不必要地写 header 来归档两次。