在 cpp 中从 mysql blob 解析 BMP 文件
Parsing BMP-file from mysql blob in cpp
我需要从 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 提取到行中后[0]
Fileheader fh;
memcpy(&fh, row[0], sizeof(Fileheader));
在以下情况下只会给出乱码值
cout << "width: " << fh.Width << ", height: " << fh.Height << endl;
即:宽度:65536,高度:5626121834492592128
有人看到这里出了什么问题吗?顺便说一句,我在 64 位 Linux 盒子上。
如果你打算以这种方式解析数据,这是不鼓励的,至少:
- 使用正确的、与平台无关的类型。
uint16_t
而不是unsigned short
,uint32_t
而不是unsigned long
- 让你的结构包装起来。
它不会在任何地方都有效,但至少应该适用于x86
和x86_64
.
鼓励这样做主要是因为它依赖于平台和编译器:
-
__attribute__ ((packed))
是 gcc 扩展。其他编译器可能会以不同的方式处理它。 - 在某些平台上,不可能紧密包装结构。在其他情况下,他们的工作速度会慢一些。
- 它只能在小端机器上运行。
此结构中的unsigned long
值应仅为 32 位。考虑到你显示的值height
你阅读的远不止于此。
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()正高度值标识第一个扫描行位于图像底部的图像。
相关文章:
- 继承函数的重载解析
- 基类中的函数名称解析
- 提升精神:解析布尔表达式并简化为规范范式
- 我正在使用嵌套的while循环来解析具有多行的文本文件,但由于某种原因,它只通过第一行,我不知道为什么
- gcc和c++17的过载解析失败
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 构造函数和转换运算符之间的重载解析
- 未解析的外部符号_MsiLocateComponentW@12.
- '尝试解析可变参数模板时无法推断出'T的模板参数
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- 如何在 cpp 中解析此文件?
- 在C++中使用 gRPC 时未解析的外部符号
- IDE (CLion) 无法解析C++模板类型
- 配置文件解析器仅返回以前的值
- 增强精神解析器规则以检测语句中的特殊结尾
- 将向量解析<string>为字符串
- 为什么 BMP 图像上的 imwrite 会卡住/不返回?
- 使用 jsoncpp 解析 json 数组字符串
- 在 cpp 中从 mysql blob 解析 BMP 文件