0

我需要从 bmp 中获取宽度和高度值,以便稍后在位图中从原始像素数据创建 gdk 像素图时将它们作为参数传递。我对 BMP 格式做了一些研究,文件头应该是这样的:

struct Fileheader
{
    unsigned short Type;          // signature - 'BM'
    unsigned  long Size;          // file size in bytes
    unsigned short Reserved1;     // 0
    unsigned short Reserved2;     // 0
    unsigned long  OffBits;       // offset to bitmap
    unsigned long  StructSize;    // size of this struct (40)
    unsigned long  Width;         // bmap width in pixels
    unsigned long  Height;        // bmap height in pixels
    unsigned short Planes;        // num planes - always 1
    unsigned short BitCount;      // bits per pixel
    unsigned long  Compression;   // compression flag
    unsigned long  SizeImage;     // image size in bytes
    long           XPelsPerMeter; // horz resolution
    long           YPelsPerMeter; // vert resolution
    unsigned long  ClrUsed;       // 0 -> color table size
    unsigned long  ClrImportant;  // important color count
    Fileheader()
    {
        Size=Width=Height=Planes=BitCount=Compression=SizeImage=XPelsPerMeter= YPelsPerMeter=ClrUsed=ClrImportant=Type=StructSize=Reserved1=Reserved2=OffBits=0;}
    };
}

在以标准方式将 blob 提取到 row[0] 后

Fileheader fh;
memcpy(&fh, row[0], sizeof(Fileheader));

cout << "width: " << fh.Width << ", height: " << fh.Height << endl;

即:宽度:65536,高度:5626121834492592128

有人看到这里有什么问题吗?顺便说一句,我在一个 64 位的 linux 盒子上。

4

3 回答 3

2

如果您打算以这种方式解析数据,这是不鼓励的,至少:

  • 使用正确的、独立于平台的类型。uint16_t而不是unsigned shortuint32_t而不是unsigned long
  • 使您的结构紧凑

它不会在任何地方都有效,但至少应该在x86and上有效x86_64

不鼓励这样做主要是因为它依赖于平台和编译器:

  • __attribute__ ((packed))是 gcc 扩展。其他编译器可能会以不同的方式处理它。
  • 在某些平台上,不可能紧密地打包一个结构。在其他方面,它们的工作速度会慢一些。
  • 它只适用于小端机器。
于 2012-06-28T16:17:33.073 回答
0

此结构中的unsigned long值应该只有 32 位。鉴于您所展示的价值,height您阅读的内容远不止于此。

于 2012-06-28T16:17:18.120 回答
0

gcc 64 位上的 long 类型是 64 位长,但原始结构使用 LONG,在 Windows 上定义为 32 位整数:

#pragma pack(push,1)
typedef struct tagBITMAPINFOHEADER {
  DWORD biSize; // use uint32_t instead
  LONG  biWidth;  // use int32_t instead
  LONG  biHeight; // use int32_t instead
  WORD  biPlanes;  // use uint16_t instead
  WORD  biBitCount;  // use uint16_t instead
  DWORD biCompression;  // use uint32_t instead
  DWORD biSizeImage;  // use uint32_t instead
  LONG  biXPelsPerMeter;  // use int32_t instead
  LONG  biYPelsPerMeter;  // use int32_t instead
  DWORD biClrUsed;  // use uint32_t instead
  DWORD biClrImportant;  // use uint32_t instead
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
#pragma pack(pop)

另外,请注意负高度值:这会识别第一个扫描行位于图像顶部的图像(您必须获得高度的 labs())正高度值识别第一个扫描行位于图像的图像在图像的底部。

于 2012-06-28T22:12:55.657 回答