Latest and greatest directory thumbnailer
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