Když se na serveru Root.cz chystalo uvedení nové verze, byla s tím spojená soutěž. Nejzajímavější mi přišel 4. díl, jehož řešení jsem si napsal v PHP. Nejprve je samozřejmě nutné na postup řešení přijít – to je asi ta zajímavější část, takže pokud o radost z vlastního vyřešení nechcete být ochuzeni, dále nečtěte a s řešením se nejprve sami potrapte.
První úkol je relativně jednoduchý – dvojbarevný obrázek má obě barvy v paletě nastavené na stejnou hodnotu RGB, takže splývají. Když jim nastavíme různou barvu, můžeme si všimnout, že je obrázek složen z kousků stejné šířky a různé výšky. Seřazením těchto kousků podle velikosti by mohlo něco vzniknout:
<?php $step = 30; // rozřezání obrázku na části $im = imagecreatefromgif("http://www.root.cz/data/soutez-4.gif"); imagecolorset($im, 1, 255, 255, 255); imagecolorset($im, 2, 0, 0, 0); $parts = array(); $max_y = 0; for ($x=0; $x < imagesx($im); $x += $step) { for ($y=0; $y < imagesy($im); $y++) { if (imagecolorat($im, $x, $y) != 0) { $y0 = $y; $y++; while (imagecolorat($im, $x, $y) != 0 && $y < imagesy($im)) { $y++; } $parts[$y-$y0] = array($x, $y0); $max_y = max($max_y, $y-$y0); } } } ksort($parts); // poskládání částí do nového obrázku $im2 = imagecreate(30 * count($parts), $max_y); imagepalettecopy($im2, $im); $x = 0; foreach ($parts as $key => $val) { imagecopy($im2, $im, $x, 0, $val[0], $val[1], $step, $key); $x += $step; } imagedestroy($im); ?>
Práci máme usnadněnou tím, že kousky nejsou v obrázku rozházeny náhodně, ale jsou seřazeny do pravidelných sloupců. Po zatřídění kousků do pole se zkopírují do nového obrázku, který se následně zobrazí:
<?php // OCR :-) header("Content-Type: image/gif"); imagegif($im2); // po přečtení obsahu obrázku zakomentovat $url = "http://www.root.cz/data/soutez-4-wsxqaz.zip"; imagedestroy($im2); ?>
URL je jednodušší z obrázku přečíst, než si psát OCR… Z uvedené adresy stáhneme archiv, ve kterém najdeme dva soubory. Jeden soubor obsahuje liché řádky výsledného obrázku, druhý sudé, barvy jsou uložené v hexadecimálním tvaru se znaky fedcba
zaměněnými za uvwxyz
:
<?php // načtení souborů v ZIPu $filename = "soutez-4.zip"; copy($url, $filename); $files = array(); $zip = zip_open($filename); while ($zip_entry = zip_read($zip)) { zip_entry_open($zip, $zip_entry); $file = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry)); $files[zip_entry_name($zip_entry)] = explode("\n", strtr($file, "uvwxyz", "fedcba")); zip_entry_close($zip_entry); } zip_close($zip); unlink($filename); ?>
Práci se vzdálenými soubory knihovna ZIP nedovoluje, proto je soubor nejprve zkopírován. Do každého ze dvou prvků pole $files
je uloženo pole jednotlivých řádek souborů již s opravenými kódy barev. Spojení těchto dvou polí do jednoho řetězce je tedy jednoduché:
<?php // spojení lichých a sudých řádek $output = ""; foreach ($files["1.txt"] as $l => $line) { $output .= $files["2.txt"][$l] . " "; $output .= "$line "; } ?>
Nyní již zbývá řetězec jen rozdělit do jednotlivých řádek obrázku podle oddělovače X
a výsledný obrázek vypsat:
<?php // poskládání výsledného obrázku $lines = explode(" X ", substr($output, 0, -1)); $im = imagecreatetruecolor(2 * substr_count(reset($lines), " ") + 1, count($lines)); $y = 0; foreach ($lines as $line) { $x = 0; foreach (explode(" ", $line) as $color) { imagesetpixel($im, $x, $y, hexdec($color)); $x++; } $y++; } header("Content-Type: image/png"); imagepng($im); ?>
Zdrojová data obsahují chybu, proto je obrázek vytvořen v dvojnásobné šířce, aby se špatně umístěné řádky měly kam vypsat.
Je radost v PHP takový kód psát – především díky mocným polím a také díky hotovým knihovnám – zde na práci s obrázky a se ZIP archivy.
Diskuse je zrušena z důvodu spamu.