Beispiel #1
0
    def __call__(self, src_ds):
        logger.info("Applying ReprojectionOptimization")
        # setup
        src_sr = osr.SpatialReference()
        src_sr.ImportFromWkt(src_ds.GetProjection())

        dst_sr = osr.SpatialReference()
        dst_sr.ImportFromEPSG(self.srid)

        if src_sr.IsSame(dst_sr) and (src_ds.GetGeoTransform()[1] > 0) \
                and (src_ds.GetGeoTransform()[5] < 0) \
                and (src_ds.GetGeoTransform()[2] == 0) \
                and (src_ds.GetGeoTransform()[4] == 0):
            logger.info("Source and destination projection are equal and image "
                        "is not flipped or has rotated axes. Thus, no "
                        "reprojection is required.")
            return src_ds

        # create a temporary dataset to get information about the output size
        tmp_ds = gdal.AutoCreateWarpedVRT(src_ds, None, dst_sr.ExportToWkt(),
                                          gdal.GRA_Bilinear, 0.125)

        try:
            # create the output dataset
            dst_ds = create_temp(tmp_ds.RasterXSize, tmp_ds.RasterYSize,
                                 src_ds.RasterCount,
                                 src_ds.GetRasterBand(1).DataType,
                                 temp_root=self.temporary_directory)

            # initialize with no data
            for i in range(src_ds.RasterCount):
                src_band = src_ds.GetRasterBand(i+1)
                if src_band.GetNoDataValue() is not None:
                    dst_band = dst_ds.GetRasterBand(i+1)
                    dst_band.SetNoDataValue(src_band.GetNoDataValue())
                    dst_band.Fill(src_band.GetNoDataValue())

            # reproject the image
            dst_ds.SetProjection(dst_sr.ExportToWkt())
            dst_ds.SetGeoTransform(tmp_ds.GetGeoTransform())

            gdal.ReprojectImage(src_ds, dst_ds,
                                src_sr.ExportToWkt(),
                                dst_sr.ExportToWkt(),
                                gdal.GRA_Bilinear)

            tmp_ds = None

            # copy the metadata
            copy_metadata(src_ds, dst_ds)

            return dst_ds
        except:
            cleanup_temp(dst_ds)
            raise
Beispiel #2
0
    def __call__(self, src_ds):
        logger.info("Applying ReprojectionOptimization")
        # setup
        src_sr = osr.SpatialReference()
        src_sr.ImportFromWkt(src_ds.GetProjection())

        dst_sr = osr.SpatialReference()
        dst_sr.ImportFromEPSG(self.srid)

        if src_sr.IsSame(dst_sr) and (src_ds.GetGeoTransform()[1] > 0) \
                and (src_ds.GetGeoTransform()[5] < 0) \
                and (src_ds.GetGeoTransform()[2] == 0) \
                and (src_ds.GetGeoTransform()[4] == 0):
            logger.info(
                "Source and destination projection are equal and image "
                "is not flipped or has rotated axes. Thus, no "
                "reprojection is required.")
            return src_ds

        # create a temporary dataset to get information about the output size
        tmp_ds = gdal.AutoCreateWarpedVRT(src_ds, None, dst_sr.ExportToWkt(),
                                          gdal.GRA_Bilinear, 0.125)

        try:
            # create the output dataset
            dst_ds = create_temp(tmp_ds.RasterXSize,
                                 tmp_ds.RasterYSize,
                                 src_ds.RasterCount,
                                 src_ds.GetRasterBand(1).DataType,
                                 temp_root=self.temporary_directory)

            # initialize with no data
            for i in range(src_ds.RasterCount):
                src_band = src_ds.GetRasterBand(i + 1)
                if src_band.GetNoDataValue() is not None:
                    dst_band = dst_ds.GetRasterBand(i + 1)
                    dst_band.SetNoDataValue(src_band.GetNoDataValue())
                    dst_band.Fill(src_band.GetNoDataValue())

            # reproject the image
            dst_ds.SetProjection(dst_sr.ExportToWkt())
            dst_ds.SetGeoTransform(tmp_ds.GetGeoTransform())

            gdal.ReprojectImage(src_ds, dst_ds, src_sr.ExportToWkt(),
                                dst_sr.ExportToWkt(), gdal.GRA_Bilinear)

            tmp_ds = None

            # copy the metadata
            copy_metadata(src_ds, dst_ds)

            return dst_ds
        except:
            cleanup_temp(dst_ds)
            raise
