Skip to content

Performance of ImageDraw::text() and potential use of FTC_Manager() #6618

@time4tea

Description

@time4tea

What did you do?

Used Pillow to render frames outputting to ffmpeg - in project https://github.com/time4tea/gopro-dashboard-overlay
Pillow is great!

I'm trying to render frames as quickly as possible, as there are many frames to render in a 1 or 2 hour video - even at 10 frames/second

I'm using the text facilities of Pillow to render text into an Image. I cache text images where possible - so rendering fixed text strings is very quick - however, with a dynamic text string, such as a datetime or GPS location - caching isn't so effective.

Looking at the call stack of drawing some text.. it seems to look something like:

ImageDraw::draw_text()
  ImageFont::getmask2()
    Font::getsize() - implemented in imagingft.c font_getsize
    Font::render() - implemented in imagingft.c font_render

When you call these functions a lot - as I do - it becomes clear that these functions probably do a lot of similar work - in a python profile of a run of my software (there are multiple call routes here so don't worry they don't all add up!)

draw_text -> 2077 calls 8259ms
  getmask2 -> 2076 calls 7567ms
    Font::getsize -> 2595 calls 4171ms
    Font::render -> 2076 calls 4195ms

Looking at imagingft.c, - they both seem to call (in my case) text_layout_raqm, which, I'm guessing calls through to FT to get the glyphs for the given string - allowing for ligatures/kerning etc.

I was wondering... FT seems to allow for glyph caching using FTC_Manager - is there any appetite for adding support for this?

I think that, in the case of rendering lots of frames of text, it has the possibility of adding quite a bit of performance. (Which is probably not a major goal for Pillow, totally fair!)

For example, rendering a compass widget using Pillow, with a few open and filled circles, lots of compass lines, and bilinear resize for AA takes about 2.6ms, but when adding in 4 characters for "N", "S","E", "W" - takes 13ms. (I could optimise this particular use case, its just an example of how the text rendering compares to the rest of Pillow)

Thanks for reading this far!
Thanks for a super library!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions