Esempio n. 1
0
def _img(
    mosaicid: str = None,
    z: int = None,
    x: int = None,
    y: int = None,
    scale: int = 1,
    ext: str = None,
    url: str = None,
    pixel_selection: str = "first",
    resampling_method: str = "nearest",
) -> Tuple:
    """Handle tile requests."""
    if not mosaicid and not url:
        return ("NOK", "text/plain", "Missing 'MosaicID or URL' parameter")

    mosaic_path = _create_mosaic_path(mosaicid) if mosaicid else url
    with MosaicBackend(mosaic_path) as mosaic:
        assets = mosaic.tile(x, y, z)
        if not assets:
            return ("EMPTY", "text/plain", f"No assets found for tile {z}-{x}-{y}")

    tilesize = 256 * scale

    if pixel_selection == "last":
        pixel_selection = "first"
        assets = list(reversed(assets))

    with rasterio.Env(aws_session):
        pixsel_method = PIXSEL_METHODS[pixel_selection]
        tile, mask = mosaic_tiler(
            assets,
            x,
            y,
            z,
            usgs_tiler,
            tilesize=tilesize,
            pixel_selection=pixsel_method(),
            resampling_method=resampling_method,
        )

    if tile is None:
        return ("EMPTY", "text/plain", "empty tiles")

    if not ext:
        ext = "jpg" if mask.all() else "png"

    driver = "jpeg" if ext == "jpg" else ext
    options = img_profiles.get(driver, {})

    if ext == "tif":
        ext = "tiff"
        driver = "GTiff"
        options = geotiff_options(x, y, z, tilesize)

    return (
        "OK",
        f"image/{ext}",
        render(tile, mask, img_format=driver, **options),
    )
Esempio n. 2
0
def _img(
    z: int = None,
    x: int = None,
    y: int = None,
    tile_size: Union[str, int] = 256,
    ext: str = 'png',
    url: str = None,
    encoding: str = 'terrarium',
    pixel_selection: str = "first",
    resampling_method: str = "nearest",
) -> Tuple:
    """Handle tile requests."""
    if not url:
        return ("NOK", "text/plain", "Missing URL parameter")

    tile_size = int(tile_size)
    assets = find_assets(x, y, z, url, tile_size)

    if assets is None:
        return ("NOK", "text/plain", "no assets found")

    rgb = load_assets(x,
                      y,
                      z,
                      assets,
                      tile_size,
                      input_format=url,
                      output_format=encoding,
                      pixel_selection=pixel_selection,
                      resampling_method=resampling_method)

    if rgb is None:
        return ("EMPTY", "text/plain", "empty tiles")

    driver = ext
    options = img_profiles.get(driver, {})

    if ext == "tif":
        ext = "tiff"
        driver = "GTiff"
        options = geotiff_options(x, y, z, tile_size)

    return (
        "OK",
        f"image/{ext}",
        render(rgb, img_format=driver, **options),
    )
Esempio n. 3
0
def test_render_geotiff():
    """Creates GeoTIFF image buffer from 3 bands array."""
    arr = np.random.randint(0, 255, size=(3, 512, 512), dtype=np.uint8)
    mask = np.zeros((512, 512), dtype=np.uint8) + 255
    ops = utils.geotiff_options(1, 0, 0)
    assert utils.render(arr, mask=mask, img_format="GTiff", **ops)
Esempio n. 4
0
async def tile(
        z: int = Path(...,
                      ge=0,
                      le=30,
                      description="Mercator tiles's zoom level"),
        x: int = Path(..., description="Mercator tiles's column"),
        y: int = Path(..., description="Mercator tiles's row"),
        scale: int = Query(
            1,
            gt=0,
            lt=4,
            description="Tile size scale. 1=256x256, 2=512x512..."),
        ext: ImageType = Query(
            None, description="Output image type. Default is auto."),
        url: str = Query(..., description="Cloud Optimized GeoTIFF URL."),
        bidx: Optional[str] = Query(
            None, description="Coma (',') delimited band indexes"),
        nodata: Optional[Union[str, int, float]] = Query(
            None, description="Overwrite internal Nodata value."),
        rescale: Optional[str] = Query(
            None, description="Coma (',') delimited Min,Max bounds"),
        color_formula: Optional[str] = Query(None, title="rio-color formula"),
        color_map: Optional[utils.ColorMapName] = Query(
            None, title="rio-tiler color map name"),
        cache_client: CacheLayer = Depends(utils.get_cache),
) -> TileResponse:
    """Handle /tiles requests."""
    timings = []
    headers: Dict[str, str] = {}

    tile_hash = utils.get_hash(**dict(
        z=z,
        x=x,
        y=y,
        ext=ext,
        scale=scale,
        url=url,
        bidx=bidx,
        nodata=nodata,
        rescale=rescale,
        color_formula=color_formula,
        color_map=color_map.value if color_map else "",
    ))
    tilesize = scale * 256

    content = None
    if cache_client:
        try:
            content, ext = cache_client.get_image_from_cache(tile_hash)
            headers["X-Cache"] = "HIT"
        except Exception:
            content = None

    if not content:
        indexes = tuple(int(s)
                        for s in re.findall(r"\d+", bidx)) if bidx else None

        if nodata is not None:
            nodata = numpy.nan if nodata == "nan" else float(nodata)

        with utils.Timer() as t:
            tile, mask = await _tile(url,
                                     x,
                                     y,
                                     z,
                                     indexes=indexes,
                                     tilesize=tilesize,
                                     nodata=nodata)
        timings.append(("Read", t.elapsed))

        if not ext:
            ext = ImageType.jpg if mask.all() else ImageType.png

        with utils.Timer() as t:
            tile = await _postprocess(tile,
                                      mask,
                                      rescale=rescale,
                                      color_formula=color_formula)
        timings.append(("Post-process", t.elapsed))

        if color_map:
            if color_map.value.startswith("custom_"):
                color_map = utils.get_custom_cmap(
                    color_map.value)  # type: ignore
            else:
                color_map = get_colormap(color_map.value)  # type: ignore

        with utils.Timer() as t:
            if ext == ImageType.npy:
                sio = BytesIO()
                numpy.save(sio, (tile, mask))
                sio.seek(0)
                content = sio.getvalue()
            else:
                driver = drivers[ext.value]
                options = img_profiles.get(driver.lower(), {})
                if ext == ImageType.tif:
                    options = geotiff_options(x, y, z, tilesize=tilesize)

                content = await _render(tile,
                                        mask,
                                        img_format=driver,
                                        colormap=color_map,
                                        **options)

        timings.append(("Format", t.elapsed))

        if cache_client and content:
            cache_client.set_image_cache(tile_hash, (content, ext))

    if timings:
        headers["X-Server-Timings"] = "; ".join([
            "{} - {:0.2f}".format(name, time * 1000)
            for (name, time) in timings
        ])

    return TileResponse(content,
                        media_type=mimetype[ext.value],
                        headers=headers)