Beispiel #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
Beispiel #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
Beispiel #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
Beispiel #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
Beispiel #7
0
    def process(self, input_filename, output_filename,
                geo_reference=None, generate_metadata=True):

        # open the dataset and create an In-Memory Dataset as copy
        # to perform optimizations
        ds = create_mem_copy(gdal.Open(input_filename))

        gt = ds.GetGeoTransform()
        footprint_wkt = None

        if not geo_reference:
            if gt == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0):
                # TODO: maybe use a better check
                raise ValueError("No geospatial reference for unreferenced "
                                 "dataset given.")
        else:
            logger.debug("Applying geo reference '%s'."
                         % type(geo_reference).__name__)
            ds, footprint_wkt = geo_reference.apply(ds)

        # apply optimizations
        for optimization in self.get_optimizations(ds):
            logger.debug("Applying optimization '%s'."
                         % type(optimization).__name__)

            try:
                new_ds = optimization(ds)

                if new_ds is not ds:
                    # cleanup afterwards
                    cleanup_temp(ds)
                    ds = new_ds
            except:
                cleanup_temp(ds)
                raise

        # generate the footprint from the dataset
        if not footprint_wkt:
            logger.debug("Generating footprint.")
            footprint_wkt = self._generate_footprint_wkt(ds)
        # check that footprint is inside of extent of generated image
        # regenerate otherwise
        else:
            tmp_extent = getExtentFromRectifiedDS(ds)
            tmp_bbox = Polygon.from_bbox((tmp_extent[0], tmp_extent[1],
                                          tmp_extent[2], tmp_extent[3]))
            tmp_footprint = GEOSGeometry(footprint_wkt)
            if not tmp_bbox.contains(tmp_footprint):
                footprint_wkt = tmp_footprint.intersection(tmp_bbox).wkt

        if self.footprint_alpha:
            logger.debug("Applying optimization 'AlphaBandOptimization'.")
            opt = AlphaBandOptimization()
            opt(ds, footprint_wkt)

        output_filename = self.generate_filename(output_filename)

        logger.debug("Writing file to disc using options: %s."
                     % ", ".join(self.format_selection.creation_options))

        logger.debug("Metadata tags to be written: %s"
                     % ", ".join(ds.GetMetadata_List("") or []))

        # save the file to the disc
        driver = gdal.GetDriverByName(self.format_selection.driver_name)
        ds = driver.CreateCopy(output_filename, ds,
                               options=self.format_selection.creation_options)

        for optimization in self.get_post_optimizations(ds):
            logger.debug("Applying post-optimization '%s'."
                         % type(optimization).__name__)
            optimization(ds)

        # generate metadata if requested
        footprint = None
        if generate_metadata:
            normalized_space = Polygon.from_bbox((-180, -90, 180, 90))
            non_normalized_space = Polygon.from_bbox((180, -90, 360, 90))

            footprint = GEOSGeometry(footprint_wkt)
            #.intersection(normalized_space)
            outer = non_normalized_space.intersection(footprint)

            if len(outer):
                footprint = MultiPolygon(
                    *map(lambda p:
                        Polygon(*map(lambda ls:
                            LinearRing(*map(lambda point:
                                (point[0] - 360, point[1]), ls.coords
                            )), tuple(p)
                        )), (outer,)
                    )
                ).union(normalized_space.intersection(footprint))
            else:
                if isinstance(footprint, Polygon):
                    footprint = MultiPolygon(footprint)

            logger.info("Calculated Footprint: '%s'" % footprint.wkt)

            # use the provided footprint
            #geom = OGRGeometry(footprint_wkt)
            #exterior = []
            #for x, y in geom.exterior_ring.tuple:
            #    exterior.append(y); exterior.append(x)

            #polygon = [exterior]
        num_bands = ds.RasterCount

        # finally close the dataset and write it to the disc
        ds = None

        return PreProcessResult(output_filename, footprint, num_bands)
