Heim >Backend-Entwicklung >PHP-Problem >Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren

Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-07-22 15:50:093304Durchsuche

ASCII ist ein Computerkodierungssystem, das auf dem lateinischen Alphabet basiert und hauptsächlich zur Darstellung von modernem Englisch und anderen westeuropäischen Sprachen verwendet wird. Tatsächlich können ASCII-Zeichen nicht nur als Standard für den Informationsaustausch verwendet werden, sondern auch zum Generieren von Bildern. Heute werden wir sie vorstellen.

Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren

Es gibt oft Bilder von Charakteren im Internet, wie zum Beispiel dieses:

Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren

Denken Sie darüber nach, hier werden hauptsächlich mehrere Kenntnisse verwendet, darunter:

  • Parsen Sie die Pixelfarbe aus dem Bild (Wird allgemein auch als RGB-Werte bezeichnet)

  • Entfärbung

  • Pixelzuordnung zu Zeichen

Als beste Sprache der Welt ist es einfach, interessante Funktionen mit PHP zu implementieren. Die konkrete Umsetzung wird im Folgenden erläutert.

1. Analysieren Sie die Pixelfarbe im Bild

Um die Pixelfarbe im Bild zu analysieren, müssen wir das Format der Bildspeicherung verstehen. Hier nehmen wir BMP-Bilder als Beispiel. Was? Sie können keine BMP-Bilder online finden? Verwenden Sie einfach QQ, um einen Screenshot zu erstellen und ihn als BMP zu speichern.

BMP-Bilder enthalten keine Pixeldaten ab dem ersten Byte der Datei, sondern jeden 14-Byte-Dateiheader, in dem die Metainformationen der Datei gespeichert sind. Daneben befindet sich eine 40-Byte-Bildheaderstruktur, in der Metainformationen zum Bild gespeichert sind.

Es wäre etwas zu langweilig, jedes Feld der Datei-Header- und Bild-Header-Struktur im Detail aufzulisten (detaillierte Header-Informationen finden Sie im Anhang). Um die Pixel eines Bildes zu analysieren, benötigen Sie nur diese 4 Informationen:

  • Die Gesamtgröße der Bilddatei (3. bis 6. Byte der Datei)

  • Wo in der Datei die Pixeldaten beginnen ( 11 bis 14 Bytes)

  • Die Breite und Höhe des Bildes (Breite: 19~22 Bytes, Höhe: 23~26 Bytes)

  • Wie viele Bytes belegt ein Pixel des Bildes (29~30 Zeichen). Abschnitt)

Wenn Sie die Daten im Binärformat analysieren möchten, können Sie unpack() in Kombination mit substr():

$data = file_get_contents('image.bmp');$ret = unpack('v/Vsize/v/v/VpixelStart/V/Vwidth/Vheight/v/vbytePerPixel/V*6',
    substr($data, 0x0, 54));/**
 * $ret的内容:
 * array (
 *     'size' => 706554,
 *     'pixelStart' => 54,
 *     'width' => 500,
 *     'height' => 471,
 *     'bytePerPixel' => 24,
 * );
 */

2 verwenden. Pixelfarbe abrufen und Farbe entfernen

Wie Sie aus dem vorherigen Abschnitt wissen können , wir wollen Für das verarbeitete Bild beginnen die Pixeldaten ab dem 54. Byte der Datei und jede Pixeldaten belegt 24 Bit. Unter diesen 24 Bits belegen die Werte von R (rot), G (grün) und B (blau) jeweils 8 Bits (1 Byte).

Wenn ich den RGB-Wert der x-ten Zeile und der y-ten Spalte des Bildes erhalten möchte, sollte die Position des entsprechenden RGB-Werts wie folgt berechnet werden:

像素(x, y)的 B 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y)
像素(x, y)的 G 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y) + 1
像素(x, y)的 R 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y) + 2

Aus der Formel wird ermittelt, dass der Die Werte der drei Primärfarben sind in der BGR-Reihenfolge angeordnet, was nicht der üblichen RGB-Reihenfolge entspricht.

Wenn Sie dieser Methode folgen und die Pixel der Reihe nach auf eine Leinwand zeichnen, werden Sie feststellen, dass das resultierende Bild auf dem Kopf steht. Dies liegt daran, dass die Pixelinformationen des Bildes verkehrt herum gespeichert sind Die linke Ecke befindet sich tatsächlich am Ende der Datei. Wenn Sie also ein direktes Bild erhalten möchten, sollten die Pixeldaten wie folgt abgerufen werden:

像素(x, y)的 B 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 3
像素(x, y)的 G 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 2
像素(x, y)的 R 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 1

Die Farbe des Pixels wird abgerufen, aber das endgültige ASCII Das Bild ist schwarzweiß. Wie entferne ich die Farbe? Es gibt viele Algorithmen zur Farbentfernung. Hier ist der einfachste und gröbste:

新的R、G、B值 = [min(R, G, B) + max(R, G, B)] / 2;

Schwarze und weiße Pixel, R, G und B haben alle den gleichen Wert. Dieser Wert kann als Helligkeit des Pixels bezeichnet werden. Die Operation zum Aufnehmen des Pixels kann als Funktion definiert werden:

