#!/usr/bin/python
# Select images with similar luma component for movie of equal brightness.
# 2008-04-16 by Nick Fankhauser
# Needs compiled lumiCalc.c in path as well as mencoder.

import sys,os,time,Image,ImageFont,ImageDraw
lcPath='/usr/bin/lumiCalc'
assert os.path.isfile(lcPath), 'Required: %s' % lcPath

effeDays=[(2008,3,18,1),(2008,3,19,1),(2008,3,21,1),(2008,3,23,1),(2008,3,24,1),(2008,3,26,1),
(2008,3,27,1),(2008,3,28,1),(2008,3,29,1),(2008,3,30,1),(2008,3,31,1),
(2008,4,3,1),(2008,4,5,1),(2008,4,6,1),(2008,4,8,1),(2008,4,10,1),(2008,4,11,1),
(2008,4,13,1),(2008,4,16,1),]
effe2Days=[(2008,4,15,1),]
skipDays=[(2008,3,25,0),(2008,3,25,1),]

effeDays,effe2Days=[],[]

if len(sys.argv)==4:
 difThr=int(sys.argv[2]) # used: 10
 lumiV=int(sys.argv[3]) # used: 60
elif len(sys.argv)==3:
 print 'Syntax: %s <top_directory> <difThr> [<lumi>]' % sys.argv[0]
 difThr=int(sys.argv[2]) # used: 10
 print 'Histogram mode running...'
else:
 print 'Syntax: %s <top_directory> <difThr> [<lumi>]' % sys.argv[0]
 sys.exit()
startDir=os.path.abspath(sys.argv[1]).rstrip('/')+'/'
tDir='/tmp/%s_q1daemmerung' % startDir.split('/')[-2]
qt='>/dev/null 2>&1'
if os.path.isdir(tDir): os.system('rm %s/*' % tDir)
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

def jheadTime(fn):
 ext='.time'
 cfn=fn+ext 
 if os.path.isfile(cfn): return int(open(cfn).read())
 dstr='Date/Time    : '  # search string to find date in jhead output
 dList=filter( lambda x: x.find(dstr)==0, os.popen('jhead '+fn).readlines() )
 if dList: dline,=dList
 else: return 0
 rt=int(time.mktime(time.strptime(dline.replace(dstr,'').strip(),"%Y:%m:%d %H:%M:%S"))+3600)
 open(cfn,'w').write(str(rt))
 return rt

def getTime(fn):
 web='bild' # webcam filenames
 zahlen=map(str,range(10)) # all numbers
 if fn.find(web)==-1: return jheadTime(fn)
 else: return int(filter(lambda z:z in zahlen,os.path.basename(fn)))

fSize=lambda x : int(os.stat(x)[6])

def lumi(fn):
 ext='.lumi2'
 cfn=fn+ext
 if os.path.isfile(cfn): 
  try: return int(open(cfn).read().strip())
  except:
   print 'Problem with %s' % fn
   return 0
 os.system('%s %s >%s%s' % (lcPath,fn,fn,ext) )
 try: return int(open(cfn).read().strip())
 except:
  print 'Problem with %s' % fn
  return 0

def ValueSort(d):
 items = d.items()
 items = [(v, k) for (k, v) in items]
 items.sort()
 items.reverse()
 return [(k, v) for (v, k) in items]

def effect(l):
 lr=list(l)
 lr.reverse()
 return l+lr+l

def effect2(l):
 lr=list(l)
 lr.reverse()
 return l+lr+l+lr+l

print 'Creating photo list...'
photoList=scanDir(startDir)
photoList=filter(lambda x:x.find('jpg')==len(x)-3,photoList)
print 'Creating time list for %d photos...' % len(photoList)
timeList=map(getTime,photoList)
print 'Creating lumi list for %d photos...' % len(photoList)
sizeList=map(lumi,photoList)

if len(sys.argv)!=4: # histogram
 ld={}
 print
 for s in sizeList: ld[s/difThr]=ld.get(s/difThr,0)+1
 print 'Lumi\tCount\tSeconds\tPercent'
 for k,v in ValueSort(ld)[:20]:
  print '%d\t%d\t%d\t%d' % (k*difThr,v,v/25,v/float(len(sizeList))*100)
 sys.exit()

aList=zip(timeList,photoList,sizeList)
dd={}
for t,fn,size in aList:
 tt=time.gmtime(t)
 tk=list(tt[:3])
 if tt[3]>12: tk.append(1)
 else: tk.append(0)
 dd[tuple(tk)]=dd.get(tuple(tk),[])+[(size,fn),]
cnt=0
print 'Y-M-D-Part\tPhotos\tSelected'
for k in sorted(dd.keys()):
 dl=sorted(map(lambda x:(abs(lumiV-x[0]),x[1]),filter(len,dd[k])))
 okImg=sorted(map(lambda x:x[1],filter(lambda x:x[0]<difThr,dl)))
 if startDir.find('gmuendcam')>-1:
  if k in skipDays: print 'skip:',k; okImg=[]
  if k in effe2Days: print 'e2:',k; okImg=effect2(okImg)
  if k in effeDays: print 'e:',k; okImg=effect(okImg)
 for f in okImg:
  img=Image.open(f)
  if startDir.find('gmuendcam')>-1: img=img.crop((0,0,320,240))
  if img.size[1]>480: img=img.resize((640,480)) # balkon
  fontSize=img.size[1]/10
  arial=ImageFont.truetype('/usr/share/fonts/corefonts/arialbd.ttf',fontSize)
  draw = ImageDraw.Draw(img) # new draw instance 
  txs=time.strftime('%b%e',time.gmtime(getTime(f)))
  #sdraw.text((5,img.size[1]-(fontSize+2)),txs,fill='blue',font=arial)
  ofn='%s/img%06d.jpg' % (tDir,cnt)
  img.save(ofn)
  cnt+=1
 print '%s\t%s\t%s' % ('-'.join(map(str,k)),len(dd[k]),len(okImg))
ofn='%s_q1dawn_l%d_t%d_f%d.avi' % (startDir.split('/')[-2],lumiV,difThr,cnt)
print '%d images -> %d seconds' % (cnt,cnt/25)
os.system('mencoder mf://%s/*.jpg -ovc lavc -lavcopts vcodec=mpeg4:vhq:vbitrate=5000 -o %s -quiet %s' % (tDir,ofn,qt) )
print 'Created',ofn