Beispiel #8
0
class NGEOPreProcessor(WMSPreProcessor):
    def __init__(self,
                 format_selection,
                 overviews=True,
                 crs=None,
                 bands=None,
                 bandmode=RGB,
                 footprint_alpha=False,
                 color_index=False,
                 palette_file=None,
                 no_data_value=None,
                 overview_resampling=None,
                 overview_levels=None,
                 overview_minsize=None,
                 radiometric_interval_min=None,
                 radiometric_interval_max=None,
                 sieve_max_threshold=None,
                 simplification_factor=None,
                 temporary_directory=None):

        self.format_selection = format_selection
        self.overviews = overviews
        self.overview_resampling = overview_resampling
        self.overview_levels = overview_levels
        self.overview_minsize = overview_minsize

        self.crs = crs

        self.bands = bands
        self.bandmode = bandmode
        self.footprint_alpha = footprint_alpha
        self.color_index = color_index
        self.palette_file = palette_file
        self.no_data_value = no_data_value
        self.radiometric_interval_min = radiometric_interval_min
        self.radiometric_interval_max = radiometric_interval_max

        if sieve_max_threshold is not None:
            self.sieve_max_threshold = sieve_max_threshold
        else:
            self.sieve_max_threshold = 0

        if simplification_factor is not None:
            self.simplification_factor = simplification_factor
        else:
            # default 2 * resolution == 2 pixels
            self.simplification_factor = 2

        self.temporary_directory = temporary_directory

    def process(self,
                input_filename,
                output_filename,
                geo_reference=None,
                generate_metadata=True,
                merge_with=None,
                original_footprint=None):

        # open the dataset and create an In-Memory Dataset as copy
        # to perform optimizations
        ds = create_mem_copy(gdal.Open(input_filename))

        gt = ds.GetGeoTransform()
        footprint_wkt = None

        if not geo_reference:
            if gt == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0):
                if ds.GetGCPCount() > 0:
                    geo_reference = InternalGCPs()
                else:
                    raise ValueError("No geospatial reference for "
                                     "unreferenced dataset given.")

        if geo_reference:
            logger.debug("Applying geo reference '%s'." %
                         type(geo_reference).__name__)
            # footprint is always in EPSG:4326
            ds, footprint_wkt = geo_reference.apply(ds)

        # apply optimizations
        for optimization in self.get_optimizations(ds):
            logger.debug("Applying optimization '%s'." %
                         type(optimization).__name__)

            try:
                new_ds = optimization(ds)

                if new_ds is not ds:
                    # cleanup afterwards
                    cleanup_temp(ds)
                    ds = new_ds
            except:
                cleanup_temp(ds)
                raise

        # generate the footprint from the dataset
        if not footprint_wkt:
            logger.debug("Generating footprint.")
            footprint_wkt = self._generate_footprint_wkt(ds)
        # check that footprint is inside of extent of generated image
        # regenerate otherwise
        else:
            tmp_extent = getExtentFromRectifiedDS(ds)
            tmp_bbox = Polygon.from_bbox(
                (tmp_extent[0], tmp_extent[1], tmp_extent[2], tmp_extent[3]))
            # transform image bbox to EPSG:4326 if necessary
            proj = ds.GetProjection()
            srs = osr.SpatialReference()
            try:
                srs.ImportFromWkt(proj)
                srs.AutoIdentifyEPSG()
                ptype = "PROJCS" if srs.IsProjected() else "GEOGCS"
                srid = int(srs.GetAuthorityCode(ptype))
                if srid != '4326':
                    out_srs = osr.SpatialReference()
                    out_srs.ImportFromEPSG(4326)
                    transform = osr.CoordinateTransformation(srs, out_srs)
                    tmp_bbox2 = ogr.CreateGeometryFromWkt(tmp_bbox.wkt)
                    tmp_bbox2.Transform(transform)
                    tmp_bbox = GEOSGeometry(tmp_bbox2.ExportToWkt())
            except (RuntimeError, TypeError), e:
                logger.warn("Projection: %s" % proj)
                logger.warn("Failed to identify projection's EPSG code."
                            "%s: %s" % (type(e).__name__, str(e)))

            tmp_footprint = GEOSGeometry(footprint_wkt)
            if not tmp_bbox.contains(tmp_footprint):
                logger.debug("Re-generating footprint because not inside of "
                             "generated image.")
                footprint_wkt = tmp_footprint.intersection(tmp_bbox).wkt

        if self.footprint_alpha:
            logger.debug("Applying optimization 'AlphaBandOptimization'.")
            opt = AlphaBandOptimization()
            opt(ds, footprint_wkt)

        output_filename = self.generate_filename(output_filename)

        if merge_with is not None:
            if original_footprint is None:
                raise ValueError(
                    "Original footprint with to be merged image required.")

            original_ds = gdal.Open(merge_with, gdal.GA_Update)
            merger = GDALDatasetMerger([
                GDALGeometryMaskMergeSource(
                    original_ds,
                    original_footprint,
                    temporary_directory=self.temporary_directory),
                GDALGeometryMaskMergeSource(
                    ds,
                    footprint_wkt,
                    temporary_directory=self.temporary_directory)
            ])

            final_ds = merger.merge(output_filename,
                                    self.format_selection.driver_name,
                                    self.format_selection.creation_options)

            # cleanup previous file
            driver = original_ds.GetDriver()
            original_ds = None
            driver.Delete(merge_with)

            cleanup_temp(ds)

        else:
            logger.debug("Writing single file '%s' using options: %s." %
                         (output_filename, ", ".join(
                             self.format_selection.creation_options)))
            logger.debug("Metadata tags to be written: %s" %
                         ", ".join(ds.GetMetadata_List("") or []))

            # save the file to the disc
            driver = gdal.GetDriverByName(self.format_selection.driver_name)
            final_ds = driver.CreateCopy(
                output_filename,
                ds,
                options=self.format_selection.creation_options)

            # cleanup
            cleanup_temp(ds)

        for optimization in self.get_post_optimizations(final_ds):
            logger.debug("Applying post-optimization '%s'." %
                         type(optimization).__name__)
            optimization(final_ds)

        # generate metadata if requested
        footprint = None
        if generate_metadata:
            normalized_space = Polygon.from_bbox((-180, -90, 180, 90))
            non_normalized_space = Polygon.from_bbox((180, -90, 360, 90))

            footprint = GEOSGeometry(footprint_wkt)

            outer = non_normalized_space.intersection(footprint)

            if len(outer):
                footprint = MultiPolygon(*map(
                    lambda p: Polygon(*map(
                        lambda ls: LinearRing(*map(
                            lambda point: (point[0] - 360, point[1]), ls.coords
                        )), tuple(p))), (outer, ))).union(
                            normalized_space.intersection(footprint))
            else:
                if isinstance(footprint, Polygon):
                    footprint = MultiPolygon(footprint)

            if original_footprint:
                logger.debug("Merging footprint.")
                footprint = footprint.union(GEOSGeometry(original_footprint))

            logger.debug("Calculated Footprint: '%s'" % footprint.wkt)

        num_bands = final_ds.RasterCount

        # finally close the dataset and write it to the disc
        final_ds = None

        return PreProcessResult(output_filename, footprint, num_bands)
