ImageText module

The ImageText module defines a Text class. Instances of this class provide a way to use fonts with text strings or bytes. The result is a simple API to apply styling to pieces of text and measure or draw them.

Example

from PIL import Image, ImageDraw, ImageFont, ImageText
font = ImageFont.truetype("Tests/fonts/FreeMono.ttf", 24)

text = ImageText.Text("Hello world", font)
text.embed_color()
text.stroke(2, "#0f0")

print(text.get_length())  # 154.0
print(text.get_bbox())  # (-2, 3, 156, 22)

im = Image.new("RGB", text.get_bbox()[2:])
d = ImageDraw.Draw(im)
d.text((0, 0), text, "#f00")

Comparison

Without ImageText.Text:

from PIL import Image, ImageDraw
im = Image.new(mode, size)
d = ImageDraw.Draw(im)

d.textlength(text, font, direction, features, language, embedded_color)
d.multiline_textbbox(xy, text, font, anchor, spacing, align, direction, features, language, stroke_width, embedded_color)
d.text(xy, text, fill, font, anchor, spacing, align, direction, features, language, stroke_width, stroke_fill, embedded_color)

With ImageText.Text:

from PIL import ImageText
text = ImageText.Text(text, font, mode, spacing, direction, features, language)
text.embed_color()
text.stroke(stroke_width, stroke_fill)

text.get_length()
text.get_bbox(xy, anchor, align)

im = Image.new(mode, size)
d = ImageDraw.Draw(im)
d.text(xy, text, fill, anchor=anchor, align=align)

Methods

class PIL.ImageText.Text(text: str | bytes, font: ImageFont | FreeTypeFont | TransposedFont | None = None, mode: str = 'RGB', spacing: float = 4, direction: str | None = None, features: list[str] | None = None, language: str | None = None)[source]
embed_color() None[source]

Use embedded color glyphs (COLR, CBDT, SBIX).

get_bbox(xy: tuple[float, float] = (0, 0), anchor: str | None = None, align: str = 'left') tuple[float, float, float, float][source]

Returns bounding box (in pixels) of text.

Use get_length() to get the offset of following text with 1/64 pixel precision. The bounding box includes extra margins for some fonts, e.g. italics or accents.

Parameters:
  • xy – The anchor coordinates of the text.

  • anchor – The text anchor alignment. Determines the relative location of the anchor to the text. The default alignment is top left, specifically la for horizontal text and lt for vertical text. See Text anchors for details.

  • align – For multiline text, "left", "center", "right" or "justify" determines the relative alignment of lines. Use the anchor parameter to specify the alignment to xy.

Returns:

(left, top, right, bottom) bounding box

get_length() float[source]

Returns length (in pixels with 1/64 precision) of text.

This is the amount by which following text should be offset. Text bounding box may extend past the length in some fonts, e.g. when using italics or accents.

The result is returned as a float; it is a whole number if using basic layout.

Note that the sum of two lengths may not equal the length of a concatenated string due to kerning. If you need to adjust for kerning, include the following character and subtract its length.

For example, instead of:

hello = ImageText.Text("Hello", font).get_length()
world = ImageText.Text("World", font).get_length()
helloworld = ImageText.Text("HelloWorld", font).get_length()
assert hello + world == helloworld

use:

hello = (
    ImageText.Text("HelloW", font).get_length() -
    ImageText.Text("W", font).get_length()
)  # adjusted for kerning
world = ImageText.Text("World", font).get_length()
helloworld = ImageText.Text("HelloWorld", font).get_length()
assert hello + world == helloworld

or disable kerning with (requires libraqm):

hello = ImageText.Text("Hello", font, features=["-kern"]).get_length()
world = ImageText.Text("World", font, features=["-kern"]).get_length()
helloworld = ImageText.Text(
    "HelloWorld", font, features=["-kern"]
).get_length()
assert hello + world == helloworld
Returns:

Either width for horizontal text, or height for vertical text.

stroke(width: float = 0, fill: float | tuple[int, ...] | str | None = None) None[source]
Parameters:
  • width – The width of the text stroke.

  • fill – Color to use for the text stroke when drawing. If not given, will default to the fill parameter from ImageDraw.ImageDraw.text().