ReadBmpFromFile/Stream
函数运行正常。 (仍然有点慢,但他们否则工作)。 WriteBmpToFile/Stream
函数的工作原理是它们成功创建了一个有效的.bmp
文件,但只有最后几千个像素,文件的其余部分为黑色。
难以理解为什么,像素数据从下到上存储,因此问题应该在文件的顶部附近。
原件:
拷贝:
我使用调试器,并且已成功从包含对象复制数据。当我从文件中读取然后立即将其写回来时,它不应该失败:
if(_keyboard->KeyDown(KEY_S)) {
BitmapFileType bmp_test;
ReadBmpFromFile("maglot.bmp_test", bmp_test);
//Change filename to not destroy original!
WriteBmpToFile("maglot_copy.bmp_test", bmp_test);
//Allegro's implementation to test correct output against.
//save_bmp("maglot_copy.bmp", image->GetImage(), nullptr);
}
位图类定义:
class BitmapFileType {
public:
struct Header {
std::vector<unsigned char> file_signature;
unsigned int file_size;
unsigned short unused1;
unsigned short unused2;
unsigned int pixel_array_offset;
unsigned int DIB_header_size;
unsigned int width;
unsigned int height;
unsigned short plane_count;
unsigned short bpp;
unsigned int compression_method;
unsigned int raw_size;
unsigned int print_resolution_horizontal;
unsigned int print_resolution_vertical;
unsigned int pallete_colors_count;
unsigned int important_colors_count;
Header() :
file_signature(2),
file_size(0),
unused1(0),
unused2(0),
pixel_array_offset(0),
DIB_header_size(0),
width(0),
height(0),
plane_count(0),
bpp(0),
compression_method(0),
raw_size(0),
print_resolution_horizontal(0),
print_resolution_vertical(0),
pallete_colors_count(0),
important_colors_count(0)
{ /* DO NOTHING */ }
Header(const Header& other) :
file_signature(other.file_signature),
file_size(other.file_size),
unused1(other.unused1),
unused2(other.unused2),
pixel_array_offset(other.pixel_array_offset),
DIB_header_size(other.DIB_header_size),
width(other.width),
height(other.height),
plane_count(other.plane_count),
bpp(other.bpp),
compression_method(other.compression_method),
raw_size(other.raw_size),
print_resolution_horizontal(other.print_resolution_horizontal),
print_resolution_vertical(other.print_resolution_vertical),
pallete_colors_count(other.pallete_colors_count),
important_colors_count(other.important_colors_count)
{ /* DO NOTHING */ }
Header& operator=(const Header& rhs) {
if(this == &rhs) return *this;
this->file_signature = rhs.file_signature;
this->file_size = rhs.file_size;
this->unused1 = rhs.unused1;
this->unused2 = rhs.unused2;
this->pixel_array_offset = rhs.pixel_array_offset;
this->DIB_header_size = rhs.DIB_header_size;
this->width = rhs.width;
this->height = rhs.height;
this->plane_count = rhs.plane_count;
this->bpp = rhs.bpp;
this->compression_method = rhs.compression_method;
this->raw_size = rhs.raw_size;
this->print_resolution_horizontal = rhs.print_resolution_horizontal;
this->print_resolution_vertical = rhs.print_resolution_vertical;
this->pallete_colors_count = rhs.pallete_colors_count;
this->important_colors_count = rhs.important_colors_count;
return *this;
}
};
struct PixelData {
std::vector<unsigned char> _pixel_data;
PixelData() : _pixel_data() { /* DO NOTHING */ }
PixelData(const PixelData& other) : _pixel_data(other._pixel_data) { /* DO NOTHING */ }
PixelData(const std::vector<unsigned char>& pixel_data) : _pixel_data(pixel_data) { /* DO NOTHING */ }
};
BitmapFileType() : _header(), _data() { /* DO NOTHING */ }
BitmapFileType(const BitmapFileType::Header& header) : _header(header), _data() { /* DO NOTHING */ }
BitmapFileType(const BitmapFileType::Header& header, const PixelData& data) : _header(header), _data(data) { /* DO NOTHING */ }
BitmapFileType& operator=(const BitmapFileType& rhs) {
if(this == &rhs) return *this;
_header = rhs._header;
_data = rhs._data;
return *this;
}
const Header& GetHeader() const {
return _header;
}
Header& GetHeader() {
return const_cast<Header&>(static_cast<const BitmapFileType&>(*this).GetHeader());
}
const PixelData& GetPixelData() const {
return _data;
}
PixelData& GetPixelData() {
return const_cast<PixelData&>(static_cast<const BitmapFileType&>(*this).GetPixelData());
}
protected:
private:
Header _header;
PixelData _data;
};
功能定义:
#include "FileTypeUtility.h"
#include <fstream>
void WriteBmpToFile(const std::string& filename, const BitmapFileType& bmp) {
std::ofstream ofs;
ofs.open(filename);
WriteBmpToStream(ofs, bmp);
ofs.close();
}
void ReadBmpFromFile(const std::string& filename, BitmapFileType& bmp) {
std::ifstream ifs;
ifs.open(filename);
ReadBmpFromStream(ifs, bmp);
ifs.close();
}
void ReadBmpFromStream(std::istream& input_stream, BitmapFileType& bmp) {
if(input_stream.fail() || input_stream.bad() || input_stream.eof()) return;
std::vector<unsigned char> file_signature(2);
input_stream.read(reinterpret_cast<char*>(file_signature.data()), file_signature.size());
if((file_signature[0] != 'B' || file_signature[1] != 'M')) {
input_stream.seekg(-2, std::ios_base::cur);
input_stream.setstate(std::ios_base::failbit);
return;
}
unsigned int file_size = 0;
input_stream.read(reinterpret_cast<char*>(&file_size), sizeof(file_size));
unsigned short unused1 = 0;
input_stream.read(reinterpret_cast<char*>(&unused1), sizeof(unused1));
unsigned short unused2 = 0;
input_stream.read(reinterpret_cast<char*>(&unused2), sizeof(unused2));
unsigned int pixel_array_offset = 0;
input_stream.read(reinterpret_cast<char*>(&pixel_array_offset), sizeof(pixel_array_offset));
unsigned int DIB_header_size = 0;
input_stream.read(reinterpret_cast<char*>(&DIB_header_size), sizeof(DIB_header_size));
unsigned int width = 0;
input_stream.read(reinterpret_cast<char*>(&width), sizeof(width));
unsigned int height = 0;
input_stream.read(reinterpret_cast<char*>(&height), sizeof(height));
unsigned short plane_count = 0;
input_stream.read(reinterpret_cast<char*>(&plane_count), sizeof(plane_count));
unsigned short bpp = 0;
input_stream.read(reinterpret_cast<char*>(&bpp), sizeof(bpp));
unsigned int compression_method = 0;
input_stream.read(reinterpret_cast<char*>(&compression_method), sizeof(compression_method));
unsigned int raw_size = 0;
input_stream.read(reinterpret_cast<char*>(&raw_size), sizeof(raw_size));
unsigned int print_resolution_horizontal = 0;
input_stream.read(reinterpret_cast<char*>(&print_resolution_horizontal), sizeof(print_resolution_horizontal));
unsigned int print_resolution_vertical = 0;
input_stream.read(reinterpret_cast<char*>(&print_resolution_vertical), sizeof(print_resolution_vertical));
unsigned int pallete_colors_count = 0;
input_stream.read(reinterpret_cast<char*>(&pallete_colors_count), sizeof(pallete_colors_count));
unsigned int important_colors_count = 0;
input_stream.read(reinterpret_cast<char*>(&important_colors_count), sizeof(important_colors_count));
std::vector<unsigned char> pixel_array(raw_size);
input_stream.read(reinterpret_cast<char*>(pixel_array.data()), pixel_array.size());
BitmapFileType::PixelData bmpPixels(pixel_array);
BitmapFileType::Header bmpHeader;
bmpHeader.file_signature = file_signature;
bmpHeader.file_size = file_size;
bmpHeader.unused1 = unused1;
bmpHeader.unused2 = unused2;
bmpHeader.pixel_array_offset = pixel_array_offset;
bmpHeader.DIB_header_size = DIB_header_size;
bmpHeader.width = width;
bmpHeader.height = height;
bmpHeader.plane_count = plane_count;
bmpHeader.bpp = bpp;
bmpHeader.compression_method = compression_method;
bmpHeader.raw_size = raw_size;
bmpHeader.print_resolution_horizontal = print_resolution_horizontal;
bmpHeader.print_resolution_vertical = print_resolution_vertical;
bmpHeader.pallete_colors_count = pallete_colors_count;
bmpHeader.important_colors_count = important_colors_count;
bmp = BitmapFileType(bmpHeader, bmpPixels);
return;
}
void WriteBmpToStream(std::ostream& output_stream, const BitmapFileType& bmp) {
if(output_stream.fail() || output_stream.bad() || output_stream.eof()) return;
const BitmapFileType::Header& bmpHeader(bmp.GetHeader());
output_stream.write(reinterpret_cast<const char*>(bmpHeader.file_signature.data()), bmpHeader.file_signature.size());
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.file_size), sizeof(bmpHeader.file_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.unused1), sizeof(bmpHeader.unused1));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.unused2), sizeof(bmpHeader.unused2));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.pixel_array_offset), sizeof(bmpHeader.pixel_array_offset));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.DIB_header_size), sizeof(bmpHeader.DIB_header_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.width), sizeof(bmpHeader.width));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.height), sizeof(bmpHeader.height));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.plane_count), sizeof(bmpHeader.plane_count));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.bpp), sizeof(bmpHeader.bpp));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.compression_method), sizeof(bmpHeader.compression_method));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.raw_size), sizeof(bmpHeader.raw_size));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.print_resolution_horizontal), sizeof(bmpHeader.print_resolution_horizontal));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.print_resolution_vertical), sizeof(bmpHeader.print_resolution_vertical));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.pallete_colors_count), sizeof(bmpHeader.pallete_colors_count));
output_stream.write(reinterpret_cast<const char*>(&bmpHeader.important_colors_count), sizeof(bmpHeader.important_colors_count));
const BitmapFileType::PixelData& bmpPixelData(bmp.GetPixelData());
output_stream.write(reinterpret_cast<const char*>(bmpPixelData._pixel_data.data()), bmpPixelData._pixel_data.size());
return;
}