GIF

GIF

Graphics Interchange Format — Palette, LZW-Kompression & Animation

GIF (Graphics Interchange Format) wurde 1987 von CompuServe entwickelt. Eine GIF-Datei beginnt mit einem 6 Byte langen Header („GIF87a“ oder „GIF89a“), gefolgt vom Logical Screen Descriptor und einer optionalen globalen Farbtabelle.

GIF ist palettenbasiert: höchstens 256 Farben pro Tabelle. Jedes Bild verweist über einen Index auf diese Palette. Das macht GIF ideal für Grafiken mit wenigen Farben, aber ungeeignet für Fotos.

Die Bilddaten werden mit LZW verlustfrei komprimiert. Mit GIF89a kamen Erweiterungsblöcke hinzu — vor allem die Graphic Control Extension, die Transparenz und Animationen (mehrere Bilder + Verzögerungen) ermöglicht.

Magic Number: 47 49 46 38 39 61  →  G I F 8 9 a

🧩 Aufbau der Datei

So liegen die Bestandteile einer GIF-Datei nacheinander im Speicher.

SignaturKopf/StrukturMetadatenBilddatenEnde
Header
6 Byte
47 49 46 38 39 61
Signatur 'GIF' + Version '87a' oder '89a'.
Logical Screen Descriptor
7 Byte
<W><H><packed><bg><ar>
Leinwandbreite/-höhe, Packed-Feld (globale Tabelle?, Farbtiefe), Hintergrundfarbe.
Global Color Table
0–768 Byte
R G B R G B …
Optionale Palette: bis zu 256 Einträge à 3 Byte (RGB).
Graphic Control Extension
8 Byte
21 F9 04 …
Nur GIF89a: Transparenzfarbe, Verzögerung (1/100 s), Entsorgungsmethode.
Image Descriptor + Daten
variabel
2C … <LZW-Sub-Blocks>
Bildposition/-größe, optionale lokale Tabelle, dann LZW-komprimierte Indizes.
Trailer
1 Byte
3B
Einzelnes Byte 0x3B markiert das Dateiende.

📐 Ablaufdiagramm (ASCII)

Schematischer Gesamtaufbau auf einen Blick.

┌──────────────────────────────────────────────────────────────┐
│ 'G''I''F''8''9''a'                     ← Header (6 Byte)       │
├──────────────────────────────────────────────────────────────┤
│ Logical Screen Descriptor (7 Byte)                            │
│   width(2) height(2) packed(1) bgColor(1) aspect(1)           │
│   packed-Bit 7 = globale Tabelle vorhanden                    │
├──────────────────────────────────────────────────────────────┤
│ [ Global Color Table ]  2^(N+1) Einträge × RGB                │
├──────────────────────────────────────────────────────────────┤
│ Block-Schleife (bis Trailer):                                 │
│   21 F9 …  Graphic Control Extension (optional, GIF89a)       │
│   2C …     Image Descriptor                                   │
│            └─ LZW-Min-Code + [len][daten]…[len][daten] 00     │
│   21 FF …  Application Extension (z. B. NETSCAPE2.0 = Loop)   │
├──────────────────────────────────────────────────────────────┤
│ 3B                                     ← Trailer (Ende)        │
└──────────────────────────────────────────────────────────────┘

📊 Tabellen & Referenz

Blocktypen (Introducer-Byte)

ByteBlockBedeutung
2CImage DescriptorLeitet ein Einzelbild ein
21 F9Graphic Control Ext.Transparenz, Verzögerung, Disposal
21 FEComment ExtensionTextkommentar
21 01Plain Text Ext.Text als Grafik (selten)
21 FFApplication Ext.z. B. NETSCAPE2.0 (Loop-Anzahl)
3BTrailerDateiende

Packed-Feld im Screen Descriptor

Bit(s)FeldBedeutung
7Global Color Table Flag1 = globale Palette folgt
4–6Color ResolutionBittiefe der Quellfarben − 1
3Sort FlagPalette nach Häufigkeit sortiert
0–2Size of GCTTabellengröße = 2^(Wert+1)

⌨️ C-Strukturen & Auslese-Code

