How do I resize an image using PIL and maintain its aspect ratio?
Solution 1
Define a maximum size.
Then, compute a resize ratio by taking min(maxwidth/width, maxheight/height)
.
The proper size is oldsize*ratio
.
There is of course also a library method to do this: the method Image.thumbnail
.
Below is an (edited) example from the PIL documentation.
import os, sys
import Image
size = 128, 128
for infile in sys.argv[1:]:
outfile = os.path.splitext(infile)[0] + ".thumbnail"
if infile != outfile:
try:
im = Image.open(infile)
im.thumbnail(size, Image.ANTIALIAS)
im.save(outfile, "JPEG")
except IOError:
print "cannot create thumbnail for '%s'" % infile
Solution 2
This script will resize an image (somepic.jpg) using PIL (Python Imaging Library) to a width of 300 pixels and a height proportional to the new width. It does this by determining what percentage 300 pixels is of the original width (img.size[0]) and then multiplying the original height (img.size[1]) by that percentage. Change "basewidth" to any other number to change the default width of your images.
from PIL import Image
basewidth = 300
img = Image.open('somepic.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('somepic.jpg')
Solution 3
I also recommend using PIL's thumbnail method, because it removes all the ratio hassles from you.
One important hint, though: Replace
im.thumbnail(size)
with
im.thumbnail(size,Image.ANTIALIAS)
by default, PIL uses the Image.NEAREST filter for resizing which results in good performance, but poor quality.
Solution 4
Based in @tomvon, I finished using the following (pick your case):
a) Resizing height (I know the new width, so I need the new height)
new_width = 680
new_height = new_width * height / width
b) Resizing width (I know the new height, so I need the new width)
new_height = 680
new_width = new_height * width / height
Then just:
img = img.resize((new_width, new_height), Image.ANTIALIAS)
Solution 5
from PIL import Image
img = Image.open('/your image path/image.jpg') # image extension *.png,*.jpg
new_width = 200
new_height = 300
img = img.resize((new_width, new_height), Image.ANTIALIAS)
img.save('output image name.png') # format may what you want *.png, *jpg, *.gif
saturdayplace
Updated on July 08, 2022Comments
-
saturdayplace almost 2 years
Is there an obvious way to do this that I'm missing? I'm just trying to make thumbnails.
-
tomvon over 15 yearsIf you are using this script in Zope as an External method you will need the line "from PIL import Image" to avoid namespace clashes with Zope's "Image".
-
gnud over 12 yearsLike it says, the example was from the pil documentation, and that example (still) doesn't use the antialias flag. Since it's probably what most people would want, though, I added it.
-
eugene over 11 yearsPIL sets the height of the new image to the size given(128 here) and calculate the width to keep the aspect ratio. Is there a way to fix the width instead of height? maybe I'll ask this in separate question.
-
gnud over 11 years@Eugene: try something like
s= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS)
? (that's for floating point division though :) -
mt88 almost 9 yearsDoes using the above guarantee that the final saved image will be 128x128?
-
Joshmaker over 8 yearsNote that
ANTIALIAS
is no longer preferred for users of the popular Pillow fork of PIL. pillow.readthedocs.org/en/3.0.x/releasenotes/… -
Zacharious over 8 yearsYour variables are all mixed up. Your post says resizing width, and then resizes height. And in the
resize
call, you are using thenew_width
for both height and width? -
Mark about 8 yearsTo build on that, ANTIALIAS is not needed from Pillow 2.5 and above.
-
Mo Beigi almost 8 yearsSuggested a fix for that @Zachafer
-
So S over 7 yearsThe Python 3 documentation for PIL says that
thumbnail
only works if the resulting image is smaller than the original one. Because of that I would guess that usingresize
is the better way. -
imrek over 7 yearsThis code gets me a 0 byte output file
sompic.jpg
. Why does this happen? I'm using Python 3.x -
imrek over 7 years– Update: the same happens in Python 2.7.
-
imrek over 7 yearsI may have figured out. If you are saving a
.jpeg
, useimg.save('sompic.jpg', 'JPEG')
. -
Fred Wu about 7 yearsnit: there is no
PIL.Image.ANTIALIAS
option forresize
, should actually bePIL.Image.LANCZOS
, although they are both1
in value, see pillow.readthedocs.io/en/3.1.x/reference/… -
Jose Luis de la Rosa almost 7 yearsThe solution provided by @tomvon worked better for me because included how to calculate the ratio
-
Daniel Möller almost 7 yearsDifferences between thumbnail and resize?
-
codezjx over 6 yearsBy default PIL
save()
method is poor quality, you can useimage.save(file_path, quality=quality_value)
to change the quality. -
Arpit Singh about 6 yearsCan we crop the image in the same way?
-
gnud about 6 years@ArpitSingh to crop, use the
Image.crop
method - pillow.readthedocs.io/en/3.1.x/reference/… -
J'e about 6 years@FredWu
PIL.Image.ANTIALIAS
is in PIL version 1.1.7. This comes with Anaconda3 v5.x -
pnd almost 6 yearsthe docs say:
In Pillow 2.5 the default filter for thumbnail() was changed from NEAREST to ANTIALIAS
-
Marc Maxmeister over 5 yearstested and WORKED with python 2.7.15, and also works with 'PNG' files without need for editing
-
Anytoe almost 5 yearsresize_contain looks actually quite useful!
-
burny over 4 yearsThis does not keep the aspect ratio of the source image. It forces the image to 200x300 and will result in a squeezed or stretched image.
-
burny over 4 yearsWith this, you can only decrease the size of an image. It is not possible to increase the size with
Image.thumbnail
. -
Black Thunder over 4 yearsBetter convert them to integer
-
AMC over 4 yearsThis does not answer the question in any way.
-
Ronen Ness over 4 yearsThis rotate some images (more info and solution here stackoverflow.com/questions/4228530/…)
-
Anthony about 4 yearsWhat is
display()
and where is it located? -
Qinjie almost 4 years@Anthony,
display()
is an iPython function and can be used in Jupyter Notebook to display images. -
max almost 4 yearsUnfortunately, this does not answer to the question, which explicitly addresses the library PIL -- and it does not keep the aspect ratio!. Further, you may provide a sort description of your approach to explain your thoughts
-
Boz about 3 yearsCould've just used .thumbnail from PIL, your solution doesn't work on increasing size, just decreasing.
-
Robin over 2 yearsGot error : integer argument expected, got float
-
Robin over 2 yearsWrong answer for the op. The question was 'How do I resize an image using PIL and maintain its ASPECT RATIO?"
-
Robin over 2 yearsThis works fine. Instead of saving the image with a new name, can I pass it directly to a canvas or frame?
-
Robin over 2 yearsI like the image.show()