Welcome, guest | Sign In | My Account | Store | Cart

On the web and various purpose, we want to thumbnail images.

Python, 106 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
#!/usr/bin/env python
# -*- python -*-
#
# Python Thumbnail image generator
#

import os
import sys
import re
import imghdr
from getopt import getopt
from StringIO import StringIO
from PIL import Image # Require PIL module.

class ThumbnailGenerator:
    "Thumbnail image generator."
    default_geom = (100, 100)
    geomfmt = re.compile('(?P<W>\d+)x(?P<H>\d+)')

    def __init__(self):
        self.limit_geom = self.default_geom
        self.outd = '.'
        self.suf = '-thumb'

    def setoutdir(self, outd):
        self.outd = outd

    def setsuffix(self, suf):
        self.suf = suf

    def setbasesize(self, geom):
        matched = self.geomfmt.match(geom)
        if not matched:
            raise ValueError, 'Geometory format is not "XxY"'
        self.limit_geom = (int(matched.group('W')), int(matched.group('H')))

    def generate(self, fn, fp=None):
        "Generate thumbnail."
        im = Image.open(fn)
        im.thumbnail(self.limit_geom)
        base, ext = os.path.splitext(fn)
        if fp: im.save(fp, imghdr.what(fn))
        else: im.save(os.path.join(self.outd, '%s%s%s'%(base, self.suf, ext)))
        return im

    def raw_generate(self, fn):
        "Generate thumbnail (retruns rawdata)"
        im = Image.open(fn)
        im.thumbnail(self.limit_geom)
        buf = StringIO()
        im.save(buf, imghdr.what(fn))
        return buf.getvalue()

def __usage():
    print >>sys.stderr, 'usage: %s [options] imagefile ...' % sys.argv[0]

def __help():
    __usage()
    print '''options:
    -b XxY       base thumbnail size
    -h           print this usage
    -o directory output directory
    -s suffix    thumbnail suffix'''

def __main():
    optdic = {}
    arglist = []
    optlist = []
    tmp = sys.argv[1:]
    while 1:
        opts, tmp = getopt(tmp, 'b:ho:s:')
        if opts: optlist += opts
        if not tmp: break
        arglist.append(tmp[0])
        tmp = tmp[1:]

    # Examine options and filenames.
    if optlist:
        for key, val in optlist:
            if key == '-h':
                __help()
                return
            if optdic.has_key(key):
                raise ValueError, '%s option duplicated' % key
            optdic[key] = val
    if not arglist:
        __usage()
        return

    generator = ThumbnailGenerator()
    if optdic.has_key('-b'): generator.setbasesize(optdic['-b'])
    if optdic.has_key('-o'): generator.setoutdir(optdic['-o'])
    if optdic.has_key('-s'): generator.setsuffix(optdic['-s'])

    # Generate thumbnails.
    for fn in arglist:
        generator.generate(fn)

if __name__ == '__main__':
    try:
        __main()
    except Exception, e:
        print >>sys.stderr, e
        __usage()
        sys.exit(1)
    sys.exit(0)

The ThumbnailGenerator.raw_generate() is generate thumbnail raw binary. It useful to Database(e.g. insert to BLOB field).

2 comments

Peter Scott 21 years ago  # | flag

X by Y. This is a nice recipe, but I think it would be better if your class didn't need to parse the geometry strings. It would be cleaner just to pass the width and height as arguments or a tuple, and have your main() function handle interaction with the user.

Thomas Guettler 21 years ago  # | flag

Using imagemagick. If you have imagemagick installed, you can use this recipe:

filename="foo.jpg"
x=60
y=60
new_filename="foo_60.jpg"

ret=os.system("convert -geometry %sx%s '%s' '%s'" % (
    x, y, filename, new_filename))
if ret!=0:
    print "File:", filename, "can't be converted"