Home > Back-end >  Read PNG file with c
Read PNG file with c

Time:11-25

I want to read a PNG image file with C without any library. From PNG (Portable Network Graphics) Specification Version 1.0 any PNG file has a signature that distinguishes it from other image formats. The signature is the first 8 bytes of the image.

Some sources like the above RFC mentioned the signature as:

137 80 78 71 13 10 26 10 (decimal)

Or like Not able to read IHDR chunk of a PNG file mentioned the signature as:

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

So, I write a simple code:

#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;
}

When I print the bytes by printf, the output is not like the above. This is what it shows:

ëPNG→►v@,

Can someone describe what happened and what can I do to modify it?

CodePudding user response:

You need to print each value with the correct format specifier. Here we want numerical representations, not character ones.

From the documentation on printf:

  • %c writes a single character
  • %d converts a signed integer into decimal representation
  • %x converts an unsigned integer into hexadecimal representation

X prints a hexadecimal with a minimum width of two characters, padding with leading zeroes, using ABCDEF (instead of abcdef).

See also implicit conversions.

An example:

#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("X ", magic[i]);
    printf("\n");

    fclose(file);
}

Output:

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