Index: gdal/apps/gdal_utilities.dox
===================================================================
--- gdal/apps/gdal_utilities.dox (revision 21277)
+++ gdal/apps/gdal_utilities.dox (working copy)
@@ -1412,6 +1412,7 @@
[-s_srs srs_def] [-pyramidOnly]
[-r {near/bilinear/cubic/cubicspline/lanczos}]
-levels numberoflevels
+ [-useDirForEachRow]
-targetDir TileDirectory input_files
\endverbatim
@@ -1428,7 +1429,7 @@
- -targetDir directory:
-
-The Directory where the tile result is created. Pyramids are stored
+The directory where the tile result is created. Pyramids are stored
in subdirs numbered from 1. Created tile names have a numbering
schema and contain the name of the source tiles(s)
@@ -1478,6 +1479,17 @@
- -csvDelim column delimiter:
-
The column delimter used in the csv file, default value is a semicolon ";"
+- -useDirForEachRow:
-
+Normally the tiles of the base image are stored as described in -targetDir.
+For large images, some file systems have performance problems if the number of files
+in a directory is to big, causing gdal_retile not to finish in reasonable time.
+Using this parameter creates a different output structure. The tiles of the base image
+are stored in a subdirectory called 0, the pyramids in subdirectories numbered 1,2,....
+Within each of these directories another level of subdirectories is created, numbered from
+0...n, depending of how many tile rows are needed for each level. Finally, a directory contains
+only the the tiles for one row for a specific level. For large images a performance improvement
+of a factor N could be achieved.
+
NOTE: gdal_retile.py is a Python script, and will only work if GDAL was built
Index: gdal/swig/python/scripts/gdal_retile.py
===================================================================
--- gdal/swig/python/scripts/gdal_retile.py (revision 21277)
+++ gdal/swig/python/scripts/gdal_retile.py (working copy)
@@ -4,6 +4,7 @@
#
# Purpose: Module for retiling (merging) tiles and building tiled pyramids
# Author: Christian Meuller, christian.mueller@nvoe.at
+# UseDirForEachRow support by Chris Giesey & Elijah Robison
#
###############################################################################
# Copyright (c) 2007, Christian Mueller
@@ -167,7 +168,7 @@
self.ct = None
self.ci = [0] * self.bands
for iband in range(self.bands):
- self.ci[iband] = fhInputTile.GetRasterBand(iband + 1).GetColorInterpretation()
+ self.ci[iband] = fhInputTile.GetRasterBand(iband + 1).GetRasterColorInterpretation()
extent = self.ogrTileIndexDS.GetLayer().GetExtent()
self.ulx = extent[0];
@@ -320,7 +321,8 @@
"""
-
+ global LastRowIndx
+ LastRowIndx=-1
OGRDS=createTileIndex("TileResult_0", TileIndexFieldName, Source_SRS,TileIndexDriverTyp)
@@ -340,16 +342,25 @@
width=ti.lastTileWidth
else:
width=ti.tileWidth
- tilename=getTileName(minfo,ti, xIndex, yIndex)
+ if UseDirForEachRow :
+ tilename=getTileName(minfo,ti, xIndex, yIndex,0)
+ else:
+ tilename=getTileName(minfo,ti, xIndex, yIndex)
createTile(minfo, offsetX, offsetY, width, height,tilename,OGRDS)
if TileIndexName is not None:
- shapeName=getTargetDir()+TileIndexName
+ if UseDirForEachRow and PyramidOnly == False:
+ shapeName=getTargetDir(0)+TileIndexName
+ else:
+ shapeName=getTargetDir()+TileIndexName
copyTileIndexToDisk(OGRDS,shapeName)
if CsvFileName is not None:
- csvName=getTargetDir()+CsvFileName
+ if UseDirForEachRow and PyramidOnly == False:
+ csvName=getTargetDir(0)+CsvFileName
+ else:
+ csvName=getTargetDir()+CsvFileName
copyTileIndexToCSV(OGRDS,csvName)
@@ -364,6 +375,9 @@
break
newFeature = feature.Clone()
basename = os.path.basename(feature.GetField(0))
+ if UseDirForEachRow :
+ t = os.path.split(os.path.dirname(feature.GetField(0)))
+ basename = t[1]+"/"+basename
newFeature.SetField(0,basename)
SHAPEDS.GetLayer().CreateFeature(newFeature)
closeTileIndex(SHAPEDS)
@@ -376,6 +390,9 @@
if feature is None:
break
basename = os.path.basename(feature.GetField(0))
+ if UseDirForEachRow :
+ t = os.path.split(os.path.dirname(feature.GetField(0)))
+ basename = t[1]+"/"+basename
csvfile.write(basename);
geom = feature.GetGeometryRef()
coords = geom.GetEnvelope();
@@ -589,8 +606,10 @@
def buildPyramid(minfo,createdTileIndexDS,tileWidth, tileHeight):
+ global LastRowIndx
inputDS=createdTileIndexDS
for level in range(1,Levels+1):
+ LastRowIndx = -1
levelMosaicInfo = mosaic_info(minfo.filename,inputDS)
levelOutputTileInfo = tile_info(levelMosaicInfo.xsize/2,levelMosaicInfo.ysize/2,tileWidth,tileHeight)
inputDS=buildPyramidLevel(levelMosaicInfo,levelOutputTileInfo,level)
@@ -634,6 +653,8 @@
"""
creates the tile file name
"""
+ global LastRowIndx
+
max = ti.countTilesX
if (ti.countTilesY > max):
max=ti.countTilesY
@@ -642,10 +663,20 @@
if parts[0][0]=="@" : #remove possible leading "@"
parts = ( parts[0][1:len(parts[0])], parts[1])
+ if UseDirForEachRow :
+ format=getTargetDir(level)+str(yIndex)+os.sep+parts[0]+"_%0"+str(countDigits)+"i"+"_%0"+str(countDigits)+"i"
+ #See if there was a switch in the row, if so then create new dir for row.
+ if LastRowIndx < yIndex :
+ LastRowIndx = yIndex
+ if (os.path.exists(getTargetDir(level)+str(yIndex)) == False) :
+ os.mkdir(getTargetDir(level)+str(yIndex))
+ else:
+ format=getTargetDir(level)+parts[0]+"_%0"+str(countDigits)+"i"+"_%0"+str(countDigits)+"i"
+ #Check for the extension that should be used.
if Extension is None:
- format=getTargetDir(level)+parts[0]+"_%0"+str(countDigits)+"i"+"_%0"+str(countDigits)+"i"+parts[1]
+ format=format+parts[1]
else:
- format=getTargetDir(level)+parts[0]+"_%0"+str(countDigits)+"i"+"_%0"+str(countDigits)+"i"+"."+Extension
+ format=format+"."+Extension
return format % (yIndex,xIndex)
def UsageFormat():
@@ -666,6 +697,7 @@
print(' [ -csv fileName [-csvDelim delimiter]]')
print(' [-s_srs srs_def] [-pyramidOnly] -levels numberoflevels')
print(' [-r {near/bilinear/cubic/cubicspline/lanczos}]')
+ print(' [-useDirForEachRow]')
print(' -targetDir TileDirectory input_files')
# =============================================================================
@@ -699,6 +731,7 @@
global ResamplingMethod
global Levels
global PyramidOnly
+ global UseDirForEachRow
gdal.AllRegister()
@@ -796,6 +829,8 @@
elif arg == '-csvDelim':
i+=1
CsvDelimiter=argv[i]
+ elif arg == '-useDirForEachRow':
+ UseDirForEachRow=True
elif arg[:1] == '-':
print('Unrecognised command option: %s' % arg)
Usage()
@@ -819,8 +854,15 @@
Usage()
return 1
+ # create level 0 directory if needed
+ if(UseDirForEachRow and PyramidOnly==False) :
+ leveldir=TargetDir+str(0)+os.sep
+ if (os.path.exists(leveldir)==False):
+ os.mkdir(leveldir)
+
if Levels > 0: #prepare Dirs for pyramid
- for levelIndx in range (1,Levels+1):
+ startIndx=1
+ for levelIndx in range (startIndx,Levels+1):
leveldir=TargetDir+str(levelIndx)+os.sep
if (os.path.exists(leveldir)):
continue
@@ -900,7 +942,10 @@
global ResamplingMethod
global Levels
global PyramidOnly
+ global LastRowIndx
+ global UseDirForEachRow
+
Verbose=False
CreateOptions = []
Names=[]
@@ -922,8 +967,11 @@
ResamplingMethod=GRA_NearestNeighbour
Levels=0
PyramidOnly=False
+ LastRowIndx=-1
+ UseDirForEachRow=False
+
#global vars
Verbose=False
CreateOptions = []
@@ -945,9 +993,9 @@
ResamplingMethod=GRA_NearestNeighbour
Levels=0
PyramidOnly=False
+LastRowIndx=-1
+UseDirForEachRow=False
-
if __name__ == '__main__':
sys.exit(main(sys.argv))
-
Index: autotest/pyscripts/test_gdal_retile.py
===================================================================
--- autotest/pyscripts/test_gdal_retile.py (revision 21277)
+++ autotest/pyscripts/test_gdal_retile.py (working copy)
@@ -97,11 +97,11 @@
test_py_scripts.run_py_script(script_path, 'gdal_retile', '-v -levels 2 -r bilinear -targetDir tmp/outretile2 ../gcore/data/rgba.tif' )
ds = gdal.Open('tmp/outretile2/2/rgba_1_1.tif')
- if ds.GetRasterBand(1).Checksum() != 35:
+ if ds.GetRasterBand(1).Checksum() != 283:
gdaltest.post_reason('wrong checksum for band 1')
print(ds.GetRasterBand(1).Checksum())
return 'fail'
- if ds.GetRasterBand(4).Checksum() != 35:
+ if ds.GetRasterBand(4).Checksum() != 122:
gdaltest.post_reason('wrong checksum for band 4')
print(ds.GetRasterBand(4).Checksum())
return 'fail'