Mimo mí­su > Volná diskuze

Prohlížeč obrázků v terminálu

(1/2) > >>

Roman Horník:
Terminál, přesněji řečeno emulátor terminálu, jistě všichni znáte. Víte nejspíš, že umí barvy, ale kdo z vás ví, že jich neumí jen 16, ale rovnou 256? Ale přesto, že má "tolik" barev (Xka vám jich nabízej 16777216, z toho 256 odstínů šedi), neumí grafiku, jen text. A když už se naskytne nějakej "prohlížeč obrázků" pro terminál, vypadá to dost blbě, protože se obrázek zobrazuje pomocí ASCII znaků, což sice obrázek připomíná, ale vypadá to zblízka jako písmenková polívka. A nehledě na to, že tohle bylo dělaný jen pro určitej typ písma s určitou velikostí, takže při změně fontu maj znaky jinej jas, než autor prohlížeče požadoval, takže to vypadá ještě hůř, než se čekalo.
Ale my jsme na to šli jinak. Napsal jsem takovou malou demonstraci toho, že i terminál může zobrazovat grafiku docela na úrovni. Je to sice pomalý, černobílý, rozlišení je závislý na velikosti okna terminálu a rozměrech znaku, ale podporuje to spoustu grafickejch formátů, výstup se dá uložit pro pozdější mnohem rychlejší zobrazení, dá se použít pro slideshow a umí to až 153 odstínů šedi. Pro použití je potřeba akorát doinstalovat ImageMagick.

Program se skládá ze 2 částí, z konvertoru a konvertoru-zobrazovače.
Nejdřív se obrázek upraví pomocí ImageMagick na požadovaný rozměry, v případě potřeby se přidaj kvůli centrování okraje a uloží do nekomprimovanýho formátu PGM. To je krásně čitelnej formát pro černobílou bimapovou grafiku, kde každej pixel je reprezentován numerickou hodnotou, tady v intervalu 0-255 (černá-bílá).
Následuje konvertor-zobrazovač, kterej čte data z onoho PGM obrázku, hodnoty decimuje na až 153 úrovní z až 256 úrovní na vstupu, ke každý z nich přidá barvu pomocí escape sekvence, výsledek se pak zobrazí. Terminál umí bezpečně 26 úrovní šedi (+ další 2, který se ovšem zobrazujou v různých terminálech jinak) na popředí i na pozadí, zbytek se míchá rozdílnou barvou popředí i pozadí, za použití trojice zvláštních znaků: ▓ (75%popředí, 25% pozadí), ▒ (50% popředí, 50% pozadí) a ░ (25% popředí, 75% pozadí). Byly nově přidány i 2 dodatkový znaky z Braillova písma pro eliminaci ostrých přechodů.

Takhle to vypadá:

To velký je Xterm, to malý terminál. Kliknutím na obrázek se načte v plný velikosti.

... a tady je kód (aktualizováno):


--- Kód: ---#!/bin/bash
O="/tmp/tmp.pgm"
R=`tput cols`x`tput lines`

## Jestli to není obrázek, nebo jestli soubor neexistuje, tak se ukonči
if [ ! -f $1 ]
then exit
elif grep -q image <<<`file $1`
then

## Schová kurzor
echo -ne "\e[?25l"

## Pro zrychlení: zmenší/zvětší obrázek podle jeho rozměrů tak, aby se velký obrázky
## zpracovávaly rychlejc, ale aby malý obrázky pokud možno neutrpěly ztrátu detailů
## U je relativní k vejšce znaku, V zase k šířce (v tomhle případě 5×8px), W je filtr.
## Je to narychlo a baj vočko udělaná prasečina, ale kupodivu funguje.
PIX=$((`identify $1 | awk '{print $3}' | sed -e 's/x/*(/g;s/$/\/2\)\/500/g'`))
if [ $PIX -le 10 ]
 then U=640; V=400; W="sincfast"
  elif [ $PIX -le 100 ]
   then U=320; V=200; W="box"
    elif [ $PIX -le 500 ]
     then U=160; V=100; W="box"
      elif [ $PIX -le 1000 ]
       then U=80; V=50; W="box"
        elif [ $PIX -le 5000 ]
         then U=40; V=25; W="box"
          elif [ $PIX -le 10000 ]
           then U=16; V=10; W="box"
            elif [ $PIX -le 20000 ]
             then U=8; V=5; W="box"
              elif [ $PIX -gt 20000 ]
               then U=4; V=2.5; W="box"
