Hlavní navigace

ASCII-Art snadno a rychle

Michal Burda

Z českých luhů a hájů vzešel jeden zajímavý počin. Je to knihovna pro jazyk C, jmenuje se AA-lib (ASCII-Art library), a my se jí dnes podíváme na zoubek.

Knihovna pro ASCII grafiku je hitovou záležitostí. Ačkoliv je její užitečnost v době výkonných grafických karet víceméně sporná (zapřísáhlí uživatelé příkazové řádky, nekamenujte mě), o to víc jde o krásné lákadlo a zajímavou hračku.

Jistě jste už alespoň slyšeli o tom, že lze například hrát Dooma nebo koukat na televizi v textovém režimu. S nějvětší pravděpodobností za tím vším stojí právě AA-lib. O co se tedy jedná?

AA-lib je knihovna poskytující grafické funkce, která ke své práci ale žádné grafické zařízení nepotřebuje. Ve skutečnosti žádný skutečný grafický výstup ani není možný. Knihovna nabízí programátorské rozhraní, díky němuž můžete vytvářet obrázky složené jen ze znaků ASCII tabulky. Interface knihovny definuje jakousi virtuální plochu a sadu základních funkcí. Pomocí nich můžete kreslit tak, jak jste zvyklí z jiných grafických knihoven. Výsledek je pak speciálními (a překvapivě efektními) algoritmy renderován na výstupní matici ASCII znaků.

Malá ukázka toho, co AA-lib umí:

