【问题标题】:C++: Write BMP image format error on WINDOWSC++:在WINDOWS上写入BMP图像格式错误
【发布时间】:2016-11-17 18:33:21
【问题描述】:

我在这里遇到了最奇怪的问题...我在 Windows 中使用相同的代码(复制粘贴)从 Linux 到 READWRITEBMP 图像。并且由于某种原因,在 Linux 中,每件事都可以完全正常,但是当我从某些地方进入 Windows 10 时,我无法打开它图片,我收到一条错误消息,怎么说是这样的:

“我们好像不支持这种文件格式。”

你知道我该怎么做吗?我会把代码放在下面。

编辑:

我已经解决了填充问题,现在可以写入图像,但它们完全是白色,知道为什么吗?我也更新了代码。

struct BMP {
    int width;
    int height;
    unsigned char header[54];
    unsigned char *pixels;
    int size;
    int row_padded;
};

void writeBMP(string filename, BMP image) {
    string fileName = "Output Files\\" + filename;
    FILE *out = fopen(fileName.c_str(), "wb");
    fwrite(image.header, sizeof(unsigned char), 54, out);

    unsigned char tmp;
    for (int i = 0; i < image.height; i++) {
        for (int j = 0; j < image.width * 3; j += 3) {
            // Convert (B, G, R) to (R, G, B)
            tmp = image.pixels[j];
            image.pixels[j] = image.pixels[j + 2];
            image.pixels[j + 2] = tmp;
        }
        fwrite(image.pixels, sizeof(unsigned char), image.row_padded, out);
    }
    fclose(out);
}

BMP readBMP(string filename) {
    BMP image;
    string fileName = "Input Files\\" + filename;
    FILE *f = fopen(fileName.c_str(), "rb");

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

    fread(image.header, sizeof(unsigned char), 54, f); // read the 54-byte header

    // extract image height and width from header
    image.width = *(int *) &image.header[18];
    image.height = *(int *) &image.header[22];

    image.row_padded = (image.width * 3 + 3) & (~3);
    image.pixels = new unsigned char[image.row_padded];
    unsigned char tmp;

    for (int i = 0; i < image.height; i++) {
        fread(image.pixels, sizeof(unsigned char), image.row_padded, f);
        for (int j = 0; j < image.width * 3; j += 3) {
            // Convert (B, G, R) to (R, G, B)
            tmp = image.pixels[j];
            image.pixels[j] = image.pixels[j + 2];
            image.pixels[j + 2] = tmp;
        }
    }
    fclose(f);
    return image;

}

在我看来,这段代码应该是跨平台的……但不是……为什么?

感谢您的帮助

【问题讨论】:

  • 您可以在windows中使用Visual Studio自带的比较工具比较两个文件。或者使用调试器确保写入相同的图像头数据。
  • 比较什么?完全一样的代码...
  • 我检查了这段代码几次,它完全一样......
  • @Mircea 比较 BMP 文件,而不是代码。
  • @Mircea 我认为他的意思是文件中的标题数据。

标签: c++ windows image bitmap bitmapimage


【解决方案1】:

检查标题

header 必须以以下两个 signature 字节开头:0x42 0x4D。如果是不同的东西,第三方应用程序会认为该文件不包含 bmp 图片,尽管文件扩展名为 .bmp。

像素的大小和存储方式也有点more complex than what you expect:您假设每个像素的位数为24,并且没有使用任何压缩。这不能保证。如果不是这种情况,您可能会读取比可用数据更多的数据,并在写回文件时损坏文件。

此外,标头的大小还取决于您使用的BMP version,其中you can detect using 是偏移量14 处的4 字节整数。

改进您的代码

加载文件时,请检查签名、bmp 版本、每个像素的位数和压缩率。出于调试目的,请考虑转储标头以手动检查:

for (int i=0; i<54; i++) 
    cout << hex << image.header[i] << " ";` 
cout <<endl; 

此外,当您fread() 检查读取的字节数是否与您想要读取的大小相对应时,请确保您没有使用未初始化的缓冲区数据。

编辑:

检查转储后,格式似乎符合预期。但是使用您计算的填充大小验证标题中的填充大小似乎错误在这里:

image.row_padded = (image.width * 3 + 3) & (~3);     // ok size of a single row rounded up to multiple of 4
image.pixels = new unsigned char[image.row_padded];  // oops !  A little short ? 

实际上你是逐行阅读,但你只保留最后一个在内存中!这与您的第一个版本不同,您确实阅读了图片的完整像素。

同样,你写最后一行重复高度的时间。

重新考虑您的填充,使用填充的总大小。

image.row_padded = (image.width * 3 + 3) & (~3);     // ok size of a single row rounded up to multiple of 4
image.size_padded = image.row_padded * image.height;  // padded full size
image.pixels = new unsigned char[image.size_padded];  // yeah ! 
if (fread(image.pixels, sizeof(unsigned char), image.size_padded, f) !=  image.size_padded) {
    cout << "Error: all bytes couldn't be read"<<endl; 
}
else { 
    ... // process the pixels as expected
}
...

【讨论】:

  • 我的问题已经解决了一部分,我编辑了我的问题,你可以再检查一遍吗?
  • 嗯……输入的图片没问题,我可以打开看看。我的问题只是输出图像。我已经多次检查了标题,它很完美,或者我看不出有什么区别。我已经检查过for (int i=0; i&lt;54; i++) cout &lt;&lt; hex &lt;&lt; image.header[i] &lt;&lt; " ";,它是一样的......现在,如果我有权利,此时我的问题不是标题,而是像素数组。由于某种原因,我以某种方式丢失了我认为的所有像素......或者我写得不正确。我认为这是我此刻的问题。
  • @Mircea 你能告诉我转储的结果吗?
  • 当然,结果的图像在这里here我不能像文本一样复制粘贴结果,因为它有很多字符
猜你喜欢
  • 2021-04-26
  • 1970-01-01
  • 2020-02-10
  • 2015-03-12
  • 1970-01-01
  • 2014-11-26
  • 2016-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多