【问题标题】:Reading from the header of a bmp file从 bmp 文件的头部读取
【发布时间】: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,然后memsetd 为0,其字段地址直接传递给fread。现在你创建了一个指针,但你没有分配内存来指向。
  • 您删除了包含原始代码的页面。没有它,问题是不完整的,我的回答没有意义。我建议进行编辑,将我昨天复制的部分插入您来源的答案中。

标签: c pointers struct bmp


【解决方案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);
    ...
}
  1. 您在 main 的堆栈(作为局部变量)中声明 Header,类型为 struct bmp_header通过这种方式,结构将在所有程序的生命周期内确定分配
  2. memset它到0
  3. 您将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() 内的freads 将写入随机位置,从而导致分段错误。


做什么

您需要将一个有效struct bmp_header 地址传递给read_bmp(),并且您有两个选项

  1. 您可以像以前一样在堆栈中分配Header,并通过&amp; 运算符将其地址传递给read_bmp()。这应该是您的第一次尝试,因为它与您的工作解决方案非常相似。
    struct bmp_header Header;

    read_bmp(BMPFile, &Header);
  1. 您可以将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 更好。
    猜你喜欢
    • 1970-01-01
    • 2015-05-15
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多