Ian> There should be an option (command line or config file) to select Ian> sorting by name, filesystem time or exif time. Name should Ian> probably be the default.
Here's a patch that dose this, plus another nagging issue: passing "optimize" and "progressive" flags to the JPEG encoder. Note that the patch is cumulative vs. 0.4; i.e. it includes your 0x0 patch. With these things in, I find lazygal almost usable :-) Now, to make it _really_ stand out of the crowd, parallelize. Number of threads should probably be another option, like make's -jn.
diff -u --recur lazygal/lazygal/generators.py lazygal-0.4/lazygal/generators.py --- lazygal/lazygal/generators.py 2008-07-03 16:14:15.000000000 -0700 +++ lazygal-0.4/lazygal/generators.py 2008-08-19 20:28:33.000000000 -0700 @@ -20,6 +20,8 @@ import locale import Image +# lazygal has her own ImageFile class, so avoid trouble +import ImageFile as PILFile import genshi import __init__ @@ -42,9 +44,14 @@ class ImageOriginal(make.FileCopy): - def __init__(self, dir, source_image): + def __init__(self, dir, source_image, size_name=None): self.dir = dir - self.path = os.path.join(self.dir.path, source_image.filename) + + dest_name = source_image.filename + if size_name: + dest_name = self.dir.album._add_size_qualifier(dest_name, size_name) + + self.path = os.path.join(self.dir.path, dest_name) make.FileCopy.__init__(self, source_image.path, self.path) def build(self): @@ -77,6 +84,7 @@ 'info') self.dir.album.log("(%s)" % self.osize_path) + im = Image.open(self.source_image.path) # Use EXIF data to rotate target image if available and required @@ -85,9 +93,19 @@ im = im.rotate(rotation) im.thumbnail(self.size, Image.ANTIALIAS) - - im.save(self.osize_path, quality = self.dir.album.quality) - + + calibrated = False + while not calibrated: + try: + im.save(self.osize_path, quality = self.dir.album.quality, **self.dir.album.save_options) + except IOError, e: + if str(e).startswith('encoder error'): + PILFile.MAXBLOCK = 2 * PILFile.MAXBLOCK + continue + else: + raise + calibrated = True + class WebalbumPicture(make.FileMakeObject): @@ -217,16 +235,18 @@ self.image = image_file WebalbumPage.__init__(self, dir, size_name, self.image.name) - self.add_dependency(ImageOtherSize(self.dir, - self.image, - self.size_name)) + if self.dir.album.browse_sizes[size_name] == (0, 0): + self.add_dependency(ImageOriginal(self.dir, self.image)) + else: + self.add_dependency(ImageOtherSize(self.dir, + self.image, + self.size_name)) + if self.dir.album.original: + self.add_dependency(ImageOriginal(self.dir, self.image)) # Depends on source directory in case an image was deleted self.add_dependency(self.dir.source_dir) - if self.dir.album.original: - self.add_dependency(ImageOriginal(self.dir, self.image)) - self.page_template = self.dir.album.templates['browse.thtml'] self.add_file_dependency(self.page_template.path) @@ -496,7 +516,14 @@ self.add_dependency(WebalbumArchive(self)) def prepare(self): - self.images.sort(lambda x, y: x.compare_date_taken(y)) + if self.album.sort_by == 'exif': + self.images.sort(lambda x, y: x.compare_date_taken(y)) + elif self.album.sort_by == 'mtime': + self.images.sort(lambda x, y: x.compare_mtime(y)) + elif self.album.sort_by == 'name': + self.images.sort(lambda x, y: x.compare_filename(y)) + else: + pass # chain images previous_image = None @@ -659,7 +686,8 @@ class Album: def __init__(self, source_dir, thumb_size, browse_sizes, - quality=85, thumbs_per_page=0, dirzip=False): + optimize=False, progressive=False, + quality=85, thumbs_per_page=0, dirzip=False, sort_by='name'): self.set_logging() self.source_dir = os.path.abspath(source_dir) @@ -675,6 +703,12 @@ self.original = False self.thumbs_per_page = thumbs_per_page self.dirzip = dirzip + self.save_options = {} + if optimize: + self.save_options['optimize'] = True + if progressive: + self.save_options['progressive'] = True + self.sort_by = sort_by def set_theme(self, theme='default', default_style=None): self.theme = theme @@ -760,6 +794,10 @@ if size_name == self.default_size_name and extension == '.html': # Do not append default size name to HTML page filename return path + elif size_name in self.browse_sizes.keys()\ + and self.browse_sizes[size_name] == (0, 0) and extension != '.html': + # Do not append size_name to unresized images. + return path else: return "%s_%s%s" % (filename, size_name, extension) diff -u --recur lazygal/lazygal/sourcetree.py lazygal-0.4/lazygal/sourcetree.py --- lazygal/lazygal/sourcetree.py 2008-07-03 16:14:15.000000000 -0700 +++ lazygal-0.4/lazygal/sourcetree.py 2008-08-19 20:29:02.000000000 -0700 @@ -116,6 +116,12 @@ delta = date1 - date2 return int(delta) + def compare_filename(self, other_img): + return cmp(self.filename, other_img.filename) + + def compare_mtime(self, other_img): + return self.get_mtime() - other_img.get_mtime() + class Directory(File): diff -u --recur lazygal/lazygal.1 lazygal-0.4/lazygal.1 --- lazygal/lazygal.1 2008-07-03 16:14:15.000000000 -0700 +++ lazygal-0.4/lazygal.1 2008-08-19 20:54:37.000000000 -0700 @@ -57,6 +57,15 @@ .TP \fB\-O\fR, \fB\-\-original\fR Include original photos in output. +.TP +\fB\-\-optimize\fR +Run an extra optimization pass an each image. +.TP +\fB\-\-progressive\fR +Generate Progressive JPEG images. +.TP +\fB\-\-sort\-by\fR=\fIORDER\fR +Sort order for images in a folder: name, mtime, or exif (default is name). .SH THEMES A theme maps to a directory that contains at least the following items : diff -u --recur lazygal/lazygal.py lazygal-0.4/lazygal.py --- lazygal/lazygal.py 2008-07-03 16:14:15.000000000 -0700 +++ lazygal-0.4/lazygal.py 2008-08-19 20:08:09.000000000 -0700 @@ -36,6 +36,14 @@ 'template-vars': '', 'thumbs-per-page': '0', 'webalbumpic-bg': 'transparent', + 'optimize': 'No', + 'progressive': 'No', + 'quiet': 'No', + 'check-all-dirs': 'No', + 'original': 'No', + 'generate-metadata': 'No', + 'make-dir-zip': 'No', + 'sort-by': 'name', } # i18n @@ -63,7 +71,7 @@ parser.add_option("", "--quiet", action="store_true", - dest="quiet", default=False, + dest="quiet", default=config.getboolean('lazygal', 'quiet'), help=_("Don't output anything except for errors.")) parser.add_option("", "--debug", action="store_true", @@ -99,13 +107,13 @@ help=_("Display program version.")) parser.add_option("", "--check-all-dirs", action="store_true", - dest="check_all_dirs", default=False, + dest="check_all_dirs", default=config.getboolean('lazygal', 'check-all-dirs'), help=_("Exhaustively go through all directories regardless of source modification time.")) parser.add_option("-s", "--image-size", action="store", type="string", dest="image_size", default=config.get('lazygal', 'image-size'), - help=_("Size of images, define as <name>=<x>x<y>,..., eg. small=800x600,medium=1024x768.")) + help=_("Size of images, define as <name>=<x>x<y>,..., eg. small=800x600,medium=1024x768. The special dimensions 0x0 use original size.")) parser.add_option("-T", "--thumbnail-size", action="store", type="string", dest="thumbnail_size", @@ -114,11 +122,11 @@ parser.add_option("-q", "--quality", action="store", type="int", dest="quality", - default=config.get('lazygal', 'quality'), + default=config.getint('lazygal', 'quality'), help=_("Quality of generated JPEG images (default is 85).")) parser.add_option("-O", "--original", action="store_true", - dest="original", default=False, + dest="original", default=config.getboolean('lazygal', 'original'), help=_("Include original photos in output.")) parser.add_option("", "--puburl", action="store", type="string", @@ -126,22 +134,34 @@ help=_("Publication URL (only usefull for feed generation).")) parser.add_option("-m", "--generate-metadata", action="store_true", - dest="metadata", default=False, + dest="metadata", default=config.getboolean('lazygal', 'generate-metadata'), help=_("Generate metadata description files where they don't exist.")) parser.add_option("-n", "--thumbs-per-page", action="store", type="int", dest="thumbs_per_page", - default=config.get('lazygal', 'thumbs-per-page'), + default=config.getint('lazygal', 'thumbs-per-page'), help=_("Maximum number of thumbs per index page. This enables index pagination (0 is unlimited).")) parser.add_option("-z", "--make-dir-zip", action="store_true", - dest="dirzip", default=False, + dest="dirzip", default=config.getboolean('lazygal', 'make-dir-zip'), help=_("Make a zip archive of original pictures for each directory.")) parser.add_option("", "--webalbum-pic-bg", action="store", type="string", dest="webalbumpic_bg", default=config.get('lazygal', 'webalbumpic-bg'), help=_("Webalbum picture background color. Default is transparent, and implies the PNG format. Any other value, e.g. red, white, blue, uses JPEG.")) +parser.add_option("", "--optimize", + action="store_true", + dest="optimize", default=config.getboolean('lazygal', 'optimize'), + help=_("Run an extra optimization pass an each image.")) +parser.add_option("", "--progressive", + action="store_true", + dest="progressive", default=config.getboolean('lazygal', 'progressive'), + help=_("Generate Progressive JPEG images.")) +parser.add_option("", "--sort-by", + action="store", default=config.get('lazygal', 'sort-by'), metavar=_('ORDER'), + dest="sort_by", help=_("Sort order for images in a folder: name, mtime, or exif. [name]")) + (options, args) = parser.parse_args() if options.show_version: @@ -173,8 +193,9 @@ thumbnail = (int(x), int(y)) album = Album(source_dir, thumbnail, sizes, quality=options.quality, + optimize=options.optimize, progressive=options.progressive, thumbs_per_page=options.thumbs_per_page, - dirzip=options.dirzip) + dirzip=options.dirzip, sort_by=options.sort_by) if options.tpl_vars or config.has_section('template-vars'): tpl_vars = {}
-- Ian Zimmerman <[EMAIL PROTECTED]> gpg public key: 1024D/C6FF61AD fingerprint: 66DC D68F 5C1B 4D71 2EE5 BD03 8A00 786C C6FF 61AD Ham is for reading, not for eating.