'Python PIL decrease letter spacing
How can I decrease the letter spacing of this text? I want to make the text more squished together by a few pixels.
I'm trying to make a transparent image, with text on it, that I want pushed together. Like this, but transparent:
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")
Solution 1:[1]
This function will automate all the pain for you. It was written to emulate Photoshop values and can render leading (the space between lines) as well as tracking (the space between characters).
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]
It takes a font and a draw object, which can be obtained via:
font = ImageFont.truetype("Arial.ttf", 30)
draw = ImageDraw.Draw(image)
Solution 2:[2]
You have to draw the text character by character and then change the x coordinate when drawing the next
Example of code:
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)
Solution 3:[3]
You can do this by changing the kerning - I am not sure how to do that with PIL at the moment, but it is possible with ImageMagick in the Terminal and with Python using wand which is a Python binding to ImageMagick.
First, in the Terminal - look at the parameter -kerning
which is first minus three then plus three:
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
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
And, somewhat similarly in 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')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Mark Setchell |