2014-08-27 15 views
0

有一天,我的raytracer停止創建位圖。所以我將代碼簡化爲Color類和BMP類,嘗試生成僅一種顏色的圖像。不幸的是,這仍然沒有創建一個位圖。C++ raytracer不寫入位圖的值

當我試圖創建陰影射線時發生錯誤。當時沒有對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)); 
} 
+0

你是說文件沒有被創建? (是否有可能在不同的目錄中創建它,而不是您期望的目錄?)或者正在創建它,但它不是有效的位圖? – 2014-08-27 16:09:27

+0

@AdrianMcCarthy該文件正在創建在正確的目錄中,但無法查看。所以,我認爲創建它時有錯誤。 – user2958542 2014-08-27 16:38:13

+0

問題可能與您的init()函數或render()函數或draw()函數有關。嘗試繪製一個簡單的三角形形狀,以找出問題所在。還要確保這不是C:驅動器文件的讀取或寫入問題。否則,您可能會遇到管理權限。 – Juniar 2014-08-27 18:23:21

回答

1

根據維基百科,而不是我自己的實驗,

像素存儲

表示位圖像素被包裝在列中的位。 通過填充將每行的大小四捨五入爲4個字節(32位DWORD)的倍數。

...

像素陣列(位圖數據)

像素陣列是32位雙字的塊,由像素描述圖像像素。 通常像素存儲「倒置」

你似乎忘填充和遍歷行倒掛。也許你的舊代碼碰巧使用4的倍數的寬度?