前几天,我的光线跟踪器突然停止创建位图。因此,我将代码缩减为Color
类和BMP
类,以尝试生成只有一种颜色的图像。不幸的是,这仍然没有创建位图。
当我尝试创建阴影射线时发生错误。当时没有对Color
或BMP
类进行任何更改会导致位图创建失败。但摆脱启用渲染的功能显示没有进展。我使用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 :(得分:1)
根据维基百科而不是我自己的实验,
像素存储空间
表示位图像素的位按行打包。 每行的大小通过填充向上舍入为4个字节(32位DWORD)的倍数。
...
像素阵列(位图数据)
像素阵列是32位DWORD的块,用于逐像素地描述图像。 通常像素会“颠倒”存储
您似乎忘记了填充并颠倒了行。也许你的旧代码碰巧使用的宽度是4的倍数?