Beispiel #9
0
    def process(self,
                input_filename,
                output_filename,
                geo_reference=None,
                generate_metadata=True,
                merge_with=None,
                original_footprint=None):

        # open the dataset and create an In-Memory Dataset as copy
        # to perform optimizations
        ds = create_mem_copy(gdal.Open(input_filename))

        gt = ds.GetGeoTransform()
        footprint_wkt = None

        if not geo_reference:
            if gt == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0):
                if ds.GetGCPCount() > 0:
                    geo_reference = InternalGCPs()
                else:
                    raise ValueError("No geospatial reference for "
                                     "unreferenced dataset given.")

        if geo_reference:
            logger.debug("Applying geo reference '%s'." %
                         type(geo_reference).__name__)
            # footprint is always in EPSG:4326
            ds, footprint_wkt = geo_reference.apply(ds)

        # apply optimizations
        for optimization in self.get_optimizations(ds):
            logger.debug("Applying optimization '%s'." %
                         type(optimization).__name__)

            try:
                new_ds = optimization(ds)

                if new_ds is not ds:
                    # cleanup afterwards
                    cleanup_temp(ds)
                    ds = new_ds
            except:
                cleanup_temp(ds)
                raise

        # generate the footprint from the dataset
        if not footprint_wkt:
            logger.debug("Generating footprint.")
            footprint_wkt = self._generate_footprint_wkt(ds)
        # check that footprint is inside of extent of generated image
        # regenerate otherwise
        else:
            tmp_extent = getExtentFromRectifiedDS(ds)
            tmp_bbox = Polygon.from_bbox(
                (tmp_extent[0], tmp_extent[1], tmp_extent[2], tmp_extent[3]))
            # transform image bbox to EPSG:4326 if necessary
            proj = ds.GetProjection()
            srs = osr.SpatialReference()
            try:
                srs.ImportFromWkt(proj)
                srs.AutoIdentifyEPSG()
                ptype = "PROJCS" if srs.IsProjected() else "GEOGCS"
                srid = int(srs.GetAuthorityCode(ptype))
                if srid != '4326':
                    out_srs = osr.SpatialReference()
                    out_srs.ImportFromEPSG(4326)
                    transform = osr.CoordinateTransformation(srs, out_srs)
                    tmp_bbox2 = ogr.CreateGeometryFromWkt(tmp_bbox.wkt)
                    tmp_bbox2.Transform(transform)
                    tmp_bbox = GEOSGeometry(tmp_bbox2.ExportToWkt())
            except (RuntimeError, TypeError), e:
                logger.warn("Projection: %s" % proj)
                logger.warn("Failed to identify projection's EPSG code."
                            "%s: %s" % (type(e).__name__, str(e)))

            tmp_footprint = GEOSGeometry(footprint_wkt)
            if not tmp_bbox.contains(tmp_footprint):
                logger.debug("Re-generating footprint because not inside of "
                             "generated image.")
                footprint_wkt = tmp_footprint.intersection(tmp_bbox).wkt
