Já zase nechápu, proč opakovaně dáváš všem na odiv svou excelentní natvrdlost. Píšu snad, že to je ASCII Art? Ne, píšu, že to s AA má některý věci společný. Pokud to nevíš, AA využívá pouze tisknutelných znaků tabulky ASCII, na Wikipedii odkazovat nebudu, ale můžeš si v terminálu spustit man ascii, abys viděl, který to jsou. Ale samozřejmě se dá program upravit na AA (bez formátování; je to mnohem rychlejší).
A o schopnostech terminálu - ukaž mi jinej program, co v terminálu dokáže zobrazit obrázek, co má víc jak 153 odstínů šedý (nebo v barvách) rychlostí jen o něco horší, než třeba prohlížeč obrázků EoG, program, co umí ze sekvence obrázků udělat video (viz níže), který se zobrazí přímo v okně terminálu a je koukatelný i na tom starým Optiplexu.
Terminál toho umí samozřejmě víc, barvy bych tam mohl udělat, ale když si ty dostupný barvy prohlídneš, zjistíš, že abys z toho získal rozumnou paletu, musel bys míchat a míchat. Už takhle to byla prdel, a to jsem míchal jen jas. Pak tady máme další 2 rozměry, odstín a sytost. Odstínů je tam poměrně dost, ale co sytost? To by se muselo míchat, to by najednou, aby to za něco stálo, byly při tomhle způsobu míchání zhruba 3 milióny kombinací, každá kombinace by se musela zapsat a ověřovat. A stejně by to ve výsledku bylo k hovnu, protože by to bylo pomalý a žravý. Jas pro dostatečnou interpretaci obrazu stačí, stejně jako stačil přes 100 let u fotek a desítky let u televize. A ještě poměrně nedávno byly ČB počítače, a co teprve mobily? Buďto mi ukážeš něco lepšího, nebo to vytvoříš (pro srovnání nejlíp jako shellovej skript), když máš tak strašně dlouhý zkušenosti, nebo přestaneš pyskovat.
P. S.: Zkoušel jsem předělat na zápis typu \e[48;2;R;G;Bm (kde R|G|B jsou hodnoty 0..255). Hodně se to zjednodušilo, protože jsem nemusel vypisovat každou barvu zvlášť, namísto toho každou hodnotu upravil pomocí awk (např. "147" > "\e[48;2;147;147;147m "), ale jednak to bylo asi stokrát pomalejší, jednak by z toho stejně vylezlo oněch až 256 barev. A taky to uměl jen XTerm, jinde bylo černo. Nepoužitelný.
Ale k věci. Dost jsem na tom zapracoval a program výrazně zdokonalil:
* V první řadě je rychlejší. Odpadla nutnost použít "meziobrázku", výstup z convertu jde rovnou do roury, kde se ihned zpracovává. Oproti předchozí verzi je to zhruba 2x rychlejší
* Odpadla potřeba použít dvou stupňů změny velikosti obrázku, poměr stran je navíc mnohem bližší originálu (záleží ale na "rozlišení" terminálu; malý okno a velký znaky zpravidla budou poměr stran zkreslovat. Dobrý je spouštět prohlížeč v Xtermu, s velikostí písma Tiny (6×10px) a ve fullscreenu
* Dále byl vyřešen problém se soubory s mezerou/mezerami v názvu
* Odpadla potřeba pozicování kurzoru pomocí tput, teď se to děje pomocí escape kódů
* Program umí načíst i vícevrstvý obrázky (GIF, TIFF, XCF,...), ale vzhledem ke způsobu výstupu z IM vždy jen první snímek, nikoliv animace
* Umí to zoomovat, teda jen do středu. Prostě se za příkaz a za cestu k obrázku napíše číslo (v %), takže 50 je poloviční velikost, 200 je dvojnásobná. 100 je výchozí hodnota, nejmenší číslo je 1(%), zadává se celočíselná hodnota (!)
* Pokud se výstup sekvence obrázků přesměrovává do souboru a ten se pak přečte přes cat (v terminálu s nezměněnou velikostí okna), zobrazí se animace. Pokud se onen výstupní soubor komprimuje do tar.gz, má zhruba desetinovou velikost a dá se přečíst přes zcat. Krátký video jsem udělal následovně:
avconv -i video.mp4 -r 20 -f image2 Složka_pro_sekvenci_obrázků/%05d.png #Rozdělení videa na snímky, v tomhle případě se snímkovou frekvencí 20fps
for X in `ls Složka_pro_sekvenci_obrázků`; do ./programek.sh Složka_pro_sekvenci_obrázků/$X >> video.txt; printf " $X\r"; done #Vytvoření videa ze snímků
cat video.txt #Zobrazení videa
Opakuju, že velikost okna terminálu musí bejt při vytváření videa stejná nebo větší i při přehrávání. Při přehrávání se nedá určit počet zobrazených snímků za vteřinu, záleží na schopnostech stroje a jeho aktuální zátěži jinými procesy.
27. 3. 2014:
* Z programu byly vyňaty zbytečnosti
* Přibyla možnost přiblížit obrázek nejen na střed, ale dá se navíc určit posun od středu. Např. prográmek obrázek.svg 200 -20+20 zajistí dvojnásobný přiblížení s tím, že se onen výřez posune o 20 znaků doleva (-) a 20 znaků dolů (+). Není to zrovna ideální vzhledem k nečtvercovosti znaků, horizontálně se v XTermu u písma Tiny už zmenšenej obrázek posune o 5×20px, vertikálně však o 8×20px. Zadávají se kladný/záporný čísla, ale vždycky s příslušným znamínkem, bez mezery mezi nima.
* Co se tejče přiblížení, teď je možný zadávat čísla jak s desetinnou tečkou, tak i s desetinnou čárkou (protože jsem to tam kopíroval přímo z kalkulačky a nechtěl jsem furt přepisovat čárku tečkou).
TODO: Parametry se budou v budoucnu zadávat pomocí jednoduchých přepínačů, bude možnost nastavit si barvu pozadí, vykreslovací motory (ve skutečnosti jich mám víc, dokonce i pro konzoli) oddělím do samostatných souborů, vytvořím konečně instalační balík a vymyslím tomu jméno.
No a tady je kód:
#!/bin/bash
## Šířka a výška znaku v px
sirka_zn=5
vyska_zn=8
## Přesnost výpočtu pro BC
presn_bc=6
## Česky: Pokud to není soubor (nebo neexistuje), pak tiše zemři,
## jinak pokud je to obrázek, pak konej následující:
if [ ! -f "$1" ]
then exit 66
elif grep -q image <<<`file "$1"`
then
## Získáme počet sloupců a řádků terminálu
poc_sloup=`tput cols`
poc_radku=`tput lines`
## Šířka a výška okna terminálu
sirka_okna=$((poc_sloup*sirka_zn))
vyska_okna=$((poc_radku*vyska_zn))
## Získáme potřebné údaje o obrázku (šířka, výška, formát)
info_obr=`identify -format '%w %h %m' "$1"[0]`
## Z toho se vypreparuje šířka, výška a typ obrázku
sirka_obr=`awk '{print $1}' <<<$info_obr`
vyska_obr=`awk '{print $2}' <<<$info_obr`
typ_obr=`awk '{print $3}' <<<$info_obr`
## Výpočet poměru stran znaku
pom_str_znaku="($sirka_zn/$vyska_zn)"
## Přiblížení. Pokud je uživatelsky zadáno jako 2. parametr
## (1. je vstupní soubor), pak se použije, pokud není, použije se
## výchozí přiblížení, tj. 100%
case "$2" in
"") zoom=100;;
*) zoom=`sed -e 's/,/./' <<<$2`;;
esac
## Tahle věcička vypočítá změnu velikosti a poměru stran obrázku tak, aby při
## úrovni zvětšení 100% právě zaplnil nejdelší rozměr obrázku odpovídající
## strany terminálu. Vzhledem k tomu, že nemají znaky terminálu poměr stran 1:1,
## k obrázkům na výšku přistupuje jinak, než k obrázkům na šířku.
if [ $((sirka_obr*vyska_okna)) -gt $((vyska_obr*sirka_okna)) ]
then vyska_zobr=`bc -l <<<"scale=$presn_bc; $poc_sloup/$sirka_obr*$zoom*$pom_str_znaku"`
else vyska_zobr=`bc -l <<<"scale=$presn_bc; $poc_radku/$vyska_obr*$zoom"`
fi
sirka_zobr=`bc -l <<<"scale=$presn_bc; $vyska_zobr/$pom_str_znaku"`
info="`basename "$1"` \
\e[7m $typ_obr, ${sirka_obr}x${vyska_obr}, \
`du -bh "$1" | awk '{print $1}'`, \
H=`bc -l <<<"scale=2; (0.005+$sirka_zobr)/1"`\045 \
V=`bc -l <<<"scale=2; (0.005+$vyska_zobr)/1"`\045"
## Hlavní motor ########
## Obrázek se zmenší na vypočtené hodnoty $vyska_zobr a $sirka_zobr,
## nastaví se mu černé pozadí (lze změnit) a právě ním se vyplní prázdné místo
## tak, aby rozměr výsledku byl totožný s rozměrem okna terminálu. Obrázek se
## tímto navíc vystředí. Nastaví se osmibitová hloubka (to kdyby se otevíraly
## šestnáctibitové obrázky; IM totiž rád zachovává bitovou hloubku originálu.
## Ale třeba čtyřbitový obrázek motoru nevadí), obrázek se překonvertuje do
## formátu PGM a rourou pošle dál, kde se ořízne hlavička. Protože numerické
## údaje hodnot jednotlivých pixelů IM zpravidla souká do poc_sloupa 20
## sloupců, je potřeba zajistit, aby těch sloupců bylo právě tolik, kolik jich
## má terminál, což spáchá "xargs -n $poc_sloup". Pro větší rychlost lze
## použít jen "xargs". Tato úprava způsobí, že data obrázku budou na jednom
## řádku (nebude jich tolik, kolik jich má terminál, nebude se na konec každého
## řádku strkat \n, xargs bude pracovat rychleji). V tom případě ale nelze
## uložený výstup zobrazit ani ve větším okně terminálu, než ve kterém byl
## vytvořen, neboť se obraz desynchronizuje.
## Pak následuje sed v roli překladače numerických hodnot na escape kódy pro
## popředí i pozadí jednotlivých znaků. Co odstín, to jeden řádek, začíná to
## bílou (255), končí černou (0). A toto celé se pak zobrazí. Pro změnu
## velikosti je použita funkce -scale, kde jako výchozí filtr je použit Box, což
## je rychlý filtr s dostačující kvalitou. Kvalitnější, leč pomalejší škálování
## poskytuje funkce -resize, kde je jako výchozí filtr použit Mitchell nebo
## Lanczos podle toho, jestli obrázek disponuje alfakanálem. Chcete-li použít
## jiný filtr, před touto funkcí definujte žádaný filtr, např.:
## -filter Lagrange -resize $sirka_zobr%x$vyska_zobr
## Seznam filtrů získáte spuštěním příkazu 'convert -list filter' v terminálu.
printf "\e[?25l\e[0;0f$(convert \
-set colorspace RGB -comment "" "$1"[0] \
-scale $sirka_zobr%x$vyska_zobr \
-background black -gravity center -extent ${poc_sloup}x${poc_radku}$3 \
-depth 8 -compress none pgm:- | tail -n+4 | xargs | sed -e '
s/$/ /g;
s/25[45] /\\e[107m /g;
s/25[23] /\\e[107;38;5;255m⡈/g;
s/25[01] /\\e[107;38;5;255m⡪/g;
s/24[89] /\\e[107;38;5;255m░/g;
s/24[67] /\\e[107;38;5;255m▒/g;
s/24[45] /\\e[107;38;5;255m▓/g;
s/24[23] /\\e[97;48;5;255m⡪/g;
s/24[01] /\\e[48;5;255m /g;
s/239 /\\e[48;5;255;38;5;254m⡪/g;
s/23[78] /\\e[48;5;255;38;5;254m░/g;
s/23[56] /\\e[48;5;255;38;5;254m▒/g;
s/23[34] /\\e[48;5;255;38;5;254m▓/g;
s/23[12] /\\e[38;5;255;48;5;254m⡪/g;
s/230 /\\e[48;5;254m /g;
s/229 /\\e[48;5;254;38;5;253m⡪/g;
s/22[78] /\\e[48;5;254;38;5;253m░/g;
s/22[56] /\\e[48;5;254;38;5;253m▒/g;
s/22[34] /\\e[48;5;254;38;5;253m▓/g;
s/22[12] /\\e[38;5;254;48;5;253m⡪/g;
s/220 /\\e[48;5;253m /g;
s/219 /\\e[48;5;253;38;5;252m⡪/g;
s/21[78] /\\e[48;5;253;38;5;252m░/g;
s/21[56] /\\e[48;5;253;38;5;252m▒/g;
s/21[34] /\\e[48;5;253;38;5;252m▓/g;
s/21[12] /\\e[38;5;253;48;5;252m⡪/g;
s/210 /\\e[48;5;252m /g;
s/209 /\\e[48;5;252;38;5;251m⡪/g;
s/20[78] /\\e[48;5;252;38;5;251m░/g;
s/20[56] /\\e[48;5;252;38;5;251m▒/g;
s/20[34] /\\e[48;5;252;38;5;251m▓/g;
s/20[12] /\\e[38;5;252;48;5;251m⡪/g;
s/200 /\\e[48;5;251m /g;
s/199 /\\e[48;5;251;38;5;250m⡪/g;
s/19[78] /\\e[48;5;251;38;5;250m░/g;
s/19[56] /\\e[48;5;251;38;5;250m▒/g;
s/19[34] /\\e[48;5;251;38;5;250m▓/g;
s/19[12] /\\e[38;5;251;48;5;250m⡪/g;
s/190 /\\e[48;5;250m /g;
s/189 /\\e[48;5;250;38;5;249m⡪/g;
s/18[78] /\\e[48;5;250;38;5;249m░/g;
s/18[56] /\\e[48;5;250;38;5;249m▒/g;
s/18[34] /\\e[48;5;250;38;5;249m▓/g;
s/18[12] /\\e[38;5;250;48;5;249m⡪/g;
s/180 /\\e[48;5;249m /g;
s/179 /\\e[48;5;249;38;5;248m⡪/g;
s/17[78] /\\e[48;5;249;38;5;248m░/g;
s/17[56] /\\e[48;5;249;38;5;248m▒/g;
s/17[34] /\\e[48;5;249;38;5;248m▓/g;
s/17[12] /\\e[38;5;249;48;5;248m⡪/g;
s/170 /\\e[48;5;248m /g;
s/169 /\\e[48;5;248;38;5;247m⡪/g;
s/16[78] /\\e[48;5;248;38;5;247m░/g;
s/16[56] /\\e[48;5;248;38;5;247m▒/g;
s/16[34] /\\e[48;5;248;38;5;247m▓/g;
s/16[12] /\\e[38;5;248;48;5;247m⡪/g;
s/160 /\\e[48;5;247m /g;
s/159 /\\e[48;5;247;38;5;246m⡪/g;
s/15[78] /\\e[48;5;247;38;5;246m░/g;
s/15[56] /\\e[48;5;247;38;5;246m▒/g;
s/15[34] /\\e[48;5;247;38;5;246m▓/g;
s/15[12] /\\e[38;5;247;48;5;246m⡪/g;
s/150 /\\e[48;5;246m /g;
s/149 /\\e[48;5;246;38;5;245m⡪/g;
s/14[78] /\\e[48;5;246;38;5;245m░/g;
s/14[56] /\\e[48;5;246;38;5;245m▒/g;
s/14[34] /\\e[48;5;246;38;5;245m▓/g;
s/14[12] /\\e[38;5;246;48;5;245m⡪/g;
s/140 /\\e[48;5;245m /g;
s/139 /\\e[48;5;245;38;5;244m⡪/g;
s/13[78] /\\e[48;5;245;38;5;244m░/g;
s/13[56] /\\e[48;5;245;38;5;244m▒/g;
s/13[34] /\\e[48;5;245;38;5;244m▓/g;
s/13[12] /\\e[38;5;245;48;5;244m⡪/g;
s/130 /\\e[48;5;244m /g;
s/129 /\\e[48;5;244;38;5;243m⡪/g;
s/12[78] /\\e[48;5;244;38;5;243m░/g;
s/12[56] /\\e[48;5;244;38;5;243m▒/g;
s/12[34] /\\e[48;5;244;38;5;243m▓/g;
s/12[12] /\\e[38;5;244;48;5;243m⡪/g;
s/120 /\\e[48;5;243m /g;
s/119 /\\e[48;5;243;38;5;242m⡪/g;
s/11[78] /\\e[48;5;243;38;5;242m░/g;
s/11[56] /\\e[48;5;243;38;5;242m▒/g;
s/11[34] /\\e[48;5;243;38;5;242m▓/g;
s/11[12] /\\e[38;5;243;48;5;242m⡪/g;
s/110 /\\e[48;5;242m /g;
s/109 /\\e[48;5;242;38;5;241m⡪/g;
s/10[78] /\\e[48;5;242;38;5;241m░/g;
s/10[56] /\\e[48;5;242;38;5;241m▒/g;
s/10[34] /\\e[48;5;242;38;5;241m▓/g;
s/10[12] /\\e[38;5;242;48;5;241m⡪/g;
s/100 /\\e[48;5;241m /g;
s/99 /\\e[48;5;241;38;5;240m⡪/g;
s/9[78] /\\e[48;5;241;38;5;240m░/g;
s/9[56] /\\e[48;5;241;38;5;240m▒/g;
s/9[34] /\\e[48;5;241;38;5;240m▓/g;
s/9[12] /\\e[38;5;241;48;5;240m⡪/g;
s/90 /\\e[48;5;240m /g;
s/89 /\\e[48;5;240;38;5;239m⡪/g;
s/8[78] /\\e[48;5;240;38;5;239m░/g;
s/8[56] /\\e[48;5;240;38;5;239m▒/g;
s/8[34] /\\e[48;5;240;38;5;239m▓/g;
s/8[12] /\\e[38;5;240;48;5;239m⡪/g;
s/80 /\\e[48;5;239m /g;
s/79 /\\e[48;5;239;38;5;238m⡪/g;
s/7[78] /\\e[48;5;239;38;5;238m░/g;
s/7[56] /\\e[48;5;239;38;5;238m▒/g;
s/7[34] /\\e[48;5;239;38;5;238m▓/g;
s/7[12] /\\e[38;5;239;48;5;238m⡪/g;
s/70 /\\e[48;5;238m /g;
s/69 /\\e[48;5;238;38;5;237m⡪/g;
s/6[78] /\\e[48;5;238;38;5;237m░/g;
s/6[56] /\\e[48;5;238;38;5;237m▒/g;
s/6[34] /\\e[48;5;238;38;5;237m▓/g;
s/6[12] /\\e[38;5;238;48;5;237m⡪/g;
s/60 /\\e[48;5;237m /g;
s/59 /\\e[48;5;237;38;5;236m⡪/g;
s/5[78] /\\e[48;5;237;38;5;236m░/g;
s/5[56] /\\e[48;5;237;38;5;236m▒/g;
s/5[34] /\\e[48;5;237;38;5;236m▓/g;
s/5[12] /\\e[38;5;237;48;5;236m⡪/g;
s/50 /\\e[48;5;236m /g;
s/49 /\\e[48;5;236;38;5;235m⡪/g;
s/4[78] /\\e[48;5;236;38;5;235m░/g;
s/4[56] /\\e[48;5;236;38;5;235m▒/g;
s/4[34] /\\e[48;5;236;38;5;235m▓/g;
s/4[12] /\\e[38;5;236;48;5;235m⡪/g;
s/40 /\\e[48;5;235m /g;
s/39 /\\e[48;5;235;38;5;234m⡪/g;
s/3[78] /\\e[48;5;235;38;5;234m░/g;
s/3[56] /\\e[48;5;235;38;5;234m▒/g;
s/3[34] /\\e[48;5;235;38;5;234m▓/g;
s/3[12] /\\e[38;5;235;48;5;234m⡪/g;
s/30 /\\e[48;5;234m /g;
s/29 /\\e[48;5;234;38;5;233m⡪/g;
s/2[78] /\\e[48;5;234;38;5;233m░/g;
s/2[56] /\\e[48;5;234;38;5;233m▒/g;
s/2[34] /\\e[48;5;234;38;5;233m▓/g;
s/2[12] /\\e[38;5;234;48;5;233m⡪/g;
s/20 /\\e[48;5;233m /g;
s/19 /\\e[48;5;233;38;5;232m⡪/g;
s/1[78] /\\e[48;5;233;38;5;232m░/g;
s/1[56] /\\e[48;5;233;38;5;232m▒/g;
s/1[34] /\\e[48;5;233;38;5;232m▓/g;
s/1[12] /\\e[38;5;233;48;5;232m⡪/g;
s/10 /\\e[48;5;232m /g;
s/9 /\\e[48;5;232;38;5;0m⡪/g;
s/[78] /\\e[48;5;232;38;5;0m░/g;
s/[56] /\\e[48;5;232;38;5;0m▒/g;
s/[34] /\\e[48;5;232;38;5;0m▓/g;
s/2 /\\e[38;5;232;48;5;0m⡪/g;
s/1 /\\e[38;5;232;48;5;0m⡈/g;
s/0 /\\e[48;5;0m /g')\e[$poc_radku;0f\e[38;5;222;48;5;22m$info \e[00m\e[0;0f\e[?25h"
## Pokračování řádku 12: Ale pokud se nejedná o obrázek, nechť program zhyne
else exit 65
fi