views:

3364

answers:

5

Is there an obvious way to do this that I'm missing? I'm just trying to make thumbnails.

+23  A: 

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 the 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)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for", infile
gnud
+2  A: 

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] )
Chris Cameron
It could be that the images were of varying sizes and the resize result was required to be of uniform size
Steen
+3  A: 

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.

import PIL
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), PIL.Image.ANTIALIAS)
img.save('sompic.jpg')
tomvon
If 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".
tomvon
+6  A: 

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.

Franz
A: 

Chris Harms shared a excellent way to compress images with the fastest way to do it. The completed code is here:

First, read the post: http://united-coders.com/christian-harms/image-resizing-tips-general-and-for-python

  def resize(img, box, fit, out):

      '''Downsample the image.

     @param img: Image -  an Image-object

     @param box: tuple(x, y) - the bounding box of the result image

     @param fix: boolean - crop the image to fill the box

     @param out: file-like-object - save the image into the output stream

     '''

      #preresize image with factor 2, 4, 8 and fast algorithm

      factor = 1

      while img.size[0]/factor > 2*box[0] and img.size[1]*2/factor > 2*box[1]:

          factor *=2

      if factor > 1:

          img.thumbnail((img.size[0]/factor, img.size[1]/factor), Image.NEAREST)


      #calculate the cropping box and get the cropped part

      if fit:

          x1 = y1 = 0

          x2, y2 = img.size

          wRatio = 1.0 * x2/box[0]

          hRatio = 1.0 * y2/box[1]

          if hRatio > wRatio:

              y1 = y2/2-box[1]*wRatio/2

              y2 = y2/2+box[1]*wRatio/2

          else:

              x1 = x2/2-box[0]*hRatio/2

              x2 = x2/2+box[0]*hRatio/2

          img = img.crop((x1,y1,x2,y2))



      #Resize the image with best quality algorithm ANTI-ALIAS

      img.thumbnail(box, Image.ANTIALIAS)



      #save it into a file-like object

      img.save(out, "JPEG", quality=75)

  #resize
tnd