#!/usr/bin/python
# Rotating zoom timelapse
# 2009-05-05 by Nick Fankhauser

import sys,os,time,Image,ImageFont,ImageDraw,string,math

movie_s=60 # max length of movie in seconds
framerate=25
wg=0.01 # circular speed
#day=10,15 # from 1000 to 1500
day=3,23 # helv -> almost everything

startDir=os.path.abspath(sys.argv[1]).rstrip('/')+'/'
tDir='/tmp/' + startDir.split('/')[-2]
qt='>/dev/null 2>&1'
if os.path.isdir(tDir): 
 for f in os.listdir(tDir): os.unlink(tDir+'/'+f)
else: os.mkdir(tDir)

def scanDir(d):
 rl=[]
 for fn in os.listdir(d):
  if os.path.isdir(d+fn): rl+=scanDir(d+fn+'/')
  else: rl.append(d+fn)
 return rl

getTime=lambda x : int(filter(lambda y : y in string.digits,os.path.basename(x)))
fSize=lambda x : int(os.stat(x)[6])

def is_day((t,s,f)):
 h=int(time.strftime('%H',time.localtime(t)))
 if h>day[0] and h<day[1]: return True

photoList=scanDir(startDir)
photoList=filter(lambda x:x.find('jpg')==len(x)-3,photoList)
print 'Photos: %d' % len(photoList)
timeList=map(getTime,photoList)
t1,t2=min(timeList),max(timeList)
print 'Start date: %s' % time.strftime('%Y-%m-%d',time.localtime(t1))
print 'End date: %s' % time.strftime('%Y-%m-%d',time.localtime(t2))
duration=(t2-t1)/(60*60*24)
print 'Duration in days: %d' % duration
sizeList=map(fSize,photoList)
bl=zip(timeList,sizeList,photoList)
bl=filter(is_day,bl)
movie_frames=movie_s*framerate
if movie_frames>len(bl):
 movie_s=len(bl)/framerate-2
 movie_frames=movie_s*framerate
print 'Photos %d - %dh: %d' % (day[0],day[1],len(bl))
bl.sort()
pack_len=len(bl)/duration+1
packs=[bl[x:x+pack_len] for x in range(0,len(bl),pack_len)]
packframes=movie_frames/len(packs)
print 'Number of packs: %d' % len(packs)
print 'Photos per pack: %d' % pack_len
print 'Used per pack: %d' % packframes
fnl=[]
for pack in packs:
 pack2=map(lambda (t,s,f) : (s,t,f),pack)
 top=sorted(pack2)[-packframes:] # most complex images
# top=sorted(pack2)[:packframes] # least complex images
 top2=map(lambda (s,t,f) : (t,s,f),top)
 fnl+=map(lambda (t,s,f) : f,sorted(top2))
cnt,wink=0,-2.5
img=Image.open(fnl[0])
#dvdx,dvdy=img.size[0]/2,img.size[1]/2 # movie resolution
#dvdx,dvdy=720,576 # for baerenpark, maybe also try 640x480
dvdx,dvdy=640,480 # for baerenpark, maybe also try 640x480
xc,yc=img.size[0]/2-dvdx/2,img.size[1]/2-dvdy/2 # center of circle
#rad=min(img.size)/3 # circle radius
rad=min(img.size)/2-min([dvdx,dvdy])/2 # circle radius
#ely=float(img.size[0])/float(img.size[1])*1.6 # elyptic factor
ely=float(img.size[0])/float(img.size[1])*0.95 # elyptic factor
print 'Source resolution: %d x %d' % (img.size[0],img.size[1])
print 'Movie length in seconds: %d' % movie_s
print 'Movie resolution: %d x %d' % (dvdx,dvdy)
print 'Circle: r = %d, M = %d / %d, ely = %2.2f, v = %2.3f' % (rad,xc,yc,ely,wg)
print 'Length in frames: %d' % len(fnl)
for f in fnl:
 img=Image.open(f)
 xi=int(rad*math.sin(wink)*ely)+xc
 yi=int(rad*math.cos(wink))+yc
 wink-=wg
 img=img.crop((xi,yi,xi+dvdx,yi+dvdy))
 fontSize=img.size[1]/15
 arial=ImageFont.truetype('/usr/share/fonts/truetype/msttcorefonts/Arial_Bold.ttf',fontSize)
 draw = ImageDraw.Draw(img) # new draw instance 
# txs=time.strftime('%b%Y',time.gmtime(getTime(f)))
 txs=time.strftime('%d%b%Y',time.gmtime(getTime(f)))
 draw.text((5,img.size[1]-(fontSize+5)),txs,fill='blue',font=arial)
 ofn='%s/img%06d.jpg' % (tDir,cnt)
 img.save(ofn)
 cnt+=1
qt='>/dev/null 2>&1'
ofn=startDir.split('/')[-2]+'.avi'
tp=tDir,ofn,qt
os.system('mencoder mf://%s/*.jpg -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=5000 -o %s -quiet %s' % tp )