Python PIL 减少字母间距

13

我该如何减少这段文本的字母间距?我想将文本压缩几个像素,使其更紧凑。

我正在尝试制作一个带有文本的透明图像,我希望将文本挤在一起。像这样,但是是透明的:

image

from PIL import Image, ImageDraw, ImageFont

(W, H) = (140, 40)

#create transparent image
image = Image.new("RGBA", (140, 40), (0,0,0,0))

#load font
font = ImageFont.truetype("Arial.ttf", 30)
draw = ImageDraw.Draw(image)

text = "kpy7n"
w,h = font.getsize(text)

draw.text(((W-w)/2,(H-h)/2), text, font=font, fill=0)

image.save("transparent-image.png")

你的代码片段中似乎没有定义 code 的值?在 w,h = font.getsize(code) 中。 - ScottMcC
@ScottMcC 抱歉,那是个错误,我重命名了变量并忘记了那行代码。 - toast
3个回答

7

这个函数将为您自动化所有的痛苦。它被编写成模拟Photoshop值,可以呈现行距(行之间的空间)和字距(字符之间的空间)。

def draw_text_psd_style(draw, xy, text, font, tracking=0, leading=None, **kwargs):
    """
    usage: draw_text_psd_style(draw, (0, 0), "Test", 
                tracking=-0.1, leading=32, fill="Blue")

    Leading is measured from the baseline of one line of text to the
    baseline of the line above it. Baseline is the invisible line on which most
    letters—that is, those without descenders—sit. The default auto-leading
    option sets the leading at 120% of the type size (for example, 12‑point
    leading for 10‑point type).

    Tracking is measured in 1/1000 em, a unit of measure that is relative to 
    the current type size. In a 6 point font, 1 em equals 6 points; 
    in a 10 point font, 1 em equals 10 points. Tracking
    is strictly proportional to the current type size.
    """
    def stutter_chunk(lst, size, overlap=0, default=None):
        for i in range(0, len(lst), size - overlap):
            r = list(lst[i:i + size])
            while len(r) < size:
                r.append(default)
            yield r
    x, y = xy
    font_size = font.size
    lines = text.splitlines()
    if leading is None:
        leading = font.size * 1.2
    for line in lines:
        for a, b in stutter_chunk(line, 2, 1, ' '):
            w = font.getlength(a + b) - font.getlength(b)
            # dprint("[debug] kwargs")
            print("[debug] kwargs:{}".format(kwargs))
                
            draw.text((x, y), a, font=font, **kwargs)
            x += w + (tracking / 1000) * font_size
        y += leading
        x = xy[0]

需要使用字体和绘图对象,可以通过以下方式获得:

font = ImageFont.truetype("Arial.ttf", 30)
draw = ImageDraw.Draw(image)

1
你需要逐个字符地绘制文本,然后在绘制下一个字符时更改x坐标。
代码示例:
w,h = font.getsize("k")
draw.text(((W,H),"K", font=font, fill=0)
draw.text(((W+w)*0.7,H),"p", font=font, fill=0)
draw.text(((W+w*2)*0.7,H),"y", font=font, fill=0)
draw.text(((W+w*3)*1,H),"7", font=font, fill=0)
draw.text(((W+w*4)*0.8,H),"n", font=font, fill=0)

1
您可以通过改变字距来实现这一点 - 我目前不确定如何使用PIL进行操作,但是在终端中使用ImageMagick或者使用Python的wand库(它是一个Python绑定到ImageMagick的库)都是可行的。
首先,在终端中查看参数-kerning,它首先为负三然后为正三。
magick -size 200x80 xc:black -gravity center -font "Arial Bold.ttf" -pointsize 50 -kerning -3 -fill white -draw "text 0,0 'kpy7n'" k-3.png

enter image description here

magick -size 200x80 xc:black -gravity center -font "Arial Bold.ttf" -pointsize 50 -kerning 3 -fill white -draw "text 0,0 'kpy7n'" k+3.png

在此输入图片描述

类似地,在Python中:

#!/usr/bin/env python3

# Needed this on macOS Monterey:
# export WAND_MAGICK_LIBRARY_SUFFIX="-7.Q16HDRI"
# export MAGICK_HOME=/opt/homebrew

from wand.image import Image
from wand.drawing import Drawing
from wand.font import Font

text = "kpy7n"

# Create a black canvas 400x120
with Image(width=400, height=120, pseudo='xc:black') as image:
    with Drawing() as draw:
        # Draw once in yellow with positive kerning
        draw.font_size = 50
        draw.font = 'Arial Bold.ttf'
        draw.fill_color = 'yellow'
        draw.text_kerning = 3.0
        draw.text(10, 80, text)
        draw(image)
        # Draw again in magenta with negative kerning
        draw.fill_color = 'magenta'
        draw.text_kerning = -3.0
        draw.text(200, 80, text)
        draw(image)
    image.save(filename='result.png')

enter image description here


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