Exemplo n.º 1
0
def test_thumbnail_from_numpy_lookuptable(input_uint8_tif_2: Path):
    writer = FileWrite()
    outfile = Path(tempfile.gettempdir()) / "test-lookuptable.jpg"
    wofs_lookup = {
        0: [150, 150, 110],  # dry
        1: [255, 255, 255],  # nodata,
        16: [119, 104, 87],  # terrain
        32: [89, 88, 86],  # cloud_shadow
        64: [216, 215, 214],  # cloud
        80: [242, 220, 180],  # cloudy terrain
        128: [79, 129, 189],  # water
        160: [51, 82, 119],  # shady water
        192: [186, 211, 242],  # cloudy water
    }

    with rasterio.open(input_uint8_tif_2) as ds:
        input_geobox = GridSpec.from_rio(ds)
        data = ds.read(1)

        image_bytes = writer.create_thumbnail_singleband_from_numpy(
            input_data=data,
            input_geobox=input_geobox,
            lookup_table=wofs_lookup)

        with open(outfile, "wb") as jpeg_file:
            jpeg_file.write(image_bytes)

        assert_image(outfile, bands=3)
Exemplo n.º 2
0
def test_thumbnail_bitflag(input_uint8_tif: Path):
    writer = FileWrite()

    outfile = Path(tempfile.gettempdir()) / "test-bitflag.jpg"

    water = 128

    writer.create_thumbnail_singleband(input_uint8_tif, Path(outfile), bit=water)

    assert_image(outfile, bands=3)
Exemplo n.º 3
0
def test_thumbnail_from_numpy_bitflag(input_uint8_tif: Path):
    writer = FileWrite()
    outfile = Path(tempfile.gettempdir()) / "test-bitflag.jpg"
    water = 128

    with rasterio.open(input_uint8_tif) as ds:
        input_geobox = GridSpec.from_rio(ds)
        data = ds.read(1)

        image_bytes = writer.create_thumbnail_singleband_from_numpy(
            input_data=data, input_geobox=input_geobox, bit=water)

        with open(outfile, "wb") as jpeg_file:
            jpeg_file.write(image_bytes)

        assert_image(outfile, bands=3)
Exemplo n.º 4
0
def test_thumbnail_lookuptable(input_uint8_tif_2: Path):
    writer = FileWrite()

    outfile = Path(tempfile.gettempdir()) / "test-lookuptable.jpg"

    wofs_lookup = {
        0: [150, 150, 110],  # dry
        1: [255, 255, 255],  # nodata,
        16: [119, 104, 87],  # terrain
        32: [89, 88, 86],  # cloud_shadow
        64: [216, 215, 214],  # cloud
        80: [242, 220, 180],  # cloudy terrain
        128: [79, 129, 189],  # water
        160: [51, 82, 119],  # shady water
        192: [186, 211, 242],  # cloudy water
    }

    writer.create_thumbnail_singleband(input_uint8_tif_2,
                                       Path(outfile),
                                       lookup_table=wofs_lookup)

    assert_image(outfile, bands=3)
Exemplo n.º 5
0
    def _write_measurement(
        self,
        name: str,
        data: numpy.ndarray,
        grid: GridSpec,
        out_path: Path,
        expand_valid_data: bool,
        nodata: int,
        overview_resampling: Resampling,
        overviews: Tuple[int, ...],
    ):
        res = FileWrite.from_existing(grid.shape).write_from_ndarray(
            data,
            out_path,
            geobox=grid,
            nodata=nodata,
            overview_resampling=overview_resampling,
            overviews=overviews,
        )

        # Ensure the file_format field is set to what we're writing.
        file_format = res.file_format.name
        if "odc:file_format" not in self.properties:
            self.properties["odc:file_format"] = file_format

        if file_format != self.properties["odc:file_format"]:
            raise RuntimeError(
                f"Inconsistent file formats between bands. "
                f"Was {self.properties['odc:file_format']!r}, now {file_format !r}"
            )

        self._measurements.record_image(
            name,
            grid,
            out_path,
            data,
            nodata=nodata,
            expand_valid_data=expand_valid_data,
        )
        # We checksum immediately as the file has *just* been written so it may still
        # be in os/filesystem cache.
        self._checksum.add_file(out_path)
