读取 BMP 文件 C++(读取 BMP 标头时出现问题)

Posted

技术标签:

【中文标题】读取 BMP 文件 C++(读取 BMP 标头时出现问题)【英文标题】:Reading BMP file C++ (trouble with reading BMP header) 【发布时间】:2014-03-01 09:15:45 【问题描述】:

我正在尝试使用阅读方法编写 BMP 图像类。我看到了 BMP 文件的 msdn 规范,所以我尝试读取标题,然后使用 biHeight 和 biWidth 信息读取每个像素的 RGB 信息。 所以,它不读取头信息,每个头参数的值都是-1。

代码如下:

#ifndef BMP_IMAGE_H
#define BMP_IMAGE_H

#include <fstream>

using namespace std;


typedef struct

    unsigned int    bfType;
    unsigned long   bfSize;
    unsigned int    bfReserved1;
    unsigned int    bfReserved2;
    unsigned long   bfOffBits;
 BitMapFileHeader;

typedef struct

    unsigned int    biSize;
    int             biWidth;
    int             biHeight;
    unsigned short  biPlanes;
    unsigned short  biBitCount;
    unsigned int    biCompression;
    unsigned int    biSizeImage;
    int             biXPelsPerMeter;
    int             biYPelsPerMeter;
    unsigned int    biClrUsed;
    unsigned int    biClrImportant;
 BitMapInfoHeader;

typedef struct

    int   rgbBlue;
    int   rgbGreen;
    int   rgbRed;
    int   rgbReserved;
 RGBColor;


class BMPImage

private:
    unsigned short read_u16();
    unsigned int   read_u32();
    int            read_s32();
public:
    ifstream pFile;
    int imageWidth;
    int imageHeight;
    RGBColor **rgb;
    BMPImage(char* fileName);
    void pixelsInfo();
;

#endif // BMP_IMAGE_H

#include "bmp_image.h"
#include <iostream>
using namespace std;
BMPImage::BMPImage(char* fileName)

     ifstream pFile(fileName, ios::in | ios::binary);


     // read the header of file
     BitMapFileHeader header __attribute__((unused));

     header.bfType      = read_u16();
     header.bfSize      = read_u32();
     header.bfReserved1 = read_u16();
     header.bfReserved2 = read_u16();
     header.bfOffBits   = read_u32();

     // read the header of image
     BitMapInfoHeader bmiHeader;

     bmiHeader.biSize          = read_u32();
     bmiHeader.biWidth         = read_s32();
     bmiHeader.biHeight        = read_s32();
     bmiHeader.biPlanes        = read_u16();
     bmiHeader.biBitCount      = read_u16();
     bmiHeader.biCompression   = read_u32();
     bmiHeader.biSizeImage     = read_u32();
     bmiHeader.biXPelsPerMeter = read_s32();
     bmiHeader.biYPelsPerMeter = read_s32();
     bmiHeader.biClrUsed       = read_u32();
     bmiHeader.biClrImportant  = read_u32();

     cout << (int)bmiHeader.biHeight <<"\n";
     RGBColor **rgb = new RGBColor*[bmiHeader.biHeight];
     for (int i = 0; i < bmiHeader.biWidth; i++)
            rgb[i] = new RGBColor[bmiHeader.biHeight];

     for (int i = 0; i < bmiHeader.biWidth; i++) 
         for (int j = 0; j < bmiHeader.biHeight; j++) 
            rgb[i][j].rgbBlue = pFile.get();
            rgb[i][j].rgbGreen = pFile.get();
            rgb[i][j].rgbRed = pFile.get();


         


         char temp;
         pFile.get(temp);
      

     imageWidth = bmiHeader.biWidth;
     imageHeight = bmiHeader.biHeight;

     pFile.close();


unsigned short BMPImage::read_u16()
    unsigned char b0, b1;
    b0 = pFile.get();
    b1 = pFile.get();

    return ((b1 << 8) | b0);


unsigned int BMPImage::read_u32()
    unsigned char b0, b1, b2, b3;
    b0 = pFile.get();
    b1 = pFile.get();
    b2 = pFile.get();
    b3 = pFile.get();

    return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);


int BMPImage::read_s32()
        unsigned char b0, b1, b2, b3;
        b0 = pFile.get();
        b1 = pFile.get();
        b2 = pFile.get();
        b3 = pFile.get();
        return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);



void BMPImage::pixelsInfo()
    for (int i = 0; i < imageWidth; i++) 
            for (int j = 0; j < imageHeight; j++) 
                std::cout << rgb[i][j].rgbRed <<" " << rgb[i][j].rgbGreen << " " << rgb[i][j].rgbBlue << std::endl;
            
            std::cout << std::endl;
        

附:谢谢大家的帮助

【问题讨论】:

检查文件是否打开成功。 if(!pFile) 错误... 您没有初始化 pFile 类成员。您的构造函数声明了一个本地 pFile(这意味着您的所有读取例程使用的 pFile 都是无效的)。 这是我的第一件事,但这不是原因,文件已被安全打开 pFile.Open(fileName, ios::in | ios::binary);替换ifstream pFile(fileName, ios::in | ios::binary); aselle,谢谢,这是个问题 【参考方案1】:

会员

ifstream pFile;

类 BMPImage 没有被初始化,所以当你在成员函数中使用它时它是无效的。相反,您在构造函数中本地定义不同的 pFile 实例。这些应该是同一个实例。

【讨论】:

我想说@aselle 的评论应该作为答案提出来!【参考方案2】:

我认为你应该改变这个:

typedef struct

    int   rgbBlue;
    int   rgbGreen;
    int   rgbRed;
    int   rgbReserved;
 RGBColor;

为此:

typedef struct

    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
 RGBColor;

参考:https://msdn.microsoft.com/en-us/library/windows/desktop/dd162938(v=vs.85).aspx

【讨论】:

以上是关于读取 BMP 文件 C++(读取 BMP 标头时出现问题)的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中读取 bmp 标头

C 中的 .BMP 文件 - DIB 标头返回图像大小 0,即使 BMP 标头返回文件大小

关于怎么用C++读取bmp图片

在 C++ 中读取 bmp 文件的宽度和高度

在 C++ 中读取 .bmp 文件

C++ - 从 BMP 文件中读取每个像素的位数