Делаем ASCII-картинку из PNG
Все мы, как известно, живём в матрице, придуманной парой чокнутых трансгендеров. Из чисел в ней рождаются картинки, обманывающие мозг, а фальшивый виртуальный мирок, натянутый на глаза, только затем и нужен, чтобы скрыть правду.
ASCII-графика хорошо показывает идею матрицы :)
Тема ASCII-графики не нова и в сети можно найти разные подходы к её автоматической генерации. Ниже прилагается небольшой класс на PHP, предназначенный для изготовления чёрно-белого ASCII-образа из рисунка или фото в формате PNG.
Идея такого преобразования очень проста - рисунок попиксельно разбивается на образцы вида 0000, 0001, ...., 1110, 1111, затем образцам сопоставляются символы. Картинку для теста брал классическую, легко прикрутить к скрипту загрузку своего файла. В браузере матрица символов будет получаться довольно большой, так что уменьшаем размер комбинацией клавиш Ctrl+(серый_минус), вернуть потом масштаб по умолчанию можно будет комбинацией клавиш Ctrl+ноль (обычный).
Ниже показан исходник, проверенный на локальном хосте с PHP 7.X, предполагается, что скрипт будет сохранён в кодировке Юникода UTF-8.
<?php class Ascii { protected function yiq($r,$g,$b) { return (($r*0.299)+($g*0.587)+($b*0.114)); } //См. https://ru.wikipedia.org/wiki/YIQ protected function getSample ($sample, $sample_mean, $mean, $sigma) { switch ($sample) { case '0000': if ($sample_mean >= $mean + $sigma || $sample_mean >= 255) return ' '; else if ($sample_mean >= $mean + 0.33 * $sigma) return '.'; else if ($sample_mean >= $mean) return '*'; break; case '0001': case '0010': return ','; break; case '0011': case '0111': return '/'; break; case '0101': case '1010': return '='; break; case '0110': return '+'; break; case '1000': case '0100': return '`'; break; case '1001': return '"'; break; case '1011':return '>'; break; case '1100': case '1110': return '\\'; break; case '1101': return '<'; break; case '1111': if ($sample_mean <= $mean - $sigma || $sample_mean <= 0) return '@'; else if ($sample_mean <= $mean - 0.33 * $sigma) return 'O'; else if ($sample_mean <= $mean) return 'o'; break; } return ' '; } public function draw ($image) { $result = ''; $width = imagesx($image); $height = imagesy($image); $sum = 0; $count = 0; $yiq = array(); for ($y=0;$y < $height;$y++) { for ($x=0;$x < $width;$x++) { $rgb = imagecolorat($image, $x, $y); $r = ($rgb >> 16) & 0xff; $g = ($rgb >> 8) & 0xff; $b = $rgb & 0xff; $offset = $y * $width + $x; $yiq[$offset] = $this->yiq($r,$g,$b); $sum += $yiq[$offset]; $count++; } } $mean = $sum / $count; //среднее $sigma = 0; //среднеквадратичное отклонение foreach ($yiq as $k => $curr) $sigma += pow($curr - $mean, 2); $sigma = sqrt($sigma / $count); //считать всё попиксельно и вычислить среднее по образцу for ($y=0; $y < $height - 2; $y+=4) { //шаг по y другой, т.к. символ ASCII не квадратный for ($x=0; $x < $width - 2; $x+=2) { $sample = ''; $sample_mean = 0; for ($i = $y; $i < $y + 2; $i++) { for ($j = $x; $j < $x + 2; $j++) { $rgb = imagecolorat($image, $j, $i); $r = ($rgb >> 16) & 0xff; $g = ($rgb >> 8) & 0xff; $b = $rgb & 0xff; $yiq1 = $yiq[$i * $width + $j]; if ($yiq1 < $mean) $sample .= '1'; //черный else $sample .= '0'; //белый $sample_mean += $yiq1; } } $sample_mean /= 4; $result .= $this->getSample ($sample, $sample_mean, $mean, $sigma); } $result .= "\n"; } return $result; } } $filename = '1.png'; //получите свой файл или загрузите его из формы $ascii = new Ascii(); $image = imagecreatefrompng($filename); echo '<pre>'.$ascii->draw($image).'</pre>'; ?>
Скрипт не создаёт стандартное HTML-обрамление страницы.
Хозяйке на заметку: чтобы создать подпись в стиле ASCII Art, погуглите по запросу "ASCII Art text generator" и обрящете: раз, два, три и т.д.
13.11.2020, 18:36 [1736 просмотров]