如何使用 ofstream 在 C++ 中将 512x512 像素数组写入 bmp 文件(256 色和 8 bpp)?
How to write 512x512 pixel array to a bmp file (256 colors and 8 bpp) in c++ using ofstream?
让我先介绍一下。我一直在阅读位图文件格式(wiki、msdn 等)并研究 how to read and write bmp files in c++。我正在用 c++ 编写一个程序,不使用 bmp 库,它可以从 bmp 中提取数据,然后使用该数据创建一个新的 bmp。这样做的目的是查看新的图像文件是否与原始图像文件相同。然后,如果它有效,我可以继续处理提取的数据以执行直方图均衡。
目前,我的程序能够成功地从原始bmp文件中获取Bitmap文件头和Bitmap信息头,然后将其写入一个新的bmp文件。然后它对颜色 Table 做同样的事情。问题发生了,或者至少这是我目前认为的,像素数据。乍一看好像读对了,甚至写对了。当我在十六进制编辑器中打开新文件并将其与原始文件进行比较时,可以看到值在偏移量 (h) 630 处开始不同。此外,打开的新图像看起来不像原始图像。
这是更新后的结构:
#pragma pack(2) // Using pragma to force structure format
struct BMPFH // Bitmap file header
{
char HeaderField[2]; // Used to identify the BMP and DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII
unsigned int Size_of_BMP; // size of the BMP file in bytes
unsigned short Reserved1; // Reserved; actual value depends on the application that creates the image
unsigned short Reserved2; // " "
unsigned int StartAddress; // offset, i.e. starting address, of the byte where the bitmap image data (pixel array) can be found
};
#pragma pack()
struct DIBH // Bitmap information header
{
unsigned int Size_of_Header; // Size of this header (40 bytes)
signed int Width; // bitmap width in pixels (signed integer)
signed int Height; // bitmap height in pixels (signed integer)
unsigned short Num_of_Planes; // number of color planes (must be 1)
unsigned short Num_of_Bits; // number of bits per pixel, which is the color depth (1, 4, 8, 16, 24, 32)
unsigned int CompMethod; // compression method being used (0, 1, 2, 3)
unsigned int Size_of_Raw; // size of the raw bitmap data
signed int HRes; // horizontal resolution of the image. (pixel per meter, signed integer)
signed int VRes; // vertical resolution of the image. (pixel per meter, signed integer)
unsigned int Num_of_Col; // number of colors in the color palette, or 0 to default to 2^n
unsigned int Num_of_ICol; // number of important colors used, or 0 when every color is important; generally ignored
};
struct ColorTable
{
unsigned char data[1024];
};
struct Pixel
{
unsigned char pix[262144];
};
这是问题的更新相关代码:
//write pixel data to new file
unsigned char p;
for (int j = 0; j < H; j++)
{
for (int i = 0; i < W; i++)
{
p = opx.pix[j*W + i];
outFile.write(reinterpret_cast<char*>(&p), sizeof(p));
}
}
这是输出到屏幕的内容:
Bitmap File Header
Header Field: BM
Size of BMP: 263222
Start Address: 1078
Bitmap Information Header
Header size: 40
Image width: 512
Image height: 512
Number of bits for pixel: 8
Used compression: 0
Image size: 0
Horizontal resolution: 2835
Vertical resolution: 2835
Number of colors in the color palette: 256
Number of important colors used: 256
---------------------------------------------------
Total number of bytes to store one row of pixels: 512
Total amount of bytes to store the array of pixels: 262144
The first three entries in color table: 0 0 0
The first three pixels (Blue, Green, Red): 98 96 91
我使用的十六进制编辑器是 HxD。我使用的编译器是 Qt Creator。
这是我正在使用的 bmp 图片:https://drive.google.com/file/d/0B4emsCaxwnh5c3IxNWdsc1k2MGs/view?usp=sharing
感谢所有花费宝贵时间查看这面文字墙的人。我会很感激反馈,如果我遗漏了一些明显的东西,一定要让我知道。
您的最终嵌套循环(输出循环)一遍又一遍地写入同一行像素数据。
//write pixel data to new file
unsigned char p;
for (int j = 0; j < H; j++)
{
for (int i = 0; i < W; i++)
{
p = opx.pix[i];
outFile.write(reinterpret_cast<char*>(&p), sizeof(p));
}
}
这一行的i
:
p = opx.pix[i];
是列偏移量。每行重新开始。
要修复它,您可以将其更改为:
p = opx.pix[j*W + i];
有更有效的方法来执行此操作,但这将使您的代码正常工作。
十六进制编辑器中的 630 是从文件开头开始的偏移量(十六进制),您的问题似乎是在那之后的六个字节开始。请注意,636h 将是第二行像素数据的第一个字节。 (文件头是 14 字节,DIB 头是 40 字节,颜色 table 是 1024 字节,第一行是 512 字节。)这是在哪里寻找问题的线索。
让我先介绍一下。我一直在阅读位图文件格式(wiki、msdn 等)并研究 how to read and write bmp files in c++。我正在用 c++ 编写一个程序,不使用 bmp 库,它可以从 bmp 中提取数据,然后使用该数据创建一个新的 bmp。这样做的目的是查看新的图像文件是否与原始图像文件相同。然后,如果它有效,我可以继续处理提取的数据以执行直方图均衡。
目前,我的程序能够成功地从原始bmp文件中获取Bitmap文件头和Bitmap信息头,然后将其写入一个新的bmp文件。然后它对颜色 Table 做同样的事情。问题发生了,或者至少这是我目前认为的,像素数据。乍一看好像读对了,甚至写对了。当我在十六进制编辑器中打开新文件并将其与原始文件进行比较时,可以看到值在偏移量 (h) 630 处开始不同。此外,打开的新图像看起来不像原始图像。
这是更新后的结构:
#pragma pack(2) // Using pragma to force structure format
struct BMPFH // Bitmap file header
{
char HeaderField[2]; // Used to identify the BMP and DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII
unsigned int Size_of_BMP; // size of the BMP file in bytes
unsigned short Reserved1; // Reserved; actual value depends on the application that creates the image
unsigned short Reserved2; // " "
unsigned int StartAddress; // offset, i.e. starting address, of the byte where the bitmap image data (pixel array) can be found
};
#pragma pack()
struct DIBH // Bitmap information header
{
unsigned int Size_of_Header; // Size of this header (40 bytes)
signed int Width; // bitmap width in pixels (signed integer)
signed int Height; // bitmap height in pixels (signed integer)
unsigned short Num_of_Planes; // number of color planes (must be 1)
unsigned short Num_of_Bits; // number of bits per pixel, which is the color depth (1, 4, 8, 16, 24, 32)
unsigned int CompMethod; // compression method being used (0, 1, 2, 3)
unsigned int Size_of_Raw; // size of the raw bitmap data
signed int HRes; // horizontal resolution of the image. (pixel per meter, signed integer)
signed int VRes; // vertical resolution of the image. (pixel per meter, signed integer)
unsigned int Num_of_Col; // number of colors in the color palette, or 0 to default to 2^n
unsigned int Num_of_ICol; // number of important colors used, or 0 when every color is important; generally ignored
};
struct ColorTable
{
unsigned char data[1024];
};
struct Pixel
{
unsigned char pix[262144];
};
这是问题的更新相关代码:
//write pixel data to new file
unsigned char p;
for (int j = 0; j < H; j++)
{
for (int i = 0; i < W; i++)
{
p = opx.pix[j*W + i];
outFile.write(reinterpret_cast<char*>(&p), sizeof(p));
}
}
这是输出到屏幕的内容:
Bitmap File Header
Header Field: BM
Size of BMP: 263222
Start Address: 1078
Bitmap Information Header
Header size: 40
Image width: 512
Image height: 512
Number of bits for pixel: 8
Used compression: 0
Image size: 0
Horizontal resolution: 2835
Vertical resolution: 2835
Number of colors in the color palette: 256
Number of important colors used: 256
---------------------------------------------------
Total number of bytes to store one row of pixels: 512
Total amount of bytes to store the array of pixels: 262144
The first three entries in color table: 0 0 0
The first three pixels (Blue, Green, Red): 98 96 91
我使用的十六进制编辑器是 HxD。我使用的编译器是 Qt Creator。
这是我正在使用的 bmp 图片:https://drive.google.com/file/d/0B4emsCaxwnh5c3IxNWdsc1k2MGs/view?usp=sharing
感谢所有花费宝贵时间查看这面文字墙的人。我会很感激反馈,如果我遗漏了一些明显的东西,一定要让我知道。
您的最终嵌套循环(输出循环)一遍又一遍地写入同一行像素数据。
//write pixel data to new file
unsigned char p;
for (int j = 0; j < H; j++)
{
for (int i = 0; i < W; i++)
{
p = opx.pix[i];
outFile.write(reinterpret_cast<char*>(&p), sizeof(p));
}
}
这一行的i
:
p = opx.pix[i];
是列偏移量。每行重新开始。
要修复它,您可以将其更改为:
p = opx.pix[j*W + i];
有更有效的方法来执行此操作,但这将使您的代码正常工作。
十六进制编辑器中的 630 是从文件开头开始的偏移量(十六进制),您的问题似乎是在那之后的六个字节开始。请注意,636h 将是第二行像素数据的第一个字节。 (文件头是 14 字节,DIB 头是 40 字节,颜色 table 是 1024 字节,第一行是 512 字节。)这是在哪里寻找问题的线索。