使用C ++读取1,8或24位BMP文件

时间:2016-11-16 04:52:38

标签: c++ c++11 bmp

我想用c ++读写BMP图像,当我使用24位图像工作的类时,但是当我使用8位图像时不工作(画面无法打开文件) ,类似于1位图像。

我使用" Open"打开一个bmp文件。功能然后我使用"保存"保存这个(及其标题)功能(我只是复制它)。仅当文件是24位bmp文件时才打开结果文件。我没有创建任何标题,我使用Open函数从源代码复制标题

我使用的代码是(请参阅加载和保存功能):

#pragma pack(push, 1)
struct FILEHEADER
{
    WORD bfType;
    DWORD bfSize;
    WORD bfReserved1;
    WORD bfReserved2;
    DWORD bOffBits;
};
#pragma pack(pop)

#pragma pack(push, 1)
struct INFOHEADER
{
    DWORD biSize;
    LONG biWidth;
    LONG biHeight;
    WORD biPlanes;
    WORD biBitCount;
    DWORD biCompression;
    DWORD biSizeImage;
    LONG biXPelsPerMeter;
    LONG biYPelsPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
};
typedef INFOHEADER infoheader;
typedef FILEHEADER fileheader;

const WORD BMP_FORMAT = 0x4D42;

class Bitmap2
{
private:
    BYTE *data;
    infoheader h_info;
    fileheader h_file;

    WORD Type();
    DWORD OffBits();
    DWORD ImageSize();
    LONG Rows();
    LONG Cols();
    WORD BitsPerPixel();
    DWORD SizeInBytes();
public:
    void Load(char *filename);
    void Save(char *filename);
    void PrintHeaders();
};

void Bitmap2::Load(char *filename)
{
    std::ifstream file;

    file.open(filename, std::fstream::binary);
    if (!file.is_open())
        return;

    file.read((char *)&(h_file), sizeof(fileheader));

    //
    if (Type() != BMP_FORMAT)
    {
        file.close();
        return;
    }

    file.read((char *)&h_info, sizeof(infoheader));

    //
    file.seekg(OffBits());

    data = new BYTE[SizeInBytes()];

    if (!data)
    {
        delete data;
        file.close();
        return;
    }

    file.read((char *)data, SizeInBytes());

    if (data == NULL)
    {
        file.close();
        return;
    }

    file.close();
}

void Bitmap2::Save(char *filename)
{
    std::ofstream file;

    if (!data)
        return;

    file.open(filename, std::fstream::binary);
    if (!file.is_open())
        return;

    file.write((char *)&(h_file), sizeof(fileheader));

    //
    if (Type() != BMP_FORMAT)
    {
        file.close();
        return;
    }

    file.write((char *)&h_info, sizeof(infoheader));

    file.write((char *)data, SizeInBytes());

    file.close();
}

void Bitmap2::PrintHeaders()
{
    std::cout << "biSize = "            << h_info.biSize            << std::endl;
    std::cout << "biWidth = "           << h_info.biWidth           << std::endl;
    std::cout << "biHeight = "          << h_info.biHeight          << std::endl;
    std::cout << "biPlanes = "          << h_info.biPlanes          << std::endl;
    std::cout << "biBitCount = "        << h_info.biBitCount        << std::endl;
    std::cout << "biCompression = "     << h_info.biCompression     << std::endl;
    std::cout << "biSizeImage = "       << h_info.biSizeImage       << std::endl;
    std::cout << "biXPelsPerMeter = "   << h_info.biXPelsPerMeter   << std::endl;
    std::cout << "biYPelsPerMeter = "   << h_info.biYPelsPerMeter   << std::endl;
    std::cout << "biClrUsed = "         << h_info.biClrUsed         << std::endl;
    std::cout << "biClrImportant = "    << h_info.biClrImportant    << std::endl;
}

WORD Bitmap2::Type()
{
    return h_file.bfType;
}

DWORD Bitmap2::OffBits()
{
    return h_file.bOffBits;
}

DWORD Bitmap2::ImageSize()
{
    return h_info.biSizeImage;
}

LONG Bitmap2::Rows()
{
    return h_info.biHeight;
}

LONG Bitmap2::Cols()
{
    return h_info.biWidth;
}
WORD Bitmap2::BitsPerPixel()
{
    return h_info.biBitCount;
}
DWORD Bitmap2::SizeInBytes()
{
    return h_info.biSizeImage;
}

int main()
{
    Bitmap2 x;

    x.Load("test.bmp");
    x.Save("test_o.bmp");
    x.PrintHeaders();
    std::cout << "__________" << std::endl;
}

1 个答案:

答案 0 :(得分:2)

biSizeImage may be 0,在这种情况下,您必须计算实际尺寸。

另外,我不知道你在哪里阅读和编写color table(调色板)。由于1位和8位位图文件需要调色板而24位不需要,我怀疑这是你的根本问题。