diff --git a/kmz2tiff.py b/kmz2tiff.py
new file mode 100644
index 0000000..6109e13
--- /dev/null
+++ b/kmz2tiff.py
@@ -0,0 +1,237 @@
+"""
+kmz2tiff.py
+ -- merge high resoulition images in kmls to one geotiff
+"""
+
+# Version: ImageMagick 6.9.10-23 Ubuntu 20.04
+
+import sys,os,string,glob,math
+import shutil
+import xml.etree.ElementTree as ET
+from PIL import Image
+
+def cleanStrings(inStr, leftstr,rightstr):
+ a = inStr.find(leftstr)
+ b = inStr.find(rightstr)
+
+ if a < 0 and b < 0:
+ return False
+
+ return inStr[a + len(leftstr):b]
+
+def getimagesize(image_file):
+ """ return image size """
+
+ img = Image.open(image_file)
+ width,height = img.size
+
+ return [width, height]
+
+
+def extractbbox(kml):
+ """ find boundingbox from a kml """
+
+ with open(kml,"r") as f:
+ kmlstring = f.read()
+ f.closed
+
+ #32.93182878
+ #32.87493534
+ #-116.0291427
+ #-116.08603614
+
+ north = cleanStrings(kmlstring, "","")
+ south = cleanStrings(kmlstring, "","")
+ east = cleanStrings(kmlstring, "","")
+ west = cleanStrings(kmlstring, "","")
+
+ bbox = map(float,[west,east,north,south])
+ return bbox
+
+def generateworldfile(image_file,bbox,imagesize):
+ """ write the world file """
+
+ # reference: http://en.wikipedia.org/wiki/World_file
+ # Line 1: A: pixel size in the x-direction in map units/pixel
+ # Line 2: D: rotation about y-axis
+ # Line 3: B: rotation about x-axis
+ # Line 4: E: pixel size in the y-direction in map units, almost always negative[3]
+ # Line 5: C: x-coordinate of the center of the upper left pixel
+ # Line 6: F: y-coordinate of the center of the upper left pixel
+
+ # no rotation in our case
+ world_file = image_file[:-4] + ".pgw"
+
+ [west,east,north,south] = bbox
+ [width, height] = imagesize
+ with open(world_file,'w') as f:
+
+ xsize = (east - west) / width
+ ysize = (south - north) / height
+ xul = west
+ yul = north
+
+ f.write("%.8f" % xsize + "\n")
+ f.write("0.0" + "\n")
+ f.write("0.0" + "\n")
+ f.write("%.8f" % ysize + "\n")
+ f.write("%.8f" % xul + "\n")
+ f.write("%.8f" % yul + "\n")
+
+ return
+
+def getint(name):
+ """ sort kml by int """
+
+ basename = string.split(name,os.path.sep)[-1][:-4]
+ alpha, num = basename.split("-")
+ return int(num)
+
+def parse_kml(dockml):
+ """ parse doc.kml """
+
+ bboxlist=[]
+ tree = ET.parse(dockml)
+ for groundoverlay in tree.iter(tag="{http://www.opengis.net/kml/2.2}GroundOverlay"):
+ V = {}
+ for elem in groundoverlay:
+ if "name" in elem.tag:
+ V['name'] = elem.text
+ continue
+ if "LatLonBox" in elem.tag:
+ for latlon_elem in elem:
+ pos_tag = latlon_elem.tag.replace('{http://www.opengis.net/kml/2.2}','')
+ V[pos_tag]=float(latlon_elem.text)
+ if "tile" in V['name']:
+ bboxlist.append(V)
+ return bboxlist
+
+def processing_kml(kmlfolder, outputfolder):
+ """ processing kml folder """
+
+ # older version
+ newversion = True
+ geotiff = os.path.basename(kmlfolder)+".tiff"
+ geotiff_compressed = os.path.basename(kmlfolder)+"_compressed.tiff"
+
+
+ kmls = glob.glob(kmlfolder + os.path.sep + "tile-*.kml")
+ if not len(kmls) == 0:
+ newversion = False
+ # sort by number from 0 ~ xxx
+ kmls.sort(key=getint)
+
+ #cmd = "gdal_merge.py -o /tmp/uid10_int.tif"
+ cmd = "montage"
+ # need to find out west most tile
+ # need to find out east most tile
+ bboxlist = []
+ totalwidth, totalheight = 0, 0
+ for kml in kmls:
+ #print kml
+ tile = string.split(kml, os.path.sep)[-1][:-4]
+ bbox = extractbbox(kml)
+ bboxlist.append(bbox)
+ image = kmlfolder + os.path.sep + "images" + os.path.sep + tile + ".png"
+ imagesize = getimagesize(image)
+ totalwidth += imagesize[0]
+ totalheight += imagesize[1]
+ #generateworldfile(image, bbox, imagesize)
+ cmd += " " + tile + ".png"
+ #os.chdir(kmlfolder + os.path.sep + "images")
+ # new version
+ if newversion:
+ totalwidth, totalheight = 0, 0
+ cmd = "montage"
+ dockml = kmlfolder + os.path.sep + "doc.kml"
+ bbox_dict = parse_kml(dockml)
+ #[west,east,north,south]
+ for item in bbox_dict:
+ image = kmlfolder + os.path.sep + "images" + os.path.sep + item['name']
+ imagesize = getimagesize(image)
+ totalwidth += imagesize[0]
+ totalheight += imagesize[1]
+ #generateworldfile(image, bbox, imagesize)
+ cmd += " " + item['name']
+ bboxlist = []
+ bboxlist.append([bbox_dict[0]['west'],bbox_dict[0]['east'],bbox_dict[0]['north'],bbox_dict[0]['south']])
+ bboxlist.append([bbox_dict[-1]['west'],bbox_dict[-1]['east'],bbox_dict[-1]['north'],bbox_dict[-1]['south']])
+
+
+ uppercorner = bboxlist[0]
+ lowercorner = bboxlist[-1]
+ lonspan = lowercorner[1]-uppercorner[0]
+ latspan = lowercorner[3]-uppercorner[2]
+ #[west,east,north,south]
+ bbox = [uppercorner[0],lowercorner[1],uppercorner[2],lowercorner[3]]
+ row = int(math.ceil(lonspan / (uppercorner[1]-uppercorner[0])))
+ col = int(math.ceil(latspan / (uppercorner[3]-uppercorner[2])))
+ print(row,col)
+ realwidth, realheight = totalwidth/col, totalheight/row
+ totalimage = kmlfolder + os.path.sep + "images" + os.path.sep + "alltest.png"
+ generateworldfile(totalimage, bbox, [realwidth,realheight])
+
+ #gdalfunction -srcnodata 0
+ #gdal_translate -a_nodata 0 -b 1 -b 2 -b 3 -mask 4 alltest.png alltest.tiff -a_srs EPSG:4326
+ #gdal_translate -a_nodata 0 alltest.tiff -co COMPRESS=DEFLATE -co TILED=YES -co BLOCKXSIZE=512 -co BLOCKYSIZE=512 alltest_compress.tiff
+ #gdaladdo -r average alltest_compress.tiff 2 4 8 16 32
+ # change folder to images folder
+ os.chdir(kmlfolder + os.path.sep + "images")
+ cmd += " -tile "+str(row)+"x" + str(col) +" -geometry +0+0 -depth 8 -background none PNG32:alltest.png"
+ print("mosaic image ...")
+ os.system(cmd)
+
+ print("gdal_translate image ...")
+ #gdal_translate -a_nodata 0 -b 1 -b 2 -b 3 -mask 4 alltest.png alltest.tiff -a_srs EPSG:4326
+ cmd = "gdal_translate alltest.png "+ geotiff + " -a_srs EPSG:4326"
+ os.system(cmd)
+ #gdal_translate -a_nodata 0 alltest.tiff -co COMPRESS=DEFLATE -co TILED=YES -co BLOCKXSIZE=512 -co BLOCKYSIZE=512 alltest_compress.tiff
+ cmd = "gdal_translate " + geotiff + " -co COMPRESS=DEFLATE -co TILED=YES -co BLOCKXSIZE=512 -co BLOCKYSIZE=512 "+ geotiff_compressed
+ os.system(cmd)
+ #gdaladdo -r average alltest_compress.tiff 2 4 8 16 32
+ cmd = "gdaladdo -r average "+ geotiff_compressed + " 2 4 8 16 32 64"
+ os.system(cmd)
+ print ("done !")
+
+ # move all tiff file
+ #cmd = "mv *.tiff " + outputfolder
+ #print "moved tiffs"
+ # only move compressed tiff
+ cmd = "mv " + geotiff_compressed + " " + outputfolder
+ print("moved compressed tiff")
+ os.system(cmd)
+
+ return
+
+def convert_kmz(kmz,outputfolder):
+ """ convert kmz to tiff """
+
+ # first unzip kmz file
+ # uzip kmz -d dir
+ kmzfolder = kmz[:-4]
+ cmd = "unzip " + kmz + " -d " + kmzfolder
+ #print cmd
+ os.system(cmd)
+ processing_kml(kmzfolder,outputfolder)
+
+ # chdir then delete folder
+ os.chdir(os.path.dirname(os.path.abspath(__file__)))
+ # remove kmz folder
+ try:
+ shutil.rmtree(kmzfolder)
+ except OSError as e:
+ print("Error: %s - %s." % (e.filename, e.strerror))
+
+ return
+
+def main():
+
+ kmzs = ["uid1540@SanAnd_08503_12023-008_13095-013_0387d_s01_L090HH_01.unw.kmz",
+ "uid1541@SanAnd_08503_12130-002_13095-013_0196d_s01_L090HH_01.unw.kmz"]
+ outputfolder = "/home/cicuser/Downloads/coding"
+ for kmz in kmzs:
+ convert_kmz(kmz,outputfolder)
+
+
+if __name__ == "__main__":
+ main()