summaryrefslogtreecommitdiff
path: root/trunk/gallery/dimbola-gallery.py
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/gallery/dimbola-gallery.py')
-rw-r--r--trunk/gallery/dimbola-gallery.py198
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()