Skip to content

Support for dashed lines? #9127

Open

Description

@larsga

I need dashed lines, and it's not really on the cards for me to implement it myself outside of Pillow, because it would be much too slow.

I'm not the only one who's wanted this.

Is there any chance this will be added to Pillow?

Activity

  1. radarhere commented on Aug 2, 2025

    @radarhere
    Member

    Are you just talking about straight lines?

    From that StackOverflow post, you're aware of how to do this in Python, but you're requesting it be implemented by us in C so that it will be faster?

  2. larsga commented on Aug 2, 2025

    @larsga
    Author

    Are you just talking about straight lines?

    Yes. In my case I need it specifically in the ImageDraw.polygon function, but I imagine if you do this it will be done for all straight lines?

    From that StackOverflow post, you're aware of how to do this in Python, but you're requesting it be implemented by us in C so that it will be faster?

    Yes, exactly.

  3. larsga commented on Aug 2, 2025

    @larsga
    Author

    Not hard to find more examples of people wanting this: 1, 2, 3.

  4. larsga commented on Aug 2, 2025

    @larsga
    Author
  5. radarhere commented on Aug 5, 2025

    @radarhere
    Member

    I'm not convinced a need for this to be fast is so widespread - it looks like most of the requests that you've linked to result in answers for how to achieve this in Python, and not comments from people asking for more speed. If you wanted this implemented in Python, that would seem achievable. From #8976, I think you have an above average need for speed.

    However, in C, we use a scanline algorithm - for polygons, we're not drawing each line one at a time like a person would, we're determining which pixels should be visible in each horizontal row. To start using dashed lines, I think we would have to take a new approach.

    I'm not saying this is impossible, just that it would not be simple. If you are able to post some example code, and precisely specify how fast you need it to run, that would be helpful.

  6. larsga commented on Aug 5, 2025

    @larsga
    Author

    From #8976, I think you have an #8976 (comment) need for speed.

    I think that's fair to say. In fact, I have implemented this in Python now, and was surprised to find that performance was completely acceptable. So if you do implement this feature request you don't need to do it for me.

    Still, I find it strange that people have to implement this themselves. To me it seems like it should be in the library, but whether you want to do something about that is of course up to you.

    I did look at implementing this myself in C, and as far as I can tell the scanlines you're talking about is for filled polygons. For unfilled polygons the draws one line at a time. It was with a view to adding a C implementation of dashing here that I first prototyped it in Python.

    In case it will be useful to someone, here's my Python implementation of the SVG algorithm:

    class Dasher:
    
        def __init__(self, dash_pattern: tuple[int]):
            self._dash_pattern = dash_pattern
            self._pixels_used = 0 # how many pixels of current step used?
            self._steps = 0       # how many steps through pattern?
    
        def make_next_step(self, max_length: float) -> float:
            current = self._steps % len(self._dash_pattern)
            step = min(
                self._dash_pattern[current] - self._pixels_used,
                max_length
            )
    
            self._pixels_used += step
            if self._pixels_used >= self._dash_pattern[current]:
                self._pixels_used = 0
                self._steps += 1
    
            return step
    
        def is_current_dash(self):
            return self._steps % 2 == 0
    
    def dist(p1, p2):
        return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
    
    def draw_dashed_polygon(draw, coords, lc, lw, fc, dashing):
        if fc:
            draw.polygon(coords, outline = None, width = 0, fill = fc)
    
        dasher = Dasher(dashing)
    
        for ix in range(len(coords) - 1):
            (x, y) = coords[ix]
            (target_x, target_y) = coords[ix + 1]
            rem_length = dist((x, y), (target_x, target_y))
            vx = (target_x - x) / rem_length
            vy = (target_y - y) / rem_length
    
            while rem_length > 0:
                step = dasher.make_next_step(rem_length)
                nx = x + vx * step
                ny = y + vy * step
    
                if dasher.is_current_dash():
                    draw.line((x, y, nx, ny), fill = lc, width = lw)
    
                x = nx
                y = ny
                rem_length -= step
  7. larsga commented on Aug 5, 2025

    @larsga
    Author

    It strikes me now that it would be possible to add support for dashed lines in the Python layer of Pillow. Is that a contribution that would be interesting?

  8. radarhere commented on Aug 5, 2025

    @radarhere
    Member

    You're offering to create a PR? Sure, feel free.

  9. added a commit that references this issue on Mar 25, 2026
    a638382
  10. radarhere commented on Jun 6, 2026

    @radarhere
    Member

    #9490 is a work-in-progress for this.

    I can think of a solution to this when the width is 1 pixel, but more than that could be complicated. Would you be happy with only supporting widths of 1 pixel?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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