function getPixelColor($x, $y) {
    global $width, $size, $data;
    $b = ord($data[$size - 3 * ($width * $x + $y) - 3]);
    $g = ord($data[$size - 3 * ($width * $x + $y) - 2]);
    $r = ord($data[$size - 3 * ($width * $x + $y) - 1]);
    return (min($r, $g, $b) + max($r, $g, $b)) >> 1;
}

3. Pixel-zu-Zeichen-Zuordnung

Im letzten Schritt müssen wir die Tiefe jedes Pixels des Bildes in ASCII-Zeichen konvertieren. ASCII-Zeichen selbst haben keine Farbschattierungen. Wenn Sie „#“ und „.“ jedoch in 100x100-Quadraten anordnen, ist „#“ optisch dunkler als „.“

Wir können mehrere Zeichen verwenden, um die Helligkeit verschiedener Pixel darzustellen. Wenn die Helligkeit eines bestimmten Pixels in einem bestimmten Bereich liegt, ersetzen Sie sie durch die entsprechende Zeichenebene:

function getChar($colorValue) {
    $map = '@#mdohsy+/-:.` ';
    return $map[(int) ($colorValue / 18)];
}

Es gibt noch eine andere Frage: ob jedes Pixel verwendet wird Wenn ein Zeichen ersetzt wird, ist das ausgegebene Zeichenbild sehr groß. Daher ist es am besten, die NxN-Pixelblöcke im Originalbild durch ein Zeichen zu ersetzen. Die Helligkeit des gesamten Pixelblocks ist die durchschnittliche Helligkeit jedes Pixels im Block.

Die oben genannten Probleme wurden gelöst. Machen Sie zum Schluss ein Foto von Mona Lisas Lächeln:

Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren

Bringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generierenDer Effekt ist nicht schlecht :-). Wenn der Hintergrund des Terminals weiß ist, kann die Reihenfolge der Zeichen, die die Helligkeit darstellen, umgekehrt werden:

// $map = '@#mdohsy+/-:.` ';
$map = ' `.:-/+yshodm#@'; // 反过来

附录

完整代码

<?php $data = file_get_contents(&#39;timg.bmp&#39;);$ret = unpack(&#39;v/Vsize/v/v/VpixelStart/V/Vwidth/Vheight/v/vbytePerPixel/V*6&#39;, substr($data, 0x0, 54));$size = $ret[&#39;size&#39;];$offset = $ret[&#39;pixelStart&#39;];$width = $ret[&#39;width&#39;];$height = $ret[&#39;height&#39;];$bitDepth = $ret[&#39;bytePerPixel&#39;];$pixelLenPerChar = 4;$charImgWidth = (int) ($width / $pixelLenPerChar);$charImgHeight = (int) ($height / $pixelLenPerChar);for ($i = 0; $i !== $charImgHeight; $i++) {    $buf = &#39;&#39;;    for ($j = 0; $j !== $charImgWidth; $j++) {        $sum = 0;        for ($k = 0; $k !== $pixelLenPerChar; $k++) {            for ($l = 0; $l !== $pixelLenPerChar; $l++) {                $sum += getPixelColor($pixelLenPerChar * $i + $k, $pixelLenPerChar * $j + $l);
            }
        }        $sum = (int) ($sum / $pixelLenPerChar / $pixelLenPerChar);        $buf = getChar($sum) . $buf;
    }    echo $buf . PHP_EOL;
}function getPixelColor($x, $y) {
    global $width, $size, $data;    $b = ord($data[$size - 3 * ($width * $x + $y) - 3]);    $g = ord($data[$size - 3 * ($width * $x + $y) - 2]);    $r = ord($data[$size - 3 * ($width * $x + $y) - 1]);    return (min($r, $g, $b) + max($r, $g, $b)) >> 1;
}function getChar($colorValue) {
    $map = '@#mdohsy+/-:.` ';    return $map[(int) ($colorValue / 18)];
}

BMP文件头格式

偏移 大小(字节) 含义 本文中图片示例值
0 2 固定为”BM”两个字符的编码 0x42 0x4d
2 4 文件大小 0x000ac7fa
6 4 保留字段,一般为 0 0x00000000
10 4 像素数据起始处偏移 0x00000036

BMP图片头格式

偏移 大小(字节) 含义 本文中图片示例值
14 4 图片头的大小(字节) 0x00000028
18 4 图片的宽度 0x000001f4
22 4 图片的高度 0x000001d7
26 2 图像的帧数(静态图都是1) 0x0001
28 2 一个像素占的比特位数 0x0018
30 4 保留字段,一般为 0 0x000000
34 4 像素数据占用的总字节数 0x000ac7c4
38 4 保留字段,一般为 0 0x000000
42 4 保留字段,一般为 0 0x000000
46 4 保留字段,一般为 0 0x000000
50 4 保留字段,一般为 0 0x000000

推荐学习:php视频教程

Das obige ist der detaillierte Inhalt vonBringen Sie Ihnen einen Trick bei, um Bilder mit ASCII-Zeichen zu generieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen