Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.tile() is not masking region outside of image when nodata used #675

Closed
banesullivan opened this issue Feb 10, 2024 · 3 comments
Closed

Comments

@banesullivan
Copy link

banesullivan commented Feb 10, 2024

I'm not sure if this is a usage issue on my part or a bug, but I'm noticing that the .tile() method sometimes doesn't mask the output image when the tile extends beyond the extent of the source dataset.

All looks good for tile x=82, y=198, z=9 when not specifying nodata:

from rio_tiler.io import Reader

class PNG(bytes):
    def _repr_png_(self):
        return self

reader = Reader('https://github.com/giswqs/data/raw/main/raster/landsat7.tif')
img = reader.tile(82, 198, 9, nodata=0)
PNG(img.render(img_format="png"))

303823332-8cef848e-0636-40fe-9379-5d5649a98531

But then when I specify nodata it seems the returned image is no longer masked outside the bounds:

img = reader.tile(82, 198, 9, nodata=-1)
PNG(img.render(img_format="png"))

303823335-c0f1fb82-cd6e-4614-8687-054ac1b1d095


Originally posted in banesullivan/localtileserver#197

@vincentsarago
Copy link
Member

@banesullivan interesting this is related to #669 where we removed WarpedVRT for nodata handling.

We know use simple rasterio.read method

data = dataset.read(
indexes=indexes,
window=window,
out_shape=(len(indexes), height, width) if height and width else None,
resampling=io_resampling,
boundless=boundless,
masked=True,
fill_value=nodata,
)
# if data has Nodata then we simply make sure the mask == the nodata
if nodata is not None:
data.mask = data.data == nodata

There might be a bug in rasterio when using boundless=True and fill_value=nodata

https://github.com/rasterio/rasterio/blob/main/rasterio/_io.pyx#L680-L735

@vincentsarago
Copy link
Member

vincentsarago commented Feb 13, 2024

import rasterio

with rasterio.open("tests/fixtures/cog.tif") as src_dst:
    arr = src_dst.read(
        masked=True, 
        fill_value=-1, 
        window=((-100,200), (-100,200)), 
        boundless=True,
)
    
print(arr.data)

>> [[[0 0 0 ... 0 0 0]
  [0 0 0 ... 0 0 0]
  [0 0 0 ... 0 0 0]
  ...
  [0 0 0 ... 1 1 1]
  [0 0 0 ... 1 1 1]
  [0 0 0 ... 1 1 1]]]

I would expect the outside to be -1 instead of 0

Interestingly the mask from rasterio is good

print(arr.mask)


>> [[[ True  True  True ...  True  True  True]
  [ True  True  True ...  True  True  True]
  [ True  True  True ...  True  True  True]
  ...
  [ True  True  True ... False False False]
  [ True  True  True ... False False False]
  [ True  True  True ... False False False]]]

but we override it in

data.mask = data.data == nodata
😓

@vincentsarago
Copy link
Member

😅 well the issue is that you're trying to use -1 as nodata value for a dataset which is of type uint8.

from rio_tiler.io import Reader
from matplotlib.pyplot import imshow
with Reader('https://github.com/giswqs/data/raw/main/raster/landsat7.tif') as reader:
    img = reader.tile(82, 198, 9, nodata=100)

imshow(img.mask)
Screenshot 2024-02-13 at 5 29 08 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants