27

For lines and ellipses in PIL, the images are rough.

I found antialiasing only in resize and thumbnail.

Is there any way to do antialiasing when drawing a line or ellipse?

Brian Burns
  • 20,575
  • 8
  • 83
  • 77
whi
  • 2,685
  • 6
  • 33
  • 40
  • 1
    You could do a low-pass filtering :) You will probably want to move to `aggdraw` (or `cairo`, or ...) for "fancier" drawing. – mmgp Jan 16 '13 at 03:02

3 Answers3

42

The only way to do it natively is with supersampling. Render your image at a multiple of the size you require, then resize it with resample=Image.LANCZOS, e.g.:

im = im.resize((width // 2, height // 2), resample=Image.LANCZOS)

If you have a very old version of PIL (before Pillow 2.7.0) you need to use ANTIALIAS instead of LANCZOS. The ANTIALIAS constant which was originally recommended with this answer has been deprecated for years, and was finally removed in Pillow 10.0.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 2
    @Hugo: In the [`Image.resize()`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.resize) method of the current stable version of the pillow fork of `PIL`, the keyword argument is named `resample`. This may have been changed in [version 2.7.0](https://pillow.readthedocs.io/en/stable/releasenotes/2.7.0.html?highlight=ANTIALIAS#image-resizing-filters). Also note that `Image.LANCZOS` [is the same thing](https://pillow.readthedocs.io/en/stable/_modules/PIL/Image.html?highlight=ANTIALIAS) as `Image.ANTIALIAS`—which isn't mentioned in the method's documentation. – martineau Apr 29 '19 at 19:14
  • 2
    `img.resize((width, height), Image.ANTIALIAS)` works for me. Thank you ! – cdrom Feb 10 '20 at 15:44
  • I was having this issue with an ellipse mask and following answer helped me: https://stackoverflow.com/a/22336005/1092815 Same answer, but with complete code example – GabLeRoux Mar 30 '20 at 14:06
  • 1
    This is great. Note that 3 times multiplier gives much better results than 2 times, and I felt actually better than 4 times. – Hugh Perkins Nov 14 '21 at 10:30
  • 1
    PIL.Image.ANTIALIAS nowadays (Pillow 9.2.0) – Conor Sep 12 '22 at 15:20
  • @Conor you don't need the `PIL.` part if you've imported `Image` directly as I often do. And there are more changes afoot, I've just updated the answer and I'll probably have to do it again soon as the constants were moved from `Image.` to `Image.Resampling.` My best research indicates that the `Image` constants were deprecated as of Pillow 9.1. – Mark Ransom Aug 12 '23 at 14:29
5

aggdraw (http://effbot.org/zone/aggdraw-index.htm) may be something you're interested in.

The aggdraw module implements the basic WCK 2D Drawing Interface on top of the AGG library. This library provides high-quality drawing, with anti-aliasing and alpha compositing, while being fully compatible with the WCK renderer.

The aggdraw module can be used with PIL or the WCK library (under Tkinter or native Windows). It can also be used as a stand-alone library.

KevinC
  • 191
  • 1
  • 4
1
im = im.resize((width // 2, height // 2), resample=Image.LANCZOS)

A new LANCZOS constant was added instead of ANTIALIAS.

When ANTIALIAS was initially added, it was the only high-quality filter based on convolutions. It’s name was supposed to reflect this. Starting from Pillow 2.7.0 all resize method are based on convolutions. All of them are antialias from now on. And the real name of the ANTIALIAS filter is LANCZOS filter.

The ANTIALIAS constant is left for backward compatibility and is an alias for LANCZOS.

doneforaiur
  • 1,308
  • 7
  • 14
  • 21
Prabhu M
  • 19
  • 1
  • 1
    You started off by ripping off my answer without explanation or attribution. Then you did a copy/paste from the Pillow documentation, again without attribution. Not cool. – Mark Ransom Aug 12 '23 at 15:04