用c读取PNG文件

Posted

技术标签:

【中文标题】用c读取PNG文件【英文标题】:Read PNG file with c 【发布时间】:2022-01-02 23:38:22 【问题描述】:

我想在没有任何库的情况下用 C 读取 PNG 图像文件。从PNG (Portable Network Graphics) Specification Version 1.0 开始,任何PNG 文件都有一个区别于其他图像格式的签名。签名是图片的前 8 个字节。

上述 RFC 等一些来源提到签名为:

137 80 78 71 13 10 26 10(十进制)

或者像Not able to read IHDR chunk of a PNG file提到的签名为:

89 50 4E 47 0D 0A 1A 0A (ASCii)

所以,我写了一个简单的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_SIZE (8)

int main(int argc, char **argv)
    
    if(argc != 2) 
        printf("Usage: %s <png file>\n", argv[0]);
        return 1;
    
    
    char *buf = (char *)malloc(MAX_SIZE);
    
    if(!buf) 
        fprintf(stderr, "Couldn't allocate memory\n");
        return 1;
    
    
    FILE *f = fopen(argv[1], "r");
    
    if(!f) 
        perror("fopen");
        printf("Invalid file\n");
        
        free(buf);
        return 1;
    
    
    int size = fread(buf, 1, MAX_SIZE, f);

    printf(%c\n", buf[1]);
    printf(%c\n", buf[2]);
    printf(%c\n", buf[3]);
    printf(%c\n", buf[4]);
    printf(%c\n", buf[5]);
    printf(%c\n", buf[6]);
    printf(%c\n", buf[7]);
    printf(%c\n", buf[8]);
      fclose(f);
      free(buf);
    system("pause");
    
    return 0;

当我通过printf 打印字节时,输出与上面不同。 这是它显示的内容:

ëPNG→►v@,

谁能描述发生了什么,我可以做些什么来修改它?

【问题讨论】:

请说明您如何“通过printf 打印字节”以及您得到的结果,因为代码中没有显示。请注意,您显示的两个签名是相同的:十进制和十六进制。 你的代码不打印任何东西... 也使用fopen(argv[1], "rb"); 读取二进制文件 你在某个地方需要这个:for (int i = 0; i &lt; MAX_SIZE; i++) printf("%02x ", buf[i]); 重新编辑 a) 你的数组索引错误(应该是 [0][7])和 b) 它是一个二进制文件:不要输出字符而不是 printf(%d\n", buf[0]); 等。跨度> 【参考方案1】:

您需要使用正确的格式说明符打印每个值。在这里,我们需要数字表示,而不是字符表示。

来自documentationprintf

%c 写入单个字符 %d 将有符号整数转换为十进制表示 %x 将无符号整数转换为十六进制表示

%02X 使用 ABCDEF(而不是 abcdef)打印一个最小宽度为两个字符的十六进制,用前导零填充。

另见implicit conversions。

一个例子:

#include <stdio.h>

#define SIZE 8

int main(int argc, char **argv) 
    unsigned char magic[SIZE];
    FILE *file = fopen(argv[1], "rb");

    if (!file || fread(magic, 1, SIZE, file) != SIZE) 
        fprintf(stderr, "Failure to read file magic.\n");
        return 1;
    

    /* Decimal */
    for (size_t i = 0; i < SIZE; i++)
        printf("%d ", magic[i]);
    printf("\n");

    /* Hexadecimal */
    for (size_t i = 0; i < SIZE; i++)
        printf("%02X ", magic[i]);
    printf("\n");

    fclose(file);

输出:

137 80 78 71 13 10 26 10 
89 50 4E 47 0D 0A 1A 0A

【讨论】:

真的,我做了你的第一次打印但没有工作。我找不到为什么以及为什么“%02X”必须工作。还有什么解释吗? @NULL "没有工作" 不是有用的problem statement。无论如何,我已经用有关printf 格式说明符的更多信息更新了答案。 非常感谢。我想我学会了需要什么。

以上是关于用c读取PNG文件的主要内容,如果未能解决你的问题,请参考以下文章

用c语言读取24位位图bmp文件

android 已经root 怎么读取data

Android 读取文件头判断文件类型

java io 可以读取啥格式的文件

Appium自动化-----数据驱动读取外部Excel文件

如何从 PNG 文件中读取像素?