"""
if len(sys.argv) == 1:
print __version__
print "Usage:", sys.argv[0], " [option] directory"
print "Options:"
print " -f list supported file formats"
print " -a set authorative times"
print " -i show associated info and tile data"
print " -v verify file headers"
print " -s store filename"
print " -t make thumb/"
print " -w where to output"
print " -q quiet, don't warn for unidentified/missing/broken files"
sys.exit(1)
try:
opt, argv = getopt.getopt(sys.argv[1:], "tafqivw:s:D")
except getopt.error, v:
print v
sys.exit(1)
thumb = do_auth = verbose = quiet = verify = 0
whereto = ''
store = ''
for o, a in opt:
if o == "-f":
Image.init()
id = Image.ID[:]
id.sort()
print "Supported formats:"
for i in id:
print i,
sys.exit(1)
elif o == "-a":
do_auth = 1
elif o == "-i":
verbose = 1
elif o == "-q":
quiet = 1
elif o == "-t":
thumb = 1
elif o == "-s":
store = a
elif o == "-w":
whereto = a
elif o == "-v":
verify = 1
elif o == "-D":
Image.DEBUG = Image.DEBUG + 1
class picture(dict):
"store info of Kai's pictures"
def __init__(self, file):
"parse interesting stuff"
self.clear()
try:
# TODO: Fix for exception
self["order"] = get_index(file)
if not quiet:
print self["order"],
# holding directory usually describes pictures
self["abstract"] = os.path.split(os.path.split(file)[0])[1]
self["mtime"] = os.stat(file)[8]
im = Image.open(file)
# EXPERIMENTAL
exif = im._getexif()
if exif:
try:
self["exiftime"] = time.mktime(time.strptime("%s" % exif[36867], '%Y:%m:%d %H:%M:%S'))
except:
print exif
print "EXIF PARSE ERROR"
self["exiftime"] = None
else:
if not quiet:
print file, "failed for exif-time"
self["exiftime"] = None
self["size"] = im.__dict__["size"]
self["filename"] = im.__dict__["filename"]
except AttributeError:
if not quiet:
print file, "has invalid index in filename"
except IOError, v:
if not quiet:
print file, "failed:", v
def __str__(self):
return "\n".join(["%s=%s" % (k, get_time(v)) for k, v in self.items() if 'time' in k]) + '\n' + \
"\n".join(["%s=%s" % (k, v) for k, v in self.items() if 'time' not in k]) + '\n'
def set_mtime(self):
self["authtime"] = self["mtime"]
if not quiet:
print "Set mtime"
print self
def set_exiftime(self):
self["authtime"] = self["exiftime"]
if not quiet:
print "Set exiftime"
print self
def interactive(self, lasttime, nexttime):
print self
prompt = """
1 Set as lasttime %s
2 Set as nexttime %s
3 Set as mtime %s
4 Set as exiftime %s
""" % tuple(map(get_time, (lasttime, nexttime, self["mtime"], self["exiftime"])))
print prompt
print "[1,2,3,4] ",
input = sys.stdin.readline()
try:
if input == '\n':
# last time is default if user smacks enter
return 1
input = int(input)
if input == 1:
return 1
elif input == 2:
return 2
elif input == 3:
return 3
elif input == 4:
return 4
else:
self.interactive(lasttime, nexttime)
except:
self.interactive(lasttime, nexttime)
def get_index(filename):
index = 0
try:
index = int(re.search('DCP_\d+', filename).group()[4:])
except:
if not quiet:
print "Invalid index:", filename
return index
def get_time(secs):
if secs:
return time.ctime(secs)
else:
return "No time"
class pictures(list):
def __init__(self):
self.archivelist = []
self.skipped = []
def add_dir(self, dir):
filenames = os.listdir(dir)
filenames.sort()
subdirs = []
for filename in filenames:
pathname = os.path.join(dir, filename)
if self.VALID_ARCHIVE(filename):
self.archivelist.append(pathname)
if os.path.isfile(pathname):
self.add_file(pathname)
if os.path.isdir(pathname):
subdirs.append(pathname)
map(self.add_dir, subdirs)
def process_archives(self):
import tarfile
# Expensive gz to end
for a in self.archivelist:
if 'gz' in a:
self.archivelist.remove(a)
self.archivelist.append(a)
# Get expensive bz2 to end
for a in self.archivelist:
if 'bz2' in a:
self.archivelist.remove(a)
self.archivelist.append(a)
for a in self.archivelist:
if not quiet: print "Opening archive:", a
openarchive = tarfile.open(a, 'r')
for f in openarchive:
if self.NEW_PICTURE(f.name):
openarchive.extract(f,'/tmp')
pathname = os.path.join('/tmp', f.name)
print len(self), "Adding:", pathname, "from archive", a
self.append(picture(pathname))
def add_file(self, pathname):
""" Check if the file is an image and check if not already in the filelist """
if self.NEW_PICTURE(pathname):
print len(self), "Adding:", pathname
self.append(picture(os.path.abspath(pathname)))
def NEW_PICTURE(self, name):
name = os.path.split(name)[1]
if re.search("^DCP_\d{4}\.JPG$", name):
index = get_index(name)
if index:
if index not in [i["order"] for i in self]:
return 1
else:
if not quiet:
print "Not new:", index, name
else:
self.skipped.append((0,os.path.abspath(name)))
elif re.search("\.(png|jpg)$", name, re.I):
self.skipped.append(name)
else:
if not quiet:
print "Skipping:", name
def VALID_ARCHIVE(self, name):
if re.search("\.(tar|tar.gz|tar.bz2)$", name, re.I):
return 1
def next_time(self, lasttime, n):
""" Seeks ahead from n to find an exif time greater than last time """
for p in self[n:]:
if "exiftime" in p:
if p["exiftime"] > lasttime:
return p["exiftime"]
def authorative(self):
""" Setup authorative time """
self.sort_byorder()
n = 0
lasttime = 0
lastans = ['',0]
for p in self:
#print n+1
nexttime = self.next_time(lasttime, n)
if "authtime" not in p and "exiftime" in p:
if p["exiftime"] >= lasttime:
p.set_exiftime()
elif p["mtime"] > lasttime and p["mtime"] < nexttime:
p.set_mtime()
else:
if p["abstract"] == lastans[0] and nexttime:
ans = lastans[1]
print "ASSUMING", lastans
# grouped by dir aka abstract
else:
ans = p.interactive(lasttime, nexttime)
if ans == 1:
p["authtime"] = lasttime
elif ans == 2:
p["authtime"] = nexttime
elif ans == 3:
if p["mtime"] < lasttime:
print "MTIME IS LESS THAN LAST TIME!"
if p["mtime"] > nexttime:
print "MTIME IS MORE THAN NEXT TIME!"
p.set_mtime()
elif ans == 4:
p.set_exiftime()
else:
raise
lastans = (p["abstract"], ans)
lasttime = p["authtime"]
n = n + 1
def sort_byorder(self):
o = zip([i["order"] for i in self], self)
o.sort()
self[:] = [j for i,j in o]
def pngthumbgen(self, where):
"""
Generate PNG thumbnail
"""
for p in self:
if "thumb" not in p and "copyto" in p:
pathtoimage = os.path.abspath(os.path.join(where, p["copyto"]))
pathtothumb = os.path.join('thumb', p["copyto"])
path = os.path.split(pathtothumb)[0]
try:
if not os.path.exists(path):
print "Creating", path
os.makedirs(path)
im = Image.open(pathtoimage) # Open original image
im.thumbnail((128,128)) # Generate thumb
im.save(pathtothumb, "PNG")
im = None
p["thumb"] = 1
except IOError, v:
if not quiet:
print pathtoimage, "failed:", v
def copy_in(self, where):
""" Copy files into new pictures directory structure according to authorative time """
for i in self:
if "authtime" in i and "copyto" not in i:
print i
i["copyto"] = time.strftime("%Y/%m/%d/", time.gmtime(i["authtime"])) + os.path.split(i["filename"])[1]
print "Copy:",
print i["filename"], "to",
print i["copyto"]
filename = os.path.join(os.path.abspath(where), i["copyto"])
path = os.path.split(filename)[0]
try:
if not os.path.exists(path):
print "Creating", path
os.makedirs(path)
shutil.copy2(i["filename"], filename)
except IOError, e:
raise e
def htmlgen(self):
output = ''
lastdir = ''
for p in self:
if "thumb" in p:
writedir = os.path.split(p["copyto"])[0]
if writedir != lastdir:
file = open('thumb/' + lastdir + '/index.shtml', 'w')
file.write(head + output + footer)
file.close()
output = ''
lastdir = writedir
output += '\n' % (p["copyto"], p["abstract"], p["copyto"])
file = open('thumb/' + lastdir + '/index.shtml', 'w')
file.write(head + output + footer)
file.close()
def main():
print "PROCESSING COLLECTION", store
try:
s = open(store)
coll = pickle.load(s)
s.close()
except:
coll = pictures()
if argv:
for a in argv: coll.add_dir(a)
if coll.archivelist:
print "Archives:", coll.archivelist
coll.process_archives()
coll.archivelist = []
print len(coll), "picture(s) in collection"
print len(coll.skipped), "picture(s) skipped"
if do_auth:
coll.authorative()
if whereto:
copyto = os.path.abspath(whereto)
coll.copy_in(copyto)
if thumb:
coll.pngthumbgen(copyto)
coll.htmlgen()
if store:
s = open(store, 'w')
pickle.dump(coll, s)
s.flush()
s.close()
print "Wrote:", store, "with", len(coll), "records"
if __name__ == "__main__":
main()