Example #1
0
    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
Example #2
0
    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
Example #3
0
    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
Example #4
0
    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
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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()
Example #8
0
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()