Skip to main content

Overview

The png_reader.h module provides functions for reading PNG files and extracting chunk information. It handles file opening, signature validation, chunk reading, and convenience functions for extracting specific chunk types.

Functions

png_open

FILE *png_open(const char *path);
Opens a PNG file and validates its signature. The PNG signature is the 8-byte sequence: 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A. If the signature is valid, the file pointer is returned positioned immediately after the signature, ready to read the first chunk.
path
const char *
required
File path to open
return
FILE *
Returns a FILE* pointer on success (positioned after signature), NULL on error (file not found, invalid signature, etc.)

Example

FILE *fp = png_open("image.png");
if (fp == NULL) {
    fprintf(stderr, "Failed to open PNG file\\n");
    return -1;
}

// File pointer is now positioned after the PNG signature
// Ready to read the first chunk
png_chunk_t chunk;
if (png_read_chunk(fp, &chunk) == 0) {
    printf("First chunk type: %s\\n", chunk.type);
    png_free_chunk(&chunk);
}

fclose(fp);

Notes

  • The PNG signature serves as a magic number to identify PNG files
  • The signature includes specific byte values that help detect file corruption
  • After successful opening, the file pointer is positioned at the start of the first chunk

png_read_chunk

int png_read_chunk(FILE *fp, png_chunk_t *out);
Reads the next PNG chunk from the file. This function reads the chunk length, type, data, and CRC. It validates the CRC by computing it over the chunk type and data, and comparing it to the stored CRC. If validation fails, the function frees any allocated memory and returns an error.
fp
FILE *
required
File pointer (must be positioned at start of chunk length field)
out
png_chunk_t *
required
Pointer to chunk structure where data will be written
return
int
Returns 0 on success, -1 on error (EOF, read error, CRC mismatch, memory allocation failure)

Example

FILE *fp = png_open("image.png");
if (fp == NULL) {
    return -1;
}

png_chunk_t chunk;
while (png_read_chunk(fp, &chunk) == 0) {
    printf("Chunk: %s, Length: %u, CRC: 0x%08X\\n", 
           chunk.type, chunk.length, chunk.crc);
    
    if (strcmp(chunk.type, "IEND") == 0) {
        png_free_chunk(&chunk);
        break;  // End of PNG file
    }
    
    png_free_chunk(&chunk);
}

fclose(fp);

Memory Management

The chunk data is dynamically allocated. The caller must free it using png_free_chunk().

Notes

  • All PNG chunks consist of 4 fields: Length (4 bytes), Type (4 bytes), Data (variable), CRC (4 bytes)
  • The CRC is computed over the chunk type and data (not the length)
  • Multi-byte integers are stored in big-endian format
  • The function automatically validates the CRC and returns an error if it doesn’t match

png_free_chunk

void png_free_chunk(png_chunk_t *chunk);
Frees memory allocated inside a chunk structure. This function safely handles NULL pointers and sets the data pointer to NULL after freeing.
chunk
png_chunk_t *
required
Pointer to chunk structure to free

Example

png_chunk_t chunk;
if (png_read_chunk(fp, &chunk) == 0) {
    // Use the chunk data...
    printf("Chunk type: %s\\n", chunk.type);
    
    // Free the chunk when done
    png_free_chunk(&chunk);
}

Notes

  • Only frees the data field of the chunk structure, not the structure itself
  • Safe to call multiple times on the same chunk
  • Safe to call with NULL chunk pointer

png_extract_ihdr

int png_extract_ihdr(FILE *fp, png_ihdr_t *out);
Extracts and parses the IHDR chunk from a PNG file. This is a convenience function that reads the first chunk, validates it is IHDR, parses it, and frees the chunk.
fp
FILE *
required
File pointer (must be positioned after PNG signature)
out
png_ihdr_t *
required
Pointer to IHDR structure where parsed data will be written
return
int
Returns 0 on success, -1 on error (chunk not found, invalid chunk, parse error)

Example

FILE *fp = png_open("image.png");
if (fp == NULL) {
    return -1;
}

png_ihdr_t ihdr;
if (png_extract_ihdr(fp, &ihdr) == 0) {
    printf("Image dimensions: %u x %u\\n", ihdr.width, ihdr.height);
    printf("Bit depth: %u\\n", ihdr.bit_depth);
    printf("Color type: %u\\n", ihdr.color_type);
    printf("Interlace: %s\\n", ihdr.interlace ? "Adam7" : "None");
}

fclose(fp);

Notes

  • The IHDR chunk must be the first chunk in a PNG file (after the signature)
  • This function automatically handles chunk reading, parsing, and cleanup
  • No need to call png_free_chunk() - handled internally

png_extract_plte

int png_extract_plte(FILE *fp, png_color_t **out_colors, size_t *out_count);
Extracts and parses the first PLTE chunk from a PNG file. This function reads chunks sequentially until it finds a PLTE chunk. It stops and returns an error if IDAT or IEND is encountered before PLTE (PLTE must come before IDAT according to the PNG specification).
fp
FILE *
required
File pointer (must be positioned after PNG signature)
out_colors
png_color_t **
required
Pointer to output pointer where allocated color array will be written
out_count
size_t *
required
Pointer to output variable where color count will be written
return
int
Returns 0 on success, -1 on error (PLTE not found, parse error, or IDAT/IEND encountered before PLTE)

Example

FILE *fp = png_open("palette_image.png");
if (fp == NULL) {
    return -1;
}

png_color_t *colors = NULL;
size_t count = 0;

if (png_extract_plte(fp, &colors, &count) == 0) {
    printf("Palette contains %zu colors:\\n", count);
    for (size_t i = 0; i < count; i++) {
        printf("  Color %zu: RGB(%u, %u, %u)\\n", 
               i, colors[i].r, colors[i].g, colors[i].b);
    }
    free(colors);  // Caller must free
}

fclose(fp);

Memory Management

The caller is responsible for freeing the allocated color array using free().

Notes

  • PLTE chunks are only present in color type 3 (palette) images
  • According to PNG specification, PLTE must appear before the first IDAT chunk
  • This function searches for PLTE by reading chunks sequentially
  • Returns error if IDAT or IEND is encountered before finding PLTE

png_summary

int png_summary(const char *filename, png_chunk_t **out_summary);
Reads all chunks from a PNG file and returns a summary array. This function reads chunks until IEND is encountered, storing only the chunk type, length, and CRC validity status (not the actual chunk data). This is useful for displaying chunk information without loading all chunk data into memory.
filename
const char *
required
Path to PNG file
out_summary
png_chunk_t **
required
Pointer to output pointer where allocated summary array will be written
return
int
Returns 0 on success, -1 on error

Example

png_chunk_t *summary = NULL;

if (png_summary("image.png", &summary) == 0) {
    int i = 0;
    while (summary[i].type[0] != '\\0') {
        printf("Chunk %d: Type=%s, Length=%u\\n", 
               i, summary[i].type, summary[i].length);
        i++;
    }
    free(summary);  // Caller must free
}

Memory Management

The caller is responsible for freeing the summary array using free(). Note that the summary chunks have data = NULL (data is not stored in the summary).

Notes

  • This function opens and closes the file internally
  • The summary array contains chunk metadata but not actual chunk data
  • Useful for displaying chunk information in -s (summary) mode
  • The array is terminated when IEND chunk is encountered

Build docs developers (and LLMs) love