首页 > 解决方案 > 无法读取 C 中图像的所有字节

问题描述

我想编写一个 C 程序来读取 png 的像素值,而无需任何外部库(不包括用于解压缩的 zlib)。我研究了png 的Wikipedia 页面,并看到了一些相同的python 教程

目前,我正在尝试将 png 的字节读入一个数组。目前,我正在使用这张图片,其中有一些黑点,我将使用这些黑点来验证最终数组中的像素坐标。但是,在打印检索到的数组时,我只得到 png 的前四个字节:

ëPNG

当我询问数组的 sizeof() 并返回 4 时,我验证它实际上不是打印问题的字节。我不明白这段代码有什么问题:

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

int main(int argc, char* argv[])
{
    FILE *fp = fopen(argv[1], "rb");
    unsigned char* file_data;
    fseek(fp, 0, SEEK_END);
    long int length = ftell(fp);
    rewind(fp);

    file_data = (char *)malloc((length+1)*sizeof(char));
    fread(file_data, length, 1, fp);
    printf("%s\n", file_data);
    printf("%d\n", sizeof(file_data)/sizeof(file_data[0]));

    fclose(fp);
    return 0;
}

标签: arrayscimagefilebinary

解决方案


WhozCraig 是对的。所有字节都在那里,但您正试图将其视为一个字符串,在 C 中它由一个空字节 ( '\0') 终止。在我的系统和 LLDB 上的 PNG 上运行此代码显示file_data实际上加载了超过四个字节:

(lldb) expr file_data
(unsigned char *) $0 = 0x0000000100205e40 "\x89PNG\r\n\x1a\n"

但是下一个字节是在十六进制编辑器中显示的空字节(选定的字节是打印的):

十六进制编辑器

所以“字符串”就停在那里。

将第 14 行更改为以下内容:

for (int i = 0; i < length; i++) {
    printf("%x", file_data[i]);
}
printf("%s\n", "");

显示所有字节:

89504e47da1aa000d494... [truncated]

您应该知道sizeof的另一件事是,它不适用于在编译时大小未知的数组(VLA 有少数例外,此处均不适用)。

printf("%d\n", sizeof(file_data)/sizeof(file_data[0]));

在这一行中,sizeof(file_data)最终查询 的类型的大小file_data,即unsigned char *。在我和任何 64 位系统上,这会解析为8(您可能在 32 位系统上,在这种情况下它会解析为4)。sizeof(file_data[0])查询数组第一个元素的大小,类型为unsigned char. ( unsigned)char被定义为始终1sizeof调用中计算结果,因此整个表达式解析为:

printf("%d\n", 8 / 1);
            // 4 on your system

这就是您尝试查找数组大小的原因4


推荐阅读