Is there an obvious way to do this that I'm missing? I'm just trying to make thumbnails.
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
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')
sompic.jpg
. Why does this happen? I'm using Python 3.x
.jpeg
, use img.save('sompic.jpg', 'JPEG')
.
PIL.Image.ANTIALIAS
option for resize
, should actually be PIL.Image.LANCZOS
, although they are both 1
in value, see pillow.readthedocs.io/en/3.1.x/reference/…
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.
Image.thumbnail
.
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)
resize
call, you are using the new_width
for both height and width?
If you are trying to maintain the same aspect ratio, then wouldn't you resize by some percentage of the original size?
For example, half the original size
half = 0.5
out = im.resize( [int(half * s) for s in im.size] )
out = im.resize( (int(half * s) for s in im.size) )
out = image.resize((s//2 for s in image.size))
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
from PIL import Image
from resizeimage import resizeimage
def resize_file(in_file, out_file, size):
with open(in_file) as fd:
image = resizeimage.resize_thumbnail(Image.open(fd), size)
image.save(out_file)
image.close()
resize_file('foo.tif', 'foo_small.jpg', (256, 256))
I use this library:
pip install python-resize-image
If you don't want / don't have a need to open image with Pillow, use this:
from PIL import Image
new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))
You can combine PIL's Image.thumbnail
with sys.maxsize
if your resize limit is only on one dimension (width or height).
For instance, if you want to resize an image so that its height is no more than 100px, while keeping aspect ratio, you can do something like this:
import sys
from PIL import Image
image.thumbnail([sys.maxsize, 100], Image.ANTIALIAS)
Keep in mind that Image.thumbnail
will resize the image in place, which is different from Image.resize
that instead returns the resized image without changing the original one.
EDIT: Image.ANTIALIAS
raises a deprecation warning, and will be removed in PIL 10 (July 2023). Instead, you should use Resampling.LANCZOS
:
import sys
from PIL import Image
from PIL.Image import Resampling
image.thumbnail([sys.maxsize, 100], Resampling.LANCZOS)
Just updating this question with a more modern wrapper This library wraps Pillow (a fork of PIL) https://pypi.org/project/python-resize-image/
Allowing you to do something like this :-
from PIL import Image
from resizeimage import resizeimage
fd_img = open('test-image.jpeg', 'r')
img = Image.open(fd_img)
img = resizeimage.resize_width(img, 200)
img.save('test-image-width.jpeg', img.format)
fd_img.close()
Heaps more examples in the above link.
I will also add a version of the resize that keeps the aspect ratio fixed. In this case, it will adjust the height to match the width of the new image, based on the initial aspect ratio, asp_rat, which is float (!). But, to adjust the width to the height, instead, you just need to comment one line and uncomment the other in the else loop. You will see, where.
You do not need the semicolons (;), I keep them just to remind myself of syntax of languages I use more often.
from PIL import Image
img_path = "filename.png";
img = Image.open(img_path); # puts our image to the buffer of the PIL.Image object
width, height = img.size;
asp_rat = width/height;
# Enter new width (in pixels)
new_width = 50;
# Enter new height (in pixels)
new_height = 54;
new_rat = new_width/new_height;
if (new_rat == asp_rat):
img = img.resize((new_width, new_height), Image.ANTIALIAS);
# adjusts the height to match the width
# NOTE: if you want to adjust the width to the height, instead ->
# uncomment the second line (new_width) and comment the first one (new_height)
else:
new_height = round(new_width / asp_rat);
#new_width = round(new_height * asp_rat);
img = img.resize((new_width, new_height), Image.ANTIALIAS);
# usage: resize((x,y), resample)
# resample filter -> PIL.Image.BILINEAR, PIL.Image.NEAREST (default), PIL.Image.BICUBIC, etc..
# https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
# Enter the name under which you would like to save the new image
img.save("outputname.png");
And, it is done. I tried to document it as much as I can, so it is clear.
I hope it might be helpful to someone out there!
I was trying to resize some images for a slideshow video and because of that, I wanted not just one max dimension, but a max width and a max height (the size of the video frame).
And there was always the possibility of a portrait video...
The Image.thumbnail
method was promising, but I could not make it upscale a smaller image.
So after I couldn't find an obvious way to do that here (or at some other places), I wrote this function and put it here for the ones to come:
from PIL import Image
def get_resized_img(img_path, video_size):
img = Image.open(img_path)
width, height = video_size # these are the MAX dimensions
video_ratio = width / height
img_ratio = img.size[0] / img.size[1]
if video_ratio >= 1: # the video is wide
if img_ratio <= video_ratio: # image is not wide enough
width_new = int(height * img_ratio)
size_new = width_new, height
else: # image is wider than video
height_new = int(width / img_ratio)
size_new = width, height_new
else: # the video is tall
if img_ratio >= video_ratio: # image is not tall enough
height_new = int(width / img_ratio)
size_new = width, height_new
else: # image is taller than video
width_new = int(height * img_ratio)
size_new = width_new, height
return img.resize(size_new, resample=Image.LANCZOS)
Have updated the answer above by "tomvon"
from PIL import Image
img = Image.open(image_path)
width, height = img.size[:2]
if height > width:
baseheight = 64
hpercent = (baseheight/float(img.size[1]))
wsize = int((float(img.size[0])*float(hpercent)))
img = img.resize((wsize, baseheight), Image.ANTIALIAS)
img.save('resized.jpg')
else:
basewidth = 64
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('resized.jpg')
Open your image file
from PIL import Image
im = Image.open("image.png")
Use PIL Image.resize(size, resample=0) method, where you substitute (width, height) of your image for the size 2-tuple.
This will display your image at original size:
display(im.resize((int(im.size[0]),int(im.size[1])), 0) )
This will display your image at 1/2 the size:
display(im.resize((int(im.size[0]/2),int(im.size[1]/2)), 0) )
This will display your image at 1/3 the size:
display(im.resize((int(im.size[0]/3),int(im.size[1]/3)), 0) )
This will display your image at 1/4 the size:
display(im.resize((int(im.size[0]/4),int(im.size[1]/4)), 0) )
etc etc
display()
and where is it located?
display()
is an iPython function and can be used in Jupyter Notebook to display images.
A simple method for keeping constrained ratios and passing a max width / height. Not the prettiest but gets the job done and is easy to understand:
def resize(img_path, max_px_size, output_folder):
with Image.open(img_path) as img:
width_0, height_0 = img.size
out_f_name = os.path.split(img_path)[-1]
out_f_path = os.path.join(output_folder, out_f_name)
if max((width_0, height_0)) <= max_px_size:
print('writing {} to disk (no change from original)'.format(out_f_path))
img.save(out_f_path)
return
if width_0 > height_0:
wpercent = max_px_size / float(width_0)
hsize = int(float(height_0) * float(wpercent))
img = img.resize((max_px_size, hsize), Image.ANTIALIAS)
print('writing {} to disk'.format(out_f_path))
img.save(out_f_path)
return
if width_0 < height_0:
hpercent = max_px_size / float(height_0)
wsize = int(float(width_0) * float(hpercent))
img = img.resize((max_px_size, wsize), Image.ANTIALIAS)
print('writing {} to disk'.format(out_f_path))
img.save(out_f_path)
return
Here's a python script that uses this function to run batch image resizing.
To make the new image half the width and half the height of the original image, Use below code :
from PIL import Image
im = Image.open("image.jpg")
resized_im = im.resize((round(im.size[0]*0.5), round(im.size[1]*0.5)))
#Save the cropped image
resized_im.save('resizedimage.jpg')
To resize with fixed width with ration:
from PIL import Image
new_width = 300
im = Image.open("img/7.jpeg")
concat = int(new_width/float(im.size[0]))
size = int((float(im.size[1])*float(concat)))
resized_im = im.resize((new_width,size), Image.ANTIALIAS)
#Save the cropped image
resized_im.save('resizedimage.jpg')
# Importing Image class from PIL module
from PIL import Image
# Opens a image in RGB mode
im = Image.open(r"C:\Users\System-Pc\Desktop\ybear.jpg")
# Size of the image in pixels (size of original image)
# (This is not mandatory)
width, height = im.size
# Setting the points for cropped image
left = 4
top = height / 5
right = 154
bottom = 3 * height / 5
# Cropped image of above dimension
# (It will not change original image)
im1 = im.crop((left, top, right, bottom))
newsize = (300, 300)
im1 = im1.resize(newsize)
# Shows the image in image viewer
im1.show()
My ugly example.
Function get file like: "pic[0-9a-z].[extension]", resize them to 120x120, moves section to center and save to "ico[0-9a-z].[extension]", works with portrait and landscape:
def imageResize(filepath):
from PIL import Image
file_dir=os.path.split(filepath)
img = Image.open(filepath)
if img.size[0] > img.size[1]:
aspect = img.size[1]/120
new_size = (img.size[0]/aspect, 120)
else:
aspect = img.size[0]/120
new_size = (120, img.size[1]/aspect)
img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:])
img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:])
if img.size[0] > img.size[1]:
new_img = img.crop( (
(((img.size[0])-120)/2),
0,
120+(((img.size[0])-120)/2),
120
) )
else:
new_img = img.crop( (
0,
(((img.size[1])-120)/2),
120,
120+(((img.size[1])-120)/2)
) )
new_img.save(file_dir[0]+'/ico'+file_dir[1][3:])
I resizeed the image in such a way and it's working very well
from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import os, sys
from PIL import Image
def imageResize(image):
outputIoStream = BytesIO()
imageTemproaryResized = imageTemproary.resize( (1920,1080), Image.ANTIALIAS)
imageTemproaryResized.save(outputIoStream , format='PNG', quality='10')
outputIoStream.seek(0)
uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" % image.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)
## For upload local folder
fs = FileSystemStorage()
filename = fs.save(uploadedImage.name, uploadedImage)
The simplest way that worked for me
image = image.resize((image.width*2, image.height*2), Image.ANTIALIAS)
Example
from PIL import Image, ImageGrab
image = ImageGrab.grab(bbox=(0,0,400,600)) #take screenshot
image = image.resize((image.width*2, image.height*2), Image.ANTIALIAS)
image.save('Screen.png')
The following script creates nice thumbnails of all JPEG images preserving aspect ratios with 128x128 max resolution.
from PIL import Image
img = Image.open("D:\\Pictures\\John.jpg")
img.thumbnail((680,680))
img.save("D:\\Pictures\\John_resize.jpg")
######get resize coordinate after resize the image using this function#####
def scale_img_pixel(points,original_dim,resize_dim):
multi_list = [points]
new_point_list = []
multi_list_point = []
for point in multi_list:
multi_list_point.append([point[0],point[1]])
multi_list_point.append([point[2],point[3]])
for lsingle_point in multi_list_point:
x1 = int((lsingle_point[0] * (resize_dim[0] / original_dim[0])))
y1 = int((lsingle_point[1] * (resize_dim[1] / original_dim[1])))
new_point_list.append(x1)
new_point_list.append(y1)
return new_point_list
points = [774,265,909,409]
original_dim = (1237,1036)
resize_dim = (640,480)
result = scale_img_pixel(points,original_dim,resize_dim)
print("result: ", result)
import cv2
from skimage import data
import matplotlib.pyplot as plt
from skimage.util import img_as_ubyte
from skimage import io
filename='abc.png'
image=plt.imread(filename)
im=cv2.imread('abc.png')
print(im.shape)
im.resize(300,300)
print(im.shape)
plt.imshow(image)
Success story sharing
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 :)ANTIALIAS
is no longer preferred for users of the popular Pillow fork of PIL. pillow.readthedocs.org/en/3.0.x/releasenotes/…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.save()
method is poor quality, you can useimage.save(file_path, quality=quality_value)
to change the quality.