def warp_27(): if test_cli_utilities.get_gdalwarp_path() is None: return 'skip' # Open source dataset src_ds = gdal.Open('../gcore/data/byte.tif') # Desfine target SRS dst_srs = osr.SpatialReference() dst_srs.ImportFromEPSG(4326) dst_wkt = dst_srs.ExportToWkt() error_threshold = 0.125 # error threshold --> use same value as in gdalwarp resampling = gdal.GRA_Bilinear # Call AutoCreateWarpedVRT() to fetch default values for target raster dimensions and geotransform tmp_ds = gdal.AutoCreateWarpedVRT( src_ds, \ None, # src_wkt : left to default value --> will use the one from source \ dst_wkt, \ resampling, \ error_threshold ) dst_xsize = tmp_ds.RasterXSize dst_ysize = tmp_ds.RasterYSize dst_gt = tmp_ds.GetGeoTransform() tmp_ds = None # Now create the true target dataset dst_ds = gdal.GetDriverByName('GTiff').Create('tmp/warp_27.tif', dst_xsize, dst_ysize, src_ds.RasterCount) dst_ds.SetProjection(dst_wkt) dst_ds.SetGeoTransform(dst_gt) # And run the reprojection cbk = warp_27_progress_callback cbk_user_data = None # value for last parameter of above warp_27_progress_callback gdal.ReprojectImage( src_ds, \ dst_ds, \ None, # src_wkt : left to default value --> will use the one from source \ None, # dst_wkt : left to default value --> will use the one from destination \ resampling, \ 0, # WarpMemoryLimit : left to default value \ error_threshold, cbk, # Progress callback : could be left to None or unspecified for silent progress cbk_user_data) # Progress callback user data # Done ! dst_ds = None # Check that we have the same result as produced by 'gdalwarp -rb -t_srs EPSG:4326 ../gcore/data/byte.tif tmp/warp_27.tif' ds = gdal.Open('tmp/warp_27.tif') cs = ds.GetRasterBand(1).Checksum() ds = None gdaltest.runexternal( test_cli_utilities.get_gdalwarp_path() + ' -rb -t_srs EPSG:4326 ../gcore/data/byte.tif tmp/warp_27_ref.tif') ds = gdal.Open('tmp/warp_27_ref.tif') ref_cs = ds.GetRasterBand(1).Checksum() ds = None if cs != ref_cs: return 'fail' gdal.Unlink('tmp/warp_27.tif') gdal.Unlink('tmp/warp_27_ref.tif') return 'success'
def warp_30(): # Open source dataset src_ds = gdal.Open('../gcore/data/byte.tif') # Desfine target SRS dst_srs = osr.SpatialReference() dst_srs.ImportFromEPSG(4326) dst_wkt = dst_srs.ExportToWkt() error_threshold = 0.125 # error threshold --> use same value as in gdalwarp resampling = gdal.GRA_Bilinear # Call AutoCreateWarpedVRT() to fetch default values for target raster dimensions and geotransform tmp_ds = gdal.AutoCreateWarpedVRT( src_ds, \ None, # src_wkt : left to default value --> will use the one from source \ dst_wkt, \ resampling, \ error_threshold ) dst_xsize = tmp_ds.RasterXSize dst_ysize = tmp_ds.RasterYSize dst_gt = tmp_ds.GetGeoTransform() tmp_ds = None # Now create the true target dataset dst_ds = gdal.GetDriverByName('GTiff').Create('/vsimem/warp_30.tif', dst_xsize, dst_ysize, src_ds.RasterCount) dst_ds.SetProjection(dst_wkt) dst_ds.SetGeoTransform(dst_gt) # And run the reprojection cbk = warp_30_progress_callback cbk_user_data = None # value for last parameter of above warp_27_progress_callback gdal.PushErrorHandler('CPLQuietErrorHandler') ret = gdal.ReprojectImage( src_ds, \ dst_ds, \ None, # src_wkt : left to default value --> will use the one from source \ None, # dst_wkt : left to default value --> will use the one from destination \ resampling, \ 0, # WarpMemoryLimit : left to default value \ error_threshold, cbk, # Progress callback : could be left to None or unspecified for silent progress cbk_user_data) # Progress callback user data gdal.PopErrorHandler() if ret == 0: gdaltest.post_reason('failed') return 'fail' old_val = gdal.GetConfigOption('GDAL_NUM_THREADS') gdal.SetConfigOption('GDAL_NUM_THREADS', '2') gdal.PushErrorHandler('CPLQuietErrorHandler') ret = gdal.ReprojectImage( src_ds, \ dst_ds, \ None, # src_wkt : left to default value --> will use the one from source \ None, # dst_wkt : left to default value --> will use the one from destination \ resampling, \ 0, # WarpMemoryLimit : left to default value \ error_threshold, cbk, # Progress callback : could be left to None or unspecified for silent progress cbk_user_data) # Progress callback user data gdal.PopErrorHandler() gdal.SetConfigOption('GDAL_NUM_THREADS', old_val) if ret == 0: gdaltest.post_reason('failed') return 'fail' return 'success'
def prepare(inputfile, logger, exc, **options): gdal.AllRegister() # Spatial Reference System of tiles out_srs = osr.SpatialReference() out_srs.ImportFromEPSG(3857) # Set output directory if not options.get('output'): # Directory with input filename without extension in actual directory output = os.path.abspath( os.path.join("%s.tiles" % os.path.splitext(inputfile)[0])) logger.info('No output specified, using %s', output) else: output = options.get('output') if os.path.exists(output): if not options.get('resume'): raise exc( 'Output %s already exists and resume is not enabled, aborting!' % output) else: if not options.get('dry_run'): os.makedirs(output) out_drv = gdal.GetDriverByName(options.get('format')) if not out_drv: raise exc( "The '%s' driver was not found, is it available in this GDAL build?", options.get('format')) # Open the input file in_ds = gdal.Open(inputfile, gdal.GA_ReadOnly) if not in_ds: raise exc("It is not possible to open the input file '%s'." % inputfile) logger.info("Input file: %s ( %sP x %sL - %s bands)", inputfile, in_ds.RasterXSize, in_ds.RasterYSize, in_ds.RasterCount) if (in_ds.GetGeoTransform() == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0)) and (in_ds.GetGCPCount() == 0): raise exc("Input file %s is not georeferenced!" % inputfile) # Read metadata from the input file if in_ds.RasterCount == 0: raise exc("Input file '%s' has no raster band" % inputfile) if in_ds.GetRasterBand(1).GetRasterColorTable(): # TODO: Process directly paletted dataset by generating VRT in memory raise exc("Please convert %s to RGB/RGBA with gdal_translate." % inputfile) # Get NODATA value in_nodata = [] for i in range(1, in_ds.RasterCount + 1): if in_ds.GetRasterBand(i).GetNoDataValue() != None: in_nodata.append(in_ds.GetRasterBand(i).GetNoDataValue()) logger.info("NODATA: %s", in_nodata) # Here we should have RGBA input dataset opened in in_ds logger.info("Preprocessed file: %s ( %sP x %sL - %s bands)", inputfile, in_ds.RasterXSize, in_ds.RasterYSize, in_ds.RasterCount) # Spatial Reference System of the input raster in_srs = None if options.get('srs'): in_srs = osr.SpatialReference() in_srs.SetFromUserInput(options.get('srs')) in_srs_wkt = in_srs.ExportToWkt() else: in_srs_wkt = in_ds.GetProjection() if not in_srs_wkt and in_ds.GetGCPCount() != 0: in_srs_wkt = in_ds.GetGCPProjection() if in_srs_wkt: in_srs = osr.SpatialReference() in_srs.ImportFromWkt(in_srs_wkt) if not in_srs: raise exc( "Input file %s has unknown SRS. Use --srs=ESPG:xyz (or similar) to provide source reference system." % inputfile) logger.info("Input SRS: %s", in_srs.ExportToProj4()) logger.info("Output SRS: %s", out_srs.ExportToProj4()) out_ds = None # Are the reference systems the same? Reproject if necessary. if (in_srs.ExportToProj4() != out_srs.ExportToProj4()) or (in_ds.GetGCPCount() != 0): logger.info("Creating AutoCreateWarpedVRT.") # Generation of VRT dataset in tile projection, default 'nearest neighbour' warping out_ds = gdal.AutoCreateWarpedVRT(in_ds, in_srs_wkt, out_srs.ExportToWkt()) # TODO: HIGH PRIORITY: Correction of AutoCreateWarpedVRT according the max zoomlevel for correct direct warping!!! #logger.info("Warping of the raster by AutoCreateWarpedVRT (result saved into 'tiles.vrt')") #out_ds.GetDriver().CreateCopy("tiles.vrt", out_ds) # Note: in_srs and in_srs_wkt contain still the non-warped reference system!!! # Correction of AutoCreateWarpedVRT for NODATA values if in_nodata != []: tempfilename = tempfile.mktemp('-bands.vrt') # TODO out_ds.GetDriver().CreateCopy(tempfilename, out_ds) # open as a text file s = open(tempfilename).read() # Add the warping options s = s.replace( """<GDALWarpOptions>""", """<GDALWarpOptions> <Option name="INIT_DEST">NO_DATA</Option> <Option name="UNIFIED_SRC_NODATA">YES</Option>""") # replace BandMapping tag for NODATA bands.... for i in range(len(in_nodata)): s = s.replace("""<BandMapping src="%i" dst="%i"/>""" % ((i + 1), (i + 1)), """<BandMapping src="%i" dst="%i"> <SrcNoDataReal>%i</SrcNoDataReal> <SrcNoDataImag>0</SrcNoDataImag> <DstNoDataReal>%i</DstNoDataReal> <DstNoDataImag>0</DstNoDataImag> </BandMapping>""" % ((i + 1), (i + 1), in_nodata[i], in_nodata[i])) # Or rewrite to white by: , 255 )) # save the corrected VRT open(tempfilename, "w").write(s) # open by GDAL as out_ds out_ds = gdal.Open(tempfilename) #, gdal.GA_ReadOnly) # delete the temporary file os.unlink(tempfilename) # set NODATA_VALUE metadata out_ds.SetMetadataItem( 'NODATA_VALUES', '%i %i %i' % (in_nodata[0], in_nodata[1], in_nodata[2])) #logger.info("Modified warping result saved into 'tiles1.vrt'") #open("tiles1.vrt","w").write(s) # ----------------------------------- # Correction of AutoCreateWarpedVRT for Mono (1 band) and RGB (3 bands) files without NODATA: # equivalent of gdalwarp -dstalpha if in_nodata == [] and out_ds.RasterCount in [1, 3]: tempfilename = tempfile.mktemp('-alpha.vrt') out_ds.GetDriver().CreateCopy(tempfilename, out_ds) # open as a text file s = open(tempfilename).read() # Add the warping options s = s.replace( """<BlockXSize>""", """<VRTRasterBand dataType="Byte" band="%i" subClass="VRTWarpedRasterBand"> <ColorInterp>Alpha</ColorInterp> </VRTRasterBand> <BlockXSize>""" % (out_ds.RasterCount + 1)) s = s.replace( """</GDALWarpOptions>""", """<DstAlphaBand>%i</DstAlphaBand> </GDALWarpOptions>""" % (out_ds.RasterCount + 1)) s = s.replace( """</WorkingDataType>""", """</WorkingDataType> <Option name="INIT_DEST">0</Option>""") # save the corrected VRT open(tempfilename, "w").write(s) # open by GDAL as out_ds out_ds = gdal.Open(tempfilename) #, gdal.GA_ReadOnly) # delete the temporary file os.unlink(tempfilename) if not out_ds: out_ds = in_ds # Here we should have a raster (out_ds) in the correct Spatial Reference system # Get alpha band (either directly or from NODATA value) alphaband = out_ds.GetRasterBand(1).GetMaskBand() if (alphaband.GetMaskFlags() & gdal.GMF_ALPHA ) or out_ds.RasterCount == 4 or out_ds.RasterCount == 2: # TODO: Better test for alpha band in the dataset dataBandsCount = out_ds.RasterCount - 1 else: dataBandsCount = out_ds.RasterCount logger.info("dataBandsCount: %s", dataBandsCount) # Read the georeference out_gt = out_ds.GetGeoTransform() # Report error in case rotation/skew is in geotransform (possible only in 'raster' profile) if (out_gt[2], out_gt[4]) != (0, 0): # TODO: Do the warping in this case automaticaly raise exc( "Georeference of the raster in input file %s contains rotation or skew. Such raster is not supported. Please use gdalwarp first." % inputfile) # Here we expect: pixel is square, no rotation on the raster # Output Bounds - coordinates in the output SRS ominx = out_gt[0] omaxx = out_gt[0] + out_ds.RasterXSize * out_gt[1] omaxy = out_gt[3] ominy = out_gt[3] + out_ds.RasterYSize * out_gt[5] # Note: maybe round(x, 14) to avoid the gdal_translate behaviour, when 0 becomes -1e-15 logger.info("Bounds (output srs): minX:%d minY:%d maxX:%d maxY:%d", ominx, ominy, omaxx, omaxy) # Calculating ranges for tiles in different zoom levels mercator = GlobalMercator( tilesize=options.get('tilesize')) # from globalmaptiles.py logger.info( 'Bounds (latlong): minX:%f minY:%f maxX:%f maxY:%f', *mercator.MetersToLatLon(ominx, ominy) + mercator.MetersToLatLon(omaxx, omaxy)) # Get the minimal zoom level (map covers area equivalent to one tile) tminz = mercator.ZoomForPixelSize( out_gt[1] * max(out_ds.RasterXSize, out_ds.RasterYSize) / float(options.get('tilesize'))) # Get the maximal zoom level (closest possible zoom level up on the resolution of raster) tmaxz = mercator.ZoomForPixelSize(out_gt[1]) logger.info('MinZoomLevel: %d (res:%f)', tminz, mercator.Resolution(tminz)) logger.info('MaxZoomLevel: %d (res:%f)', tmaxz, mercator.Resolution(tmaxz)) # Generate table with min max tile coordinates for all zoomlevels tminmax = {k: 0 for k in range(tminz, tmaxz + 1)} for tz in range(tminz, tmaxz + 1): tminx, tminy = mercator.MetersToTile(ominx, ominy, tz) tmaxx, tmaxy = mercator.MetersToTile(omaxx, omaxy, tz) # crop tiles extending world limits (+-180,+-90) tminx, tminy = max(0, tminx), max(0, tminy) tmaxx, tmaxy = min(2**tz - 1, tmaxx), min(2**tz - 1, tmaxy) logger.info("tiles at zoom %d: %d", tz, (tmaxy - tminy + 1) * (tmaxx - tminx + 1)) tminmax[tz] = (tminx, tminy, tmaxx, tmaxy) # TODO: Maps crossing 180E (Alaska?) if options.get('dry_run'): logger.info( "This is only a dry-run, stopping before any tasks are dispatched ..." ) workerfile = os.path.abspath("%s.worker" % inputfile) out_ds.GetDriver().CreateCopy(workerfile, out_ds) tr = TileRenderer() for tz in range(tmaxz, tminz - 1, -1): tminx, tminy, tmaxx, tmaxy = tminmax[tz] for tx in range(tminx, tmaxx + 1): tiledir = os.path.abspath(os.path.join(output, str(tz), str(tx))) if not os.path.exists(tiledir) and not options.get('dry_run'): logger.debug("Creating tile directory: %s", tiledir) os.makedirs(tiledir) for ty in range(tmaxy, tminy - 1, -1): tilefile = os.path.join( tiledir, "%s.%s" % (ty, options.get('format').lower())) if options.get('resume') and os.path.exists(tilefile): logger.debug("Skip existing tile: %s", tilefile) continue args = (workerfile, tilefile, tx, ty, tz, options.get('tilesize'), dataBandsCount) kwargs = {'driver': options.get('format')} logger.debug("Task: %s, %s", repr(args), repr(kwargs)) if not options.get('dry_run'): tr.apply_async(args, kwargs)
def init_map(self, zoom_parm): 'initialize geo-parameters and generate base zoom level' #---------------------------- # init variables self.tiles_prefix = self.options.tiles_prefix self.src_dir, src_f = os.path.split(self.src) self.base = os.path.splitext(src_f)[0] self.base_resampling = base_resampling_map[ self.options.base_resampling] self.resampling = resampling_map[self.options.overview_resampling] #~ if self.options.verbose > 0: #~ print('\n%s -> %s '%(self.src, self.dest), end='') logging.info(' %s -> %s ' % (self.src, self.dest)) if os.path.isdir(self.dest): if self.options.noclobber and os.path.exists(self.dest): logging.error('Target already exists: skipping') return False else: shutil.rmtree(self.dest, ignore_errors=True) # connect to src dataset try: self.get_src_ds() except RuntimeError as exc: if self.options.skip_invalid: logging.error('%s' % exc.message[:-1]) return False else: raise # calculate zoom range self.calc_zoom(zoom_parm) self.max_zoom = self.zoom_range[0] # shift target SRS to avoid crossing 180 meridian shifted_srs = self.shift_srs(self.max_zoom) shift_x = GdalTransformer(SRC_SRS=shifted_srs, DST_SRS=self.proj_srs).transform_point( (0, 0))[0] if shift_x != 0: self.proj_srs = shifted_srs self.proj2geog = GdalTransformer(SRC_SRS=self.proj_srs, DST_SRS=self.geog_srs) self.pix_origin = (self.pix_origin[0] - shift_x, self.pix_origin[1]) self.tile_origin = (self.tile_origin[0] - shift_x, self.tile_origin[1]) ld('new_srs', shifted_srs, 'shift_x', shift_x, 'pix_origin', self.pix_origin) # get corners at the target SRS target_ds = gdal.AutoCreateWarpedVRT(self.src_ds, None, txt2wkt(shifted_srs)) target_bounds = GdalTransformer(target_ds).transform([ (0, 0), (target_ds.RasterXSize, target_ds.RasterYSize) ]) # self.bounds are set to a world raster, now clip to the max tileset area self.bounds = ((target_bounds[0][0], min(self.bounds[0][1], target_bounds[0][1])), (target_bounds[1][0], max(self.bounds[1][1], target_bounds[1][1]))) ld('target raster') ld('Upper Left', self.bounds[0], target_bounds[0], self.proj2geog.transform([self.bounds[0], target_bounds[0]])) ld('Lower Right', self.bounds[1], target_bounds[1], self.proj2geog.transform([self.bounds[1], target_bounds[1]])) # orig_ul = GdalTransformer(SRC_SRS=self.geog_srs, DST_SRS=self.srs).transform_point( # self.proj2geog.transform_point(target_bounds[0])) # ld(orig_ul[0]-target_bounds[0][0], orig_ul) return True
def pre_process_inumpyut(self, _inumpyut): """Initialization of the inumpyut raster, reprojection if necessary""" print "Processing: %s" % _inumpyut inumpyut_or_vrt = _inumpyut if not self.mem_drv: raise Exception( "The 'MEM' driver was not found, is it available in this GDAL build?" ) # Open the inumpyut file if self.inumpyut: in_ds = gdal.Open(_inumpyut, gdal.GA_ReadOnly) else: raise Exception("No inumpyut file was specified") if self.options.verbose: print( "Inumpyut file:", "( %sP x %sL - %s bands)" % (self.in_ds.RasterXSize, self.in_ds.RasterYSize, self.in_ds.RasterCount)) if not in_ds: # Note: GDAL prints the ERROR message too self.error("It is not possible to open the inumpyut file '%s'." % _inumpyut) # Read metadata from the inumpyut file if in_ds.RasterCount == 0: self.error("Inumpyut file '%s' has no raster band" % _inumpyut) if in_ds.GetRasterBand(1).GetRasterColorTable(): # TODO: Process directly paletted dataset by generating VRT in memory self.error( "Please convert this file to RGB/RGBA and run gdal2tiles on the result.", """From paletted file you can create RGBA file (temp.vrt) by: gdal_translate -of vrt -expand rgba %s temp.vrt then run: gdal2tiles temp.vrt""" % _inumpyut) # Get NODATA value in_nodata = [] for i in range(1, in_ds.RasterCount + 1): if in_ds.GetRasterBand(i).GetNoDataValue() != None: ndata = in_ds.GetRasterBand(i).GetNoDataValue() if math.isnan(ndata): ndata = 'none' in_nodata.append(ndata) if self.options.srcnodata: nds = list(map(float, self.options.srcnodata.split(','))) if len(nds) < in_ds.RasterCount: in_nodata = (nds * in_ds.RasterCount)[:in_ds.RasterCount] else: in_nodata = nds if self.options.verbose: print("NODATA: %s" % in_nodata) # # Here we should have RGBA inumpyut dataset opened in in_ds # if self.options.verbose: print( "Preprocessed file:", "( %sP x %sL - %s bands)" % (in_ds.RasterXSize, in_ds.RasterYSize, in_ds.RasterCount)) # Spatial Reference System of the inumpyut raster self.in_srs = None if self.options.s_srs: self.in_srs = osr.SpatialReference() self.in_srs.SetFromUserInumpyut(self.options.s_srs) self.in_srs_wkt = self.in_srs.ExportToWkt() else: self.in_srs_wkt = in_ds.GetProjection() if not self.in_srs_wkt and in_ds.GetGCPCount() != 0: self.in_srs_wkt = in_ds.GetGCPProjection() if self.in_srs_wkt: self.in_srs = osr.SpatialReference() self.in_srs.ImportFromWkt(self.in_srs_wkt) # Spatial Reference System of tiles self.out_srs = osr.SpatialReference() self.out_srs.ImportFromEPSG(4326) # Are the reference systems the same? Reproject if necessary. out_ds = None if (in_ds.GetGeoTransform() == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0)) and (in_ds.GetGCPCount() == 0): self.error( "There is no georeference - neither affine transformation (worldfile) nor GCPs. You can generate only 'raster' profile tiles.", "Either gdal2tiles with parameter -p 'raster' or use another GIS software for georeference e.g. gdal_transform -gcp / -a_ullr / -a_srs" ) in_srs_code = self.in_srs.GetAttrValue("AUTHORITY", 0) in_ds_srs = osr.SpatialReference() res = in_ds_srs.ImportFromWkt(in_ds.GetProjection()) if res != 0 and in_srs_code is None: print "ERROR! The inumpyut file %s has no SRS associated and no SRS has been defined in inumpyut (-s parameter)" % _inumpyut exit(1) if self.in_srs: if in_ds_srs.ExportToProj4() != self.out_srs.ExportToProj4(): if (self.in_srs.ExportToProj4() != self.out_srs.ExportToProj4()) or (in_ds.GetGCPCount() != 0): print "WARNING! Inumpyut file %s has a SR different from EPSG:4326 (WGS84). This can make the processing significantly slow." % _inumpyut # Generation of VRT dataset in tile projection, default 'nearest neighbour' warping out_ds = gdal.AutoCreateWarpedVRT( in_ds, self.in_srs_wkt, self.out_srs.ExportToWkt()) # TODO: HIGH PRIORITY: Correction of AutoCreateWarpedVRT according the max zoomlevel for correct direct warping!!! if self.options.verbose: print( "Warping of the raster by AutoCreateWarpedVRT (result saved into 'tiles.vrt')" ) out_ds.GetDriver().CreateCopy("%s.vrt" % _inumpyut, out_ds) inumpyut_or_vrt = "%s.vrt" % _inumpyut # Note: self.in_srs and self.in_srs_wkt contain still the non-warped reference system!!! else: self.error( "Inumpyut file has unknown SRS.", "Use --s_srs ESPG:xyz (or similar) to provide source reference system." ) if out_ds and self.options.verbose: print( "Projected file:", "tiles.vrt", "( %sP x %sL - %s bands)" % (out_ds.RasterXSize, out_ds.RasterYSize, out_ds.RasterCount)) if not out_ds: out_ds = in_ds # # Here we should have a raster (out_ds) in the correct Spatial Reference system # # Get alpha band (either directly or from NODATA value) alphaband = out_ds.GetRasterBand(1).GetMaskBand() if (alphaband.GetMaskFlags() & gdal.GMF_ALPHA ) or out_ds.RasterCount == 4 or out_ds.RasterCount == 2: # TODO: Better test for alpha band in the dataset dataBandsCount = out_ds.RasterCount - 1 else: dataBandsCount = out_ds.RasterCount # Read the georeference out_gt = out_ds.GetGeoTransform() # Report error in case rotation/skew is in geotransform (possible only in 'raster' profile) if (out_gt[2], out_gt[4]) != (0, 0): self.error( "Georeference of the raster contains rotation or skew. Such raster is not supported. Please use gdalwarp first." ) # TODO: Do the warping in this case automaticaly # # Here we expect: pixel is square, no rotation on the raster # # Output Bounds - coordinates in the output SRS ominx = out_gt[0] omaxx = out_gt[0] + out_ds.RasterXSize * out_gt[1] omaxy = out_gt[3] ominy = out_gt[3] - out_ds.RasterYSize * out_gt[1] # Note: maybe round(x, 14) to avoid the gdal_translate behaviour, when 0 becomes -1e-15 if self.options.verbose: print("Bounds (output srs):", round(ominx, 13), ominy, omaxx, omaxy) # # Calculating ranges for tiles in different zoom levels # geodetic = GlobalGeodetic() # from globalmaptiles.py # Generate table with min max tile coordinates for all zoomlevels tminmax = list(range(0, 32)) for tz in range(0, 32): tminx, tminy = geodetic.LatLonToTile(ominx, ominy, tz) tmaxx, tmaxy = geodetic.LatLonToTile(omaxx, omaxy, tz) # crop tiles extending world limits (+-180,+-90) tminx, tminy = max(0, tminx), max(0, tminy) tmaxx, tmaxy = min(2**(tz + 1) - 1, tmaxx), min(2**tz - 1, tmaxy) tminmax[tz] = (tminx, tminy, tmaxx, tmaxy) # Get the maximal zoom level (closest possible zoom level up on the resolution of raster) tminz = geodetic.ZoomForPixelSize( out_gt[1] * max(out_ds.RasterXSize, out_ds.RasterYSize) / float(self.tilesize)) if self.options.verbose: print('Min Zoom: %s' % tminz) # Get the maximal zoom level (closest possible zoom level up on the resolution of raster) tmaxz = geodetic.ZoomForPixelSize(out_gt[1]) if self.options.verbose: print('Max Zoom: %s' % tmaxz) self.inumpyuts_data[_inumpyut] = [ tminz, tmaxz, tminmax, out_gt[1], out_gt[5] ] self.inumpyuts_files_or_vrt.append(inumpyut_or_vrt) if self.options.verbose: print("Bounds (latlong):", ominx, ominy, omaxx, omaxy)
def process_file(spath, tpath): old_ds = gdal.Open(spath) vrt_ds = gdal.AutoCreateWarpedVRT(old_ds, None, srs.ExportToWkt(), gdal.GRA_Bilinear) gdal.GetDriverByName('gtiff').CreateCopy(tpath, vrt_ds)
def _get_map(obj, params, request): p_layers = params['LAYERS'].split(',') p_bbox = _validate_bbox([float(v) for v in params['BBOX'].split(',', 3)]) p_width = int(params['WIDTH']) p_height = int(params['HEIGHT']) p_format = params.get('FORMAT', IMAGE_FORMAT.PNG) p_style = params.get('STYLES') p_bgcolor = params.get('BGCOLOR') p_transparent = params.get('TRANSPARENT', 'FALSE') p_srs = params.get('SRS', params.get('CRS')) if p_format not in IMAGE_FORMAT.enum: raise ValidationError("Invalid FORMAT parameter.", data=dict(code="InvalidFormat")) if p_style and not (p_style == "," * (len(p_layers) - 1)): raise ValidationError("Style not found.", data=dict(code="StyleNotDefined")) if p_srs is None: raise ValidationError(message="CRS/SRS parameter required.") if p_bgcolor: r, g, b = _validate_bgcolor(p_bgcolor) bgcolor = (r, g, b) else: bgcolor = (255, 255, 255) if p_transparent.upper() == 'TRUE': img_mode = 'RGBA' bgcolor = bgcolor + (0, ) else: img_mode = 'RGB' p_size = (p_width, p_height) img = Image.new(img_mode, p_size, bgcolor) try: epsg, axis_sy = parse_srs(p_srs) except SRSParseError as e: raise ValidationError(message=str(e), data=dict(code="InvalidSRS")) try: srs = SRS.filter_by(id=epsg).one() except NoResultFound: raise ValidationError(message="SRS (id=%d) not found." % epsg, data=dict(code="InvalidSRS")) def scale(delta, img_px): dpi = 96 img_inch = float(img_px) / dpi img_m = img_inch * 0.0254 return delta / img_m xmin, ymin, xmax, ymax = p_bbox if srs.is_geographic: distance = geographic_distance(xmin, ymin, xmax, ymax) else: distance = xmax - xmin w_scale = scale(distance, p_width) for lname in p_layers: lobj = layer_by_keyname(obj, lname) res = lobj.resource request.resource_permission(DataScope.read, res) if (lobj.min_scale_denom is None or lobj.min_scale_denom >= w_scale) and \ (lobj.max_scale_denom is None or w_scale >= lobj.max_scale_denom): req = res.render_request(res.srs) # Do not use foreign SRS as it does not work correctly yet if srs.id == res.srs.id: limg = req.render_extent(p_bbox, p_size) else: mem = gdal.GetDriverByName('MEM') dst_geo = (xmin, (xmax - xmin) / p_width, 0, ymax, 0, (ymin - ymax) / p_height) dst_ds = mem.Create('', p_width, p_height, 4, gdal.GDT_Byte) dst_ds.SetGeoTransform(dst_geo) vrt = gdal.AutoCreateWarpedVRT(dst_ds, srs.wkt, res.srs.wkt) src_width = vrt.RasterXSize src_height = vrt.RasterYSize src_geo = vrt.GetGeoTransform() vrt = None src_bbox = (src_geo[0], src_geo[3] + src_geo[5] * src_height, src_geo[0] + src_geo[1] * src_width, src_geo[3]) limg = req.render_extent(src_bbox, (src_width, src_height)) if limg is not None: data = numpy.asarray(limg) img_h, img_w, band_count = data.shape src_ds = mem.Create('', src_width, src_height, band_count, gdal.GDT_Byte) src_ds.SetGeoTransform(src_geo) for i in range(band_count): bandArray = data[:, :, i] src_ds.GetRasterBand(i + 1).WriteArray(bandArray) gdal.ReprojectImage(src_ds, dst_ds, res.srs.wkt, srs.wkt) array = numpy.zeros((p_height, p_width, band_count), numpy.uint8) for i in range(band_count): array[:, :, i] = gdal_array.BandReadAsArray( dst_ds.GetRasterBand(i + 1)) limg = Image.fromarray(array) src_ds = dst_ds = None if limg is not None: img.paste(limg, (0, 0), limg) buf = BytesIO() if p_format == IMAGE_FORMAT.JPEG: img.convert('RGB').save(buf, 'jpeg') elif p_format == IMAGE_FORMAT.PNG: img.save(buf, 'png', compress_level=3) buf.seek(0) return Response(body_file=buf, content_type=p_format)
def netcdf_cfproj_testcopy(projTuples, origTiff, interFormats, inPath, outPath, resFilename): """Test a Geotiff file can be converted to NetCDF, and projection in CF-1 conventions can be successfully maintained. Save results to file. :arg: projTuples - list of tuples :arg: interFormats - dict of intermediate format overrides :arg: outPath - path to save output :arg: resFilename - results filename to write to. """ silent = True gdaltest.netcdf_drv_silent = True bWriteGdalTags = "YES" # silent = False gdaltest.netcdf_drv_silent = False # bWriteGdalTags="NO" result = 'success' # Test if ncdump is available try: (_, err) = gdaltest.runexternal_out_and_err('ncdump -h') except OSError: # nothing is supported as ncdump not found pytest.skip('NOTICE: netcdf version not found') i = err.find('netcdf library version ') # version not found if i == -1: pytest.skip('NOTICE: netcdf version not found') if not os.path.exists(outPath): os.makedirs(outPath) resFile = open(os.path.join(outPath, resFilename), "w") if not os.path.exists(outPath): os.makedirs(outPath) heading = "Testing GDAL translation results to NetCDF\n" resFile.write(heading) resFile.write(len(heading) * "=" + "\n") # now = datetime.datetime.now() # resFile.write("*Date/time:* %s\n" % (now.strftime("%Y-%m-%d %H:%M"))) resFile.write("\n") resPerProj = {} dsTiff = gdal.Open(os.path.join(inPath, origTiff), gdal.GA_ReadOnly) s_srs_wkt = dsTiff.GetProjection() # objects to hold the various tests i_t = 0 tst_res = {} for proj in projTuples: try: intFmt = interFormats[proj[0]] except KeyError: intFmt = netcdf_cfproj_def_int_format intExt = netcdf_cfproj_format_fnames[intFmt] # Our little results data structures if not silent: print("") print("Testing %s (%s) translation:" % (proj[0], proj[1])) if not silent: print("About to create raster in chosen SRS") # projVrt = os.path.join(outPath, "%s_%s.vrt" % \ # (origTiff.rstrip('.tif'), proj[0] )) projRaster = os.path.join( outPath, "%s_%s.%s" % (os.path.basename(origTiff).rstrip('.tif'), proj[0], intExt)) srs = osr.SpatialReference() srs.SetFromUserInput(proj[2]) t_srs_wkt = srs.ExportToWkt() if not silent: print("going to warp file " + origTiff + "\n" + s_srs_wkt + "\ninto file " + projRaster + "\n" + t_srs_wkt) dswarp = gdal.AutoCreateWarpedVRT(dsTiff, s_srs_wkt, t_srs_wkt, gdal.GRA_NearestNeighbour, 0) drv_inter = gdal.GetDriverByName(intFmt) drv_netcdf = gdal.GetDriverByName("netcdf") dsw = drv_inter.CreateCopy(projRaster, dswarp, 0) if not silent: print("Warped %s to %s" % (proj[0], projRaster)) projNc = os.path.join(outPath, "%s_%s.nc" % (origTiff.rstrip('.tif'), proj[0])) # Force GDAL tags to be written to make testing easier, with preserved datum etc # ncCoOpts = "-co WRITE_GDAL_TAGS=yes" if not silent: print("About to translate to NetCDF") dst = drv_netcdf.CreateCopy(projNc, dsw, 0, ['WRITE_GDAL_TAGS=' + bWriteGdalTags]) # For drivers like HFA, line below ESSENTIAL so that all info is # saved to new raster file - which we'll reopen later and want # to be fully updated. dsw = None del dst if not silent: print("Translated to %s" % (projNc)) transWorked, resDetails = netcdf_cfproj_test_cf(proj, projNc) resPerProj[proj[0]] = resDetails resFile.write("%s (%s): " % (proj[0], proj[1])) if transWorked: resFile.write("OK\n") else: resFile.write("BAD\n") if 'missingProjName' in resPerProj[proj[0]]: resFile.write("\tMissing proj name '%s'\n" % (resPerProj[proj[0]]['missingProjName'])) for attrib in resPerProj[proj[0]]['missingAttrs']: resFile.write("\tMissing attrib '%s'\n" % (attrib)) for cVarStdName in resPerProj[proj[0]]['missingCoordVarStdNames']: resFile.write("\tMissing coord var with std name '%s'\n" % (cVarStdName)) if 'cfcheck_error' in resPerProj[proj[0]]: resFile.write("\tFailed cf check: %s\n" % (resPerProj[proj[0]]['cfcheck_error'])) # test file copy # We now copy to a new file, just to be safe projNc2 = projNc.rstrip('.nc') + '2.nc' projRaster2 = os.path.join( outPath, "%s_%s2.%s" % (origTiff.rstrip('.tif'), proj[0], intExt)) tst_res[i_t + 1] = netcdf_test_copy(projRaster, 1, None, projNc2, [], 'NETCDF') tst_res[i_t + 2] = netcdf_test_copy(projNc2, 1, None, projRaster2, [], intFmt) if tst_res[i_t + 1] == 'fail' or tst_res[i_t + 2] == 'fail': result = 'fail' i_t = i_t + 2 resFile.close() if not silent: print("\n" + "*" * 80) print("Saved results to file %s" % (os.path.join(outPath, resFilename))) # result = 'success' resFile = open(os.path.join(outPath, resFilename), "r") resStr = resFile.read() if resStr.find('BAD') != -1: print( '\nCF projection tests failed, here is the output (stored in file %s)\n' % (os.path.join(outPath, resFilename))) print(resStr) result = 'fail' return result
def gdal_reproject(src, dst=None, src_srs=None, dst_srs=None, epsg=None, error_threshold=0.125, resampling=gdalconst.GRA_NearestNeighbour, as_gdal_grid=False): """ Reproject a raster image. Based on: https://github.com/OpenDataAnalytics/ gaia/blob/master/gaia/geo/gdal_functions.py Parameters ---------- src: :obj:`str` or :func:`gdal.Dataset` or :func:`~GDALGrid` The source image. dst: :obj:`str`, optional The filepath of the output image to write to. src_srs: :func:`osr.SpatialReference`, optional The source image projection. dst_srs: :func:`osr.SpatialReference`, optional The destination projection. If not provided, the code will use `epsg`. epsg: int, optional The EPSG code to reproject to. If not provided, the code will use `dst_srs`. error_threshold: float, optional Default is 0.125 (same as gdalwarp commandline). resampling: :func:`osgeo.gdalconst` Method to use for resampling. Default method is `gdalconst.GRA_NearestNeighbour`. as_gdal_grid: bool, optional Return as :func:`~GDALGrid`. Default is False. Returns ------- :func:`gdal.Dataset` or :func:`~GDALGrid` By default, it returns `gdal.Dataset`. It will return :func:`~GDALGrid` if `as_gdal_grid` is True. """ # Open source dataset src_ds = load_raster(src)[0] # Define target SRS if dst_srs is None: dst_srs = osr.SpatialReference() dst_srs.ImportFromEPSG(int(epsg)) dst_wkt = dst_srs.ExportToWkt() # Resampling might be passed as a string if not isinstance(resampling, int): resampling = getattr(gdal, resampling) src_wkt = None if src_srs is not None: src_wkt = src_srs.ExportToWkt() # Call AutoCreateWarpedVRT() to fetch default values # for target raster dimensions and geotransform reprojected_ds = gdal.AutoCreateWarpedVRT(src_ds, src_wkt, dst_wkt, resampling, error_threshold) # Create the final warped raster if dst: gdal.GetDriverByName('GTiff').CreateCopy(dst, reprojected_ds) if as_gdal_grid: return GDALGrid(reprojected_ds) return reprojected_ds
def run(self): """Run method that performs all the real work""" # prepare dialog parameters settings = QSettings() lastDir = settings.value("/UI/lastShapefileDir") filter = "GarminCustomMap-files (*.kmz)" out_putFile = QgsEncodingFileDialog(None, "Select output file", 'My_CustomMap.kmz', "GarminCustomMap (*.kmz)") out_putFile.setDefaultSuffix("kmz") out_putFile.setFileMode(QFileDialog.AnyFile) out_putFile.setAcceptMode(QFileDialog.AcceptSave) # out_putFile.setConfirmOverwrite(True) if out_putFile.exec_() == QDialog.Accepted: kmz_file = out_putFile.selectedFiles()[0] # Get mapCanvas and mapRenderer variables canvas = self.iface.mapCanvas() scale = canvas.scale() mapSettings = canvas.mapSettings() mapRect = canvas.extent() width = int(round(mapSettings.outputSize().width())) height = int(round(mapSettings.outputSize().height())) srs = mapSettings.destinationCrs() SourceCRS = str(srs.authid()) # Save settings for resetting the mapRenderer after GCM production old_width = mapSettings.outputSize().width() old_height = mapSettings.outputSize().height() old_dpi = mapSettings.outputDpi() # Give information about project projection, mapCanvas size and Custom map settings if (height * width) % (1024.0 * 1024.0) >= 1: expected_tile_n_unzoomed = int( (height * width) / (1024.0 * 1024.0)) + 1 else: expected_tile_n_unzoomed = int( (height * width) / (1024.0 * 1024.0)) if len(str(int(sqrt(100 / ((height * width) / (1024.0 * 1024.0)))))) == 1: max_zoom_100 = str( sqrt(100 / ((height * width) / (1024.0 * 1024.0))))[0:3] else: max_zoom_100 = str( sqrt(100 / ((height * width) / (1024.0 * 1024.0))))[0:4] if len(str(int(sqrt(500 / ((height * width) / (1024.0 * 1024.0)))))) == 1: max_zoom_500 = str( sqrt(500 / ((height * width) / (1024.0 * 1024.0))))[0:3] else: max_zoom_500 = str( sqrt(500 / ((height * width) / (1024.0 * 1024.0))))[0:4] if SourceCRS != 'EPSG:4326': def projWaring(): proj_msg = QMessageBox() proj_msg.setWindowTitle( "Coordinate Reference System mismatch") proj_msg.setText( "The coordinate reference system (CRS) of your project differs from WGS84 (EPSG: 4326). " "It is likely, that you will produce a better Custom Map " "when your project and data has CRS WGS84!\n" "\n" "The number of rows and columns in the exported image " "will be affected by reprojecting to WGS84 and estimates for " "the number of tiles etc. in the \"Setting hints\"-Tab will be incorrect!" ) proj_msg.exec_() widget = iface.messageBar().createMessage( "WARNING", "Project CRS differs from WGS84 (EPSG: 4326)") button = QPushButton(widget) button.setText("Info") button.pressed.connect(projWaring) widget.layout().addWidget(button) iface.messageBar().pushWidget(widget, Qgis.Critical, duration=10) # create the dialog dlg = GarminCustomMapDialog() # Update the dialog dlg.textBrowser.setHtml( "<p>The following information should help you " "to adjust the settings for your Garmin Custom Map.</p>" "<p>Your current map canvas contains<br>" + str(height) + " rows and<br>" + str(width) + " colums.</p>" "<p>Zooming level 1.0 (map scale of the current map canvas which is 1:" + str(round(scale)) + ") will result in " + str(expected_tile_n_unzoomed) + " tile(s) " "(single images within your Garmin Custom Map).</p>" "<p>In general, Garmin Custom Maps are limited to a number of 100 tiles in total (across all Garmin Custom Maps on the device). " "A Garmin Custom Map produced with the current Zoom level will occupy " + str(expected_tile_n_unzoomed) + "% " "of the total capacity of most types of Garmin GPS units.<br>" "To comply with a limit of 100 tiles, you should use a zoom factor <= " + max_zoom_100 + ". " "This will result in a scale of your Garmin Custom Map of 1 : " + str(int(round(scale / float(max_zoom_100)))) + ".</p>" "<p>However, newer Garmin GPS units (Montana, Oregon 6x0, and GPSMAP 64) have a limit of 500 tiles in total (across all Garmin Custom Maps on the device. " "For such GPS units, a Garmin Custom Map produced with the current Zoom level will occupy" + str(round((expected_tile_n_unzoomed / 5.0), 1)) + "% " "of the maximum possible number of tiles across all Custom Maps on your GPS unit.<br>" "To comply with a limit of 500 tiles, you should use a zoom factor <= " + max_zoom_500 + ". " "This will result in a scale of your Garmin Custom Map of 1 : " + str(int(round(scale / float(max_zoom_500)))) + ".</p>" "<p>For more information on size limits and technical details regarding the " """Garmin Custom Maps format see \"About-Tab\" and/or <a href="https://forums.garmin.com/showthread.php?t=2646">https://forums.garmin.com/showthread.php?t=2646</a></p> """ ) dlg.zoom_100.setText( "Max. zoom for devices with <= 100 tiles: " + max_zoom_100 + " (1:" + str(int(round(scale / float(max_zoom_100)))) + ")") dlg.zoom_500.setText( "Max. zoom for devices with <= 500 tiles: " + max_zoom_500 + " (1:" + str(int(round(scale / float(max_zoom_500)))) + ")") # Show the dialog dlg.show() result = dlg.exec_() # See if OK was pressed if result == 1: # Set variables optimize = int(dlg.flag_optimize.isChecked()) skip_empty = int(dlg.flag_skip_empty.isChecked()) max_y_ext_general = int(dlg.nrows.value()) max_x_ext_general = int(dlg.ncols.value()) qual = int(dlg.jpg_quality.value()) # Set options for jpg-production options = [] options.append("QUALITY=" + str(qual)) draworder = dlg.draworder.value() zoom = float(dlg.zoom.value()) in_file = os.path.basename(kmz_file[0:(len(kmz_file) - 4)]) max_pix = (1024 * 1024) # Create tmp-folder out_folder = tempfile.mkdtemp('_tmp', 'gcm_') out_put = os.path.join(out_folder, in_file) input_file = out_put + u'.png' tname = in_file # Set QGIS objects target_dpi = int(round(zoom * mapSettings.outputDpi())) # Initialise temporary output image x, y = 0, 0 width = mapSettings.outputSize().width() * zoom height = mapSettings.outputSize().height() * zoom mapSettings.setOutputSize(QSize(width, height)) mapSettings.setOutputDpi(target_dpi) mapSettings.setExtent(mapRect) mapSettings.setFlags(QgsMapSettings.Antialiasing | QgsMapSettings.UseAdvancedEffects | QgsMapSettings.ForceVectorOutput | QgsMapSettings.DrawLabeling) # create output image and initialize it image = QImage(QSize(width, height), QImage.Format_RGB555) image.fill(qRgb(255, 255, 255)) # adjust map canvas (renderer) to the image size and render imagePainter = QPainter(image) imagePainter.begin(image) mapRenderer = QgsMapRendererCustomPainterJob( mapSettings, imagePainter) mapRenderer.start() mapRenderer.waitForFinished() imagePainter.end() # Save the image image.save(input_file, "png") # Set Geotransform and NoData values input_dataset = gdal.Open(input_file) # Set Geotransform values ULy = mapRect.yMaximum() ULx = mapRect.xMinimum() LRx = mapRect.xMaximum() LRy = mapRect.yMinimum() xScale = (LRx - ULx) / width yScale = (LRy - ULy) / height input_dataset.SetGeoTransform([ULx, xScale, 0, ULy, 0, yScale]) # Close dataset input_dataset = None # Reset mapSettings to old size (monitor) mapSettings.setOutputSize(QSize(old_width, old_height)) # Warp the exported image to WGS84 if necessary if SourceCRS != 'EPSG:4326': # Define input and output file input_geofile = out_put + "wgs84.tif" output_geofile = os.path.join(out_folder, input_geofile) # Register tif-driver driver = gdal.GetDriverByName("GTiff") driver.Register() # Define input CRS in_CRS = srs.toWkt() # in_CRS = srs.toWkt().encode('UTF-8') # print type(in_CRS) # Define output CRS out_CRS = QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem.EpsgCrsId).toWkt() # out_CRS = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId).toWkt().encode('UTF-8') # print type(out_CRS) # Open input dataset input_dataset = gdal.Open(input_file) # Create VRT reproj_file = gdal.AutoCreateWarpedVRT( input_dataset, in_CRS, out_CRS) reproj_file.GetRasterBand(1).Fill(255) reproj_file.GetRasterBand(2).Fill(255) reproj_file.GetRasterBand(3).Fill(255) # Reproject gdal.ReprojectImage(input_dataset, reproj_file, in_CRS, out_CRS) reproj_attributes = reproj_file.GetGeoTransform() # Update relevant georef variables ULx = reproj_attributes[0] ULy = reproj_attributes[3] xScale = reproj_attributes[1] yScale = reproj_attributes[5] driver = gdal.GetDriverByName("GTiff") warped_input = driver.CreateCopy(output_geofile, reproj_file, 0) input_dataset = None reproj_file = None warped_input = None input_file = output_geofile # Calculate tile size and number of tiles indataset = gdal.Open(input_file) x_extent = indataset.RasterXSize y_extent = indataset.RasterYSize if optimize == 1: # Identify length of the short and long side of the map canvas and their relation short_ext = min(x_extent, y_extent) long_ext = max(x_extent, y_extent) s_l_side_relation = 0 # Estimate number of tiles in the result if float(x_extent * y_extent) % (1024 * 1024) >= 1: expected_tile_n = int( float(x_extent * y_extent) / (1024 * 1024)) + 1 else: expected_tile_n = int( float(x_extent * y_extent) / (1024 * 1024)) # Find settings for tiling with: # 1 minimum number of tiles, # 2 a short / long size relation close to 1, # 3 and a minimum numer of pixels in each tile for tc in range(1, expected_tile_n + 1, 1): if expected_tile_n % tc >= 1: continue else: if short_ext % tc >= 1: s_pix = int(short_ext / tc) + 1 else: s_pix = int(short_ext / tc) if long_ext % tc >= 1: l_pix = int(long_ext / (expected_tile_n / tc)) + 1 else: l_pix = int(long_ext / (expected_tile_n / tc)) if (s_pix * l_pix) <= (1024 * 1024): if min((float(s_pix) / float(l_pix)), (float(l_pix) / float(s_pix))) >= s_l_side_relation: s_l_side_relation = min( (float(s_pix) / float(l_pix)), (float(l_pix) / float(s_pix))) s_pix_opt = s_pix l_pix_opt = l_pix # Set tile size variable according to optimal setings if short_ext == x_extent: max_x_ext_general = s_pix_opt max_y_ext_general = l_pix_opt else: max_y_ext_general = s_pix_opt max_x_ext_general = l_pix_opt # Identify number of rows and columns n_cols_rest = x_extent % max_x_ext_general n_rows_rest = y_extent % max_y_ext_general # if n_cols_rest >= 1: n_cols = (x_extent / max_x_ext_general) + 1 else: n_cols = (x_extent / max_x_ext_general) # if n_rows_rest >= 1: n_rows = (y_extent / max_y_ext_general) + 1 else: n_rows = (y_extent / max_y_ext_general) # Check if number of tiles is below Garmins limit of 100 tiles (across all custom maps) n_tiles = (n_rows * n_cols) if n_tiles > 100: iface.messageBar().pushMessage( "WARNING", "The number of tiles is likely to exceed Garmins limit of 100 tiles! Not all tiles will be displayed on your GPS unit. Consider reducing your map size (extend or zoom-factor).", duration=5) progressMessageBar = iface.messageBar().createMessage( "Producing tiles...") progress = QProgressBar() progress.setMaximum(n_tiles) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) # Check if size of tiles is below Garmins limit of 1 megapixel (for each tile) n_pix = (max_x_ext_general * max_y_ext_general) if n_pix > max_pix: iface.messageBar().pushMessage( "WARNING", "The number of pixels in a tile exceeds Garmins limit of 1 megapixel per tile! Images will not be displayed properly.", level=Qgis.Warning, duration=5) kmz = zipfile.ZipFile(kmz_file, 'w') with open(os.path.join(out_folder, 'doc.kml'), 'w') as kml: # Write kml header kml.write('<?xml version="1.0" encoding="UTF-8"?>\n') kml.write('<kml xmlns="http://www.opengis.net/kml/2.2">\n') kml.write(' <Document>\n') kml.write(' <name>' + tname.encode('UTF-8').decode('utf-8') + '</name>\n') # Produce .jpg tiles using gdal_translate looping through the complete rows and columns (1024x1024 pixel) y_offset = 0 x_offset = 0 r = 1 c = 1 n_tiles = 0 empty_tiles = 0 # Loop through rows for r in range(1, int(n_rows) + 1, 1): # Define maximum Y-extend of tiles if r == (n_rows) and n_rows_rest > 0: max_y_ext = n_rows_rest else: max_y_ext = max_y_ext_general # (Within row-loop) Loop through columns for c in range(1, int(n_cols) + 1, 1): # Define maximum X-extend of tiles if c == int(n_cols) and n_cols_rest > 0: max_x_ext = n_cols_rest else: max_x_ext = max_x_ext_general # Define name for tile-jpg t_name = tname + '_%(r)d_%(c)d.jpg' % { "r": r, "c": c } # Set parameters for "gdal_translate" (JPEG-driver has no Create() (but CreateCopy()) method so first a VRT has to be created band by band # Create VRT dataset for tile mem_driver = gdal.GetDriverByName("MEM") mem_driver.Register() t_file = mem_driver.Create('', max_x_ext, max_y_ext, 3, gdalconst.GDT_Byte) t_band_1 = indataset.GetRasterBand(1).ReadAsArray( x_offset, y_offset, max_x_ext, max_y_ext) t_band_2 = indataset.GetRasterBand(2).ReadAsArray( x_offset, y_offset, max_x_ext, max_y_ext) t_band_3 = indataset.GetRasterBand(3).ReadAsArray( x_offset, y_offset, max_x_ext, max_y_ext) if skip_empty == 1: if t_band_1.min() == 255 and t_band_2.min( ) == 255 and t_band_3.min() == 255: empty_tiles = empty_tiles + 1 t_file.GetRasterBand(1).WriteArray(t_band_1) t_file.GetRasterBand(2).WriteArray(t_band_2) t_file.GetRasterBand(3).WriteArray(t_band_3) t_band_1 = None t_band_2 = None t_band_3 = None # Translate MEM dataset to JPG jpg_driver = gdal.GetDriverByName("JPEG") jpg_driver.Register() jpg_driver.CreateCopy(os.path.join( out_folder, t_name), t_file, options=options) # Close GDAL-datasets t_file = None t_jpg = None # Get bounding box for tile n = ULy + (y_offset * yScale) s = ULy + ((y_offset + max_y_ext) * yScale) e = ULx + ((x_offset + max_x_ext) * xScale) w = ULx + (x_offset * xScale) # Add .jpg to .kmz-file and remove it together with its meta-data afterwards kmz.write(os.path.join(out_folder, t_name), t_name) os.remove(os.path.join(out_folder, t_name)) # Write kml-tags for each tile (Name, DrawOrder, JPEG-Reference, GroundOverlay) kml.write('') kml.write(' <GroundOverlay>\n') kml.write(' <name>' + tname.encode('UTF-8').decode('utf-8') + ' Tile ' + str(r) + '_' + str(c) + '</name>\n') # %{"r":r, "c":c} kml.write( ' <drawOrder>' + str(draworder) + '</drawOrder>\n') # %{"draworder":draworder} kml.write(' <Icon>\n') kml.write(' <href>' + tname.encode('UTF-8').decode('utf-8') + '_' + str(r) + '_' + str(c) + '.jpg</href>\n') # %{"r":r, "c":c} kml.write(' </Icon>\n') kml.write(' <LatLonBox>\n') kml.write(' <north>' + str(n) + '</north>\n') kml.write(' <south>' + str(s) + '</south>\n') kml.write(' <east>' + str(e) + '</east>\n') kml.write(' <west>' + str(w) + '</west>\n') kml.write(' </LatLonBox>\n') kml.write(' </GroundOverlay>\n') # Calculate new X-offset x_offset = (x_offset + max_x_ext) n_tiles = (n_tiles + 1) # Update progress bar progress.setValue(n_tiles) # Calculate new Y-offset y_offset = (y_offset + max_y_ext) # Reset X-offset x_offset = 0 # Write kml footer kml.write(' </Document>\n') kml.write('</kml>\n') # Close kml file # kml.close() # Close GDAL dataset indataset = None # Remove temporary geo-tif file os.remove(out_put + u'.png') os.remove(out_put + u'.png.aux.xml') # Remove reprojected temporary geo-tif file if necessary if SourceCRS != 'EPSG:4326': os.remove(output_geofile) # Add .kml to .kmz-file and remove it together with the rest of the temporary files kmz.write(os.path.join(out_folder, u'doc.kml'), u'doc.kml') os.remove(os.path.join(out_folder, u'doc.kml')) kmz.close() os.rmdir(out_folder) # Clear progressbar iface.messageBar().clearWidgets() tiles_total = n_tiles - empty_tiles # Give success message iface.messageBar().pushMessage( "Done", "Produced " + str(tiles_total) + " tiles, with " + str(n_rows) + " rows and " + str(int(n_cols)) + " colums.", level=Qgis.Info, duration=5)
def get_aster(ifile): """ Gets ASTER Data Parameters ---------- ifile : str filename to import Returns ------- dat : PyGMI raster Data dataset imported """ dat = [] ifile = ifile[:] dataset = gdal.Open(ifile, gdal.GA_ReadOnly) subdata = dataset.GetSubDatasets() latentry = [i for i in subdata if 'Latitude' in i[1]] subdata.pop(subdata.index(latentry[0])) dataset = gdal.Open(latentry[0][0], gdal.GA_ReadOnly) rtmp = dataset.GetRasterBand(1) lats = rtmp.ReadAsArray() latsdim = ((lats.max() - lats.min()) / (lats.shape[0] - 1)) / 2 lonentry = [i for i in subdata if 'Longitude' in i[1]] subdata.pop(subdata.index(lonentry[0])) dataset = gdal.Open(lonentry[0][0], gdal.GA_ReadOnly) rtmp = dataset.GetRasterBand(1) lons = rtmp.ReadAsArray() lonsdim = ((lons.max() - lons.min()) / (lons.shape[1] - 1)) / 2 lonsdim = latsdim tlx = lons.min() - abs(lonsdim / 2) tly = lats.max() + abs(latsdim / 2) cols = int((lons.max() - lons.min()) / lonsdim) + 1 rows = int((lats.max() - lats.min()) / latsdim) + 1 newx2, newy2 = np.mgrid[0:rows, 0:cols] newx2 = newx2 * lonsdim + tlx newy2 = tlx - newy2 * latsdim subdata = [i for i in subdata if 'ImageData' in i[0]] i = -1 for ifile2, bandid2 in subdata: dataset = gdal.Open(ifile2, gdal.GA_ReadOnly) rtmp2 = dataset.ReadAsArray() tmpds = gdal.AutoCreateWarpedVRT(dataset) rtmp2 = tmpds.ReadAsArray() gtr = tmpds.GetGeoTransform() tlx, lonsdim, _, tly, _, latsdim = gtr nval = 0 i += 1 dat.append(Data()) dat[i].data = rtmp2 if dat[i].data.dtype.kind == 'i': if nval is None: nval = 999999 nval = int(nval) elif dat[i].data.dtype.kind == 'u': if nval is None: nval = 0 nval = int(nval) else: if nval is None: nval = 1e+20 nval = float(nval) dat[i].data = np.ma.masked_invalid(dat[i].data) dat[i].data.mask = dat[i].data.mask | (dat[i].data == nval) if dat[i].data.mask.size == 1: dat[i].data.mask = (np.ma.make_mask_none(dat[i].data.shape) + dat[i].data.mask) dat[i].nrofbands = dataset.RasterCount dat[i].tlx = tlx dat[i].tly = tly dat[i].dataid = bandid2 dat[i].nullvalue = nval dat[i].rows = dat[i].data.shape[0] dat[i].cols = dat[i].data.shape[1] dat[i].xdim = abs(lonsdim) dat[i].ydim = abs(latsdim) dat[i].gtr = gtr srs = osr.SpatialReference() srs.ImportFromWkt(dataset.GetProjection()) srs.AutoIdentifyEPSG() dat[i].wkt = srs.ExportToWkt() if dat == []: dat = None return dat
def load_file(self, filename, env, cog=False): ds, imfilename = self._gdalds(filename) dsdriver = ds.GetDriver() dsproj = ds.GetProjection() dsgtran = ds.GetGeoTransform() if dsdriver.ShortName not in DRIVERS.enum: raise ValidationError( _("Raster has format '%(format)s', however only following formats are supported: %(all_formats)s." ) # NOQA: E501 % dict(format=dsdriver.ShortName, all_formats=", ".join(SUPPORTED_DRIVERS))) if not dsproj or not dsgtran: raise ValidationError( _("Raster files without projection info are not supported.")) # Workaround for broken encoding in WKT. Otherwise, it'll cause SWIG # TypeError (not a string) while passing to GDAL. try: dsproj.encode('utf-8', 'strict') except UnicodeEncodeError: dsproj = dsproj.encode('utf-8', 'replace').decode('utf-8') data_type = None alpha_band = None has_nodata = None for bidx in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(bidx) if data_type is None: data_type = band.DataType elif data_type != band.DataType: raise ValidationError( _("Mixed band data types are not supported.")) if band.GetRasterColorInterpretation() == gdal.GCI_AlphaBand: assert alpha_band is None, "Multiple alpha bands found!" alpha_band = bidx else: has_nodata = (has_nodata is None or has_nodata) and (band.GetNoDataValue() is not None) src_osr = osr.SpatialReference() if src_osr.ImportFromWkt(dsproj) != 0: raise ValidationError( _("GDAL was uanble to parse the raster coordinate system.")) if src_osr.IsLocal(): raise ValidationError( _("The source raster has a local coordinate system and can't be " "reprojected to the target coordinate system.")) dst_osr = osr.SpatialReference() dst_osr.ImportFromEPSG(int(self.srs.id)) reproject = not src_osr.IsSame(dst_osr) add_alpha = reproject and not has_nodata and alpha_band is None if reproject: cmd = [ 'gdalwarp', '-of', 'GTiff', '-t_srs', 'EPSG:%d' % self.srs.id ] if add_alpha: cmd.append('-dstalpha') ds_measure = gdal.AutoCreateWarpedVRT(ds, src_osr.ExportToWkt(), dst_osr.ExportToWkt()) assert ds_measure is not None, gdal.GetLastErrorMsg() else: cmd = ['gdal_translate', '-of', 'GTiff'] ds_measure = ds size_expected = raster_size(ds_measure, 1 if add_alpha else 0) ds_measure = None size_limit = env.raster_layer.options['size_limit'] if size_limit is not None and size_expected > size_limit: raise ValidationError(message=_( "The uncompressed raster size (%(size)s) exceeds the limit " "(%(limit)s) by %(delta)s. Reduce raster size to fit the limit." ) % dict( size=format_size(size_expected), limit=format_size(size_limit), delta=format_size(size_expected - size_limit), )) cmd.extend(('-co', 'COMPRESS=DEFLATE', '-co', 'TILED=YES', '-co', 'BIGTIFF=YES', imfilename)) fobj = FileObj(component='raster_layer') dst_file = env.raster_layer.workdir_filename(fobj, makedirs=True) self.fileobj = fobj self.cog = cog if not cog: subprocess.check_call(cmd + [dst_file]) self.build_overview() else: # TODO: COG driver with NamedTemporaryFile() as tf: tmp_file = tf.name subprocess.check_call(cmd + [tmp_file]) self.build_overview(fn=tmp_file) cmd = ['gdal_translate', '-of', 'Gtiff'] cmd.extend(('-co', 'COMPRESS=DEFLATE', '-co', 'TILED=YES', '-co', 'BIGTIFF=YES', '-co', 'COPY_SRC_OVERVIEWS=YES', tmp_file, dst_file)) subprocess.check_call(cmd) os.unlink(tmp_file + '.ovr') ds = gdal.Open(dst_file, gdalconst.GA_ReadOnly) assert raster_size(ds) == size_expected, "Expected size mismatch" self.dtype = gdal.GetDataTypeName(data_type) self.xsize = ds.RasterXSize self.ysize = ds.RasterYSize self.band_count = ds.RasterCount
def main(argv): argv = ogr.GeneralCmdLineProcessor(argv) ogr_ds_name = None lyr_name = None tileitem = 'location' tilesrs = None srsname = None nArgc = len(argv) iArg = 1 while iArg < nArgc: if argv[iArg] == "-lyr_name" and iArg < nArgc - 1: iArg = iArg + 1 lyr_name = argv[iArg] elif argv[iArg] == "-tileindex" and iArg < nArgc - 1: iArg = iArg + 1 tileitem = argv[iArg] elif argv[iArg] == "-src_srs_name" and iArg < nArgc - 1: iArg = iArg + 1 tilesrs = argv[iArg] elif argv[iArg] == "-t_srs" and iArg < nArgc - 1: iArg = iArg + 1 srsname = argv[iArg] elif argv[iArg][0] == '-': return Usage() elif ogr_ds_name is None: ogr_ds_name = argv[iArg] iArg = iArg + 1 if ogr_ds_name is None or tilesrs is None: return Usage() ogr_ds = ogr.Open(ogr_ds_name) if ogr_ds is None: raise Exception('cannot open %s' % ogr_ds_name) if ogr_ds.GetLayerCount() == 1: lyr = ogr_ds.GetLayer(0) elif lyr_name is None: raise Exception('-lyr_name should be specified') else: lyr = ogr_ds.GetLayerByName(lyr_name) if lyr.GetLayerDefn().GetFieldIndex(tileitem) < 0: raise Exception('%s field cannot be found in layer definition' % tileitem) if lyr.GetLayerDefn().GetFieldIndex(tilesrs) < 0: raise Exception('%s field cannot be found in layer definition' % tilesrs) lyr_srs = lyr.GetSpatialRef() if srsname is not None: srs = osr.SpatialReference() if srs.SetFromUserInput(srsname) != 0: raise Exception('invalid value for -t_srs : %s' % srsname) # Sanity check if lyr_srs is not None: lyr_srs_proj4 = lyr_srs.ExportToProj4() lyr_srs = osr.SpatialReference() lyr_srs.SetFromUserInput(lyr_srs_proj4) lyr_srs_proj4 = lyr_srs.ExportToProj4() srs_proj4 = srs.ExportToProj4() if lyr_srs_proj4 != srs_proj4: raise Exception( '-t_srs overrides the layer SRS in an incompatible way : (%s, %s)' % (srs_proj4, lyr_srs_proj4)) else: srs = lyr_srs if srs is None: raise Exception('cannot fetch source SRS') srs.AutoIdentifyEPSG() authority_name = srs.GetAuthorityName(None) authority_code = srs.GetAuthorityCode(None) dst_wkt = srs.ExportToWkt() if authority_name != 'EPSG' or authority_code is None: raise Exception('cannot fetch source SRS as EPSG:XXXX code : %s' % dst_wkt) counter = 0 xres = 0 yres = 0 while True: feat = lyr.GetNextFeature() if feat is None: break # feat.DumpReadable() gdal_ds_name = feat.GetField(tileitem) if not os.path.isabs(gdal_ds_name): gdal_ds_name = os.path.join(os.path.dirname(ogr_ds_name), gdal_ds_name) gdal_ds = gdal.Open(gdal_ds_name) if gdal_ds is None: raise Exception('cannot open %s' % gdal_ds_name) warped_vrt_ds = gdal.AutoCreateWarpedVRT(gdal_ds, None, dst_wkt) if warped_vrt_ds is None: raise Exception('cannot warp %s to %s' % (gdal_ds_name, dst_wkt)) gt = warped_vrt_ds.GetGeoTransform() xres += gt[1] yres += gt[5] warped_vrt_ds = None counter = counter + 1 if counter == 0: raise Exception('tileindex is empty') xres /= counter yres /= counter (xmin, xmax, ymin, ymax) = lyr.GetExtent() xsize = (int)((xmax - xmin) / xres + 0.5) ysize = (int)((ymax - ymin) / abs(yres) + 0.5) layername = lyr.GetName() if ogr_ds.GetDriver().GetName() != 'ESRI Shapefile': print("""LAYER NAME "%s_tileindex" TYPE POLYGON STATUS OFF CONNECTIONTYPE OGR CONNECTION "%s,%s" PROJECTION "+init=epsg:%s" END END""" % (layername, ogr_ds_name, lyr.GetName(), authority_code)) print("") tileindex = "%s_tileindex" % layername else: tileindex = ogr_ds_name print("""LAYER NAME "%s" TYPE RASTER STATUS ON TILEINDEX "%s" TILEITEM "%s" TILESRS "%s" PROJECTION "+init=epsg:%s" END METADATA "wcs_label" "%s" "wcs_rangeset_name" "Range 1" ### required to support DescribeCoverage request "wcs_rangeset_label" "My Label" ### required to support DescribeCoverage request "wcs_extent" "%f %f %f %f" "wcs_size" "%d %d" "wcs_resolution" "%f %f" END END""" % (layername, tileindex, tileitem, tilesrs, authority_code, layername, xmin, ymin, xmax, ymax, xsize, ysize, xres, abs(yres))) return 0
def reproject(self, epsg=None, proj4=None, match=None, error_threshold=0.125, target_filename=None): """ Reproject the data from the current projection to the specified target projection `epsg` or `proj4` or to `match` an existing GeoTIFF file. .. warning:: **Watch Out!** This operation is performed in place on the actual data. The raw data will no longer be accessible afterwards. To keep the original data, use the :meth:`~pySW4.utils.geo.GeoTIFF.copy` method to create a copy of the current object. Parameters ---------- epsg : int The target projection EPSG code. See the `Geodetic Parameter Dataset Registry <http://www.epsg-registry.org/>`_ for more information. proj4 : str The target Proj4 string. If the EPSG code is unknown or a custom projection is required, a Proj4 string can be passed. See the `Proj4 <https://trac.osgeo.org/proj/wiki/GenParms>`_ documentation for a list of general Proj4 parameters. match : str or :class:`~pySW4.utils.geo.GeoTIFF` instance Path (relative or absolute) to an existing GeoTIFF file or :class:`~pySW4.utils.geo.GeoTIFF` instance (already in memory) to match size and projection of. Current data is resampled to match the shape and number of pixels of the existing GeoTIFF file or object. It is assumed that both GeoTIFF objects cover the same extent. error_threshold : float Error threshold for transformation approximation in pixel units. (default is 0.125 for compatibility with gdalwarp) target_filename : str If a target filename is given then the reprojected data is saved as target_filename and read into memory replacing the current data. This is faster than reprojecting and then saving. Otherwise the :meth:`~pySW4.utils.geo.GeoTIFF.write_GeoTIFF` method can be used to save the data at a later point if further manipulations are needed. Notes ----- Examples of some EPSG codes and their equivalent Proj4 strings are:: 4326 -> '+proj=longlat +datum=WGS84 +no_defs' 32636 -> '+proj=utm +zone=36 +datum=WGS84 +units=m +no_defs' 102009 -> '+proj=lcc +lat_1=20 +lat_2=60 +lat_0=40 +lon_0=-96 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs' and so on ... See the `Geodetic Parameter Dataset Registry <http://www.epsg-registry.org/>`_ for more information. """ if epsg and proj4 and match: msg = 'Only `epsg`, `proj4`, or `match` should be specified.' raise ValueError(msg) elif not epsg and not proj4 and not match: msg = '`epsg`, `proj4`, or `match` MUST be specified.' raise ValueError(msg) if not target_filename: target_filename = 'dst_temp.tif' dstSRS = osr.SpatialReference() if epsg or proj4: try: dstSRS.ImportFromEPSG(epsg) except TypeError: dstSRS.ImportFromProj4(proj4) temp_ds = gdal.AutoCreateWarpedVRT(self._src_ds, None, dstSRS.ExportToWkt(), gdal.GRA_NearestNeighbour, error_threshold) dst_ds = gdal.GetDriverByName('GTiff').CreateCopy( target_filename, temp_ds) # isinstance(match, GeoTIFF) elif match: self.write_GeoTIFF('src_temp.tif') src_ds = gdal.Open('src_temp.tif') src_proj = src_ds.GetProjection() src_geotrans = src_ds.GetGeoTransform() if type(match) is str: match = read_GeoTIFF(match, 1) gdal_dtype = gdal_array.NumericTypeCodeToGDALTypeCode(self.dtype) dstSRS.ImportFromProj4(match.proj4) dst_ds = gdal.GetDriverByName('GTiff').Create( target_filename, match.nx, match.ny, 1, gdal_dtype) dst_ds.SetGeoTransform(match.geotransform) dst_ds.SetProjection(dstSRS.ExportToWkt()) gdal.ReprojectImage(src_ds, dst_ds, src_proj, dstSRS.ExportToWkt(), gdal.GRA_NearestNeighbour, error_threshold) os.remove('src_temp.tif') dst_ds = None self._read(target_filename, 1) try: os.remove('dst_temp.tif') except OSError: pass
def open_input(self): gdal.AllRegister() # Initialize necessary GDAL drivers self.out_drv = gdal.GetDriverByName(self.tiledriver) self.mem_drv = gdal.GetDriverByName('MEM') if not self.out_drv: raise Exception( "The '%s' driver was not found, is it available in this GDAL build?", self.tiledriver) if not self.mem_drv: raise Exception( "The 'MEM' driver was not found, is it available in this GDAL build?" ) # Open the input file self.in_ds = gdal.Open(self.input, gdal.GA_ReadOnly) # Get base image data & info self.width = self.in_ds.RasterXSize self.height = self.in_ds.RasterYSize self.bandnum = self.in_ds.RasterCount # Spatial Reference System of tiles out_srs = osr.SpatialReference() out_srs.ImportFromEPSG(3857) # Spatial Reference System of input self.wkt = self.in_ds.GetProjection() srs_in = osr.SpatialReference() srs_in.ImportFromWkt(self.wkt) # WGS84 Reference System srs4326 = osr.SpatialReference() srs4326.ImportFromEPSG(4326) # Are the reference systems the same? Reproject if necessary. self.out_ds = None if (srs_in.ExportToProj4() != out_srs.ExportToProj4()): # Generation of VRT dataset in tile projection, default 'nearest neighbour' warping self.out_ds = gdal.AutoCreateWarpedVRT(self.in_ds, self.wkt, out_srs.ExportToWkt()) if not self.out_ds: self.out_ds = self.in_ds # Get alpha band (either directly or from NODATA value) self.alphaband = self.in_ds.GetRasterBand(1).GetMaskBand() # Get reference systems transformer self.ctutmto84 = osr.CoordinateTransformation(srs_in, srs4326) self.ct84toutm = osr.CoordinateTransformation(srs4326, srs_in) self.ctmerto84 = osr.CoordinateTransformation(out_srs, srs4326) self.ct84tomer = osr.CoordinateTransformation(srs4326, out_srs) # Get GeoTransform self.transform = self.out_ds.GetGeoTransform() # Get input bounds in WGS84 Coordinate System lu = self.MERtoWGS84(self.transform[0], self.transform[3]) rl = self.MERtoWGS84( self.transform[0] + self.transform[1] * self.out_ds.RasterXSize, self.transform[3] + self.transform[5] * self.out_ds.RasterYSize) self.omaxx = rl[0] self.ominx = lu[0] self.omaxy = lu[1] self.ominy = rl[1] # Generate table with min max tile coordinates for all zoomlevels self.tminmax = list(range(0, MAXZOOMLEVEL)) for tz in range(0, MAXZOOMLEVEL): tminy, tminx = self.tools.BLHtoRowCol(tz, self.ominy, self.ominx) tmaxy, tmaxx = self.tools.BLHtoRowCol(tz, self.omaxy, self.omaxx) # crop tiles extending world limits (+-180,+-90) tminx, tminy = max(0, tminx), max(0, tminy) tmaxx, tmaxy = min(10 * 2**tz - 1, tmaxx), min(5 * 2**tz - 1, tmaxy) self.tminmax[tz] = (tminx, tminy, tmaxx, tmaxy)
def vrtwarp_4(): src_ds = gdal.Open('../gcore/data/byte.tif') tmp_ds = gdal.GetDriverByName('GTiff').CreateCopy('tmp/vrtwarp_4.tif', src_ds) cs_main = tmp_ds.GetRasterBand(1).Checksum() tmp_ds.BuildOverviews('NONE', overviewlist=[2, 4]) tmp_ds.GetRasterBand(1).GetOverview(0).Fill(127) cs_ov0 = tmp_ds.GetRasterBand(1).GetOverview(0).Checksum() tmp_ds.GetRasterBand(1).GetOverview(1).Fill(255) cs_ov1 = tmp_ds.GetRasterBand(1).GetOverview(1).Checksum() vrtwarp_ds = gdal.AutoCreateWarpedVRT(tmp_ds) tmp_ds = None for i in range(3): if vrtwarp_ds.GetRasterBand(1).GetOverviewCount() != 2: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).Checksum() != cs_main: print(i) gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).GetOverview(0).Checksum() != cs_ov0: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).GetOverview(1).Checksum() != cs_ov1: gdaltest.post_reason('fail') return 'fail' if i == 0: vrtwarp_ds.SetDescription('tmp/vrtwarp_4.vrt') vrtwarp_ds = None vrtwarp_ds = gdal.Open('tmp/vrtwarp_4.vrt') elif i == 1: vrtwarp_ds = None tmp_ds = gdal.Open('tmp/vrtwarp_4.tif') vrtwarp_ds = gdal.AutoCreateWarpedVRT(tmp_ds) vrtwarp_ds.SetMetadataItem('SrcOvrLevel', 'AUTO') vrtwarp_ds.SetDescription('tmp/vrtwarp_4.vrt') tmp_ds = None # Add an explicit overview vrtwarp_ds.BuildOverviews('NEAR', overviewlist=[2, 4, 8]) vrtwarp_ds = None ds = gdal.GetDriverByName('MEM').Create('', 3, 3, 1) ds.GetRasterBand(1).Fill(255) expected_cs_ov2 = ds.GetRasterBand(1).Checksum() ds = None vrtwarp_ds = gdal.Open('tmp/vrtwarp_4.vrt') if vrtwarp_ds.GetRasterBand(1).GetOverviewCount() != 3: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).Checksum() != cs_main: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).GetOverview(0).Checksum() != cs_ov0: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).GetOverview(1).Checksum() != cs_ov1: gdaltest.post_reason('fail') return 'fail' if vrtwarp_ds.GetRasterBand(1).GetOverview( 2).Checksum() != expected_cs_ov2: gdaltest.post_reason('fail') return 'fail' vrtwarp_ds = None gdal.Unlink('tmp/vrtwarp_4.vrt') gdal.Unlink('tmp/vrtwarp_4.tif') return 'success'
########################## 10.6.3 Reprojecting images ######################## # Reproject the nat_color.tif from UTM to unprojected lat/lon. First create # the output SRS. srs = osr.SpatialReference() srs.SetWellKnownGeogCS('WGS84') # Open the nat_color file. os.chdir(os.path.join(data_dir, 'Landsat', 'Washington')) old_ds = gdal.Open('nat_color.tif') # Create a VRT in memory that does the reproject. vrt_ds = gdal.AutoCreateWarpedVRT(old_ds, None, srs.ExportToWkt(), gdal.GRA_Bilinear) # Copy the VRT to a GeoTIFF so we have a file on disk. gdal.GetDriverByName('gtiff').CreateCopy('nat_color_wgs84.tif', vrt_ds) ########################### 10.7 Callback functions ########################## # Let's calculate statistics on the natural color Landsat image and show # progress while it does it (this image probably already has stats, so this # will go really fast). Watch your output window to see what happens. os.chdir(os.path.join(data_dir, 'Landsat', 'Washington')) ds = gdal.Open('nat_color.tif') for i in range(ds.RasterCount): ds.GetRasterBand(i + 1).ComputeStatistics(False, gdal.TermProgress_nocb)
xres = 0 yres = 0 while True: feat = lyr.GetNextFeature() if feat is None: break # feat.DumpReadable() gdal_ds_name = feat.GetField(tileitem) if not os.path.isabs(gdal_ds_name): gdal_ds_name = os.path.join(os.path.dirname(ogr_ds_name), gdal_ds_name) gdal_ds = gdal.Open(gdal_ds_name) if gdal_ds is None: raise Exception('cannot open %s' % gdal_ds_name) warped_vrt_ds = gdal.AutoCreateWarpedVRT(gdal_ds, None, dst_wkt) if warped_vrt_ds is None: raise Exception('cannot warp %s to %s' % (gdal_ds_name, dst_wkt)) gt = warped_vrt_ds.GetGeoTransform() xres += gt[1] yres += gt[5] warped_vrt_ds = None counter = counter + 1 if counter == 0: raise Exception('tileindex is empty') xres /= counter yres /= counter (xmin, xmax, ymin, ymax) = lyr.GetExtent()
def reproject_raster(dataset, epsg_from=None, epsg_to=None, fltr=gdal.GRA_NearestNeighbour): """reproject a gdal raster dataset :param dataset: a gdal dataset :param epsg_from: the input epsg; if None get from the sorce :param epsg_to: the output epsg; if None throw exception :param fltr: the filter to apply when reprojecting GRA_NearestNeighbour Nearest neighbour (select on one input pixel) GRA_Bilinear Bilinear (2x2 kernel) GRA_Cubic Cubic Convolution Approximation (4x4 kernel) GRA_CubicSpline Cubic B-Spline Approximation (4x4 kernel) GRA_Lanczos Lanczos windowed sinc interpolation (6x6 kernel) GRA_Average Average (computes the average of all non-NODATA contributing pixels) GRA_Mode Mode (selects the value which appears most often of all the sampled points) #############NearestNeighbour filter is good for categorical data########### :return: the reprojected dataset """ try: if epsg_to is None: raise Exception( "select the destination projected spatial reference!!!") if epsg_from == epsg_to: print("the input and output projections are the same!") return dataset # Define input/output spatial references if epsg_from: source = osr.SpatialReference() source.ImportFromEPSG(epsg_from) inwkt = source.ExportToWkt() else: source = osr.SpatialReference() source.ImportFromWkt(dataset.GetProjection()) source.MorphFromESRI() #this is to avoid reprojection errors inwkt = source.ExportToWkt() destination = osr.SpatialReference() destination.ImportFromEPSG(epsg_to) outwkt = destination.ExportToWkt() vrt_ds = gdal.AutoCreateWarpedVRT(dataset, inwkt, outwkt, fltr) return vrt_ds except RuntimeError as err: raise err except Exception as e: raise e