Python PIL: best scaling method that preserves lines

Don picture Don · Aug 17, 2011 · Viewed 7.7k times · Source

I have a 2D drawing with a black background and white lines (exported from Autocad) and I want to create a thumbnail preserving lines, using Python PIL library.

But what I obtain using the 'thumbnail' method is just a black picture scattered with white dots.

Note that if I put the image into an IMG tag with fixed width, I obtain exactly what I want (but the image is entirely loaded).

After your comments, here is my sample code:

from PIL import Image
fn = 'filename.gif'
im = Image(fn)
im.convert('RGB')
im.thumbnail((300, 300), Image.ANTIALIAS)
im.save('newfilename.png', 'PNG')

How can I do?

Answer

Mark Ransom picture Mark Ransom · Aug 17, 2011

The default resizing method used by thumbnail is NEAREST, which is a really bad choice. If you're resizing to 1/5 of the original size for example, it will output one pixel and throw out the next 4 - a one-pixel wide line has only a 1 out of 5 chance of showing up at all in the result!

The surprising thing is that BILINEAR and BICUBIC aren't much better. They take a formula and apply it to the 2 or 3 closest pixels to the source point, but there's still lots of pixels they don't look at, and the formula will deemphasize the line anyway.

The best choice is ANTIALIAS, which appears to take all of the original image into consideration without throwing away any pixels. The lines will become dimmer but they won't disappear entirely; you can do an extra step to improve the contrast if necessary.

Note that all of these methods will fall back to NEAREST if you're working with a paletted image, i.e. im.mode == 'P'. You must always convert to 'RGB'.

from PIL import Image
im = Image.open(fn)
im = im.convert('RGB')
im.thumbnail(size, Image.ANTIALIAS)

Here's an example taken from the electronics.stackexchange site https://electronics.stackexchange.com/questions/5412/easiest-and-best-poe-ethernet-chip-micro-design-for-diy-interface-with-custom-ard/5418#5418

Using the default NEAREST algorithm, which I assume is similar to the results you had:

NEAREST

Using the ANTIALIAS algorithm:

ANTIALIAS