Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an arc with a given thickness using PIL's Imagedraw

I am trying to create a segmented arc using PIL and Imagedraw. The arc function allows me to draw an arc easily, but it is just a line. I need to be able to place an arc of given radius and thickness(ID to OD), but AI cannot find any type of thickness or width setting. Is there a way to do this? If not, is there some other way to do this using PIL?

Snippet:

import Image
import ImageDraw

conv = 0.1
ID = 15
OD = 20
image = Image.new('1',(int(ceil(OD/conv))+2,int(ceil(OD/conv))+1), 1)
draw = ImageDraw.Draw(image)
diam = OD-ID
box=(1, 1, int(ceil(diam/conv)), int(ceil(diam/conv))) #create bounding box
draw.arc(box, 0, 90, 0) #draw circle in black
like image 601
Elliot Avatar asked Aug 15 '11 21:08

Elliot


People also ask

How do you create an arc in Python?

Wand arc() function in Pythonarc() function draws an arc in the image. You'll need to define three pairs of (x, y) coordinates. First & second pair of coordinates will be the minimum bounding rectangle, and the last pair define the starting & ending degree. pair which represents starting x and y of the arc.

What module contains pillow's shape drawing code?

The 'ImageDraw' module provides simple 2D graphics support for Image Object. Generally, we use this module to create new images, annotate or retouch existing images and to generate graphics on the fly for web use. The graphics commands support the drawing of shapes and annotation of text.

How to Draw Image in Python?

PIL is the Python Imaging Library which provides the python interpreter with image editing capabilities. The ImageDraw module provide simple 2D graphics for Image objects. You can use this module to create new images, annotate or retouch existing images, and to generate graphics on the fly for web use. ImageDraw.

How do you draw a line in Python?

line() Draws a line between the coordinates in the xy list. Parameters: xy – Sequence of either 2-tuples like [(x, y), (x, y), …] or numeric values like [x, y, x, y, …].


2 Answers

I created the following arc replacement function based on Mark's suggestion:

https://gist.github.com/skion/9259926

Probably not pixel perfect (nor fast), but seems to come close for what I need it for. If you have a better version please comment in the Gist.

def arc(draw, bbox, start, end, fill, width=1, segments=100):
    """
    Hack that looks similar to PIL's draw.arc(), but can specify a line width.
    """
    # radians
    start *= math.pi / 180
    end *= math.pi / 180

    # angle step
    da = (end - start) / segments

    # shift end points with half a segment angle
    start -= da / 2
    end -= da / 2

    # ellips radii
    rx = (bbox[2] - bbox[0]) / 2
    ry = (bbox[3] - bbox[1]) / 2

    # box centre
    cx = bbox[0] + rx
    cy = bbox[1] + ry

    # segment length
    l = (rx+ry) * da / 2.0

    for i in range(segments):

        # angle centre
        a = start + (i+0.5) * da

        # x,y centre
        x = cx + math.cos(a) * rx
        y = cy + math.sin(a) * ry

        # derivatives
        dx = -math.sin(a) * rx / (rx+ry)
        dy = math.cos(a) * ry / (rx+ry)

        draw.line([(x-dx*l,y-dy*l), (x+dx*l, y+dy*l)], fill=fill, width=width)
like image 200
Pieter Ennes Avatar answered Oct 13 '22 12:10

Pieter Ennes


PIL can't draw wide arcs, but Aggdraw can, and works well with PIL (same author).

like image 44
Ned Batchelder Avatar answered Oct 13 '22 10:10

Ned Batchelder