Esempio n. 5
0
def _img(
    mosaicid: str = None,
    z: int = None,
    x: int = None,
    y: int = None,
    scale: int = 1,
    ext: str = None,
    url: str = None,
    indexes: Optional[Sequence[int]] = None,
    rescale: str = None,
    color_ops: str = None,
    color_map: str = None,
    pixel_selection: str = "first",
    resampling_method: str = "nearest",
) -> Tuple:
    """Handle tile requests."""
    if not mosaicid and not url:
        return ("NOK", "text/plain", "Missing 'MosaicID or URL' parameter")

    mosaic_path = _create_mosaic_path(mosaicid) if mosaicid else url
    with MosaicBackend(mosaic_path) as mosaic:
        assets = mosaic.tile(x, y, z)
        if not assets:
            return ("EMPTY", "text/plain", f"No assets found for tile {z}-{x}-{y}")

    if indexes is not None and isinstance(indexes, str):
        indexes = list(map(int, indexes.split(",")))

    tilesize = 256 * scale

    if pixel_selection == "last":
        pixel_selection = "first"
        assets = list(reversed(assets))

    with rasterio.Env(aws_session):
        pixsel_method = PIXSEL_METHODS[pixel_selection]
        tile, mask = mosaic_tiler(
            assets,
            x,
            y,
            z,
            cogeoTiler,
            indexes=indexes,
            tilesize=tilesize,
            pixel_selection=pixsel_method(),
            resampling_method=resampling_method,
        )

    if tile is None:
        return ("EMPTY", "text/plain", "empty tiles")

    rtile = _postprocess(tile, mask, rescale=rescale, color_formula=color_ops)

    if not ext:
        ext = "jpg" if mask.all() else "png"

    driver = "jpeg" if ext == "jpg" else ext
    options = img_profiles.get(driver, {})

    if ext == "tif":
        ext = "tiff"
        driver = "GTiff"
        options = geotiff_options(x, y, z, tilesize)

    if color_map:
        options["colormap"] = cmap.get(color_map)

    return (
        "OK",
        f"image/{ext}",
        render(rtile, mask, img_format=driver, **options),
    )
Esempio n. 6
0
def _tile(
    z: int,
    x: int,
    y: int,
    scale: int = 1,
    ext: str = None,
    url: str = None,
    indexes: Optional[Union[str, Tuple]] = None,
    expr: Optional[str] = None,
    nodata: Optional[Union[str, int, float]] = None,
    rescale: Optional[str] = None,
    color_formula: Optional[str] = None,
    color_map: Optional[str] = None,
    resampling_method: str = "bilinear",
    **kwargs,
) -> Tuple[str, str, bytes]:
    """Handle /tiles requests."""
    if indexes and expr:
        raise TilerError("Cannot pass indexes and expression")

    if not url:
        raise TilerError("Missing 'url' parameter")

    if nodata is not None:
        nodata = numpy.nan if nodata == "nan" else float(nodata)

    tilesize = scale * 256

    if isinstance(indexes, str):
        indexes = tuple(map(int, indexes.split(",")))

    with rasterio.Env(aws_session):
        with COGReader(url) as cog:
            tile, mask = cog.tile(
                x,
                y,
                z,
                tilesize=tilesize,
                indexes=indexes,
                expression=expr,
                nodata=nodata,
                resampling_method=resampling_method,
                **kwargs,
            )
            color_map = cmap.get(color_map) if color_map else cog.colormap

    if not ext:
        ext = "jpg" if mask.all() else "png"

    tile = utils.postprocess(tile, mask, rescale=rescale, color_formula=color_formula)

    if ext == "npy":
        sio = io.BytesIO()
        numpy.save(sio, (tile, mask))
        sio.seek(0)
        content = sio.getvalue()
    else:
        driver = drivers[ext]
        options = img_profiles.get(driver.lower(), {})

        if ext == "tif":
            options = geotiff_options(x, y, z, tilesize=tilesize)

        if color_map:
            options["colormap"] = color_map

        content = render(tile, mask, img_format=driver, **options)

    return ("OK", mimetype[ext], content)