GIF
GIF je velmi populární formát pro sdílení animací. GIF
animace
se skládá z jednoho nebo více tzv. snímků (frames), které mají určenou délku, po kterou se mají
zobrazit. Při přehrání animace se pak jednotlivé snímky zobrazují postupně jeden za druhým, což
vytváří dojem animace.
Pořád se jedná o relativně jednoduchý formát, nicméně je už trošku složitější než např. TGA, protože používá kompresi a pixely nejsou uloženy v souboru přímo, místo toho je každý pixel reprezentován indexem do tabulky (palety) předpřipravených barev.
Pro vytvoření GIF
animace tak použijeme kód, který už pro nás připravil někdo jiný. Konkrétně se
bude jednat o knihovnu gifenc
1. Stáhněte si soubory
gifenc.c
a gifenc.h
a použijte je při překladu
svého programu.
1I když jsme se předtím bavili o tom, že sdílet knihovny ve formě zdrojových kódů není úplně běžné, tato knihovna je velmi malá a jednoduchá a zároveň je open-source, takže zkopírovat její zdrojové kódy do našeho programu je asi nejjednodušší způsob, jak ji použít.
Vytvoření GIF
animace
Pro práci s GIF
souborem si nejprve musíme nadefinovat tzv. paletu (palette). Paleta není
nic jiného než pole barev, které můžeme v naší animaci používat. Jednotlivým pixelům každého snímku
pak pouze řekneme, jaký index z této palety se má použít pro jejich vykreslení. Například tato paleta
definuje čtyři barvy:
typedef unsigned char byte;
byte palette[] = {
0x00, 0x00, 0x00, /* 0 -> černá (R=0, G=0, B=0) */
0xFF, 0x00, 0x00, /* 1 -> červená (R=255, G=0, B=0) */
0x00, 0xFF, 0x00, /* 2 -> zelená (R=0, G=255, B=0) */
0x00, 0x00, 0xFF, /* 3 -> modrá (R=0, G=0, B=255) */
};
Pokud použijeme pro pixel index 1
, bude vykreslen červenou barvou, protože v této paletě se na
pozici 1
nachází červená barva.
Jakmile máme nadefinovanou paletu, můžeme použít funkci ge_new_gif
, která umožňuje vytvořit nový
GIF
soubor. Funkci musíme předat cestu k výstupnímu souboru, jeho rozměry, informace o paletě a o
tom, kolikrát se má animace přehrát2:
2Pro použití hlavičkového souboru knihovny nezapomeňte na začátku svého programu
vložit hlavičkový soubor
gifenc.h
.
int width = 300;
int height = 300;
ge_GIF* gif = ge_new_gif(
"output.gif",
width,
height,
palette,
2, /* hloubka palety */
0 /* opakovat neustále dokola */
);
Parametr hloubky palety by měl být nastaven na dvojkový logaritmus počtu baret v paletě. V naší
paletě jsou 4 barvy, takže jsme zde předali hodnotu parametru 2
. Poslední parametr udává, kolikrát
se má animace přehrát. Hodnota 0
udává, že se má animace opakovat neustále dokola3.
3Všechny tyto údaje lze vyčíst z dokumentace knihovny.
Zápis snímků
Když nyní máme vytvořenou animaci, můžeme do ní postupně zapisovat snímky. Zápis probíhá následovně:
- Do pole uloženého v atributu
gif->frame
zapíšeme hodnoty všech pixelů jednoho snímku. Každá hodnota by měla být indexem odpovídající barvy z námi zvolené palety. Pro adresování použijeme klasický převod z 2D na 1D index. - Zavoláme funkci
ge_add_frame
, které řekneme, na jak dlouhou dobu se má tento snímek zobrazit. Tato doba je v setinách vteřiny.
Jakmile zapíšeme jeden snímek, můžeme celý proces opakovat pro zápis dalších snímků.
Uhodnete, jakou animaci vygeneruje následující kód4?
4Pro ověření tipu si program přeložte a podívejte se na výslednou animaci. Zakomentujte řádek
s memset
a zkuste odhadnout, jak a proč to změní výslednou animaci.
for (int i = 0; i < 100; i++) {
memset(gif->frame, 0, sizeof(uint8_t) * width * height);
for (int row = 0; row < height; row++) {
gif->frame[row * height + i] = ((i * 10) / 30) % 3 + 1;
}
for (int col = 0; col < width; col++) {
gif->frame[i * height + col] = ((i * 10) / 30) % 3 + 1;
}
ge_add_frame(gif, 8);
}
Výsledek animace
Dokončení práce s animací
Jakmile zapíšeme všechny snímky, které chceme v animaci mít, nesmíme zapomenout animaci uložit do
souboru a uvolnit její paměť pomocí funkce ge_close_gif
:
ge_close_gif(gif);
Načtení GIF
animace
Pokud byste naopak chtěli nějakou GIF
animaci načíst ze souboru a něco s ní dále provést, můžete
použít knihovnu gifdec
od stejného autora, která slouží k
načítání GIF
souborů.
Cvičení 🏋
Zkuste použít knihovnu gifdef
pro převod animace z GIF
do TGA
:
- Načtěte
GIF
animaci z disku. - Projděte všechny snímky animace.
- Pro každý snímek převeďte pixely snímku z indexované palety do klasické mřížky pixelů používané
ve formátu
TGA
. - Zapište každý snímek na disk jako individuální
TGA
obrázek. Můžete na kraj obrázku vykreslit informaci o pořadí snímku.