Exemplo n.º 6
0
    def write_thumbnail_singleband(
        self,
        measurement: str,
        bit: int = None,
        lookup_table: Dict[int, Tuple[int, int, int]] = None,
        kind: str = None,
    ):
        """
        Write a singleband thumbnail out, taking in an input measurement and
        outputting a JPG with appropriate settings.

        Options are to
        EITHER
        Use a bit (int) as the value to scale from black to white to
        i.e., 0 will be BLACK and bit will be WHITE, with a linear scale between.
        OR
        Provide a lookuptable (dict) of int (key) [R, G, B] (value) fields
        to make the image with.
        """

        thumb_path = self.names.thumbnail_name(self._work_path, kind=kind)

        _, image_path = self.measurements.get(measurement, (None, None))

        if image_path is None:
            raise IncompleteDatasetError(
                ValidationMessage(
                    Level.error,
                    "missing_thumb_measurement",
                    f"Thumbnail measurement is missing: no measurements called {measurement!r}. ",
                    hint=
                    f"Available measurements: {', '.join(self.measurements)}",
                ))

        FileWrite().create_thumbnail_singleband(
            image_path,
            thumb_path,
            bit,
            lookup_table,
        )

        self._document_thumbnail(thumb_path, kind)
Exemplo n.º 7
0
    def write_thumbnail(
        self,
        red: str,
        green: str,
        blue: str,
        resampling: Resampling = Resampling.average,
        static_stretch: Tuple[int, int] = None,
        percentile_stretch: Tuple[int, int] = (2, 98),
        scale_factor: int = 10,
        kind: str = None,
    ):
        """
        Write a thumbnail for the dataset using the given measurements (specified by name) as r/g/b.

        (the measurements must already have been written.)

        A linear stretch is performed on the colour. By default this is a dynamic 2% stretch
        (the 2% and 98% percentile values of the input). The static_stretch parameter will
        override this with a static range of values.


        :param red: Name of measurement to put in red band
        :param green: Name of measurement to put in green band
        :param blue: Name of measurement to put in blue band
        :param kind: If you have multiple thumbnails, you can specify the 'kind' name to distinguish
                     them (it will be put in the filename).
                     Eg. GA's ARD has two thumbnails, one of kind ``nbar`` and one of ``nbart``.
        :param scale_factor: How many multiples smaller to make the thumbnail.
        :param percentile_stretch: Upper/lower percentiles to stretch by
        :param resampling: rasterio :class:`rasterio.enums.Resampling` method to use.
        :param static_stretch: Use a static upper/lower value to stretch by instead of dynamic stretch.
        """
        thumb_path = self.names.thumbnail_name(self._work_path, kind=kind)
        measurements = dict(
            (name, (grid, path)) for grid, name, path in self._measurements.iter_paths()
        )

        missing_measurements = {red, green, blue} - set(measurements)
        if missing_measurements:
            raise IncompleteDatasetError(
                ValidationMessage(
                    Level.error,
                    "missing_thumb_measurements",
                    f"Thumbnail measurements are missing: no measurements called {missing_measurements!r}. ",
                    hint=f"Available measurements: {', '.join(measurements)}",
                )
            )
        rgbs = [measurements[b] for b in (red, green, blue)]
        unique_grids: List[GridSpec] = list(set(grid for grid, path in rgbs))
        if len(unique_grids) != 1:
            raise NotImplementedError(
                "Thumbnails can only currently be created from measurements of the same grid spec."
            )
        grid = unique_grids[0]

        FileWrite().create_thumbnail(
            tuple(path for grid, path in rgbs),
            thumb_path,
            out_scale=scale_factor,
            resampling=resampling,
            static_stretch=static_stretch,
            percentile_stretch=percentile_stretch,
            input_geobox=grid,
        )
        self._checksum.add_file(thumb_path)

        accessory_name = "thumbnail"
        if kind:
            accessory_name += f":{kind}"
        self.add_accessory_file(accessory_name, thumb_path)