Skip to content

Major (non-linear) performance regression with ImageDraw.polygon #5700

@ntninja

Description

@ntninja

What did you do?

See the sample program below for a minimal test case – it simply draws a polygon from a list of input coordinates.

What did you expect to happen?

Time taken to render the polygon line to be linear (and very small) even for 100'000s of points.

What actually happened?

Apparently in any Pillow version after 7.0.0 the time taken to draw coordinate lists appears to increase non-linear with the number of input coordinates. When processing larger input files we regularily end up with 100'000s or perhaps even 1'000'000s points to be (nicely) drawn by Pillow for file visualization. With 7.0.0 this was no problem, with drawing times hardly ever exceeding a second at most, but since 7.1.1 (and likely also 7.1.0) the drawing suddenly turned into the slowest part of our production pipeline for larger files.

What are your OS, Python and Pillow versions?

  • OS: Linux x86-64 with Conda
  • Python: 3.6 or 3.9
  • Pillow: 7.1.1 (and any later version, 7.1.0 is likely affected too ) – using conda-forge build

Very likely related: #4333

#!/usr/bin/env python3                                                              
import json                                                                         
                                                                                    
from PIL import Image, ImageDraw, ImageFont                                         
                                                                                    
oversampling_factor = 2                                                             
width = 707                                                                         
height = 90                                                                         
scolor = "#000000"                                                                  
background_color = "#FFFFFF"                                                        
                                                                                    
image = Image.new(                                                                  
    "RGB",                                                                          
    (width * oversampling_factor, height * oversampling_factor),                    
    background_color,                                                               
)                                                                                   
                                                                                    
draw = ImageDraw.Draw(image)                                                        
with open("pillow_slow_polygon_coords.json", "r") as f:                             
    draw.polygon(json.load(f), scolor)                                              
                                                                                    
image = image.resize((width, height), Image.ANTIALIAS)                              
image.save("pillow_slow_polygon_output.png")

Referenced JSON file: pillow_slow_polygon_coords.json – this is audio waveform data but the issue is likely the same for other data as only the number of coordinates appear to matter.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions