开发者

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

Is there any way to make nice round corners with python? Currently PIL and 开发者_JS百科GD2 are used in my project. Both of them have an arc() method, that allows you to draw a quater-circle, but the quater-circle is not antialiased, so the image looks crispy.

Is there any neat way to make antialiased/smooth round corners?


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

border.png

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

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:

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

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.

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

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')


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!


Use Xiaolin Wu's circle algorithm as described in Graphics Gems II. A concise summary and example (in php) han be found here: http://create.stephan-brumme.com/antialiased-circle/

As for drawing an arc (partial circle), you must determine if a given point is within the arc's angular range before plotting it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