Mimo mí­su > Volná diskuze

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

<< < (2/2)

Roman Horník:
Trochu jsem tenhle prohlížeč obrázků po čase oprášil a podle mýho z něj vytáhnul co do kvality zobrazení maximum. Jo, aplikoval jsem tam to, čemu jsem se vyhejbal, takže umí barvy, ale je tam ještě něco navíc.
To navíc je skutečnost, že se nepracuje s fixní paletou terminálu, kde má bejt 256 barev, ale je jich kvůli duplicitám jen 249, z každýho obrázku si totiž vycucne optimální paletu až 256 barev z 16777216 možnejch. To trvá bohužel o něco dýl, protože se obrázek musí načíst dvakrát za sebou (možná ještě přijdu na to, jak tohle obejít), jednou kvůli paletě a jednou kvůli samotnýmu obrázku, kterej se na základě týhle palety musí přemapovat, k čemuž se navíc nepoužívaj decimální čísla, ale hexadecimální (vstup pro barvy č. 1 a 2 např.: 12 58 6 128 1 24 → \e]4;1;#0C3A06\a\e]4;1;#800118\a).
Bohužel, přemapování barev v terminálu se kvůli drastický úspoře času musí vykonat na černý "obrazovce", jinak totiž trvá neúnosně dlouho, přičemž předchozí obrázek, stále zobrazenej, přeblikává a postupně a relativně pomalu mění barvy (při každý změně se celej obsah překresluje).
Nicméně, protože tam už není znakovej dithering, mohl jsem si dovolit ještě jedno malý "kouzlo", který má za následek dvojnásobný horizontální rozlišení.
No a proč vlastně ta šaškárna s vlastní paletou barev, když terminál si ty hodnoty sám zaokrouhlí na barvy, který má ve vnitřní paletě? Protože by se jednak nezobrazily ani z daleka všechny barvy (tady se využije dostupný maximum), takže obraz může vypadat hrozně a jednak ta zabudovaná paleta neobsahuje barvy s nižší sytostí a jasem, takže zhruba do poloviny jasu by byly části obrázků černobílý. Přesto se ale terminálový zaokrouhlování používá, ale na barvy injektovaný palety.
Taky nepoužívám žádnej dithering - totiž často byl větším zlem, než současný "schody" jemnejch barevnejch přechodů - kolikrát se zbláznil a prskal příliš tmavý body vedle světlejch. U obrázků, kde má bod velikost jednoho pixelu to nevadí, ale u znaků je to vidět dost.

Jádro je zhruba stejný, akorát se nezpracovává vždycky jen jedna jasová hodnota (0-255) z obrázku typu PGM, ale rovnou 6 hodnot (taky každá 0-255), R, G, B popředí a R, G, B pozadí z obrázku typu PPM, kdy právě dvojnásobnýho vodorovnýho rozlišení dosahuju obarvováním znaku "▌" - levá půlka se obarví barvou popředí, pravá barvou pozadí. Dále se nepoužívá monstrózní míchátko pomocí sed, aby se z 24 odstínů šedi namíchalo asi 151 odstínů, pouze se šestice hodnot RGBRGB obalí do adekvátní ANSI sekvence (\e[38;2;R;G;B;m\e[48;2;R;G;B;m, který mimo jiný rozumí dokonce i šestnáctibarevná konzole (ale jen šestnáctibarevná, kde ty barvy jsou fixní). Takovej dvojznak, aby se vykreslil, ale potřebuje 26-32 bajtů (předtím to bylo jen 18-22 bajtů, ovšem, dlužno dodat, pro poloviční rozlišení).

Tady je kód. Nejsou tam žádný komentáře, ty lze víceméně odvodit z předchozí černobílý verze:


--- Kód: ---#!/bin/bash -e
sirka_zn=5
vyska_zn=8
presn_bc=8
interpol=1

if [ ! -f "$1" ]
  then exit 66
  elif grep -q image <<<`file "$1"`
then
poc_sloup=$((`tput cols`*12))
poc_radku=`tput lines`
sirka_okna=$((poc_sloup*sirka_zn))
vyska_okna=$((poc_radku*vyska_zn))
info_obr=`identify -format '%w %h' "$1"[0]`
sirka_obr=`awk '{print $1}' <<<$info_obr`
vyska_obr=`awk '{print $2}' <<<$info_obr`
pom_str_znaku="($sirka_zn/$vyska_zn)"

case "$2" in
  "") zoom=100;;
   *) zoom=`sed -e 's/,/./' <<<$2`;;
esac

if [ $((sirka_obr*vyska_okna)) -gt $((vyska_obr*sirka_okna/12)) ]
  then vyska_zobr=`bc -l <<<"scale=$presn_bc; $poc_sloup/$sirka_obr*$zoom*$pom_str_znaku/12"`
  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*2"`

printf "\e[2J`convert -comment "" "$1"[0] \
-depth 8 -filter lanczos2 -resize $(bc -l <<< "$sirka_zobr*$interpol")%x$(bc -l <<< "$vyska_zobr*$interpol") \
-background black -gravity center -extent $(bc -l <<< "$poc_sloup*$interpol/6")x$(bc -l <<< "$poc_radku*$interpol")$3 -resize ${poc_sloup}x${poc_radku} \
-dither none -colors 256 -unique-colors -compress none ppm:- | tail -n+5 | xargs -n$((poc_sloup*poc_radku)) printf "%02x%02x%02x " | xargs -n1 | awk '{print "\033]4;" NR-1 ";#" $1 "\a"}' | tr -d '\n'`\e[?25l\e[0;0f$(convert -comment "" "$1"[0] \
-depth 8 -filter lanczos2 -resize $(bc -l <<< "$sirka_zobr*$interpol")%x$(bc -l <<< "$vyska_zobr*$interpol") \
-background black -gravity center -extent $(bc -l <<< "$poc_sloup*$interpol/6")x$(bc -l <<< "$poc_radku*$interpol")$3 -resize ${poc_sloup}x${poc_radku} \
-compress none ppm:- | tail -n+5 | xargs -n$(($poc_sloup/2)) | sed -e 's:$: :g;s:\([0-9]\+\) \([0-9]\+\) \([0-9]\+\) \([0-9]\+\) \([0-9]\+\) \([0-9]\+\) :\\e\[38;2;\1;\2;\3;48;2;\4;\5;\6m▌:g')\e[00m\e[0;0f\e[?25h"
else exit 65
fi
--- Konec kódu ---

Vejšku a šířku znaku je potřeba nastavit podle jeho rozměrů v terminálu, 5×8 maj znaky v XTermu při velikosti "Tiny" (lze změnit pomocí [L-Ctrl] + [pravý myšítko]).
Jo a tady je menší galerie, jak to zobrazuje.

Roman Horník:
Poslední verze, kterou jsem teď navíc pověsil na GitHub. Výrazně zjednodušená a zrychlená, protože minimálně XTerm a Mate/GNOME terminal uměj 24bitovou hloubku barev, takže odpadá pomalá procedura získání optimální palety barev obrázku a redefinice palety terminálu.

P. S.: Objevil jsem konkurenta, program catimg, kterej je v repu a kterej funguje snad jen náhodou na velmi podobným principu. Je sice o něco rychlejší, ale za cenu toho, že používá horší interpolaci a nevejde se zpravidla do okna terminálu. Samozřejmě neumí ani zoomovat.

Navigace

[0] Seznam témat

[*] Předchozí strana

Přejít na plnou verzi