from string import Template
#PictureGallery.py, This version released on 26th July 2012
#This allows you to creates a gallery of pictures from a file of image names.
#you need to install the Image module also known as the Python Imaging Library
# from here http://www.pythonware.com/products/pil/
#you need to edit the test code after the "if __name__=="__main__"
#to do: load images+information as JSON files
import os.path
import os
import re
import Image
def combine_dicts(dict1,dict2):
return dict(dict1.items()+dict2.items())
def file_extension(path):
pos = path.rfind(".")
if pos == -1:
return ""
else:
return path[pos:].lower()
def without_extension(path):
pos = path.rfind(".")
if pos == -1:
return path
else:
return path[:pos]
def get_image_base(path):
return without_extension(os.path.basename(path))
def get_image_size(image_path):
"returns a tuple of (with,height) giving the real size of the image in pixels"
im = Image.open(image_path)
size = im.size
return size
class PictureGallery(object):
def __init__(self, title):
self.title = title #use this for title bar
#self.nb_levels = nb_levels #the number of zoom levels: to do
self.index_header_template = Template('''
$title
$h1_title
$click_message
$extra_message
''')
self.index_footer = """
"""
self.image_page_template = Template('''
$image_base
$BeforePrev Prev $after_prev | Index| Home |$before_next Next $after_next
$image_footer
''')
self.bg_colour = "black"#default
self.text_colour = "grey"
self.h1_title = title #default
self.year="2012"
self.std_suffix = "_std"#default string to add to end of image name
self.std_size = [1500,1500]#default size of box containing standard image, this is a recommended size, the real one may be different
self.thumb_suffix = "_thm"#default
self.thumb_size = [150,150]#default size of box containing thumb, this is a recommended size, the real one may be different
self.click_message = "Click on thumbnails"
self.extra_message = ""
self.overwrite = False#by default forbid overwriting a file by one with the same name during generation
self.thumb_template = Template('')
self.before_thumb_template = Template('')
self.after_thumb='\r\n'
self.images = [] #have to load them
def load_from_directory(self, dirpath):
"loads all image files in a given directory, in that order"
self.images.extend([os.path.join(dirpath,entry) for entry in os.listdir(dirpath) if file_extension(entry) in [".jpg",".tif",".bmp"]])
def load_from_text_file(self, path):
"""loads the image file names from a text file, each image path is on a separate line.
You call this repeatedly to add more image files. ignores empty lines and lines beginning with #.
"""
ifh = open(path,"r")
lines = ifh.readlines()
ifh.close()
self.images.append([line.strip() for line in lines if len(line)>0 and line[0]!='#'])
def reduce_image(self,path_original, size_reduced, path_reduced):
"use size_reduced as a box to reduce the images"
if os.path.exists(path_reduced) and not self.overwrite:
return
#print "reduce_image(",original,size,reduced,")"
statv = os.stat(path_original)
atime = statv.st_atime
mtime = statv.st_mtime
if path_reduced == path_original:
print "reduce_image called on same input and output",original
sys.exit(1)
img = Image.open(path_original)
img.thumbnail(size_reduced,Image.ANTIALIAS)
img.save(path_reduced,"JPEG")
os.utime(path_reduced,(atime,mtime))#copy time
return mtime
#you will be likely to use this one
def set_h1_title(self, h1_title):
self.h1_title = h1_title
def set_std_size(size):
self.std_size= size # size of box containing standard image, this is a recommended size, the real one may be different
def set_thumb_size(size):
self.thumb_size= size # size of box containing standard image, this is a recommended size, the real one may be different
def set_bg_colour(self, bg_colour):
self.bg_color = bg_colour
#it's unlikely you will use these:
def set_thumb_suffix(suffix):
self.thumb_suffix = suffix
def set_std_suffix(suffix):
self.std_suffix = suffix
def write(self,target_directory):
self.target_dir = target_directory
"Writes both the HTML of the index, the individual HTML pages perm image and the image files"
ofh = open(os.path.join(target_directory,"index.htm"),"w")
header = self.index_header_template.substitute(self.__dict__)
footer = self.index_footer
ofh.write(header)
image_counter = 1
nb_images = len(self.images)
for image_path in self.images:
print "image_path",image_path
single_image_page = SingleImagePage(image_path,self,image_counter,nb_images - image_counter)
single_image_page.write_images()#write images first so we know real sizes of thumbs and standard images
single_image_page.write_HTML()
ofh.write(self.before_thumb_template.substitute(combine_dicts(self.__dict__, single_image_page.__dict__)))
ofh.write(self.thumb_template.substitute(combine_dicts(self.__dict__, single_image_page.__dict__)))
ofh.write(self.after_thumb)
image_counter += 1
ofh.write(footer)
ofh.close()
class SingleImagePage(object):
def __init__(self,image_path,parent,imageNb,nbLeft):
self.image_path=image_path
self.image_base = get_image_base(image_path)
#print "image_base" ,self.image_base
self.parent = parent
self.image_nb = imageNb
if self.image_nb == 1:
self.BeforePrev = ""
self.after_prev = ""
else:
self.BeforePrev = ''%(get_image_base(parent.images[imageNb -2])+self.parent.std_suffix)
self.after_prev = ""
self.nb_left = nbLeft
if self.nb_left== 0:
self.before_next = ""
self.after_next = ""
else:
self.before_next = ''%(get_image_base(parent.images[imageNb])+self.parent.std_suffix)
self.after_next = ""
self.image_footer=""
def get_thumb_path(self):
return os.path.join(self.parent.target_dir,self.image_base+self.parent.thumb_suffix+".jpg")
def get_std_path(self):
return os.path.join(self.parent.target_dir,self.image_base+self.parent.std_suffix+".jpg")
def write_HTML(self):
"writes the html file to display the standard image"
ofh = open(os.path.join(self.parent.target_dir,self.image_base+self.parent.std_suffix+".htm"),"w")
page_string = self.parent.image_page_template.substitute(combine_dicts(self.__dict__ ,self.parent.__dict__ ))
ofh.write(page_string)
ofh.close()
def write_images(self):
"writes thumb and standard size images"
thumb_target_path = self.get_thumb_path()
self.parent.reduce_image(self.image_path,self.parent.thumb_size,thumb_target_path)
thumb_size = get_image_size(thumb_target_path)
self.thumb_width = thumb_size[0]
self.thumb_height = thumb_size[1]
std_target_path = self.get_std_path()
self.parent.reduce_image(self.image_path,self.parent.std_size,std_target_path)
std_size = get_image_size(std_target_path)
self.std_width = std_size[0]
self.std_height = std_size[1]
#below is sample test code
if __name__ == "__main__":
g = PictureGallery("Craon")
g.set_h1_title("Le chateau de Craon")
#g.image_page_template.substitute(g.__dict__, image_base="",BeforePrev="",after_prev="",before_next="",after_next="",image_footer="")
g.load_from_directory(r"E:\Mes images\Chateaux\Craon\BestOf")
g.write(r"E:\Mes images\Chateaux\Craon\BestOf\HTML")#the directory had to be created first