生成的大型 BMP 文件已损坏
Large generated BMP file corrupted
我创建了一些东西来生成大型 BMP 文件。在 BMP 文件变大之前,它工作得很好。出于某种原因,由于“无效的 header 数据”,它无法在 windows 和 Linux 上显示。我不明白,因为它完全在 BMP 文件的 header 的数值范围内,并且它适用于完美查找的小文件。我最好的猜测是某种类型的数据溢出,但我无法在任何地方找到它。我什至检查了生成的 BMP 文件的二进制数据,一切似乎都在它应该在的地方!不管怎样,这是我的代码,我将要 link 几个示例文件——一个有效,一个无效。 (BMP文件是每像素一位)。
void gen_headers(std::fstream& file, size_t image_px_width, size_t image_px_height) {
constexpr size_t header_size = 14;
constexpr size_t info_header_size = 40;
constexpr size_t color_table_size = 8;
constexpr size_t image_offset = header_size + info_header_size + color_table_size;
constexpr size_t bpp = 1;
size_t row_width = static_cast<size_t>(std::ceil(image_px_width / 32.0) * 4);
size_t image_size = row_width * image_px_height;
size_t file_size = image_offset + image_size;
unsigned char file_header[header_size] = { 0 };
unsigned char info_header[info_header_size] = { 0 };
unsigned char color_table[color_table_size] = { 0 };
//header file type
file_header[0] = 'B';
file_header[1] = 'M';
//header file size info
file_header[2] = static_cast<unsigned char>(file_size);
file_header[3] = static_cast<unsigned char>(file_size >> 8);
file_header[4] = static_cast<unsigned char>(file_size >> 16);
file_header[5] = static_cast<unsigned char>(file_size >> 24);
//header offset to pixel data
file_header[10] = image_offset;
//info header size
info_header[0] = info_header_size;
//info header image width
info_header[4] = static_cast<unsigned char>(image_px_width);
info_header[5] = static_cast<unsigned char>(image_px_width >> 8);
info_header[6] = static_cast<unsigned char>(image_px_width >> 16);
info_header[7] = static_cast<unsigned char>(image_px_width >> 24);
//info header image height
info_header[8] = static_cast<unsigned char>(image_px_height);
info_header[9] = static_cast<unsigned char>(image_px_height >> 8);
info_header[10] = static_cast<unsigned char>(image_px_height >> 16);
info_header[11] = static_cast<unsigned char>(image_px_height >> 24);
//info header planes
info_header[12] = 1;
//info header bits per pixel
info_header[14] = static_cast<unsigned char>(bpp);
//image size
info_header[20] = static_cast<unsigned char>(image_size);
info_header[21] = static_cast<unsigned char>(image_size >> 8);
info_header[22] = static_cast<unsigned char>(image_size >> 16);
info_header[23] = static_cast<unsigned char>(image_size >> 24);
//resolution
info_header[24] = 1;
info_header[28] = 1;
//color table white
color_table[4] = 255;
color_table[5] = 255;
color_table[6] = 255;
file.seekp(0);
file.write((char*)file_header, header_size);
file.write((char*)info_header, info_header_size);
file.write((char*)color_table, color_table_size);
}
std::fstream file(name, std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
gen_headers(file, image_width, image_height);
size_t row_width = static_cast<size_t>(std::ceil(image_width / 32.0) * 4);
char* row = new char[row_width];
std::fill(row, row + row_width, 255);
for (size_t y = 0; y < image_height; ++y) {
file.write(row, row_width);
}
delete[] row;
编辑:
为了清楚起见,我已经将图像生成剥离到最基本的部分。出现同样的问题。
编辑 2:
在我的计算机上,可以查看的 bmp 之间的阈值介于 23,000 x 23,000 (64,598kb) 和 24,000 x 24,000 (70,313kb) 之间。同样值得注意的是:在文件资源管理器中查看图像属性时,如果文件“损坏”,windows 无法确定图像的宽度、高度或深度。我相信这是 header 年代的另一个原因。
编辑 3:
在编写了一个读取 header 数据的快速应用程序后,我确认 header 没有任何问题。没有任何溢出或失败。我想解决方案是不使用 BMP。
你的第二张图片是 100001×100001,即 10 十亿像素。虽然我在网上找不到关于 BMP 的最大允许大小的官方声明,但很可能很多软件将宽度和高度限制为 32767 或 65535,或者在内部将双层图像扩展为每个像素一个字节并限制大小将该内部表示缩小到几千兆字节。
我创建了一些东西来生成大型 BMP 文件。在 BMP 文件变大之前,它工作得很好。出于某种原因,由于“无效的 header 数据”,它无法在 windows 和 Linux 上显示。我不明白,因为它完全在 BMP 文件的 header 的数值范围内,并且它适用于完美查找的小文件。我最好的猜测是某种类型的数据溢出,但我无法在任何地方找到它。我什至检查了生成的 BMP 文件的二进制数据,一切似乎都在它应该在的地方!不管怎样,这是我的代码,我将要 link 几个示例文件——一个有效,一个无效。 (BMP文件是每像素一位)。
void gen_headers(std::fstream& file, size_t image_px_width, size_t image_px_height) {
constexpr size_t header_size = 14;
constexpr size_t info_header_size = 40;
constexpr size_t color_table_size = 8;
constexpr size_t image_offset = header_size + info_header_size + color_table_size;
constexpr size_t bpp = 1;
size_t row_width = static_cast<size_t>(std::ceil(image_px_width / 32.0) * 4);
size_t image_size = row_width * image_px_height;
size_t file_size = image_offset + image_size;
unsigned char file_header[header_size] = { 0 };
unsigned char info_header[info_header_size] = { 0 };
unsigned char color_table[color_table_size] = { 0 };
//header file type
file_header[0] = 'B';
file_header[1] = 'M';
//header file size info
file_header[2] = static_cast<unsigned char>(file_size);
file_header[3] = static_cast<unsigned char>(file_size >> 8);
file_header[4] = static_cast<unsigned char>(file_size >> 16);
file_header[5] = static_cast<unsigned char>(file_size >> 24);
//header offset to pixel data
file_header[10] = image_offset;
//info header size
info_header[0] = info_header_size;
//info header image width
info_header[4] = static_cast<unsigned char>(image_px_width);
info_header[5] = static_cast<unsigned char>(image_px_width >> 8);
info_header[6] = static_cast<unsigned char>(image_px_width >> 16);
info_header[7] = static_cast<unsigned char>(image_px_width >> 24);
//info header image height
info_header[8] = static_cast<unsigned char>(image_px_height);
info_header[9] = static_cast<unsigned char>(image_px_height >> 8);
info_header[10] = static_cast<unsigned char>(image_px_height >> 16);
info_header[11] = static_cast<unsigned char>(image_px_height >> 24);
//info header planes
info_header[12] = 1;
//info header bits per pixel
info_header[14] = static_cast<unsigned char>(bpp);
//image size
info_header[20] = static_cast<unsigned char>(image_size);
info_header[21] = static_cast<unsigned char>(image_size >> 8);
info_header[22] = static_cast<unsigned char>(image_size >> 16);
info_header[23] = static_cast<unsigned char>(image_size >> 24);
//resolution
info_header[24] = 1;
info_header[28] = 1;
//color table white
color_table[4] = 255;
color_table[5] = 255;
color_table[6] = 255;
file.seekp(0);
file.write((char*)file_header, header_size);
file.write((char*)info_header, info_header_size);
file.write((char*)color_table, color_table_size);
}
std::fstream file(name, std::fstream::binary | std::fstream::in | std::fstream::out | std::fstream::trunc);
gen_headers(file, image_width, image_height);
size_t row_width = static_cast<size_t>(std::ceil(image_width / 32.0) * 4);
char* row = new char[row_width];
std::fill(row, row + row_width, 255);
for (size_t y = 0; y < image_height; ++y) {
file.write(row, row_width);
}
delete[] row;
编辑:
为了清楚起见,我已经将图像生成剥离到最基本的部分。出现同样的问题。
编辑 2:
在我的计算机上,可以查看的 bmp 之间的阈值介于 23,000 x 23,000 (64,598kb) 和 24,000 x 24,000 (70,313kb) 之间。同样值得注意的是:在文件资源管理器中查看图像属性时,如果文件“损坏”,windows 无法确定图像的宽度、高度或深度。我相信这是 header 年代的另一个原因。
编辑 3:
在编写了一个读取 header 数据的快速应用程序后,我确认 header 没有任何问题。没有任何溢出或失败。我想解决方案是不使用 BMP。
你的第二张图片是 100001×100001,即 10 十亿像素。虽然我在网上找不到关于 BMP 的最大允许大小的官方声明,但很可能很多软件将宽度和高度限制为 32767 或 65535,或者在内部将双层图像扩展为每个像素一个字节并限制大小将该内部表示缩小到几千兆字节。