diff options
Diffstat (limited to 'trunk/gallery/dimbola-gallery.py')
-rw-r--r-- | trunk/gallery/dimbola-gallery.py | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/trunk/gallery/dimbola-gallery.py b/trunk/gallery/dimbola-gallery.py new file mode 100644 index 0000000..04a5b6f --- /dev/null +++ b/trunk/gallery/dimbola-gallery.py @@ -0,0 +1,198 @@ +#!/usr/bin/python + +import os +import subprocess +import sys + +import pyexiv2 + +class DefaultDict(dict): + + def __getitem__(self, key): + if key in self: + return dict.__getitem__(self, key) + else: + return "" + +class App(object): + + def run(self): + self.target_dir = sys.argv[2] + self.root = os.path.abspath(sys.argv[1]) + self.index_template = self.read_template("index") + self.image_template = self.read_template("image") + self.index_image_template = self.read_template("indeximage") + self.index_dir_template = self.read_template("indexdir") + for parent, dirname, subdirs, images in self.find_images(self.root): + self.generate_html_for_dir(parent, dirname, subdirs, images) + + def read_template(self, basename): + return file(basename + ".template").read() + + def find_images(self, root): + for dirname, dirnames, filenames in os.walk(root, topdown=False): + filenames = [x for x in filenames if self.is_image_file(dirname, x)] + dirnames = [x for x in dirnames if self.has_image_files(dirname, x)] + if dirnames or filenames: + if dirname == root: + parent = None + else: + parent = self.chop_root(root, os.path.dirname(dirname)) + dirname = self.chop_root(root, dirname) + yield parent, dirname, dirnames, filenames + + def chop_root(self, root, pathname): + if pathname == root: + return "." + if not root.endswith(os.sep): + root += os.sep + if pathname == root: + return "." + assert pathname.startswith(root), "%s %s" % (pathname, root) + return pathname[len(root):] + + def is_image_file(self, dirname, basename): + return basename.lower().endswith(".jpg") + + def has_image_files(self, dirname, basename): + fullname = os.path.join(dirname, basename) + basenames = os.listdir(fullname) + for x in basenames: + if self.is_image_file(fullname, x): + return True + return False + + def generate_html_for_dir(self, parent, dirname, subdirs, images): + if not os.path.exists(self.target(dirname)): + os.makedirs(self.target(dirname)) + self.generate_html_for_index(parent, dirname, subdirs, images) + for i in range(len(images)): + image = images[i] + prev = images[i-1] + next = images[(i+1) % len(images)] + self.generate_html_for_image(dirname, image, prev, next) + + def target(self, pathname, *args): + return os.path.join(self.target_dir, pathname, *args) + + def generate_html_for_index(self, parent, dirname, subdirs, images): + imagelist = self.generate_snippet_for_index_image_list(dirname, images) + subdirlist = self.generate_snippet_for_subdir_list(parent, dirname, + subdirs) + values = { + "directorydescription": os.path.abspath(dirname), + "indeximagelist": imagelist, + "subdirlist": subdirlist, + } + self.apply_template(dirname, "index.html", self.index_template, values) + + def generate_snippet_for_index_image_list(self, dirname, images): + snippet = [] + + for image in images: + basename, suffix = os.path.splitext(image) + target_dirname = self.target(dirname) + image_path = os.path.join(self.root, dirname, image) + thumb = os.path.basename(self.thumbnail_path(dirname, image)) + values = { + "imagebasename": basename, + "thumbnailname": thumb, + "imagepathname": self.relative_path(target_dirname, image_path) + } + snippet.append(self.index_image_template % values) + + return "".join(snippet) + + def generate_snippet_for_subdir_list(self, parent, dirname, subdirs): + snippet = [] + + if parent: + target_dirname = self.target(dirname) + target_parent = self.target(parent) + relative_parent = self.relative_path(target_dirname, target_parent) + subdirs = [relative_parent] + subdirs + + for subdir in subdirs: + values = { + "subdirname": subdir, + } + snippet.append(self.index_dir_template % values) + + return "".join(snippet) + + def generate_html_for_image(self, dirname, image, prev, next): + basename, suffix = os.path.splitext(image) + target_dirname = self.target(dirname) + image_path = os.path.join(self.root, dirname, image) + prev_basename, suffix = os.path.splitext(os.path.basename(prev)) + next_basename, suffix = os.path.splitext(os.path.basename(next)) + values = DefaultDict({ + "description": basename, + "imagepathname": self.relative_path(target_dirname, image_path), + "nextimage": next_basename + ".html", + "previmage": prev_basename + ".html", + }) + img = pyexiv2.Image(image_path) + img.readMetadata() + for key in img.exifKeys() + img.iptcKeys(): + values[key] = img[key] + self.apply_template(dirname, basename + ".html", self.image_template, + values) + self.create_thumbnail(dirname, image) + + def common_ancestor(self, path1, path2): + """Find the common ancestor directory of two paths. + + Both paths must be absolute. + + """ + + parts1 = path1.split(os.sep) + parts2 = path2.split(os.sep) + parts = [] + while parts1 and parts2 and parts1[0] == parts2[0]: + parts.append(parts1[0]) + del parts1[0] + del parts2[0] + return os.sep.join(parts) + os.sep + + def relative_path(self, dirname, pathname): + """Create a relative path from dirname to pathname. + + For example, if dirname is '/home/liw/public_html/gallery' and + pathname is '/home/liw/public_html/images/lamola/img_1234.jpg', + this function would return '../images/lamola/img_1234.jpg'. + + """ + + dirname = os.path.abspath(dirname) + pathname = os.path.abspath(pathname) + if not dirname.endswith(os.sep): + dirname += os.sep + common_ancestor = self.common_ancestor(dirname, pathname) + dirname_relative = dirname[len(common_ancestor):] + dirname_relative = [".." for x in dirname_relative.split(os.sep) if x] + dirname_relative = os.sep.join(dirname_relative) + pathname_relative = pathname[len(common_ancestor):] + return os.path.join(dirname_relative, pathname_relative) + + def apply_template(self, dirname, filename, template, values): + self.write(self.target(dirname, filename), template % values) + + def write(self, filename, contents): + f = file(filename, "w") + f.write(contents) + f.close() + + def thumbnail_path(self, dirname, image): + basename, suffix = os.path.splitext(image) + return os.path.join(self.target_dir, dirname, + basename + "_thumbnail.jpg") + + def create_thumbnail(self, dirname, image): + image_path = os.path.join(self.root, dirname, image) + subprocess.check_call(["convert", "-geometry", "200x200", image_path, + self.thumbnail_path(dirname, image)]) + +if __name__ == "__main__": + App().run() |