如何轻松打印 ASCII 艺术文字?

64

我有一个程序会输出大量内容,我希望其中一些内容可以脱颖而出。一种方法是使用ASCII艺术渲染重要文本,例如,像这个网站所做的那样:

 #    #   ##   #####  #    # # #    #  ####  
 #    #  #  #  #    # ##   # # ##   # #    # 
 #    # #    # #    # # #  # # # #  # #      
 # ## # ###### #####  #  # # # #  # # #  ### 
 ##  ## #    # #   #  #   ## # #   ## #    # 
 #    # #    # #    # #    # # #    #  ####  

其他解决方案可以将输出着色或加粗。那么如何在Python中轻松实现这种操作呢?


2
你可以调用 figlet,一个 Unix 实用程序。 - Marcin
1
@Marcin:谢谢,figlet看起来很不错!有些人甚至似乎已经为它实现了Python包装器。 - static_rtti
1
这里有一个纯Python的figlet端口:https://github.com/pwaller/pyfiglet - Adam
1
不知道 figlet(听起来哪个更好),但是你在问题中描述的正是 banner 的输出。祝你好运。 - shellter
尝试使用此代码 - https://dev59.com/yGDVa4cB1Zd3GeqPb0dX#70863752 - Jotham
显示剩余2条评论
3个回答

107
pip install pyfiglet
  • termcolor - 用于 ANSI 颜色格式化的辅助函数

  • pip install termcolor
    
  • colorama - 多平台支持(Windows)

  • pip install colorama
    
    import sys
    
    from colorama import init
    init(strip=not sys.stdout.isatty()) # strip colors if stdout is redirected
    from termcolor import cprint 
    from pyfiglet import figlet_format
    
    cprint(figlet_format('missile!', font='starwars'),
           'yellow', 'on_red', attrs=['bold'])
    

    示例

    $ python print-warning.py 
    

    导弹

    $ python print-warning.py | cat
    .___  ___.  __       _______.     _______. __   __       _______  __ 
    |   \/   | |  |     /       |    /       ||  | |  |     |   ____||  |
    |  \  /  | |  |    |   (----`   |   (----`|  | |  |     |  |__   |  |
    |  |\/|  | |  |     \   \        \   \    |  | |  |     |   __|  |  |
    |  |  |  | |  | .----)   |   .----)   |   |  | |  `----.|  |____ |__|
    |__|  |__| |__| |_______/    |_______/    |__| |_______||_______|(__)
    

    10
    感谢大力支持导弹预警系统! :) - CppLearner
    4
    如果你被导弹击中,那么你的眼睛可能不是唯一感到灼热的部位。 - jfs

    37

    PIL提供了一种很酷的方法来完成这个非常简单的任务。您可以将文本呈现在黑白图像上,然后将该位图转换为字符串流,将黑色和白色像素替换为字符。

    from PIL import Image, ImageFont, ImageDraw
    
    ShowText = 'Python PIL'
    
    font = ImageFont.truetype('arialbd.ttf', 15) #load the font
    size = font.getsize(ShowText)  #calc the size of text in pixels
    image = Image.new('1', size, 1)  #create a b/w image
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), ShowText, font=font) #render the text to the bitmap
    for rownum in range(size[1]): 
    #scan the bitmap:
    # print ' ' for black pixel and 
    # print '#' for white one
        line = []
        for colnum in range(size[0]):
            if image.getpixel((colnum, rownum)): line.append(' '),
            else: line.append('#'),
        print ''.join(line)
     
    

    它呈现了下一个结果:

     #######                 ##                              #######   ##  ##
     ##   ###           ##   ##                              ##   ###  ##  ##
     ##    ##           ##   ##                              ##    ##  ##  ##
     ##    ## ##    ## ####  ######     ####    ######       ##    ##  ##  ##
     ##    ##  ##  ###  ##   ###  ##   ##  ##   ###  ##      ##    ##  ##  ##
     ##   ##   ##  ##   ##   ##   ##  ##    ##  ##   ##      ##   ##   ##  ##
     ######    ##  ##   ##   ##   ##  ##    ##  ##   ##      ######    ##  ##
     ##         ## #    ##   ##   ##  ##    ##  ##   ##      ##        ##  ##
     ##         ####    ##   ##   ##  ##    ##  ##   ##      ##        ##  ##
     ##         ####    ##   ##   ##   ##  ##   ##   ##      ##        ##  ##
     ##          ##     ###  ##   ##    ####    ##   ##      ##        ##  ########
                 ##
                 ##
               ###             
             ##
           ###
    

    我用函数式编程方式制作了一个更为全面的例子。

    import Image, ImageFont, ImageDraw
    
    ShowText = 'Python PIL'
    
    
    font = ImageFont.truetype('arialbd.ttf', 15) #load the font
    size = font.getsize(ShowText)  #calc the size of text in pixels
    image = Image.new('1', size, 1)  #create a b/w image
    draw = ImageDraw.Draw(image)
    draw.text((0, 0), ShowText, font=font) #render the text to the bitmap
    
    def mapBitToChar(im, col, row):
        if im.getpixel((col, row)): return ' '
        else: return '#'
    
    for r in range(size[1]):
        print ''.join([mapBitToChar(image, c, r) for c in range(size[0])])
    

    13

    这真是有趣。我已经弄清楚如何使用PIL(当然是“Pillow”分支版本)和Numpy来完全“向量化”进行操作,即无需循环:

    text = "Hi there"
    from PIL import Image, ImageDraw, ImageFont
    import numpy as np
    myfont = ImageFont.truetype("verdanab.ttf", 12)
    size = myfont.getbbox(text)[2:]
    img = Image.new("1",size,"black")
    draw = ImageDraw.Draw(img)
    draw.text((0, 0), text, "white", font=myfont)
    pixels = np.array(img, dtype=np.uint8)
    chars = np.array([' ','#'], dtype="U1")[pixels]
    strings = chars.view('U' + str(chars.shape[1])).flatten()
    print( "\n".join(strings))
    

               ##           ##                            
     ##    ##  ##      ##   ##                            
     ##    ##          ##   ##                            
     ##    ##  ##     ##### #####    ####   ## ##  ####   
     ##    ##  ##      ##   ##  ##  ##  ##  ##### ##  ##  
     ########  ##      ##   ##  ##  ##  ##  ##    ##  ##  
     ##    ##  ##      ##   ##  ##  ######  ##    ######  
     ##    ##  ##      ##   ##  ##  ##      ##    ##      
     ##    ##  ##      ##   ##  ##  ##   #  ##    ##   #  
     ##    ##  ##       ### ##  ##   ####   ##     ####   
    

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接