c从BMP中获取数据

  • 本文关键字:获取 数据 BMP c bmp
  • 更新时间 :
  • 英文 :


我发现自己正在编写一个简单的程序来从bmp文件中提取数据。我刚刚开始,我正处于WTF的一个时刻。

当我运行程序并提供此图像时:http://www.hack4fun.org/h4f/sites/default/files/bindump/lena.bmp

我得到输出:

type: 19778
size: 12
res1: 0
res2: 54
offset: 2621440

实际图像大小为786486字节。为什么我的代码报告12个字节?

中指定的标头格式,http://en.wikipedia.org/wiki/BMP_file_format与我的BMP_FILE_HEADER结构匹配。那么,为什么它充满了错误的信息呢?

图像文件似乎没有损坏,其他图像的输出也同样错误。我错过了什么?

#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned short type;
unsigned int size;
unsigned short res1;
unsigned short res2;
unsigned int offset;
} BMP_FILE_HEADER;
int main (int args, char ** argv) {
char *file_name = argv[1];
FILE *fp = fopen(file_name, "rb");
BMP_FILE_HEADER file_header;
fread(&file_header, sizeof(BMP_FILE_HEADER), 1, fp);
if (file_header.type != 'MB') {
printf("ERROR: not a .bmp");
return 1;
}
printf("type: %insize: %inres1: %inres2: %inoffset: %in", file_header.type, file_header.size, file_header.res1, file_header.res2, file_header.offset);
fclose(fp);
return 0;
}

这里是十六进制的头:

0000000 42 4d 36 00 0c 00 00 00 00 00 36 00 00 00 28 00
0000020 00 00 00 02 00 00 00 02 00 00 01 00 18 00 00 00

长度字段是字节36 00 0c 00`,按intel顺序排列;作为32位值处理,它是0x000c0036或十进制786486(与保存的文件大小相匹配)。

可能您的C编译器正在将每个字段对齐到32位边界。启用包结构选项、杂注或指令。

我可以在您的代码中找到两个错误。

第一个错误:你必须将结构打包为1,所以每个类型大小都是它想要的大小,所以编译器不会对齐它,例如4字节对齐。因此,在您的代码short中,它不是2个字节,而是4个字节。诀窍是使用编译器指令来打包最近的结构:

#pragma pack(1)
typedef struct {
unsigned short type;
unsigned int size;
unsigned short res1;
unsigned short res2;
unsigned int offset;
} BMP_FILE_HEADER;

现在,它应该正确对齐。

另一个错误在这里:

if (file_header.type != 'MB')

您正在尝试检查short类型(2个字节)和char类型(使用'')(1个字节)。编译器可能会就此向您发出警告,单引号只包含1个1字节大小的字符是规范的。

为了解决这个问题,您可以将这2个字节划分为2个已知的1字节字符(MB),并将它们组合成一个word。例如:

if (file_header.type != (('M' << 8) | 'B'))

如果你看到这个表达式,就会发生这种情况:

'M'(在ASCII中为0x4D)向左移动8位,将产生0x4D00,现在您只需下一个字符添加到右零:0x4D00 | 0x42 = 0x4D42(其中0x42在ASCII中是'B')。这样想,你可以写:

if (file_header.type != 0x4D42)

那么您的代码应该可以工作了。

相关内容

  • 没有找到相关文章

最新更新