【问题标题】:Programmatically making an bmp image以编程方式制作 bmp 图像
【发布时间】:2014-08-17 15:50:34
【问题描述】:

我正在尝试创建自己的类来操作 BMP 图像..

我从这个简单的代码开始:

本维基百科link.中给出的一切都已完成

我有两个问题:

  1. 当我尝试打开图片时出现错误

    Premature end of file detected
    
  2. 我创建的实际文件超出了应有的文件大小两个字节。

代码如下:

#include <fstream>
#include <iostream>

using namespace std;

struct BMP_Header
{
    public :

    char id[2];
    unsigned int total_image_size;
    short int app_data1,app_data2;
    unsigned int offset;
};

struct DIB_Header 
{
    public :

    unsigned int dib_header_size;
    int image_width;
    int image_height;
    short int no_colour_planes;
    short int colour_depth;
    unsigned int compression_method;
    unsigned int raw_image_size;
    unsigned int horizontal_resolution;
    unsigned int vertical_resolution;
    unsigned int num_colours_palette;
    unsigned int imp_colours_used;
};


int main ()
{
    int index=0;

    BMP_Header bmp_header;
    DIB_Header dib_header;
    char pixel_array[16];

    bmp_header.total_image_size=70;
    bmp_header.offset=54;
    bmp_header.id[0]='B';
    bmp_header.id[1]='M';
    bmp_header.app_data1=0;
    bmp_header.app_data2=0;

    dib_header.dib_header_size=40;
    dib_header.image_width=2;
    dib_header.image_height=2;
    dib_header.colour_depth=24;
    dib_header.raw_image_size=16;
    dib_header.horizontal_resolution=2835;
    dib_header.vertical_resolution=2835;
    dib_header.no_colour_planes=1;
    dib_header.compression_method=0;
    dib_header.num_colours_palette=0;   
    dib_header.imp_colours_used=0;

    pixel_array[index++]=0;
    pixel_array[index++]=0;
    pixel_array[index++]=255;

    pixel_array[index++]=255;
    pixel_array[index++]=255;
    pixel_array[index++]=255;

    pixel_array[index++]=0;
    pixel_array[index++]=0;

    pixel_array[index++]=255;
    pixel_array[index++]=0;
    pixel_array[index++]=0;

    pixel_array[index++]=0;
    pixel_array[index++]=255;
    pixel_array[index++]=0;

    pixel_array[index++]=0;
    pixel_array[index++]=0;

// Image Made
    fstream file;
    file.open ("abc.bmp",ios::out | ios::binary);
    file.write ((char*)&bmp_header,sizeof (bmp_header));
    file.write ((char*)&dib_header,sizeof (dib_header));
    file.write ((char*)pixel_array,sizeof (pixel_array));

    file.close ();
return 0;
}

【问题讨论】:

  • 这段代码只将一个条目放入pixel_array 数组中。您可能希望在此处使用循环,以便覆盖数组中的每个index。此外,我强烈建议在这些原始数组上使用 c++ 标准库容器,例如 std::vectorstd::array
  • 我已经初始化了像素数组的所有元素......请看看......
  • 考虑使用struct 来明确BMP_HeaderDIB_Header 应该是POD。还可以考虑将成员初始化器直接放在成员声明上,这样您就可以删除自定义构造函数...接下来,您确定需要将这些强制转换为char*
  • 好的...会尝试这样做..btw 什么是 POD....?
  • 除此之外,您应该使用固定宽度类型,否则在另一个平台/编译器上,您可能会因为不同的大小类型而弄乱内存布局。

标签: c++ image bmp


【解决方案1】:

你不应该使用 C 结构来读/写像 BMP 头这样的东西,因为不能保证精确的二进制布局:特别是因为 fields alignment and padding。还有小字节序的问题,你必须意识到这一点。

一种解决方法是包含编译器编译指示/设置以禁用结构填充;更好的选择是显式编写每个字段。

添加:更糟糕的是,正如评论中所指出的,将 C 普通类型 (int...) 用于固定宽度字段是错误的;实际宽度将取决于平台。你应该使用int32_t 或类似的东西。

【讨论】:

  • 实际上,你可以(大部分)。不过,添加一些静态断言是个好主意...
  • 我在维基百科中阅读了这篇文章......所有必须以小端序输入的数据......所以这应该不是问题......所以你的意思是说我将每个字段分别写入文件....?
  • @Deduplicator :你说得对,我把“不能”改成了“不应该”
  • "这应该不是问题" 但是你的程序不能在不同的架构上运行,这(通常)很糟糕。 “所以你的意思是说我将每个字段分别写入文件?”是的
  • 填充的东西似乎是我发现的问题....将尝试分别编写每个字段
【解决方案2】:
struct DIB_Header 
{
    public :

    unsigned int dib_header_size;
    int image_width;
    int image_height;
    short int no_colour_planes;
    short int colour_depth;
    unsigned int compression_method;
    unsigned int raw_image_size;
    unsigned int horizontal_resolution;
    unsigned int vertical_resolution;
    unsigned int num_colours_palette;
    unsigned int imp_colours_used;


} __attribute__ ((packed));

这应该可以消除您报告的填充问题,前提是您的元素大小适合标题(我没有交叉检查)。在 C/C++ 中处理 bmp 没有问题。 YMMV 取决于编译器,因为每个编译器对打包属性的处理方式略有不同。但是,在这种情况下,您应该是鳍。

此外,请注意 BMP 文件在数据元素中期望的行填充。根据http://en.wikipedia.org/wiki/BMP_file_format 的格式指南:

代表位图像素的位被打包成行。规模 每行的四舍五入为 4 字节(一个 32 位 DWORD)的倍数 填充。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    • 2013-10-08
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 2017-02-26
    相关资源
    最近更新 更多