【问题标题】:Getting incorrect values from a bmp file [duplicate]从 bmp 文件中获取不正确的值 [重复]
【发布时间】:2012-09-17 04:32:44
【问题描述】:

可能重复:
How to read a binary file in c? (video, images, or text)

我正在尝试使用 C 程序读取 bmp file 的内容。我能够阅读内容,但读取的值与我的预期相矛盾。我的代码是:


FILE *fp=NULL;
fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","r");

if(fp!=NULL)
{
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));

    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
    printf("%c\n",fgetc(fp));
}

else
    printf("Error reading the file");

我在这里只是逐字节阅读,只是为了理解。前两个字节读取BM,这是正确的。接下来的四个字节读取*t。预期值为 40。请参阅format。有人可以解释一下正在发生的事情吗?如果我需要执行一些转换,我该如何获得40 的值。

【问题讨论】:

  • 你得到了什么……?如果您的期望值是正确的,我会期望 BM(*** 或类似的东西。
  • 字节 3 到 6 给出文件大小,“所有整数值都以小端格式存储(即最低有效字节在前)。”你能把字节 3-6 的值打印为数字,并检查它是否与文件大小匹配?
  • 现在从这里,我如何获取文件大小。如何对四个字节进行缩放以获得单个整数值?

标签: c image image-processing


【解决方案1】:

我相信你的问题是你打开文件的方式:

fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","r"); 

"r" 是 ASCII 读取,你想用二进制打开它:

fp=fopen("C:\\Users\\Saurabh\\Pictures\\nice.bmp","rb"); 

编辑: fgetc() 返回一个 int,所以我尝试使用一个 int 来获取返回值,你也想看到 hex 的结果,所以我们使用一个 hex 输出格式:

FILE *readf;
int i;
unsigned int size = 0;

//Open file
readf = fopen("blackbuck.bmp", "rb");

i = fgetc(readf);
printf("%#x\n",i);   // 0x42
i = fgetc(readf);
printf("%#x\n",i);   // 0x4D
for(i=0; i<3; i++)
    size |= fgetc(readf) << (i*8); // 0xC0036

此更新将前两个值作为 0x42 0x4D,然后连接接下来的 3 个字节,给出位图的大小(0xC0036 = 786486 字节)

我使用这张图片进行测试:http://people.sc.fsu.edu/~jburkardt/data/bmp/blackbuck.bmp

您可以看到结果具有正确的 bmp 标头字节码 0x42 0x4d the header field used to identify the BMP &amp; DIB file is 0x42 0x4D in hexadecimal, same as BM in ASCII

【讨论】:

  • 这通常仅在输入中的行尾(\n\r)中通常存在字符时才有意义。我不希望它这么早地破坏输入。
  • 即使使用“rb”,我得到相同的输出..
  • @CSSS - 试试我刚刚发布的代码/图片组合,如果它仍然不适合你,请告诉我。
  • @Mike:我试过你的代码,它以十六进制打印得很好。但是如何以十进制打印呢?
  • @CSSS - 只需更改格式说明符printf("%d\n",i);。我只是想,因为您正在查看格式的页面是以十六进制报告值,这对您来说会更容易。
【解决方案2】:

虽然我同意 Mike 的观点,即您应该以二进制模式阅读此文件,但它不应该给您带来问题。最终会,但前 6 个字符不应中断,除非任何大小的字节包含 10 或 13。

为了读取 int,您可以执行类似的操作

int result;
fread(fp, sizeof (int), 1, &result);

但请注意,这是不可移植的。 (它至少假设 32 位整数和本机字节顺序。BMP,由于它们的起源,是小端的......如果你只是在一个大的 -字节序机器。)

另一种方式:

unsigned long result = 0;
for (int i = 0; i < 4; ++i) {
     result |= (unsigned long) fgetc(fp) << (i * 8);
}

这至少应该总是读取正确的字节数并考虑字节序。 unsigned long 的长度足以容纳任何 32 位数字,而 int(即使是无符号的)则不能保证。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-21
    • 2020-01-09
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-18
    • 2015-04-23
    相关资源
    最近更新 更多