反转BMP图片最终结果一团糟

Inverting BMP pictures final result is messed up

我正在尝试反转 bmp 文件,并且非常接近获得正确的输出,但我不知道哪里出错了。

[我的输出][1]

与反转图像一样,原图是白色背景,黑色框和中间的 x。但是,右上角没有黑线(我的输出在右上角附近有一条白线)。如有任何澄清,我们将不胜感激。

执行反相的循环:

int index = 0;
while (index < dibHeader.width) {
    int index2 = 0;
    while (index2< dibHeader.length) {

        fread(&pixel.b, 1, 1, file);
        unsigned int blue = pixel.b;
        blue = ~blue;
        pixel.b = (char) blue;

        ... Same for green/red

        fseek(file, -3, SEEK_CUR);
        f(write(&pixel.b, 1, 1, file);

        ... Same for green/red

        index2++;
    }
    index++;
}

像素结构:

struct Pixels {
    unsigned char b, g, r;
}

像素声明

struct Pixels pixel;

这里至少有两点值得怀疑:

首先,使用 pixel.b = (char) blue,您先将一个无符号整数转换为一个字符,然后再将其分配给一个无符号字符。只需写pixel.b = blue

其次,无论何时在读写之间切换,即使不移动文件位置索引,也必须调用fseek(或fflush);否则行为未定义。因此,您必须在写入后引入 fseek

index2++;
fseek(file, 0, SEEK_CUR);

请注意,您的程序需要以二进制模式打开文件,即 "rb+"

我认为你需要重写这个:

unsigned int blue = pixel.b;
blue = ~blue;
pixel.b = (char) blue;

对此:

pixel.b ~= pixel.b;

并为数据使用缓冲区。不需要读写几个字节。读取缓冲区中的所有数据,处理它们,然后从文件中写入数据。我还看到你在文件中写入数据后忘记插入 fseek(file, -3, SEEK_CUR);。但无论如何,使用缓冲区更强大和完美。

您发布的图片宽度为 273 像素。您的代码似乎正在处理 24 位图像。必须填充 24 位图像中的宽度以确保它是 4 的倍数。

int padding = dibHeader.width % 4; 

位图从下往上读取,逐行读取,然后逐列读取。在这种情况下,从上到下并不重要,但您必须先遍历行和列,然后为每一行应用填充。

//24-bit image:
int padding = dibHeader.width % 4;
index = 0;
while(index < dibHeader.height) //<== go through the height
{
    index2 = 0;
    while(index2 < dibHeader.width) 
    {
        fread...
        pixel.r = ~pixel.r;
        pixel.b = ~pixel.b;
        pixel.g = ~pixel.g;

        fseek(f, -3, SEEK_CUR);
        fwrite...
        fflush(f);
        index2++;
    }
    fseek(f, padding, SEEK_CUR); //<== skip padding
    index++;
}