Einfache C-Strukturen, die exakt dem Byte-Layout entsprechen, plus Beispielcode zum Einlesen.

Header & Logical Screen Descriptor · c
#include <stdint.h>

#pragma pack(push, 1)
typedef struct {
    char    signature[3];   /* 'G','I','F'                    */
    char    version[3];     /* '8','7','a' oder '8','9','a'    */
} gif_header_t;

typedef struct {
    uint16_t width;         /* Leinwandbreite  (Little-Endian)*/
    uint16_t height;        /* Leinwandhöhe    (Little-Endian)*/
    uint8_t  packed;        /* siehe Bitfeld unten            */
    uint8_t  bg_color_index;/* Index in globale Palette       */
    uint8_t  pixel_aspect;  /* Seitenverhältnis (meist 0)     */
} gif_lsd_t;
#pragma pack(pop)

/* Bitmasken für das packed-Feld */
#define GIF_HAS_GCT(p)   (((p) & 0x80) != 0)
#define GIF_GCT_SIZE(p)  (1 << (((p) & 0x07) + 1))  /* Farbanzahl */

ℹ️ Wichtig: GIF speichert Mehrbyte-Zahlen Little-Endian (anders als PNG/JPEG!).

Image Descriptor & Graphic Control Extension · c
#pragma pack(push, 1)
typedef struct {
    uint8_t  separator;     /* immer 0x2C                     */
    uint16_t left, top;     /* Position auf der Leinwand      */
    uint16_t width, height; /* Bildgröße                      */
    uint8_t  packed;        /* lokale Palette?, Interlace     */
} gif_image_descriptor_t;

typedef struct {
    uint8_t  introducer;    /* 0x21 Extension                 */
    uint8_t  label;         /* 0xF9 Graphic Control           */
    uint8_t  block_size;    /* immer 4                        */
    uint8_t  packed;        /* Disposal + Transparenz-Flag    */
    uint16_t delay_cs;      /* Verzögerung in 1/100 Sekunden  */
    uint8_t  transp_index;  /* transparenter Paletten-Index   */
    uint8_t  terminator;    /* 0x00                           */
} gif_gce_t;
#pragma pack(pop)
GIF-Header einlesen & validieren · c
#include <stdio.h>
#include <string.h>

int read_gif_header(FILE *f, gif_lsd_t *lsd) {
    gif_header_t h;
    if (fread(&h, 1, sizeof h, f) != sizeof h) return -1;
    if (memcmp(h.signature, "GIF", 3) != 0) return -1;     /* kein GIF */

    int v89 = (memcmp(h.version, "89a", 3) == 0);
    int v87 = (memcmp(h.version, "87a", 3) == 0);
    if (!v89 && !v87) return -1;                            /* unbekannt */

    fread(lsd, 1, sizeof *lsd, f);
    printf("GIF%.3s  %ux%u  Palette: %s (%d Farben)\n",
           h.version, lsd->width, lsd->height,
           GIF_HAS_GCT(lsd->packed) ? "global" : "keine",
           GIF_GCT_SIZE(lsd->packed));
    return 0;
}

ℹ️ Little-Endian-Felder können auf x86 direkt gelesen werden, auf Big-Endian-CPUs nicht.

🗜️ Kompression

GIF komprimiert die Paletten-Indizes mit LZW (Lempel-Ziv-Welch) — verlustfrei. LZW baut während des Lesens ein wachsendes Wörterbuch aus bereits gesehenen Index-Folgen auf und ersetzt Wiederholungen durch kurze Codes. Die komprimierten Daten liegen in „Sub-Blocks“ (je max. 255 Byte, Länge vorangestellt), abgeschlossen durch ein Null-Byte.

💡 Wissenswert

✨Die Aussprache ist bis heute umstritten — der Erfinder Steve Wilhite sagte „Jif“ (wie das Erdnussbutter-Logo).
✨Animationen sind technisch nur eine Folge von Image-Blöcken mit Graphic Control Extensions dazwischen.
✨Endlosschleifen entstehen durch die NETSCAPE2.0-Application-Extension — sie steht nicht im Original-Standard.
← Zurück zur Übersicht