ASCII は、ラテン文字をベースにしたコンピュータ コード システムで、主に現代英語やその他の西ヨーロッパ言語を表示するために使用されます。実は、ASCII 文字は情報交換の標準としてだけでなく、画像の生成にも使用できるので、今日はそれを紹介します。
インターネット上には、次のような文字で構成された画像がよくあります。
よく考えてみてください。ここで重要なのは、次のようないくつかの知識が使用されることです。
画像からピクセル カラーを解析する (通常は RGB 値)
脱色
文字へのピクセル マッピング
世界最高の言語である PHP では、興味深い関数を簡単に実装できます。具体的な実装については以下で説明します。
画像のピクセル カラーを分析するには、画像ストレージの形式を理解する必要があります。ここでは BMP 画像を例に挙げます。 。何? BMP 画像がオンラインで見つかりませんか? QQ を使用してスクリーンショットを撮り、BMP として保存するだけです。
BMP 画像には、ファイルの最初のバイトから始まるピクセル データはありませんが、ファイルのメタ情報を保存する 14 バイトの各ファイル ヘッダーがあります。その隣には 40 バイトの画像ヘッダー構造があり、画像に関連するメタ情報が格納されます。
ファイル ヘッダーと画像ヘッダー構造の各フィールドを詳細にリストするのは少し退屈です (詳細なヘッダー情報については、付録を参照してください)。画像のピクセルを解析するには、次の 4 つの情報だけが必要です:
$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. ピクセル カラーの取得とカラーの削除前のセクションからわかるように、写真の場合、ファイルの 54 バイト目からピクセル データが始まり、各ピクセル データは 24 ビットを占めます。この24ビットのうち、R(赤)、G(緑)、B(青)の値がそれぞれ8ビット(1バイト)を占めます。 画像の行 x と列 y の RGB 値を取得したい場合、対応する RGB 値の位置は次のように計算する必要があります。
像素(x, y)的 B 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y) 像素(x, y)的 G 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y) + 1 像素(x, y)的 R 值偏移 = 像素数据开始位置 + 3 * (图片宽度 * x + y) + 2これは、三原色の値を求める式 BGR の順序は通常の RGB の順序ではありません。 この方法に従って、キャンバス上にピクセルを 1 つずつ順番に描画すると、結果として得られる絵が上下逆さまになることがわかります。これは、絵のピクセル情報が上下逆さまに保存されているためです。左上隅のピクセルは実際にはファイルの最後にあるため、単純な画像を取得したい場合は、次のようにピクセル データを取得する必要があります。
像素(x, y)的 B 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 3 像素(x, y)的 G 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 2 像素(x, y)的 R 值偏移 = 文件大小 - 3 * (图片宽度 * x + y) - 1ピクセルの色が取得されます。 , しかし、最終的な ASCII 画像は白黒です。どうすればよいですか? 色の除去はどうすればよいですか?色の除去には多くのアルゴリズムがありますが、最も単純で粗雑なアルゴリズムを次に示します:
新的R、G、B值 = [min(R, G, B) + max(R, G, B)] / 2;黒と白のピクセルの場合、R、G、B はすべて同じ値を持ちます。この値は、ピクセルの明るさと呼ぶことができます。ピクセル最後に、ピクセルを取得する操作は関数として定義できます:
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. ピクセルから文字へのマッピング最後のステップでは、画像の各ピクセルの深さを ASCII 文字に変換します。 ASCII 文字自体には色合いがありません。しかし、「#」と「.」を100×100の正方形に配置すると、視覚的には「#」の方が「.」よりも暗くなります。 さまざまなピクセルの明るさを表すために複数の文字を使用できます。特定のピクセルの明るさが特定の範囲にある場合は、対応するレベルの文字に置き換えます:
function getChar($colorValue) { $map = '@#mdohsy+/-:.` '; return $map[(int) ($colorValue / 18)]; }別の質問: 各ピクセルを文字に置き換えると、出力される文字画像は非常に巨大になります。したがって、文字を使用して元の画像の NxN ピクセル ブロックを置き換えるのが最善です。ピクセル ブロック全体の明るさは、ブロック内の各ピクセルの平均明るさです。 上記の問題は解決されました。最後に、モナリザの笑顔を撮ってテストしてみました: その効果かなり良いです:-)。端末の背景が白の場合、明るさを表す文字列を
のように反転できます。
// $map = '@#mdohsy+/-:.` '; $map = ' `.:-/+yshodm#@'; // 反过来
<?php $data = file_get_contents('timg.bmp');$ret = unpack('v/Vsize/v/v/VpixelStart/V/Vwidth/Vheight/v/vbytePerPixel/V*6', substr($data, 0x0, 54));$size = $ret['size'];$offset = $ret['pixelStart'];$width = $ret['width'];$height = $ret['height'];$bitDepth = $ret['bytePerPixel'];$pixelLenPerChar = 4;$charImgWidth = (int) ($width / $pixelLenPerChar);$charImgHeight = (int) ($height / $pixelLenPerChar);for ($i = 0; $i !== $charImgHeight; $i++) { $buf = ''; 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)]; }
偏移 | 大小(字节) | 含义 | 本文中图片示例值 |
---|---|---|---|
0 | 2 | 固定为”BM”两个字符的编码 | 0x42 0x4d |
2 | 4 | 文件大小 | 0x000ac7fa |
6 | 4 | 保留字段,一般为 0 | 0x00000000 |
10 | 4 | 像素数据起始处偏移 | 0x00000036 |
偏移 | 大小(字节) | 含义 | 本文中图片示例值 |
---|---|---|---|
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视频教程
以上がASCII 文字を使用して画像を生成するコツを教えますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。