def __call__(self, src_ds): dst_ds = create_mem(src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GDT_Byte) if not self.palette_file: # create a color table as a median of the given dataset ct = gdal.ColorTable() gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), 256, ct) else: # copy the color table from the given palette file pct_ds = gdal.Open(self.palette_file) pct_ct = pct_ds.GetRasterBand(1).GetRasterColorTable() if not pct_ct: raise ValueError("The palette file '%s' does not have a Color " "Table." % self.palette_file) ct = pct_ct.Clone() pct_ds = None dst_ds.GetRasterBand(1).SetRasterColorTable(ct) gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), dst_ds.GetRasterBand(1), ct) copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds
def __call__(self, src_ds): dst_ds = create_mem(src_ds.RasterXSize, src_ds.RasterYSize, len(self.bands), self.datatype) dst_range = get_limits(self.datatype) multiple = 0 for dst_index, (src_index, dmin, dmax) in enumerate(self.bands, 1): # check if next band is equal if dst_index < len(self.bands) and (src_index, dmin, dmax) == self.bands[dst_index]: multiple += 1 continue # check that src band is available if src_index > src_ds.RasterCount: continue # initialize with zeros if band is 0 if src_index == 0: src_band = src_ds.GetRasterBand(1) data = numpy.zeros((src_band.YSize, src_band.XSize), dtype=gdal_array.codes[self.datatype]) src_min, src_max = (0, 0) # use src_ds band otherwise else: src_band = src_ds.GetRasterBand(src_index) data = src_band.ReadAsArray() src_min, src_max = src_band.ComputeRasterMinMax() # get min/max values or calculate from band if dmin is None: dmin = get_limits(src_band.DataType)[0] elif dmin == "min": dmin = src_min if dmax is None: dmax = get_limits(src_band.DataType)[1] elif dmax == "max": dmax = src_max src_range = (float(dmin), float(dmax)) # perform clipping and scaling data = (dst_range[1] - dst_range[0]) * ( (numpy.clip(data, dmin, dmax) - src_range[0]) / (src_range[1] - src_range[0]) ) # set new datatype data = data.astype(gdal_array.codes[self.datatype]) # write result dst_band = dst_ds.GetRasterBand(dst_index) dst_band.WriteArray(data) # write equal bands at once if multiple > 0: for i in range(multiple): dst_band = dst_ds.GetRasterBand(dst_index - 1 - i) dst_band.WriteArray(data) multiple = 0 copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds
def __call__(self, src_ds): logger.info("Applying ColorIndexOptimization") try: dst_ds = create_temp(src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GDT_Byte, temp_root=self.temporary_directory) if not self.palette_file: # create a color table as a median of the given dataset ct = gdal.ColorTable() gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), 256, ct) else: # copy the color table from the given palette file pct_ds = gdal.Open(self.palette_file) pct_ct = pct_ds.GetRasterBand(1).GetRasterColorTable() if not pct_ct: raise ValueError("The palette file '%s' does not have a " "Color Table." % self.palette_file) ct = pct_ct.Clone() pct_ds = None dst_ds.GetRasterBand(1).SetRasterColorTable(ct) gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), dst_ds.GetRasterBand(1), ct) copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds except: cleanup_temp(dst_ds) raise
def __call__(self, src_ds): logger.info("Applying ColorIndexOptimization") try: dst_ds = create_temp(src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GDT_Byte, temp_root=self.temporary_directory) if not self.palette_file: # create a color table as a median of the given dataset ct = gdal.ColorTable() gdal.ComputeMedianCutPCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), 256, ct) else: # copy the color table from the given palette file pct_ds = gdal.Open(self.palette_file) pct_ct = pct_ds.GetRasterBand(1).GetRasterColorTable() if not pct_ct: raise ValueError("The palette file '%s' does not have a " "Color Table." % self.palette_file) ct = pct_ct.Clone() pct_ds = None dst_ds.GetRasterBand(1).SetRasterColorTable(ct) gdal.DitherRGB2PCT(src_ds.GetRasterBand(1), src_ds.GetRasterBand(2), src_ds.GetRasterBand(3), dst_ds.GetRasterBand(1), ct) copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds except: cleanup_temp(dst_ds) raise
def __call__(self, src_ds): logger.info("Applying BandSelectionOptimization") try: dst_ds = create_temp(src_ds.RasterXSize, src_ds.RasterYSize, len(self.bands), self.datatype, temp_root=self.temporary_directory) dst_range = get_limits(self.datatype) multiple, multiple_written = 0, False for dst_index, (src_index, dmin, dmax) in enumerate(self.bands, 1): # check if next band is equal if dst_index < len(self.bands) and \ (src_index, dmin, dmax) == self.bands[dst_index]: multiple += 1 continue # check that src band is available if src_index > src_ds.RasterCount: continue # initialize with zeros if band is 0 if src_index == 0: src_band = src_ds.GetRasterBand(1) data = numpy.zeros((src_band.YSize, src_band.XSize), dtype=gdal_array.codes[self.datatype]) src_min, src_max = (0, 0) # use src_ds band otherwise else: src_band = src_ds.GetRasterBand(src_index) src_min, src_max = src_band.ComputeRasterMinMax() # get min/max values or calculate from band if dmin is None: dmin = get_limits(src_band.DataType)[0] elif dmin == "min": dmin = src_min if dmax is None: dmax = get_limits(src_band.DataType)[1] elif dmax == "max": dmax = src_max src_range = (float(dmin), float(dmax)) block_x_size, block_y_size = src_band.GetBlockSize() num_x = int(math.ceil(float(src_band.XSize) / block_x_size)) num_y = int(math.ceil(float(src_band.YSize) / block_y_size)) dst_band = dst_ds.GetRasterBand(dst_index) if src_band.GetNoDataValue() is not None: dst_band.SetNoDataValue(src_band.GetNoDataValue()) for block_x, block_y in product(range(num_x), range(num_y)): offset_x = block_x * block_x_size offset_y = block_y * block_y_size size_x = min(src_band.XSize - offset_x, block_x_size) size_y = min(src_band.YSize - offset_y, block_y_size) data = src_band.ReadAsArray(offset_x, offset_y, size_x, size_y) # perform clipping and scaling data = ((dst_range[1] - dst_range[0]) * ((numpy.clip(data, dmin, dmax) - src_range[0]) / (src_range[1] - src_range[0]))) # set new datatype data = data.astype(gdal_array.codes[self.datatype]) # write result dst_band.WriteArray(data, offset_x, offset_y) # write equal bands at once if multiple > 0: for i in range(multiple): dst_band_multiple = dst_ds.GetRasterBand( dst_index - 1 - i) dst_band_multiple.WriteArray( data, offset_x, offset_y) multiple_written = True if multiple_written: multiple = 0 multiple_written = False copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds except: cleanup_temp(dst_ds) raise
def __call__(self, src_ds): logger.info("Applying BandSelectionOptimization") try: dst_ds = create_temp(src_ds.RasterXSize, src_ds.RasterYSize, len(self.bands), self.datatype, temp_root=self.temporary_directory) dst_range = get_limits(self.datatype) multiple, multiple_written = 0, False for dst_index, (src_index, dmin, dmax) in enumerate(self.bands, 1): # check if next band is equal if dst_index < len(self.bands) and \ (src_index, dmin, dmax) == self.bands[dst_index]: multiple += 1 continue # check that src band is available if src_index > src_ds.RasterCount: continue # initialize with zeros if band is 0 if src_index == 0: src_band = src_ds.GetRasterBand(1) data = numpy.zeros( (src_band.YSize, src_band.XSize), dtype=gdal_array.codes[self.datatype] ) src_min, src_max = (0, 0) # use src_ds band otherwise else: src_band = src_ds.GetRasterBand(src_index) src_min, src_max = src_band.ComputeRasterMinMax() # get min/max values or calculate from band if dmin is None: dmin = get_limits(src_band.DataType)[0] elif dmin == "min": dmin = src_min if dmax is None: dmax = get_limits(src_band.DataType)[1] elif dmax == "max": dmax = src_max src_range = (float(dmin), float(dmax)) block_x_size, block_y_size = src_band.GetBlockSize() num_x = int(math.ceil(float(src_band.XSize) / block_x_size)) num_y = int(math.ceil(float(src_band.YSize) / block_y_size)) dst_band = dst_ds.GetRasterBand(dst_index) if src_band.GetNoDataValue() is not None: dst_band.SetNoDataValue(src_band.GetNoDataValue()) for block_x, block_y in product(range(num_x), range(num_y)): offset_x = block_x * block_x_size offset_y = block_y * block_y_size size_x = min(src_band.XSize - offset_x, block_x_size) size_y = min(src_band.YSize - offset_y, block_y_size) data = src_band.ReadAsArray( offset_x, offset_y, size_x, size_y ) # perform clipping and scaling data = ((dst_range[1] - dst_range[0]) * ((numpy.clip(data, dmin, dmax) - src_range[0]) / (src_range[1] - src_range[0]))) # set new datatype data = data.astype(gdal_array.codes[self.datatype]) # write result dst_band.WriteArray(data, offset_x, offset_y) # write equal bands at once if multiple > 0: for i in range(multiple): dst_band_multiple = dst_ds.GetRasterBand( dst_index-1-i ) dst_band_multiple.WriteArray( data, offset_x, offset_y ) multiple_written = True if multiple_written: multiple = 0 multiple_written = False copy_projection(src_ds, dst_ds) copy_metadata(src_ds, dst_ds) return dst_ds except: cleanup_temp(dst_ds) raise
def _generate_footprint_wkt(self, ds): """ Generate a fooptrint from a raster, using black/no-data as exclusion """ # create an empty boolean array initialized as 'False' to store where # values exist as a mask array. nodata_map = numpy.zeros((ds.RasterYSize, ds.RasterXSize), dtype=numpy.bool) for idx in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(idx) raster_data = band.ReadAsArray() nodata = band.GetNoDataValue() if nodata is None: nodata = 0 # apply the output to the map nodata_map |= (raster_data != nodata) # create a temporary in-memory dataset and write the nodata mask # into its single band tmp_ds = create_mem(ds.RasterXSize + 2, ds.RasterYSize + 2, 1, gdal.GDT_Byte) copy_projection(ds, tmp_ds) tmp_band = tmp_ds.GetRasterBand(1) tmp_band.WriteArray(nodata_map.astype(numpy.uint8)) # create an OGR in memory layer to hold the created polygon sr = osr.SpatialReference(); sr.ImportFromWkt(ds.GetProjectionRef()) ogr_ds = ogr.GetDriverByName('Memory').CreateDataSource('out') layer = ogr_ds.CreateLayer('poly', sr.sr, ogr.wkbPolygon) fd = ogr.FieldDefn('DN', ogr.OFTInteger) layer.CreateField(fd) # polygonize the mask band and store the result in the OGR layer gdal.Polygonize(tmp_band, tmp_band, layer, 0) if layer.GetFeatureCount() != 1: # if there is more than one polygon, compute the minimum bounding polygon geometry = ogr.Geometry(ogr.wkbPolygon) while True: feature = layer.GetNextFeature() if not feature: break geometry = geometry.Union(feature.GetGeometryRef()) # TODO: improve this for a better minimum bounding polygon geometry = geometry.ConvexHull() else: # obtain geometry from the first (and only) layer feature = layer.GetNextFeature() geometry = feature.GetGeometryRef() if geometry.GetGeometryType() != ogr.wkbPolygon: raise RuntimeError("Error during poligonization. Wrong geometry " "type.") # check if reprojection to latlon is necessary if not sr.IsGeographic(): dst_sr = osr.SpatialReference(); dst_sr.ImportFromEPSG(4326) try: geometry.TransformTo(dst_sr.sr) except RuntimeError: geometry.Transform(osr.CoordinateTransformation(sr.sr, dst_sr.sr)) gt = ds.GetGeoTransform() resolution = min(abs(gt[1]), abs(gt[5])) simplification_value = self.simplification_factor * resolution # simplify the polygon. the tolerance value is *really* vague try: # SimplifyPreserveTopology() available since OGR 1.9.0 geometry = geometry.SimplifyPreserveTopology(simplification_value) except AttributeError: # use GeoDjango bindings if OGR is too old geometry = ogr.CreateGeometryFromWkt(GEOSGeometry(geometry.ExportToWkt()).simplify(simplification_value, True).wkt) return geometry.ExportToWkt()
def generate_footprint_wkt(ds, simplification_factor=2): """ Generate a fooptrint from a raster, using black/no-data as exclusion """ # create an empty boolean array initialized as 'False' to store where # values exist as a mask array. nodata_map = np.zeros((ds.RasterYSize, ds.RasterXSize), dtype=np.bool) for idx in range(1, ds.RasterCount + 1): band = ds.GetRasterBand(idx) raster_data = band.ReadAsArray() nodata = band.GetNoDataValue() if nodata is None: nodata = 0 # apply the output to the map nodata_map |= (raster_data != nodata) # create a temporary in-memory dataset and write the nodata mask # into its single band with temporary_dataset(ds.RasterXSize + 2, ds.RasterYSize + 2, 1, gdal.GDT_Byte) as tmp_ds: copy_projection(ds, tmp_ds) tmp_band = tmp_ds.GetRasterBand(1) tmp_band.WriteArray(nodata_map.astype(np.uint8)) # create an OGR in memory layer to hold the created polygon sr = osr.SpatialReference() sr.ImportFromWkt(ds.GetProjectionRef()) ogr_ds = ogr.GetDriverByName('Memory').CreateDataSource('out') layer = ogr_ds.CreateLayer('poly', sr.sr, ogr.wkbPolygon) fd = ogr.FieldDefn('DN', ogr.OFTInteger) layer.CreateField(fd) # polygonize the mask band and store the result in the OGR layer gdal.Polygonize(tmp_band, tmp_band, layer, 0) if layer.GetFeatureCount() != 1: # if there is more than one polygon, compute the minimum bounding polygon geometry = ogr.Geometry(ogr.wkbPolygon) while True: feature = layer.GetNextFeature() if not feature: break geometry = geometry.Union(feature.GetGeometryRef()) # TODO: improve this for a better minimum bounding polygon geometry = geometry.ConvexHull() else: # obtain geometry from the first (and only) layer feature = layer.GetNextFeature() geometry = feature.GetGeometryRef() if geometry.GetGeometryType() not in (ogr.wkbPolygon, ogr.wkbMultiPolygon): raise RuntimeError("Error during poligonization. Wrong geometry " "type.") # check if reprojection to latlon is necessary if not sr.IsGeographic(): dst_sr = osr.SpatialReference() dst_sr.ImportFromEPSG(4326) try: geometry.TransformTo(dst_sr.sr) except RuntimeError: geometry.Transform(osr.CoordinateTransformation(sr.sr, dst_sr.sr)) gt = ds.GetGeoTransform() resolution = min(abs(gt[1]), abs(gt[5])) simplification_value = simplification_factor * resolution # simplify the polygon. the tolerance value is *really* vague try: # SimplifyPreserveTopology() available since OGR 1.9.0 geometry = geometry.SimplifyPreserveTopology(simplification_value) except AttributeError: # use GeoDjango bindings if OGR is too old geometry = ogr.CreateGeometryFromWkt( GEOSGeometry(geometry.ExportToWkt()).simplify( simplification_value, True).wkt) return geometry.ExportToWkt()