反转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++;
}
我正在尝试反转 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++;
}