November 18, 2020

Подобие на ASCII арт на Python + Pillow

Результат работы:


Начнём как обычно с импортов зависимостей:

from PIL import Image, ImageDraw, ImageFont
import random
import math

Я не стал разбивать код на функции так как его не много. Начнём с так называемых констант:

BACK_COLOR = "BLACK"
IN_IMG = '1.png'
FNT = ImageFont.truetype('4.TTF', 7)

Сначала зададим цвет фона. Затем исходное изображение, оно обязательно должно быть png с прозрачными местами. Далее идут настройки шрифта. Советую использовать этот шрифт и размер, т.к. для него все рассчитано (количество символов на строку и количество строк на размер файла).

Далее нам необходимо узнать разрешение файла что бы составить для него текст который будет заполнять всю картинку, благодаря чему наша надпись картинка будет выглядеть так будто написана единицами и нулями

im = Image.open(IN_IMG)
(width, height) = im.size

Получаем мы значения в таком формате: (1920, 1080).
Я рассчитал что на квадрат из 50 пикселей нужно 13 символов в строку и 6 строк.

Исходя из этого будет считать сколько символов нам понадобиться:

line = math.ceil(im.size[0]/50 * 13 * 1.2)
row = math.ceil(im.size[1]/50 * 6 * 1.2)

Тут в конце умножение на 1.2 т.к. при тестировании с английским алфавитом картинка наполняется символами не до конца. То есть мы просто умножаем на 20%.

Дальше пойдет цикл генерации строки:

string = ''
for i in range(row):
	for j in range(line):
		string += str(random.choice([0, 1]))
	string += '\n'

Тут все довольно таки просто. Row это количество строк, а line это сама строка. Тут мы генерируем большую строку для заполнения картинки.

Далее нам необходимо создать изображение с фоном который мы указали в константах:

img = Image.new('RGBA', (im.size[0], im.size[1]), BACK_COLOR)    
draw_text = ImageDraw.Draw(img)
draw_text.text((1,1), string, spacing=1, font=FNT, fill=0)
img2 = Image.open(IN_IMG)
alphaComposited = Image.alpha_composite(img2, img)

Тут мы сначала создаём изображение с размерами как у того что будем "рисовать", задаём ему цвет который указан в константе, затем рисуем это изображение, после этого записываем на него сгенерированный ранее текст из едениц и нулей, после чего открываем оригинальное изображение и совмещаем созданную нами картинку с той что была указана в константе (путь до неё).

Далее мы будем делать из png картинки jpeg. Сначала берём ту картинку что была создана на прошлом шаге. Затем мы создаём новое изображение на которое будем помещать наше, заливаем фон цветом который был указан в константе, размер берём от изначального изображения. Далее вставляем ранее сгенерированную картинку на нашу картинку, конвертируем, конвертируем в RGB, сохраняем, после чего открываем для просмотра.

image = alphaComposited
new_image = Image.new("RGBA", image.size, BACK_COLOR) 
new_image.paste(image, (0, 0), image) 
new_image.convert('RGB').save('READY_RESULT.jpg', "JPEG") 
img22 = Image.open('READY_RESULT.jpg')
img22.show()

Полный листинг программы:

from PIL import Image, ImageDraw, ImageFont
import random
import math


BACK_COLOR = "BLACK"
IN_IMG = '1.png'
FNT = ImageFont.truetype('4.TTF', 7)


im = Image.open(IN_IMG)
(width, height) = im.size


line = math.ceil(im.size[0]/50 * 13 * 1.2)
row = math.ceil(im.size[1]/50 * 6 * 1.2)


string = ''
for i in range(row):
	for j in range(line):
		string += str(random.choice([0, 1]))
	string += '\n'
	

img = Image.new('RGBA', (im.size[0], im.size[1]), BACK_COLOR)    
draw_text = ImageDraw.Draw(img)
draw_text.text((1,1), string, spacing=1, font=FNT, fill=0)
img2 = Image.open(IN_IMG)
alphaComposited = Image.alpha_composite(img2, img)


image = alphaComposited
new_image = Image.new("RGBA", image.size, BACK_COLOR) 
new_image.paste(image, (0, 0), image) 
new_image.convert('RGB').save('READY_RESULT.jpg', "JPEG") 
img22 = Image.open('READY_RESULT.jpg')
img22.show()
Прошу меня простить за мой ужасный код, вы всегда можете модифицировать мой код и использовать как хотите, я не несу за это ответственности.

Телеграм канал: https://t.me/CodingCommunity