如果我理解正确,您想要的图像看起来好像有人对 ascii 艺术进行了截图,就像它在一个巨大的无限文本编辑器中一样。
我已经做了类似的事情来使用 PILLOW 以编程方式生成文本。这是一个从我的this 代码修改的示例。希望这段代码可以帮助您和其他人避免我必须做的摆弄才能弄清楚如何使事情看起来合理。
这是由以下代码生成的示例结果。
代码是对链接库的直接修改,以使用文本文件而不是字符串。您应该可以将其粘贴到控制台或文件中并直接运行。
from math import ceil
from PIL import (
Image,
ImageFont,
ImageDraw,
)
PIL_GRAYSCALE = 'L'
PIL_WIDTH_INDEX = 0
PIL_HEIGHT_INDEX = 1
COMMON_MONO_FONT_FILENAMES = [
'DejaVuSansMono.ttf', # Linux
'Consolas Mono.ttf', # MacOS, I think
'Consola.ttf', # Windows, I think
]
def main():
image = textfile_to_image('content.txt')
image.show()
image.save('content.png')
def textfile_to_image(textfile_path):
"""Convert text file to a grayscale image.
arguments:
textfile_path - the content of this file will be converted to an image
font_path - path to a font file (for example impact.ttf)
"""
# parse the file into lines stripped of whitespace on the right side
with open(textfile_path) as f:
lines = tuple(line.rstrip() for line in f.readlines())
# choose a font (you can see more detail in the linked library on github)
font = None
large_font = 20 # get better resolution with larger size
for font_filename in COMMON_MONO_FONT_FILENAMES:
try:
font = ImageFont.truetype(font_filename, size=large_font)
print(f'Using font "{font_filename}".')
break
except IOError:
print(f'Could not load font "{font_filename}".')
if font is None:
font = ImageFont.load_default()
print('Using default font.')
# make a sufficiently sized background image based on the combination of font and lines
font_points_to_pixels = lambda pt: round(pt * 96.0 / 72)
margin_pixels = 20
# height of the background image
tallest_line = max(lines, key=lambda line: font.getsize(line)[PIL_HEIGHT_INDEX])
max_line_height = font_points_to_pixels(font.getsize(tallest_line)[PIL_HEIGHT_INDEX])
realistic_line_height = max_line_height * 0.8 # apparently it measures a lot of space above visible content
image_height = int(ceil(realistic_line_height * len(lines) + 2 * margin_pixels))
# width of the background image
widest_line = max(lines, key=lambda s: font.getsize(s)[PIL_WIDTH_INDEX])
max_line_width = font_points_to_pixels(font.getsize(widest_line)[PIL_WIDTH_INDEX])
image_width = int(ceil(max_line_width + (2 * margin_pixels)))
# draw the background
background_color = 255 # white
image = Image.new(PIL_GRAYSCALE, (image_width, image_height), color=background_color)
draw = ImageDraw.Draw(image)
# draw each line of text
font_color = 0 # black
horizontal_position = margin_pixels
for i, line in enumerate(lines):
vertical_position = int(round(margin_pixels + (i * realistic_line_height)))
draw.text((horizontal_position, vertical_position), line, fill=font_color, font=font)
return image
if __name__ == '__main__':
main()
顺便说一句,所有代码不应该被塞进一个函数中,但我认为这样更容易理解示例代码。