Any way to make nice antialiased round corners for images in python?

So, okay, i found the solution.

I used the supersampling method bobince proposed before, but i found that the images become blurry. So, I would not provide the full code, but i'll explain my solution.

It may seem kind of idiotistic, but i haven't found any other way to do it without involving any other libraries.

With PIL you draw white (or whatever color you need, involving transparent ones) corners on the image. Then you copy it. You should now have two images with crispy non-antialiased white round corners.

Now you should use scale-up -> scale-down supersampling (see bobince's answer above for details) method to make one of the images smooth (i used 8x scaling).

Now you have two images - one with crispy corners and another one with smooth corners, but with blurry picture.

You have now to make corners on crispy image transparent and paste the whole image on the smooth one. I used the Image.composite(crispy_image, smooth_image, crispy_image) method in PIL library to do this.

Voila!


What I usually do is use an image as a mask, like this one for example:

border.png

alt text

border = Image.open('border.png')
source = border.convert('RGB')
img.paste(source, mask=border)

The mask can be resized to fit the dimensions you want. Just make sure to use the Image.ANTIALIAS method.

You can refer to the tutorial I wrote a while ago for more details (shameless plug)

If you want more control over the size and the radius then you need to use arc or pieslice. I don't know about you but this rounded rectangle I created with PIL looks smooth enough to me:

alt text

Here is the code I used to draw it

Maybe you should check phatch: http://photobatch.wikidot.com/tutorials It is written in Python and PIL and can apply round corners to photos.

alt text

Here is a link to the code used to apply round corners: http://bazaar.launchpad.net/~stani/phatch/trunk/annotate/head:/phatch/actions/round.py

That also looks smooth enough to me.


You'll have to supersample: draw the arc to a larger image and scale it down.

eg. a white, smoothly semi-transparent bottom-right 16x16 border, with 4x4x square supersampling:

>>> import Image, ImageDraw
>>> im= Image.new('RGBA', (16*4, 16*4), (255, 255, 255, 0))
>>> dr= ImageDraw.ImageDraw(im)
>>> dr.pieslice((-64, -64, 64, 64), 0, 340, fill=(255,255,255,255))
>>> im= im.resize((16, 16), Image.ANTIALIAS)
>>> im.save('border-se.png')