c++ - 使用 C++ 读取 1、8 或 24 位 BMP 文件

标签 c++ c++11 bmp

我想使用 C++ 读写 BMP 图像,当我将我的类与 24 位图像一起使用时,但当我使用 8 位图像时不起作用(绘画无法打开文件),类似于 1位图。

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

我使用的代码是(参见加载和保存函数):

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

最佳答案

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

此外,我看不到您在哪里读写 color table (调色板)。由于 1 位和 8 位位图文件需要调色板,而 24 位位图文件不需要,我怀疑这是您的根本问题。

关于c++ - 使用 C++ 读取 1、8 或 24 位 BMP 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40624303/

相关文章:

c++ - boost::filesystem3::detail::dir_itr_imp 在 boost::shared_ptr 解引用中的含义

c++ - QSet 中的重复项

C++11 operator""with double parameter

c++ - 使用 C++11 可变参数模板初始化 Enum To String Map

c++ - 在 lambda 函数中捕获和传递参数之间的区别

c# - 在 C# 中将所有内容转换为 JPG

java - 在 Google App Engine 中使用 Java,如何从 int r、g、b 值的数组中制作 BMP 图像?

c++ - v3 make_iterator_range 要求

java - 安卓 : save a Bitmap to bmp file format

类字符串访问冲突的 C++ At() 函数