Windows Bitmap编码器只写下几千像素

时间:2014-06-27 12:47:11

标签: c++ windows

ReadBmpFromFile/Stream函数运行正常。 (仍然有点慢,但他们否则工作)。 WriteBmpToFile/Stream函数的工作原理是它们成功创建了一个有效的.bmp文件,但只有最后几千个像素,文件的其余部分为黑色。

难以理解为什么,像素数据从下到上存储,因此问题应该在文件的顶部附近。

参考:BMP File structure

原件:

Sprite sheet original to be read from

拷贝:

Copy of original written to a different filename

我使用调试器,并且已成功从包含对象复制数据。当我从文件中读取然后立即将其写回来时,它不应该失败:

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;
}

0 个答案:

没有答案