【问题标题】:Converting a .txt file to an image in Python在 Python 中将 .txt 文件转换为图像
【发布时间】:2015-04-20 23:45:08
【问题描述】:

我有一些将图像转换为 ascii 艺术图像的代码。 目前它将其输出为 .txt 文件,但该文件可以有几十万个字符。如何将文件转换为 .png 文件等图像?

目前它根据像素密度构建一个字符向量,然后将向量写入一个.txt图像。

【问题讨论】:

  • 澄清一下,.txt 文件是 ascii 艺术,您想要文本的图像(如屏幕截图)?
  • 是的,完全正确。我想输出一个看起来像 .txt 文件的 png。
  • 我根据我过去所做的事情发布了一个答案。以后,我建议您多花点精力创建一个Minimal, Complete and Verifiable Example。我认为你会得到更热情的回答和更多的答案,因为这表明你已经为这个问题付出了一些努力。在这种情况下,如果您对代码一无所知,至少您应该提供一个示例输入并尽可能描述您想要的输出。

标签: python ipython


【解决方案1】:

如果我理解正确,您想要的图像看起来好像有人对 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()

顺便说一句,所有代码不应该被塞进一个函数中,但我认为这样更容易理解示例代码。

【讨论】:

  • 非常感谢,效果很好!如何用这段代码使文本换行?
  • 抱歉,不确定您的意思。如果是简单的改变,你能解释得更详细吗?如果这是一个重大变化,您可能想提出一个新问题并参考这个问题。
  • 谢谢,我的意思是:将文本粘贴到类似的列中,而不仅仅是一个高列。我想我做到了,我完成了 95% 的代码。我想让图像变成正方形,所以我做了一些数学运算,math.sqrt(N_lines)....,这里是代码pastebin.com/jPWy9J0e,它并不完美,你知道为什么文本没有在所有列上平均分割吗?这是输出imgur.com/a/OOvnrF7
  • 我明白了。这是一个完全不同的问题,所以如果您仍然需要帮助,我建议您开始一个新问题。即使您已经解决了,上次我检查时也允许发布问题并自己回答。这可能会对某人有所帮助。
【解决方案2】:

看看Pillow(文档here

从上面的链接文档:

这是一个简单的例子:

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)

【讨论】:

  • 我已经有一段时间没有使用 PIL 了,所以不知道它的状态,也不知道 Pillow 已经成功了 - 我已经更新了答案以反映这一点。
  • 问题是“如何将文件转换为 .png 文件等图像?”我认为指向提供这样做的方法的库是一个合适的答案。
  • 如果您可以使用 Pillow(或任何其他库)显示一段工作代码,该代码读取 ASCII 艺术并吐出 PNG,我肯定会支持您的答案。
【解决方案3】:

我喜欢上面的 ImageFont-ImageDraw 解决方案,因为它要短得多。但是当我尝试它时它没有用。因此,我想出了一些产生所需输出的方法。

在下面的示例代码 1 中,生成了一个白色图像。然后将测试写在图像上:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-13
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多