如何使用ofstream在c ++中将512x512像素阵列写入bmp文件(256色和8 bpp)?

时间:2016-01-20 23:05:24

标签: c++ qt bitmap bmp ofstream

让我先介绍一下。我一直在阅读有关位图文件格式(wiki,msdn等)和研究how to read and write bmp files in c++的内容。我正在用c ++编写一个程序,不使用bmp库,可以从bmp中提取数据,然后使用该数据创建一个新的bmp。这样做的目的是查看新图像文件是否与原始图像文件相同。然后,如果它工作,我可以继续操纵提取的数据,以执行直方图均衡。

目前,我的程序能够从原始bmp文件成功检索Bitmap文件头和位图信息头,然后将其写入新的bmp文件。然后它与颜色表做同样的事情。使用像素数据会出现问题,或者至少这是我目前所认为的问题。看起来它正在被正确读取,甚至看起来乍一看它是正确的。当我在十六进制编辑器中打开新文件并将其与原始文件进行比较时,可以看到值在偏移量(h)630处开始不同。此外,打开时的新图像看起来与原始图像不同。

以下是更新的结构:

var hello = "world";
var hello = 'world';
var hello = "world", var2, var3 = 'value';
var hello = {
   prop: "world"
};
var hello = ["world"];

这是问题的更新相关代码:

#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));
        }
    }

我正在使用的十六进制编辑器是HxD。我正在使用的编译器是Qt Creator。

这是我正在使用的bmp图像:https://drive.google.com/file/d/0B4emsCaxwnh5c3IxNWdsc1k2MGs/view?usp=sharing

感谢任何花费宝贵时间浏览这一文字墙的人。我很感激反馈,如果我错过了一些明显的东西,请务必告诉我。

1 个答案:

答案 0 :(得分:2)

您的最终嵌套循环(输出循环)反复写入同一行像素数据。

//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个字节,颜色表是1024个字节,第一行是512个字节。)这是在哪里寻找问题的线索。