Tabulka č. 117
-.:.-.:.-.:.-.:.-.:.- -     - :.-.:.-.:.-.:.-.:.-.
.:..:..:.:..:..:.:          __. -..:.:..:..:.:..:.
-.--.--.-.--.--.-           +~-   :...--.--.-.--.-
.:.-.:.:.-.-.:.:     .       .     :.:.--.:.-.:.-.
-.-.:..-.:.:.-..  _qgw   ,ggmm,     :.-.:..:.:..:.
.:.:..:.:..-.:.:. ] _]f  V' ^]h    .-.:..:..-.--.-
-.-.--.-.--.:..-. "\RXoZbuXssV'     :.-.:.---.:.-.
.:.:.--.:.--.--.: =nXXZXSSX12s[     -.:.-.-.--.-.:
-.-.-.--.-.--.--- ]s%Y1Xs%xXooL,-[(  ..:.:.:.-.:.-
.:.:.:.-.:.:.--.. ]mmXaaaXmmQQQQ/     :...-.-.:..:
-.-.-.-.:..-.-  _wWQWmmmmQWWWWWWQ/      :.:.:..:.-
.:.:.-.:..:.    JQWWWWWWWQWWWWWW$Q        -..:.-.:
-.-.-.:..:.  . jmQWWQWWWWWWQWWmmmmm/- .     :.-.:.
.:.:.:..:.  . jQWWWWWWWWWQWWWWWWWWmm/ ;:.    :.:..
-.-.-.--. .-_mQQQWWQWQWWQWWQWQWQWWQQW    .   .:..:
.:.:.-.-    jQWQWWQWmWWWWWQWWWWWWQWWW/  .     -.:.
-.-.-.:   . WWWWWQWWWWWWWQWWWQWQWWWWQf  .     -.-.
.:.:.:._s_/'$WWWQWWWmWWWWWWQWWWWWQWQW' ~ -  . .:.:
-.-.-.xoXZ#X,"9$WWQWQWWWWQWWWQWQWW3SX}      aX,:..
.ss_uoXXXXXX#X, )?WWWWWWQWWQWWWWWXuXon]___aoXXL:.:
)S2ZZZSXXXXXXXS,   3WWQWWWQWWQWQQXln222oXXXXZXXaa
)oXXZXXXXddXXXXXs,wWWWWWQWWWQWWW?'xvXXXZZZXZXXXdXX
)oXXXdXXXdXXZXXXXo7?WWQWWWQP??    ioSXXXXdXXXXXX2"
"I1122oXSSXXXXdXo1i;             .xxXSXXSX22!^`-.:
:-.:.-~+~++lII1li|~.   :........ :=iIl1II|`...:-..

Poznáváte maskota Linuxu? (Obrázek byl vyroben programem  aview.)

AA-lib je v současné době součástí mnohem ambicióznějšího AA-projectu, takže chcete-li zjistit o AA-lib něco bližšího, je vhodné začít právě tam. (Ale až po přečtení tohoto článku. :-)

Zkusme si teď napsat nějaký prográmek, ve kterém světu poodhalíme naše umělecké vlohy na poli ASCII-artu.

#include <aalib.h>
#include <stdio.h>
#include <math.h>

/* konstanta pi */
#define PI 3.141592654

/* platno, na ktere budeme malovat */
aa_context *context;

/* pozor, zaciname */
int main(void) {
  float x, y, r, t, sx, sy;
  int keyb_ok;

  /* inicializace grafiky */
  context = aa_autoinit(&aa_defparams);

  /* inicializace ovladace klavesnice */
  keyb_ok = aa_autoinitkbd(context, 0);

  /* obsluha chyb */
  if ((context == NULL) || !keyb_ok) {
    fprintf(stderr, "Nelze inicializovat AA-lib!");
    exit(1);
  }

  /* stred kruznice */
  sx = aa_imgwidth(context) / 2;
  sy = aa_imgheight(context) / 2;

  /* polomer kruznice */
  r = 20;

  /* kreslime... */
  for (t = 0; t < PI/2; t += 0.01) {
    x = 2 * r * sin(t);
    y = r * cos(t);
    aa_putpixel(context, (int) (sx + x), (int) (sy + y), 255);
    aa_putpixel(context, (int) (sx - x), (int) (sy + y), 255);
    aa_putpixel(context, (int) (sx + x), (int) (sy - y), 255);
    aa_putpixel(context, (int) (sx - x), (int) (sy - y), 255);
  }

  /* renderuj obrazek */
  aa_fastrender(context, 0, 0, aa_scrwidth(context), aa_scrheight(context));

  /* vykresli obrazek */
  aa_flush(context);

  /* cekej na stisk klavesy */
  aa_getevent(context, 1);

  /* konec prace s grafikou */
  aa_close(context);
}

Máte-li knihovnu AA-lib správně nainstalovánu, uvedený kód můžete zkompilovat příkazem:

gcc -laa -lm kruz.c -o kruz.o

Po spuštění by se na obrazovce měla objevit asi takováto elipsa:

Tabulka č. 118
             qaaaaaaaaaaaap
         qaP??            ??4ap
      qa?'                    )?ap
    qy?                          ?bp
   a?                              ?a
  y'                                )b
 y'                                  )b
]'                                    )f
P                                      4
f                                      ]
f                                      ]
f                                      ]
b                                      y
]p                                    qf
 4p                                  qP
  4p                                qP
   ?a                              a?
    )4a                          aP'
      )?ap                    qa?'
         )?baa            aay?'
             )??????P?????'

Proberme si naši ukázku trochu podrobněji. Na začátku zavádíme různé hlavičkové soubory. Protože budeme pracovat i s knihovnou AA-lib, nesmíme zapomenout includovat její  aalib.h.

Knihovna AA-lib pracuje na bázi tzv. grafických kontextů. Grafický kontext (typ aa_context) si můžeme pro jednoduchost představit jako virtuální malířské plátno. Chceme-li něco nakreslit, musíme si nejprve nějakou kreslicí plochu obstarat. Děti vytáhnou skicák, sprejeři najdou hezkou zeď a my si zavedeme globální proměnnou context, která je počítačovou reprezentací našeho malířského plátna.

Na samotném začátku programu se kreslicí plocha inicializuje. Za tímto účelem voláme funkci aa_autoinit(), která se automatickou detekcí hardwaru počítače postará o vytvoření vhodné pracovní plochy. AA-lib umí zobrazovat grafiku na ASCII terminál, do okna X-Window, nebo ji uložit do textového souboru. Autodetekce vybere nejvhodnější možnost. Jako parametr se funkci předává konfigurační záznam. Nám vyhovují defaultní hodnoty, předáváme proto pointer na strukturu  aa_defparams.

Aby program po vykreslení ihned neskončil, ale počkal na stisk libovolné klávesy, musíme inicializovat i ovladač klávesnice. Voláme funkci aa_autoinitkbd(), která se o to postará. Jejími parametry musí být grafický kontext (u nás proměnná context) a mód zpracování stisku kláves. Mód 0 znamená normální klávesnici – to je naše volba. Pro pořádek uvedu, že ještě existuje mód AA_SENDRELEASE, který informuje i o události uvolnění klávesy.

Proces inicializace je náročná záležitost, která nemusí vždy dopadnout dobře. V programu se na takovou situaci musíme připravit a o případné chybě uživatele informovat.

Další část programu realizuje samotné kreslení. Do proměnných sx a sy se vypočítává střed obrazovky. Využíváme k tomu makra aa_imgwidth() a aa_imgheight(), které vrací šířku a výšku pracovní plochy v „pixelech“.

Každá kreslicí plocha je tvořena polem bajtů, do kterých se ukládá číslo určující stupeň šedi. Každému pixelu odpovídá jeden bajt tohoto pole. Programátor tedy může psát algoritmy pro kreslení naprosto stejně, jak je zvyklý z klasických grafických knihoven. Výsledkem, který se v konečné fázi na obrazovce objeví, je matice znaků, v níž každému z nich odpovídá jedna čtveřice sousedních pixelů.

Samotné nakreslení elipsy je klasický algoritmus, který tady rozebírat nebudu. Postupně se vypočítávají jednotlivé pixely tvořící obvod a ty se zobrazují pomocí volání aa_putpixel(). Makro aa_putpixel() vyžaduje čtyři parametry. Prvním z nich je grafický kontext, kterého se operace týká, následují x-ová a y-ová souřadnice a odstín šedi v intervalu 0 (černá) až 255 (bílá).

V současnosti knihovna AA-lib nedisponuje žádnými dalšími grafickými funkcemi, vykreslení pixelu je jediná věc, kterou umí. Naprogramování dalších obvyklých algoritmů (jako třeba kreslení čar, oblouků a podobně) jistě nebude pro pilného čtenáře problémem.

Na tomto místě je vhodné se zmínit o tom, jak AA-lib pracuje s barvami: nijak. Veškeré kreslení se odehrává v odstínech šedi. Pro snazší přechod z „barevných“ programů je v AA-lib zapracován mechanizmus barevných palet, do kterých se jednotlivé barvy ukládají pod indexy. Barvy ukládané do palety můžete specifikovat v modelu RGB. AA-lib si je na šedou převede sama. V naší jednoduché ukázce jsme práci s paletami vynechali a kreslili jsme jenom „bílou“ barvou ( 255).

Odstín pixelu má vliv na to, jak bude obrázek nakonec vypadat. Pro intenzivnější odstíny použije AA-lib jiné (silnější) znaky a naopak.

Na začátku jsem o svém produktu hrdě prohlásil, že se jedná o elipsu. Ve skutečnosti vypadá spíše jako kružnice. Celá věc s sebou totiž nese ještě jeden problém. Jelikož AA-lib umožňuje používat různá zařízení, nemůžeme předem vědět, jak vysoké každé písmeno vlastně je. No a tady vzniká široký prostor pro deformaci obrázků. Naše elipsa má být podle rovnic spíše širší než delší. V Xovém okně také tak vypadala. Když jsem si ji ale zobrazil v terminálu, byla spíše protáhlá na výšku. Naštěstí zde existuje způsob, jak se deformacím vyhnout. Pomocí několika funkcí knihovny můžete zjistit deformační poměr a kreslení obrázku tomu přizpůsobit. Vše záleží jenom na vaší šikovnosti.

Samotné použití makra aa_putpixel() k zobrazení výsledku na obrazovku ale nestačí. Předtím musíme celý výtvor vyrenderovat (převést na ASCII-znaky). V naší ukázce se to dělá funkcí aa_fastrender(), která je nejrychlejší a má nejjednodušší použití. Kromě ní ještě existují podobné funkce aa_render() a aa_renderpalette(), které se liší hlavně kvalitou výsledku. Pomocí nich můžete knihovnu AA-lib přimět, aby při konstrukci výsledného ASCII obrazu používala dithering, lze také měnit kontrast a dělat další parádičky.

Máme-li kresbu vyrenderovanou, nezbývá nic jiného, než ji poslat na výstup. Dělá se to pomocí funkce aa_flush(). Až po provedení této rutiny se uživateli obrázek vykreslí!

V naší ukázce následuje po aa_flush() už jen funkce aa_getevent(), která zachycuje událost stisku klávesy. Jednička ve druhém parametru jí říká, že na událost má čekat a nepustit chod programu dále, dokud se nějaká neobjeví.

Po stisku klávesy se program hne k poslednímu volání aa_close(), kterým se práce s grafikou ukončí a uvolní se paměť přiřazená grafickému kontextu.

Tak co, líbí? Mně nezbývá než konstatovat, že AA-lib je prostě kouzelná. A to jsem se nezmínil o dalších funkcích. AA-lib umí zachycovat události myši, podporuje různá uživatelská nastavení z příkazové řádky, a tak dále.

Jestli se chcete podívat na nějaký hotový software pracující s AA-lib, zkuste třeba tyto odkazy:



Poznámka redakce:
Věhlasný vývojář Honza Hubička dal na srozuměnou, že v současné době pracuje na nové verzi AA-libu, do níž během tří let práce implementoval spoustu vzrušujících vylepšení (včetně možnosti hrát Quake) a také nový klávesový driver, který dokáže shodit celý systém. Na stránce aa-project.source­forge.net lze údajně nalézt dostatečně vyvinutou verzi, která již nyní funguje daleko lépe, než verze předchozí :).
Johanka

Našli jste v článku chybu?

23. 9. 2004 1:04

mailo (neregistrovaný)

Bez Xek je to v pohode. Obecne mi dela mensi problem sehnat aplikaci pro konzoli, nez pro Xka

1. 11. 2001 12:27

KLON (neregistrovaný)

Nevím zda je nejlepší nápad si kazit oči jen kvůli koukaní na obrázky v aa-lib. Ono totiž stačí oči jen přivřít a pak je to super.

120na80.cz: 5 nejčastějších mýtů o kondomech

5 nejčastějších mýtů o kondomech

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

DigiZone.cz: Velká cena v Abú Dhabí: 131 ti­síc diváků

Velká cena v Abú Dhabí: 131 ti­síc diváků

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

DigiZone.cz: ČRo rozšiřuje DAB do Berouna

ČRo rozšiřuje DAB do Berouna

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

DigiZone.cz: Recenze Westworld: zavraždit a...

Recenze Westworld: zavraždit a...

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Lupa.cz: Propustili je z Avastu, už po nich sahá ESET

Propustili je z Avastu, už po nich sahá ESET

Vitalia.cz: Potvrzeno: Pobyt v lese je skvělý na imunitu

Potvrzeno: Pobyt v lese je skvělý na imunitu

Měšec.cz: Air Bank zruší TOP3 garanci a zdražuje kurzy

Air Bank zruší TOP3 garanci a zdražuje kurzy

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

Měšec.cz: Stavební spoření: alternativa i pro seniory

Stavební spoření: alternativa i pro seniory