Skip to content

Commit

Permalink
#5 kmz2tiff tested
Browse files Browse the repository at this point in the history
  • Loading branch information
webgisdeveloper authored Dec 30, 2021
1 parent 6265289 commit d6441ca
Showing 1 changed file with 237 additions and 0 deletions.
237 changes: 237 additions & 0 deletions kmz2tiff.py
Original file line number Diff line number Diff line change
@@ -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

#<north>32.93182878</north>
#<south>32.87493534</south>
#<east>-116.0291427</east>
#<west>-116.08603614</west>

north = cleanStrings(kmlstring, "<north>","</north>")
south = cleanStrings(kmlstring, "<south>","</south>")
east = cleanStrings(kmlstring, "<east>","</east>")
west = cleanStrings(kmlstring, "<west>","</west>")

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()

0 comments on commit d6441ca

Please sign in to comment.