Beispiel #10
0
    def process(self, input_filename, output_filename,
                geo_reference=None, generate_metadata=True):

        # open the dataset and create an In-Memory Dataset as copy
        # to perform optimizations
        ds = create_mem_copy(gdal.Open(input_filename))

        gt = ds.GetGeoTransform()
        footprint_wkt = None

        if not geo_reference:
            if gt == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0):
                # TODO: maybe use a better check
                raise ValueError("No geospatial reference for unreferenced "
                                 "dataset given.")
        else:
            logger.debug("Applying geo reference '%s'."
                         % type(geo_reference).__name__)
            ds, footprint_wkt = geo_reference.apply(ds)

        # apply optimizations
        for optimization in self.get_optimizations(ds):
            logger.debug("Applying optimization '%s'."
                         % type(optimization).__name__)

            try:
                new_ds = optimization(ds)

                if new_ds is not ds:
                    # cleanup afterwards
                    cleanup_temp(ds)
                    ds = new_ds
            except:
                cleanup_temp(ds)
                raise

        # generate the footprint from the dataset
        if not footprint_wkt:
            logger.debug("Generating footprint.")
            footprint_wkt = self._generate_footprint_wkt(ds)
        # check that footprint is inside of extent of generated image
        # regenerate otherwise
        else:
            tmp_extent = getExtentFromRectifiedDS(ds)
            tmp_bbox = Polygon.from_bbox((tmp_extent[0], tmp_extent[1],
                                          tmp_extent[2], tmp_extent[3]))
            tmp_footprint = GEOSGeometry(footprint_wkt)
            if not tmp_bbox.contains(tmp_footprint):
                footprint_wkt = tmp_footprint.intersection(tmp_bbox).wkt

        if self.footprint_alpha:
            logger.debug("Applying optimization 'AlphaBandOptimization'.")
            opt = AlphaBandOptimization()
            opt(ds, footprint_wkt)

        output_filename = self.generate_filename(output_filename)

        logger.debug("Writing file to disc using options: %s."
                     % ", ".join(self.format_selection.creation_options))

        logger.debug("Metadata tags to be written: %s"
                     % ", ".join(ds.GetMetadata_List("") or []))

        # save the file to the disc
        driver = gdal.GetDriverByName(self.format_selection.driver_name)
        ds = driver.CreateCopy(output_filename, ds,
                               options=self.format_selection.creation_options)

        for optimization in self.get_post_optimizations(ds):
            logger.debug("Applying post-optimization '%s'."
                         % type(optimization).__name__)
            optimization(ds)

        # generate metadata if requested
        footprint = None
        if generate_metadata:
            normalized_space = Polygon.from_bbox((-180, -90, 180, 90))
            non_normalized_space = Polygon.from_bbox((180, -90, 360, 90))

            footprint = GEOSGeometry(footprint_wkt)
            #.intersection(normalized_space)
            outer = non_normalized_space.intersection(footprint)

            if len(outer):
                footprint = MultiPolygon(
                    *map(lambda p:
                        Polygon(*map(lambda ls:
                            LinearRing(*map(lambda point:
                                (point[0] - 360, point[1]), ls.coords
                            )), tuple(p)
                        )), (outer,)
                    )
                ).union(normalized_space.intersection(footprint))
            else:
                if isinstance(footprint, Polygon):
                    footprint = MultiPolygon(footprint)

            logger.info("Calculated Footprint: '%s'" % footprint.wkt)

            # use the provided footprint
            #geom = OGRGeometry(footprint_wkt)
            #exterior = []
            #for x, y in geom.exterior_ring.tuple:
            #    exterior.append(y); exterior.append(x)

            #polygon = [exterior]
        num_bands = ds.RasterCount

        # finally close the dataset and write it to the disc
        ds = None

        return PreProcessResult(output_filename, footprint, num_bands)
