C ++ raytracer没有将值写入位图

时间:2014-08-27 15:55:21

标签: c++ bitmap

前几天,我的光线跟踪器突然停止创建位图。因此,我将代码缩减为Color类和BMP类,以尝试生成只有一种颜色的图像。不幸的是,这仍然没有创建位图。

当我尝试创建阴影射线时发生错误。当时没有对ColorBMP类进行任何更改会导致位图创建失败。但摆脱启用渲染的功能显示没有进展。我使用Visual Studio 2013在x64上编译和运行。除了这个小小的打嗝之外,没有其他错误。

Main.cpp的

 #include "color.h"
 #include "bmp.h"

int WIDTH = 50;
int HEIGHT = 50;

int main(int argc, char **argv) {
 std::cout << "rendering..." << std::endl;
 BMP Image(WIDTH, HEIGHT); 
 Color blue = Color(0,0,255);

 for (int x = 0; x < HEIGHT; x++) {
  for (int y = 0; y < WIDTH; y++) {
   Image.setPixel(y, x, blue);
  }
 }

 string errMsg;
 string fileName = "onecolor.bmp";

 if (!Image.write(fileName, errMsg)) {
  std::cout << errMsg << std::endl;
 }
 else {
  std::cout << "Successfully wrote file: [" << fileName << "]" << std::endl;
 }
}

Color.h

public: 
    unsigned char r, g, b;

    ~Color() {}
    Color() : r(255), g(255), b(255) {}
    Color(unsigned char _r, unsigned char _g, unsigned char _b) 
        : r(_r), g(_g), b(_b) {}

    Color& operator=(Color rhs);
    void swap(Color& rhs);
};

Color& Color::operator=(Color rhs) {
    swap(rhs);
    return *this;
}

void Color::swap(Color& rhs) {
    using std::swap;

    swap(this->r, rhs.r);
    swap(this->g, rhs.g);
    swap(this->b, rhs.b);
}

bmp.h

using std::ofstream;
using std::string;
using std::ios;

typedef std::vector<Color> ColorRow; 

class BMP {
public:
    BMP(int _width, int _height);

    void setPixel(int _x, int _y, unsigned char _r, 
        unsigned char _g, unsigned char _b);
    void setPixel(int _x, int _y, const Color& Color);


    bool write(string& fileName, string& errMsg) const;

private:
    int bmpWidth;
    int bmpHeight;
    std::vector<ColorRow> Image;
};

// Local Function Prototypes
static void doWrite(ofstream &out, int value);
static void doWrite(ofstream &out, short value);
static void doWrite(ofstream &out, const Color &theColor);

BMP::BMP(int _width, int _height) : bmpWidth(_width), bmpHeight(_height) {
    for (int i = 0; i < bmpHeight; i++) {
        ColorRow row;
        for (int j = 0; j < bmpWidth; j++)
            row.push_back(Color());

        Image.push_back(row);
    }
}

void BMP::setPixel(int _x, int _y, unsigned char _r,
    unsigned char _g, unsigned char _b) {

    bool setThis = true;

    if (_x < 0 || _x >= bmpWidth) {
        std::cout << "Invalid value : " << _x << std::endl;
        setThis = false;
    }

    if (_y < 0 || _y >= bmpHeight) {
        std::cout << "Invalid value : " << _y << std::endl;
        setThis = false;
    }

    if (setThis) Image[_y][_x] = Color(_r, _g, _b);
}

void BMP::setPixel(int _x, int _y, const Color& Color) {
    setPixel(_x, _y, Color.r, Color.g, Color.b);
}

bool BMP::write(std::string& fileName, std::string& errMsg) const {
    ofstream out(fileName.c_str(), ios::binary);

    if (out.fail())
    {
        errMsg = "Could not open: [" + fileName + "]";
        return(false);
    }

    // Header sizes ...
    const int BMP_FILE_HEADER_SIZE = 14;
    const int BMP_INFO_HEADER_SIZE = 40;

    // The bmp file header
    out.put('B');
    out.put('M');

    int fileSize =
        bmpWidth * bmpHeight * 3 +
        BMP_FILE_HEADER_SIZE + BMP_INFO_HEADER_SIZE;

    doWrite(out, fileSize);

    short reserved = 0;
    doWrite(out, reserved);
    doWrite(out, reserved);

    int offset = BMP_FILE_HEADER_SIZE + BMP_INFO_HEADER_SIZE;
    doWrite(out, offset);

    // The bmp information header
    int headerSize = BMP_INFO_HEADER_SIZE;
    doWrite(out, headerSize);

    doWrite(out, bmpWidth);
    doWrite(out, bmpHeight);

    short colorPlanes = 1;
    doWrite(out, colorPlanes);

    short bitsPerPixel = 24;
    doWrite(out, bitsPerPixel);

    int zero = 0;

    for (int i = 0; i < 6; i++)
        doWrite(out, zero);

    for (int i = 0; i < bmpHeight; i++)
        for (int j = 0; j < bmpWidth; j++)
            doWrite(out, Image[i][j]);

    out.close();

    return(true);
}

static void doWrite(ofstream& out, int value) {
    out.write((const char*)&value, sizeof(int));
}

static void doWrite(ofstream& out, short value) {
    out.write((const char *)&value, sizeof(short));
}

static void doWrite(ofstream& out, const Color &Color) {
    out.write((const char *)&Color.b, sizeof(unsigned char));
    out.write((const char *)&Color.g, sizeof(unsigned char));
    out.write((const char *)&Color.r, sizeof(unsigned char));
}

1 个答案:

答案 0 :(得分:1)

根据维基百科而不是我自己的实验,

  

像素存储空间

     

表示位图像素的位按行打包。 每行的大小通过填充向上舍入为4个字节(32位DWORD)的倍数。

     

...

     

像素阵列(位图数据)

     

像素阵列是32位DWORD的块,用于逐像素地描述图像。 通常像素会“颠倒”存储

您似乎忘记了填充并颠倒了行。也许你的旧代码碰巧使用的宽度是4的倍数?