从 bmp 文件的头部读取
Posted
技术标签:
【中文标题】从 bmp 文件的头部读取【英文标题】:Reading from the header of a bmp file 【发布时间】:2020-04-12 20:55:19 【问题描述】:我正在编写一个程序来读取 bmp 标头。我编写了一些在main
中工作的代码。如何将此代码实现为自己的功能,然后将其实现到 main 上?
这是整个代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdin.h>
struct bmp_header
uint16_t type;
uint32_t size;
uint16_t reserved1;
uint16_t reserved2;
uint32_t offset;
uint32_t dib_size;
uint32_t width;
uint32_t height;
uint16_t planes;
uint16_t bpp;
uint32_t compression;
uint32_t image_size;
uint32_t x_ppm;
uint32_t y_ppm;
uint32_t num_colors;
uint32_t important_colors;
;
void read_bmp(FILE *BMPFile,struct bmp_header* Header)
fread(&(Header->type), 2, 1, BMPFile);
fread(&(Header->size),4,1,BMPFile);
fread(&(Header->reserved1),2,1,BMPFile);
fread(&(Header->reserverd2),2,1,BMPFile);
fread(&(Header->offset),4,1,BMPFile);
fread(&(Header->dib_size),4,1,BMPFile);
fread(&(Header->width),4,1,BMPFile);
fread(&(Header->height),4,1,BMPFile);
fread(&(Header->planes),2,1,BMPFile);
fread(&(Header->bpp),2,1,BMPFile);
fread(&(Header->compression),4,1,BMPFile);
fread(&(Header->image_size),4,1,BMPFile);
fread(&(Header->x_ppm),4,1,BMPFile);
fread(&(Header->y_pp),4,1,BMPFile);
fread(&(Header->num_colors),4,1,BMPFile);
fread(&(Header->important_colors),4,1,BMPFile);
int main()
FILE *BMPFile = fopen("image.bmp","rb");
if(BMPFile == NULL)
return;
struct bmp_header* Header;
read_bmp(BMPFile,Header);
fclose(BMPFile);
return 0;
在main
中具有所有读取操作的程序版本的相关部分,按预期工作,报告如下
int main( void )
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
return 0;
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
fread(&Header.size),4,1,BMPFile);
fread(&Header.reserved1),2,1,BMPFile);
fread(&Header.reserverd2),2,1,BMPFile);
fread(&Header.offset),4,1,BMPFile);
fread(&Header.dib_size),4,1,BMPFile);
fread(&Header.width),4,1,BMPFile);
fread(&Header.height),4,1,BMPFile);
fread(&Header.planes),2,1,BMPFile);
fread(&Header.bpp),2,1,BMPFile);
fread(&Header.compression),4,1,BMPFile);
fread(&Header.image_size),4,1,BMPFile);
fread(&Header.x_ppm),4,1,BMPFile);
fread(&Header.y_pp),4,1,BMPFile);
fread(&Header.num_colors),4,1,BMPFile);
fread(&Header.important_colors),4,1,BMPFile);
/* Header fields print section */
/* ... */
【问题讨论】:
我是否正确理解您有工作代码,并且您希望您的工作代码看起来更像您发布的(但工作)?如果是这样,您可以发布工作代码吗?编辑: struct bmp_header 是一个指针,但它从来没有给任何内存使用。所以这是一个问题。 在堆栈中定义了工作函数bmp_header
,然后memset
d 为0,其字段地址直接传递给fread。现在你创建了一个指针,但你没有分配内存来指向。
您删除了包含原始代码的页面。没有它,问题是不完整的,我的回答没有意义。我建议进行编辑,将我昨天复制的部分插入您来源的答案中。
【参考方案1】:
每当工作代码停止工作时,关注两个代码版本之间的变化是很有用的。那么,为什么您的原始代码可以正常工作?它看起来像这样:
int main( void )
FILE *BMPFile = fopen ("lenna.bmp", "rb");
if (BMPFile == NULL)
return 0;
struct bmp_header Header;
memset(&Header, 0, sizeof(Header));
fread(&Header.type, 2, 1, BMPFile);
...
-
您在 main 的堆栈(作为局部变量)中声明
Header
,类型为 struct bmp_header
。 通过这种方式,结构将在所有程序的生命周期内确定分配。
你memset
它到0
您将Header
的字段地址直接传递给fread
在新版本的程序中,你有一个函数定义为
void read_bmp(FILE *BMPFile,struct bmp_header* Header);
所以你需要一个指向struct bmp_header
的指针来传递给它。因此,您声明
struct bmp_header* 标头;
并致电read_bmp(BMPFile,Header);
。
与工作版本有什么不同?嗯,指针!向编译器声明一个指针,它包含一个地址,在本例中是read_bmp()
所需的结构的地址。
但是你从不告诉编译器地址是什么,这样read_bmp()
内的fread
s 将写入随机位置,从而导致分段错误。
做什么
您需要将一个有效struct bmp_header
地址传递给read_bmp()
,并且您有两个选项。
-
您可以像以前一样在堆栈中分配
Header
,并通过&
运算符将其地址传递给read_bmp()
。这应该是您的第一次尝试,因为它与您的工作解决方案非常相似。
struct bmp_header Header;
read_bmp(BMPFile, &Header);
-
您可以将
Header
声明为指针,但您需要通过malloc
动态分配其内存:
struct bmp_header * Header = malloc(sizeof(struct bmp_header));
read_bmp(BMPFile, Header);
【讨论】:
【参考方案2】:你必须创建 struct bmp_header* 类型的函数。接下来在您的函数中创建 struct bmp_header 指针并为返回的引用分配内存(标头大小 == 54B)。
【讨论】:
虽然文件使用了 54 字节的头部,但struct bmp_header
由于填充,不一定包含 54 字节。使用sizeof(struct bmp_header)
比使用硬编码 54 更好。以上是关于从 bmp 文件的头部读取的主要内容,如果未能解决你的问题,请参考以下文章