#!/usr/bin/python

#
# (c) Emmanuel Christophe emmanuel.christophe@gmail.com
#                       http://www.melaneum.com  
#
# This script is released under the GPL v3 license
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# This program extract location information from jpeg image file and
# generate a kml file to display images on google map

import os, sys, fnmatch, pyexiv2, Image, kmldom

#Function to retrieve data from exif tags
def getExifData(filename):
  image = pyexiv2.Image(filename)
  image.readMetadata()
  lonRational=image['Exif.GPSInfo.GPSLongitude']
  lon=eval('0.0+'+str(lonRational[0])+'+1/60.*'+str(lonRational[1])+'+1/3600.*'+str(lonRational[2]))
  latRational=image['Exif.GPSInfo.GPSLatitude']
  lat=eval('0.0+'+str(latRational[0])+'+1/60.*'+str(latRational[1])+'+1/3600.*'+str(latRational[2]))
  width=image['Exif.Photo.PixelXDimension']
  height=image['Exif.Photo.PixelYDimension']
  alt=eval('1.0*'+str(image['Exif.GPSInfo.GPSAltitude']))
  datetime=image['Exif.Image.DateTime']
  orient=image['Exif.Image.Orientation']
  return (lon, lat, alt, width, height, datetime, orient)

#Function to create thumbnail from jpeg file (resize and rotate)
def createThumbnail(fileName, maxSize, folder, prefix, orient):
  try:
      im=Image.open(folder+'/'+fileName)
      width=int(im.size[0])
      height=int(im.size[1])
      if width>height:
	  max=width
      else:
	  max=height
      zoom=float(maxSize/max)
      im.thumbnail((int(width*zoom),int(height*zoom)))
      if orient == 6:
	im=im.rotate(270)
      if orient == 8:
	im=im.rotate(90)
      im.save(folder+"/"+prefix+fileName)
  except:
      print "Warning: didn't create thumbnail, no JPG file ?"

#KML style
def createStyle():
  factory = kmldom.KmlFactory_GetFactory()
  
  hotSpot=factory.CreateHotSpot()
  hotSpot.set_x(20)
  hotSpot.set_y(2)

  iconStyleIcon=factory.CreateIconStyleIcon()
  
  iconStyleIcon.set_href("http://maps.google.com/mapfiles/kml/pal4/icon38.png")
  
  iconStyle=factory.CreateIconStyle()
  iconStyle.set_icon(iconStyleIcon)
  iconStyle.set_hotspot(hotSpot)
  
  style=factory.CreateStyle()
  style.set_id("camera")
  style.set_iconstyle(iconStyle)
  return style

#KMK placemark
def createPlacemark(lon, lat, alt, fileName, url):
  factory = kmldom.KmlFactory_GetFactory()
  coordinates = factory.CreateCoordinates()
  coordinates.add_point3(lon,lat,alt)
  point = factory.CreatePoint()
  point.set_coordinates(coordinates)
  placemark = factory.CreatePlacemark()
  placemark.set_id(fileName)
  placemark.set_name(fileName)
  descriptionString="<![CDATA[<a href='"+url+"w"+fileName+"' target='_blank'> <img src='"+url+"_thb_w"+fileName+"'/></a>]]>"
  placemark.set_description(descriptionString)
  placemark.set_styleurl("#camera")
  placemark.set_geometry(point)
  return placemark

#Main function
def main():
  #Variable to set according to the desired output
  folder="/where/the/photos/are"
  url="http://www.mysite.sth/where/the/photos/and/thumbnail/will/be/"


  factory = kmldom.KmlFactory_GetFactory()

  document = factory.CreateDocument()

  document.add_styleselector(createStyle())

  #Go through jpeg files and create the corresponding placemark
  for fileName in os.listdir ( folder ):
      if (fnmatch.fnmatch (fileName, '*.JPG') or fnmatch.fnmatch (fileName, '*.jpg')) and (not fnmatch.fnmatch (fileName, '_thb_*')) and (not fnmatch.fnmatch (fileName, 'w*')):
	  print "\nFound fileName ",fileName," Processing now ..."
	  (lon, lat, alt, width, height, datetime, orient)=getExifData(folder+'/'+fileName)
	  
	  #Create thumb and make a preview
	  if fnmatch.fnmatch (fileName, '*.JPG') or fnmatch.fnmatch (fileName, '*.jpg'):
	      createThumbnail(fileName, 800.0, folder, "w", orient)
	      createThumbnail(fileName, 160.0, folder, "_thb_w", orient)

	  placemark=createPlacemark(lon, lat, alt, fileName, url)
	  document.add_feature(placemark)
		 

  kml = factory.CreateKml()
  kml.set_feature(document)
    
  kmlfilename="doc.kml"
  f = open(kmlfilename, 'w')
  f.write('<?xml version="1.0" encoding="UTF-8"?>\n')
  f.write(kmldom.SerializePretty(kml))
  f.close()

  print "\nkml saved in ", kmlfilename

if __name__ == '__main__':
  main()

