PNG
PNG (Portable Network Graphics) wurde 1996 als patentfreier Ersatz fΓΌr GIF entworfen. Eine PNG-Datei beginnt immer mit einer 8 Byte langen Signatur und besteht danach aus einer Folge von βChunksβ.
Jeder Chunk hat denselben Aufbau: 4 Byte LΓ€nge, 4 Byte Typ, die Nutzdaten und eine 4 Byte CRC-PrΓΌfsumme. Genau drei Chunk-Typen sind Pflicht: IHDR (Kopf), IDAT (Bilddaten) und IEND (Ende).
Die Bilddaten in IDAT werden mit DEFLATE (zlib) verlustfrei komprimiert β vorher wird jede Bildzeile durch einen βFilterβ vorhergesagt, um die Kompression zu verbessern.
89 50 4E 47 0D 0A 1A 0A Β βΒ \x89 P N G \r \n \x1a \nπ§© Aufbau der Datei
So liegen die Bestandteile einer PNG-Datei nacheinander im Speicher.
π Ablaufdiagramm (ASCII)
Schematischer Gesamtaufbau auf einen Blick.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β 89 50 4E 47 0D 0A 1A 0A β 8-Byte Signatur β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β βββ Chunk-Schema (fΓΌr jeden Chunk identisch) ββββββββββββββ β β β [LΓ€nge 4B] [Typ 4B] [Daten β¦] [CRC-32 4B] β β β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€ β IHDR β Breite/HΓΆhe/Bittiefe/Farbtyp β β gAMA β optional: Gamma β β PLTE β optional: Farbpalette (bei Farbtyp 3 Pflicht) β β IDAT β zlib( filter(zeile_0) + filter(zeile_1) + β¦ ) β β IDAT β (kann fortgesetzt werden) β β IEND β Ende β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Tabellen & Referenz
Pflicht- & wichtige Chunks
| Typ | Pflicht | Bedeutung |
|---|---|---|
| IHDR | Ja | Bildkopf: Abmessungen & Farbcodierung |
| PLTE | Bedingt | Farbpalette (Pflicht bei Farbtyp 3) |
| IDAT | Ja | Komprimierte Bilddaten |
| IEND | Ja | Dateiende-Markierung |
| tRNS | Nein | Transparenz fΓΌr Paletten/Graustufen |
| gAMA / sRGB | Nein | Farb-/Gamma-Verwaltung |
| tEXt / zTXt | Nein | Textuelle Metadaten |
Farbtypen im IHDR
| Wert | Farbtyp | KanΓ€le |
|---|---|---|
| 0 | Graustufen | 1 (G) |
| 2 | Truecolor (RGB) | 3 (R,G,B) |
| 3 | Palette (indexiert) | 1 (Index β PLTE) |
| 4 | Graustufen + Alpha | 2 (G,A) |
| 6 | Truecolor + Alpha | 4 (R,G,B,A) |
β¨οΈ C-Strukturen & Auslese-Code
Einfache C-Strukturen, die exakt dem Byte-Layout entsprechen, plus Beispielcode zum Einlesen.
#include <stdint.h>
/* Die ersten 8 Bytes jeder PNG-Datei */
static const uint8_t PNG_SIGNATURE[8] = {
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
};
/* Jeder Chunk hat exakt diesen Rahmen (Big-Endian!) */
typedef struct {
uint32_t length; /* LΓ€nge des data-Feldes in Byte */
char type[4]; /* z. B. "IHDR", "IDAT", "IEND" */
/* uint8_t data[length]; -- folgt direkt, variable LΓ€nge */
uint32_t crc; /* CRC-32 ΓΌber type[] + data[] */
} png_chunk_header_t;βΉοΈ Achtung: Alle Mehrbyte-Zahlen in PNG sind Big-Endian (Netzwerk-Byteorder).
#pragma pack(push, 1) /* keine Ausrichtungs-LΓΌcken */
typedef struct {
uint32_t width; /* Bildbreite (Big-Endian) */
uint32_t height; /* BildhΓΆhe (Big-Endian) */
uint8_t bit_depth; /* 1,2,4,8 oder 16 Bit/Sample */
uint8_t color_type; /* 0,2,3,4,6 (siehe Tabelle) */
uint8_t compression; /* immer 0 = DEFLATE */
uint8_t filter_method; /* immer 0 = adaptive Filter */
uint8_t interlace; /* 0 = keins, 1 = Adam7 */
} png_ihdr_t;
#pragma pack(pop)#include <stdio.h>
#include <string.h>
#include <arpa/inet.h> /* ntohl: Big-Endian -> Host */
int read_png_header(FILE *f, png_ihdr_t *out) {
uint8_t sig[8];
if (fread(sig, 1, 8, f) != 8) return -1;
if (memcmp(sig, PNG_SIGNATURE, 8) != 0) return -1; /* keine PNG */
png_chunk_header_t ch;
fread(&ch.length, 4, 1, f);
fread(ch.type, 1, 4, f);
if (memcmp(ch.type, "IHDR", 4) != 0) return -1; /* IHDR fehlt */
fread(out, 1, 13, f);
out->width = ntohl(out->width); /* Byteorder korrigieren */
out->height = ntohl(out->height);
printf("PNG %ux%u, %d Bit, Farbtyp %d\n",
out->width, out->height, out->bit_depth, out->color_type);
return 0;
}βΉοΈ Big-Endian-Werte mΓΌssen auf Little-Endian-Maschinen (x86) getauscht werden.