我有一些代码可以将图像转换为ascii艺术图像。 目前它将其输出为.txt文件,但该文件可以有几十万个字符。如何将文件转换为图像,如.png文件?
目前,它会根据像素密度构建一个字符向量,然后将该向量写入.txt图像。
答案 0 :(得分:7)
如果我理解正确,你想要的图片看起来好像有人拍摄了ascii艺术的截图,就像在巨大的无限文本编辑器中看到的一样。
我做过类似的事情,用PILLOW以编程方式生成文本。以下是根据我的this代码修改的示例。希望这段代码可以帮助你和其他人避免摆弄我必须做的事情来弄清楚如何使事情看起来合理。
以下是根据以下代码制作的示例结果。
代码是链接库的直接修改,可以使用文本文件而不是字符串。
import PIL
import PIL.Image
import PIL.ImageFont
import PIL.ImageOps
import PIL.ImageDraw
PIXEL_ON = 0 # PIL color to use for "on"
PIXEL_OFF = 255 # PIL color to use for "off"
def main():
image = text_image('content.txt')
image.show()
image.save('content.png')
def text_image(text_path, font_path=None):
"""Convert text file to a grayscale image with black characters on a white background.
arguments:
text_path - the content of this file will be converted to an image
font_path - path to a font file (for example impact.ttf)
"""
grayscale = 'L'
# parse the file into lines
with open(text_path) as text_file: # can throw FileNotFoundError
lines = tuple(l.rstrip() for l in text_file.readlines())
# choose a font (you can see more detail in my library on github)
large_font = 20 # get better resolution with larger size
font_path = font_path or 'cour.ttf' # Courier New. works in windows. linux may need more explicit path
try:
font = PIL.ImageFont.truetype(font_path, size=large_font)
except IOError:
font = PIL.ImageFont.load_default()
print('Could not use chosen font. Using default.')
# make the background image based on the combination of font and lines
pt2px = lambda pt: int(round(pt * 96.0 / 72)) # convert points to pixels
max_width_line = max(lines, key=lambda s: font.getsize(s)[0])
# max height is adjusted down because it's too large visually for spacing
test_string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
max_height = pt2px(font.getsize(test_string)[1])
max_width = pt2px(font.getsize(max_width_line)[0])
height = max_height * len(lines) # perfect or a little oversized
width = int(round(max_width + 40)) # a little oversized
image = PIL.Image.new(grayscale, (width, height), color=PIXEL_OFF)
draw = PIL.ImageDraw.Draw(image)
# draw each line of text
vertical_position = 5
horizontal_position = 5
line_spacing = int(round(max_height * 0.8)) # reduced spacing seems better
for line in lines:
draw.text((horizontal_position, vertical_position),
line, fill=PIXEL_ON, font=font)
vertical_position += line_spacing
# crop the text
c_box = PIL.ImageOps.invert(image).getbbox()
image = image.crop(c_box)
return image
if __name__ == '__main__':
main()
顺便说一句,所有代码都可能不应该填充在一个函数中,但我认为它使得代码示例更简单。
答案 1 :(得分:0)
从以上链接的文档:
这是一个简单的例子:
import ImageFont, ImageDraw draw = ImageDraw.Draw(image) # use a bitmap font font = ImageFont.load("arial.pil") draw.text((10, 10), "hello", font=font) # use a truetype font font = ImageFont.truetype("arial.ttf", 15) draw.text((10, 25), "world", font=font)
答案 2 :(得分:0)
我喜欢上面的 ImageFont-ImageDraw 解决方案,因为它要短得多。但它并没有像我尝试的那样工作。因此,我想出了一些产生所需输出的方法。
在下面的示例代码中,第一个是生成白色图像。之后测试写在图片上:
from PIL import Image, ImageFont, ImageDraw
img = Image.new('RGB', (200, 50), color = (255,255,255))
fnt = ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", 30)
ImageDraw.Draw(img).text((0,0), "hello world", font=fnt, fill=(0,0,0))
img