GIF
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.
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.
π 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)
| Byte | Block | Bedeutung |
|---|---|---|
| 2C | Image Descriptor | Leitet ein Einzelbild ein |
| 21 F9 | Graphic Control Ext. | Transparenz, VerzΓΆgerung, Disposal |
| 21 FE | Comment Extension | Textkommentar |
| 21 01 | Plain Text Ext. | Text als Grafik (selten) |
| 21 FF | Application Ext. | z. B. NETSCAPE2.0 (Loop-Anzahl) |
| 3B | Trailer | Dateiende |
Packed-Feld im Screen Descriptor
| Bit(s) | Feld | Bedeutung |
|---|---|---|
| 7 | Global Color Table Flag | 1 = globale Palette folgt |
| 4β6 | Color Resolution | Bittiefe der Quellfarben β 1 |
| 3 | Sort Flag | Palette nach HΓ€ufigkeit sortiert |
| 0β2 | Size of GCT | TabellengrΓΆΓe = 2^(Wert+1) |
β¨οΈ C-Strukturen & Auslese-Code
Einfache C-Strukturen, die exakt dem Byte-Layout entsprechen, plus Beispielcode zum Einlesen.
#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!).
#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)#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.