Beispiel #11
0
    def process(self, input_filename, output_filename,
                geo_reference=None, generate_metadata=True,
                merge_with=None, original_footprint=None):

        # open the dataset and create an In-Memory Dataset as copy
        # to perform optimizations
        ds = create_mem_copy(gdal.Open(input_filename))

        gt = ds.GetGeoTransform()
        footprint_wkt = None

        if not geo_reference:
            if gt == (0.0, 1.0, 0.0, 0.0, 0.0, 1.0):
                if ds.GetGCPCount() > 0:
                    geo_reference = InternalGCPs()
                else:
                    raise ValueError("No geospatial reference for "
                                     "unreferenced dataset given.")

        if geo_reference:
            logger.debug("Applying geo reference '%s'."
                         % type(geo_reference).__name__)
            # footprint is always in EPSG:4326
            ds, footprint_wkt = geo_reference.apply(ds)

        # apply optimizations
        for optimization in self.get_optimizations(ds):
            logger.debug("Applying optimization '%s'."
                         % type(optimization).__name__)

            try:
                new_ds = optimization(ds)

                if new_ds is not ds:
                    # cleanup afterwards
                    cleanup_temp(ds)
                    ds = new_ds
            except:
                cleanup_temp(ds)
                raise

        # generate the footprint from the dataset
        if not footprint_wkt:
            logger.debug("Generating footprint.")
            footprint_wkt = self._generate_footprint_wkt(ds)
        # check that footprint is inside of extent of generated image
        # regenerate otherwise
        else:
            tmp_extent = getExtentFromRectifiedDS(ds)
            tmp_bbox = Polygon.from_bbox((tmp_extent[0], tmp_extent[1],
                                          tmp_extent[2], tmp_extent[3]))

            # transform image bbox to EPSG:4326 if necessary
            proj = ds.GetProjection()
            srs = osr.SpatialReference()
            try:
                srs.ImportFromWkt(proj)
                srs.AutoIdentifyEPSG()
                ptype = "PROJCS" if srs.IsProjected() else "GEOGCS"
                srid = int(srs.GetAuthorityCode(ptype))
                if srid != '4326':
                    out_srs = osr.SpatialReference()
                    out_srs.ImportFromEPSG(4326)
                    transform = osr.CoordinateTransformation(srs, out_srs)
                    tmp_bbox2 = ogr.CreateGeometryFromWkt(tmp_bbox.wkt)
                    tmp_bbox2.Transform(transform)
                    tmp_bbox = GEOSGeometry(tmp_bbox2.ExportToWkt())
            except (RuntimeError, TypeError), e:
                logger.warn("Projection: %s" % proj)
                logger.warn("Failed to identify projection's EPSG code."
                    "%s: %s" % ( type(e).__name__ , str(e) ) )

            tmp_footprint = GEOSGeometry(footprint_wkt)
            if not tmp_bbox.contains(tmp_footprint):
                footprint_wkt = tmp_footprint.intersection(tmp_bbox).wkt