O Elixiru, LiveView, SVG, JPG, knihovnách a Poisson disc samplingu.
Jakmile jsem zjistila, že pomocí programování můžu ovládat grafiku (SVG), hned jsem viděla ten potenciál. Nikdy jsem si nedovedla vybrat mezi svým technickým já a svým uměleckým já; mezi programováním a malováním. Doteď si tvrdohlavě myslím, že můžu dělat obojí, na střídačku. Nejen to, teď si dokonce začínám malinko myslet, že můžu dělat obojí najednou.
Když jsem se na chvíli rozhodla, že teda budu praktická, a začala programovat, jakmile jsem něco málo uměla, první nápad hned byl: super, teď tomu přidám obrázky! :-D (Jako důkaz moje první aplikace – s hrochem ;-))
Líbilo by se mi dělat generovanou grafiku (třeba něco jako Patterns), ale nejlepší by bylo ji ještě na závěr zvládnout vyexportovat do bitmapového obrázku, který by šel dál použít. Taková mlhavá idea, protože jsem si ani nedovedla představit, kde vůbec začít.
Rovnoměrně náhodné rozdělení
Ale pak jsem se na to trochu mrkla. Jako první krok jsem chtěla zjistit, jak generovat rozmístění objektů. Protože náhodné rozmístění (random) nevypadá harmonicky (někde se shlukují a jinde je prázdno – prostě moc náhodné), a pravidelné rozmístění je zas nuda. Potřebovala bych nějaký algoritmus na rovnoměrně náhodné rozdělení v ploše a narazila jsem na Poisson disc sampling. Hledala jsem na to knihovnu pro Elixir a žádnou nenašla. Tak to mám smůlu a holt se nedá nic dělat.
Za čas jsem se k tomu opět vrátila a říkám si – když není, tak ji teda asi budu muset naprogramovat já. :-D Vůbec jsem nevěděla, jak na to, ale naštěstí je tu dnes Youtube. ;-) Tam jsem našla tutoriál, který vysvětluje, jak Poisson disc sampling naprogramovat v JavaScriptu s použitím algoritmu Roberta Bridsona (PDF) (kteroužto matematiku v angličtině bych bez vysvětlení nechopila) .
Podle něj jsem to v podstatě opsala. Měla jsem v plánu kód nejdřív přepsat doslova, jen v Elixiru, a pak upravit. Ale v průběhu toho jsem zjistila, že mnohem jednodušší je psát ho rovnou Elixirovým funkcionálním způsobem, než doslova opisovat krkolomný JavaScript. A když to poprvé vygenerovalo hezky rozmístěné puntíky, nechtělo se mi věřit, že to fakt tak snadno funguje. :-)
Vytvoření vlastní knihovny v Elixiru
Tenhle algoritmus budu logicky chtít využít ve více různých aplikacích, tak jsem se rozhodla dát si ho do samostatné knihovny („vytknout“ ho mimo tenhle projekt). A celkově, umět si vyrobit vlastní knihovnu mi připadalo jako další level. Poptala jsem se tedy, jak na to, a zjistila, jak je to jednoduché – ostatně jako všechno v Elixiru. Člověk nad něčím přemýšlí, a když už to vybádá, ukáže se, že celé řešení je na jeden řádek (nebo max na tři ;-)).
Takže například vytvoření knihovny: příslušné funkce prostě přesunete do samostatného projektu, a ten pak přidáte do závislostí (deps). Buď jako odkaz na lokální adresář, nebo odkaz na GitHub:
-
{:my_awesome_library, path: "../myawesomelibrary"}
-
{:my_awesome_library, git: "https://github.com/miladamilli/myawesomelibrary.git"}
Vykreslení SVG
Když mi to generovalo rozmístění „puntíků“, přidala jsem jim i vzhled – různé barvy, velikosti, průhlednost. Vlastně jednoduše vykresluju SVG objekty (circle) pomocí LiveView do HTML:
<%= for object <- @objects do %> < circle cx="<%= object.x %>" cy="<%= object.y %>" r="<%= object.style.radius %>" fill="<%= object.style.fill %>" /> <% end %>
A pomocí funkce EEx.eval_file
je skoro stejným způsobem vykreslím i do SVG souboru, který jde otevřít třeba v Inkscape. (Všechno se to učím v trochu zpřeházeném pořadí, takže nejdřív jsem uměla ovládat SVG pomocí LiveView, a až teď jsem zjistila, že LiveView vychází z EEx (Embedded Elixir), takže na exportu přímo do SVG vlastně není nic zvláštního a fungovalo to už dávno.)
Export do JPG
A pak se mi podařilo obrázek s využitím ImageMagick i překonvertovat z SVG do JPG!
System.cmd("convert", [file <> ".svg", file <> ".jpg"])
Teď ještě umět totéž online – ne jen u sebe na počítači, ale i na serveru. Zpětně vidím, že na tom taky nic není, ale to byl snad největší oříšek z celého procesu. :-) (Sehnat Heroku buildpack ImageMagicku – který funguje. A pak doladit SVG kód, aby se obrázek exportoval, jak má, protože lokální ImageMagick zřejmě ke konverzi využívá Inkscape, kdežto ten na Heroku ne, takže jeden rozezná průhlednost ve fill-opacity, druhý ji chce mít v HSLA barvě. A taky ty neexistující obrysy, které ale při konverzi najednou vidět jsou a dělají tam bordel… No nic, to jen abych nezapomněla :-))
Takže závěr, a zároveň začátek:
Výsledkem je kód, který generuje rovnoměrně náhodně rozmístěná kolečka, v náhodných barvách z daného rozmezí. A výsledný obrázek lze uložit. Trochu se mi zdá, že jsem omylem vyrobila aplikaci na vytváření originálních wallpaperů. :-)
Zde si ji můžete vyzkoušet online a něco vytvořit: Poisson Disc Sampling & Colors.
Ke stažení
Kód aplikace: Poisson & Colors (GitHub)
Knihovna Poisson disc sampling algorithm – Elixir (GitHub)
V češtině se o Elixiru můžete dozvědět více na blogu Elixirlab.cz o programovacím jazyku Elixir, kde jsem jedním z autorů, nebo sledovat náš twitter @elixirlabcz.