Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS 

Latest and greatest directory thumbnailer

This does basically the same thing as my original code (http://www.bigbold.com/snippets/posts/show/1296), but significantly faster. Thumbnail sizes are cached between executions, and they could probably be kept around as static data in the mod_python environment if I could figure out how.

Also note that the thumbnailing function no longer returns a complete page, but rather a single table (compatible with either HTML or XHTML). This allows the code to be embedded into something like a photo gallery.

A simple function is shown at the end of this snippet, to set up thumbnailing with mod_python on apache.

   1  
   2  from os.path import join,exists
   3  from os import stat,mkdir,listdir
   4  import re
   5  from PIL import Image
   6  import cPickle
   7  
   8  images_per_row = 5
   9  max_width,max_height = 150,150
  10  
  11  search = re.compile("(.*\.jpe?g$)|(.*\.png$)|(.*\.gif$)", re.IGNORECASE)
  12  
  13  def list_directory(path):
  14    thumbnail_size_cache = {}
  15    thumbnail_size_cache_changed = False
  16  
  17    return_value = []
  18    dir_list = listdir(path)
  19    images = [file for file in dir_list if search.match(file)]
  20  
  21    if len(images) < 1:
  22      return ''
  23  
  24    # Interesting directories
  25    thumbsdir = join(path, ".thumbnails")
  26  
  27    # Try to load the size cache from a file
  28    cache_file_path = join(thumbsdir, "thumbnail_size_cache.dat")
  29    if exists (cache_file_path):
  30      cache_file = open(cache_file_path, "r")
  31      thumbnail_size_cache = cPickle.load(cache_file)
  32      cache_file.close()
  33  
  34    images.sort()
  35    return_value.append('<table width="100%" border="0"><tr>\n')
  36    row_template = '<td><a href="%(name)s"><img src=".thumbnails/%(name)s" alt="%(name)s" width="%(width)d" height="%(height)d"/></a>'
  37  
  38    # If the thumbnail directory does not exist, create it
  39    if not exists(thumbsdir):
  40      mkdir(thumbsdir)
  41  
  42    image_num = 0
  43    for image in images:
  44      image_num += 1
  45  
  46      thumbfile = join(thumbsdir, image)
  47      filepath = join(path, image)
  48      width,height = 0,0
  49  
  50      # Check if there is an already-existing thumbnail
  51      create_new_thumbnail = True
  52      if exists(thumbfile):
  53        thumb_stat = stat(thumbfile)
  54        img_stat = stat(filepath)
  55  
  56        # Check if the thumbnail is newer than the image
  57        if img_stat.st_mtime < thumb_stat.st_mtime:
  58          try:
  59            width,height = thumbnail_size_cache[image]
  60            create_new_thumbnail = False
  61          except KeyError:
  62            pass
  63  
  64      if create_new_thumbnail:
  65        # Thumbnail the image
  66        thumbnail = Image.open(filepath)
  67        thumbnail.thumbnail((max_width, max_height), Image.ANTIALIAS)
  68        thumbnail.save(thumbfile)
  69        thumbnail_size_cache[image] = thumbnail.size
  70        thumbnail_size_cache_changed = True
  71        width,height = thumbnail.size
  72  
  73      return_value.append(row_template % {'name': image, 'width': width, 'height': height})
  74  
  75      if image_num % images_per_row:
  76        return_value.append('</td>\n')
  77  
  78      else:
  79        return_value.append('</td></tr><tr>\n')
  80  
  81    return_value.append("</tr></table>")
  82  
  83    # Save the cache
  84    if thumbnail_size_cache_changed:
  85      return_value.append("Saved cache")
  86      cache_file = open(cache_file_path, "w")
  87      cPickle.dump(thumbnail_size_cache, cache_file, cPickle.HIGHEST_PROTOCOL)
  88      cache_file.close()
  89  
  90    return ''.join(return_value)
  91  
  92  ####################################
  93  ### mod_python stuff starts here ###
  94  ####################################
  95  
  96  from mod_python import apache
  97  
  98  html_header = '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  99  <html>
 100  <head><title>Directory Listing</title></head>
 101  <body><div>'''
 102  
 103  xhtml_header = '''<?xml version="1.0" encoding="UTF-8"?>
 104  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml111/DTD/xhtml111.dtd">
 105  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 106  <head><title>Directory Listing</title></head>
 107  <body><div>'''
 108  
 109  def handler(req):
 110    if not os.path.isdir(req.filename):
 111      file = open(req.filename)
 112      req.write(file.read())
 113      return apache.OK
 114  
 115    return_value = []
 116    # Check for XHTML acceptance
 117    accept_types = req.headers_in["Accept"].split(",")
 118  
 119    # Don't do any measure of preference for now
 120    if "application/xhtml+xml" in accept_types:
 121      # Accepts XHTML
 122      return_value.append(xhtml_header)
 123      req.content_type="application/xhtml+xml"
 124    else:
 125      # Does not accept XHTML
 126      return_value.append(html_header)
 127      req.content_type="text/html"
 128  
 129    return_value.append(list_directory(req.filename))
 130    return_value.append("</div></body></html>")
 131    req.write(''.join(return_value))
 132    return apache.OK

Thumbnails of all (gif, jpeg, and png) images in a directory

I've gone with just gif, jpeg, and png for now, but it should be easy enough to add any others that PIL supports - just update the regex.

This code generates a basic page with thumbnails of all images in the directory it is run from. It caches thumbnails in the .thumbnails directory. It requires mod_python and PIL to run, though mod_python can be removed trivially.

   1  
   2  from mod_python import apache
   3  import os
   4  import re
   5  from PIL import Image
   6  
   7  header = '''<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
   8  <html>
   9  <head><title>Directory Listing</title></head>
  10  <body>'''
  11  images_per_row = 5
  12  max_width,max_height = 150,150
  13  
  14  path = os.path.dirname(__file__)
  15    
  16  def thumbnail(filename):
  17    if os.path.exists(path + "/.thumbnails/" + filename):
  18      return
  19  
  20    image = Image.open(path + "/" + filename)
  21    image.thumbnail((max_width, max_height), Image.ANTIALIAS)
  22    image.save(path + "/.thumbnails/" + filename)
  23  
  24  def index(req):
  25    return_value = header
  26  
  27    dir_list = os.listdir(path)
  28    image_list = []
  29  
  30    search = re.compile("(.*\.[Jj][Pp][Ee]?[Gg]$)|(.*\.[Pp][Nn][Gg]$)|(.*\.[Gg][Ii][Ff]$)")
  31  
  32    image_count = 0
  33    for file in dir_list:
  34      if search.match(file):
  35        image_count += 1
  36        image_list.append(file)
  37  
  38    if image_count > 0:
  39      image_list.sort()
  40      num_rows = image_count / images_per_row
  41  
  42      image_num = 0
  43      return_value += '<table width="100%" border="0"><tr>\n'
  44  
  45      for image in image_list:
  46        thumbnail(image)
  47        image_num += 1
  48        return_value += '<td><a href="' + image + '"><img src=".thumbnails/' + image + '" alt="' + image + '"></a>'
  49  
  50        if image_num % images_per_row:
  51          return_value += '</td>\n'
  52  
  53        else:
  54          return_value += '</td></tr><tr>\n'
  55  
  56    return_value += "</table></body></html>"
  57    return return_value
« Newer Snippets
Older Snippets »
Showing 1-2 of 2 total  RSS