Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python PIL: best scaling method that preserves lines

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?

like image 908
Don Avatar asked Aug 17 '11 16:08

Don


People also ask

What does PIL resize do?

Resizing Images To resize an image, you call the resize() method on it, passing in a two-integer tuple argument representing the width and height of the resized image. The function doesn't modify the used image; it instead returns another Image with the new dimensions.

What does image bicubic do?

The bicubic algorithm is frequently used for scaling images and video for display (see bitmap resampling). It preserves fine detail better than the common bilinear algorithm.


2 Answers

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

like image 183
Mark Ransom Avatar answered Oct 25 '22 03:10

Mark Ransom


By default, im.resize uses the NEAREST filter, which is going to do what you're seeing -- lose information unless it happens to fall on an appropriately moduloed pixel.

Instead call

im.resize(size, Image.BILINEAR)

This should preserve your lines. If not, try Image.BICUBIC or Image.ANTIALIAS. Any of those should work better than NEAREST.

like image 33
Leopd Avatar answered Oct 25 '22 02:10

Leopd