fi

## Nastavení správných rozměrů, konverze do PGM
convert \
-comment img2term \
$1 \
-filter $W \
-resize $U%x$V \
-filter Triangle \
-resize $R \
-gamma 2 \
-background black \
-gravity center \
-extent $R \
-depth 8 \
-compress none \
$O

tput cup 0 0

## Načtení dat z PGM obrázku, přeformátování na takovej počet sloupců, jako má terminál,
## decimace barevný palety, aby se 256 odstínů vešlo do 153 odstínů, vykreslení
echo -ne "$(cat $O | tail -n $((`cat $O | wc -l`-4)) | xargs -n `cat $O | sed -n 3p | awk '{print $1}'` | sed -e '
s/$/ /g;
s/255 /\\e[107m /g;
s/254 /\\e[107;38;5;255m⡈/g;
s/25[23] /\\e[107;38;5;255m⡪/g;
s/25[01] /\\e[107;38;5;255m░/g;
s/24[7-9] /\\e[107;38;5;255m▒/g;
s/24[56] /\\e[107;38;5;255m▓/g;
s/24[34] /\\e[97;48;5;255m⡪/g;
s/24[0-2] /\\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/232 /\\e[38;5;255;48;5;254m⡪/g;
s/23[01] /\\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/222 /\\e[38;5;254;48;5;253m⡪/g;
s/22[01] /\\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/212 /\\e[38;5;253;48;5;252m⡪/g;
s/21[01] /\\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/202 /\\e[38;5;252;48;5;251m⡪/g;
s/20[01] /\\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/192 /\\e[38;5;251;48;5;250m⡪/g;
s/19[01] /\\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/182 /\\e[38;5;250;48;5;249m⡪/g;
s/18[01] /\\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/172 /\\e[38;5;249;48;5;248m⡪/g;
s/17[01] /\\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/162 /\\e[38;5;248;48;5;247m⡪/g;
s/16[01] /\\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/152 /\\e[38;5;247;48;5;246m⡪/g;
s/15[01] /\\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/142 /\\e[38;5;246;48;5;245m⡪/g;
s/14[01] /\\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/132 /\\e[38;5;245;48;5;244m⡪/g;
s/13[01] /\\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/122 /\\e[38;5;244;48;5;243m⡪/g;
s/12[01] /\\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/112 /\\e[38;5;243;48;5;242m⡪/g;
s/11[01] /\\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/102 /\\e[38;5;242;48;5;241m⡪/g;
s/10[01] /\\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/92 /\\e[38;5;241;48;5;240m⡪/g;
s/9[01] /\\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/82 /\\e[38;5;240;48;5;239m⡪/g;
s/8[01] /\\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/72 /\\e[38;5;239;48;5;238m⡪/g;
s/7[01] /\\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/62 /\\e[38;5;238;48;5;237m⡪/g;
s/6[01] /\\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/52 /\\e[38;5;237;48;5;236m⡪/g;
s/5[01] /\\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/42 /\\e[38;5;236;48;5;235m⡪/g;
s/4[0-1] /\\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/32 /\\e[38;5;235;48;5;234m⡪/g;
s/3[01] /\\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/22 /\\e[38;5;234;48;5;233m⡪/g;
s/2[01] /\\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/12 /\\e[38;5;233;48;5;232m⡪/g;
s/1[01] /\\e[48;5;232m /g;
s/9 /\\e[48;5;232;38;5;0m⡪/g;
s/[78] /\\e[48;5;232;30m░/g;
s/[56] /\\e[48;5;232;30m▒/g;
s/[34] /\\e[48;5;232;30m▓/g;
s/2 /\\e[38;5;232;40m⡪/g;
s/1 /\\e[38;5;232;40m⡈/g;
s/0 /\\e[40m /g')\e[00m"
tput cup `tput lines` 0

## Informace o obrázku vlevo dole
echo -ne "\e[38;5;228;48;5;22m `identify $1|awk '{print $1, "\e[38;5;22;48;5;228m", $3, "\b,", $7}'` \e[00m"

tput cup `tput lines` `tput cols`
echo -ne "\e[?12l\e[?25h"
else exit
fi
tput cup 0 0
--- Konec kódu ---

Uložte to do souboru třeba blablabla.sh, nastavte mu spustitelnej příznak (chmod +x soubor) a spusťte /cesta/k/blablabla.sh obrázek.png

Pro spuštění slideshow:
cd /cesta/ke/složce_obrázků/
for X in `ls .`; do /cesta/k/blablabla.sh $X; sleep 5; done

U pomalejších počítačů se může sleep 5; vypustit, ta pětka jinak znamená čekat 5s


P. S.:
*Nefunguje v konzoli. Ta většinou neumí ani použitý escape sekvence, natož 256 barev.
*Lepší použít jako terminál Xterm- má rychlejší vykreslování a dá se dát do plnýho fullscreenu, aniž by tam vadilo menu
*Výstup se dá přesměrovat do souboru, kterej  se dá potom zobrazit třeba pomocí cat. Např. blablabla.sh obrázek.jpg > obrázek.txt, pro zobrazení pak cat obrázek.txt. Bacha ale na velikost okna!

Matesax:
Co to tu rozjíždíš za hovna? Grafika vůbec nesouvisí s místem, odkud ji používáš. I konzole může mít miliardy barev. Vždyť to spolu nesouvisí - nespojuj vůbec konzoli s černou a bílou - blbost... Nejprve pochop, co je to VGA - jak to celé začalo. Jak se postupně vyvíjelo SVGA, XGA, SXGA, SXGA+ - prostě:
http://cs.wikipedia.org/wiki/Soubor:Video_Standards.svg

No a aby se tohle nemuselo řešit, připsalo se pod vytyčenou částí RAM pro BIOS - část CMOS Battery - extended BIOS data - ve vyšší paměti - nad řádkem A20 celé jednotné grafické prostředí všech zemí - Super VGA (od QVGA po ...) - VESA... Cílem VESy je zvolení nejlepšího grafického rozhraní - rozlišení, barevná hloubka atd. A proto lze už v BIOSu aplikovat rozšířená data BIOSu - nad 0x4A00 - pro kabel grafiky atd. Ano - mnoho konzolí raději využije staršího RT přístupu - TTY - protože už to dost věcí řeší za programátora. Ale TTY Linuxu je založeno na rozšiřujících driverech. Prostě základem je FrameBuffer a XORG. (XVESA) A tak lze normálně vykreslovat v miliardách barev přímo přes soubor fbdev(2). X POUZE poskytují grafické rozhraní! Není to ovladač, nebo tak... Důkazem jest Mplayer - který používám a X nemám... Obrázky - W3M - parráda... Atd. FrameBuffer je vpodstatě jen zabalená Vesa... A tak lze rastrové obrázky vykreslit jen předáním pixelů... U komrese typu JPEG/PNG je trochu složitější se k pixelům dostat, ale to už je jen vnější nadstavba. Typické BMP obsahuje hlavičku - v ní pointer na první pixel - no a od prvního pixelu to jede jeden za druhým. Vykresluje se od spoda nahoru - Y-- a X zleva doprava normálně - X++... + u nedwordových šířek se aplikuje zarovnání řádku do podoby dělitelné dwordem - 4 byte... Hodnotou zarovnání může být buď 0, nebo filler - který se dá použít třeba pro nadbytečné informace... Zkrátka - grafika NESOUVISÍ s použitým shellem/... Vždy se dá vykreslovat v maximálních možnostech karty... Například v DOSu to dokazuje Arachne - respektive jeho moderní předěl... Používám jej a užívám si plnohodnotné prohlížení webu, editaci obrázků atd...

EDIT:

Vyšší pamětí nemyslím 32bit - ale tu co už není garantována dle IBM - http://wiki.osdev.org/Memory_Map_(x86) Tedy stále ji bez problému obsluhuje prvotní 16 bit režim... A chápu proč si pamětníci DOSu spojují konzoli s omezením barev - dříve to nebylo možné technicky. Ale proč i moderní generace??? Dříve na to nebyl HW - i když už HW něco více uměl, nebyl tak úplně využitelný - ostatně dnes to platí o to více - nevyužije se mnohdy až 30% HW možností... Ale s příslušným HW a využitím Vesy (který šílenec by se snažil udělat vlastní verzi Vesy - kromě mě... :D) má už 40% BIOSů plnohodntnou grafiku - některé i myš. A když už to nevypadá jako Desktop, tak to má loga atp. Čily když už i BIOS se tváří jako Desktop - tak nevidím problém... :D

Roman Horník:
To samozřejmě vím, ale dělal jsem to na stařičkým Optiplexu GX150. PIII @ 1GHz, 512MiB SDRAM @ 133MHz, chipset i815. V čemkoliv jiným, než v Xkách 640×480 se 16 barvama, v Xkách sice až 1600×1200, ale jen se 65536 barvama (=16 bitů). A takovýhle ščoty má ještě hromada lidí, vlastně většina těch, co mi zavolali, abych se jim na počítač "kouknul". Proč taky ne, když jim to stačí a/nebo si prostě novej dovolit nemůžou? Cokoliv jde na tomhle stroji dobře, o to líp pak půjde na strojích novejch. Sice jsem tenhle Optiplex v pondělí dovybavil tím nejlepším, co mi do AGP zůstalo, a sice ATI Rage 128 Pro Ultra TF, což byla ve svý době mocná karta (pro zprovoznění jsem musel ukrást ze Squeezeho z balíku libgl1-mesa-dri knihovničku r128_dri.so, která se od Wheezyho v onom balíku nevyskytuje, bez níž maj GLX kolečka 17FPS namísto současných ~950FPS), ale i když si konečně můžu zvolit rozlišení konzole, furt mám 16 barev- teda jen pomocí ANSI escape sekvencí (\e[xxxm).
Ale tenhle prohlížeč o tom není. Je to jen něco jako ASCII art, ale nepoužívá znaky z ASCII tabulky, nepoužívá pro ně 2-3 odstíny šedi, používá tu černobílou část z 256 barev, který lze pomocí escape sekvencí vyvolat, ale je stejně jako ASCII art omezenej rozměrama znaku. A navíc je to zase jen bashovina, a jak známo, takovej skriptovací jazyk má spoustu omezení. Ale funguje to, dokonce jsem to zrychlil a o trochu zvednul počet odstínů ze 101 na 153 díky znakům Braillovic písma.

P. S.: BMP jsem nezkoumal, ale vím, že se vykresluje opačně, každopádně jsem zvolil PGM, protože nic jednoduššího, než zápis hodnot {0..255}, není (i když by bylo jednodušší a úspornější, kdyby ty hodnoty byly v hexa soustavě, tedy {00..FF})- ta jednoduchost je nutná kvůli použitýmu SEDu.

Jo, dělal jsem to jen jako demonstraci toho, že ten terminál není tak zlej, neschopnej a ošklivej, jak se může na první pohled jevit. Tečka.

Matesax:
Nechápu jak mi chceš namluvit že ASCII art ukáže čeho je terminál schopen. Spíše to odradí ještě více lidí... Nevidím problém v tom místo kvalitních formátů používat mobilní, které nebude problém na takovémto PC přehrát přes Mplayer... I na takovémto hrozném PC lze používat HighColors - takže nechápu proč jít úmyslně do horšího...

http://en.wikipedia.org/wiki/List_of_16-bit_computer_hardware_palettes

Roman Horník:
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:

--- 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
--- Konec kódu ---

Navigace

[0] Seznam témat

[#] Další strana

Přejít na plnou verzi