Skip to content

Conversation

@kylebarron
Copy link
Member

@kylebarron kylebarron commented Jan 28, 2026

Change list

  • Implements fetch_tile and fetch_tiles on the GeoTIFF class (for fetching full-resolution tiles) and on the Overview class (for fetching reduced-resolution tiles)
    • This API does not let users multiplex tile requests at the Rust level between two different overview resolutions. This essentially just means there won't be tile request coalescing between tiles of different resolutions. But of course the Python user can still use asyncio.gather on multiple Python async requests.
    • This simplifies the APIs; fetch_tile has the same signature on both GeoTIFF and on Overview.
  • Creates a new Array class. The Array holds numpy arrays for the data (and possibly also for the mask). It also holds the per-tile affine transform, a reference to the image's CRS, and height and width.

TODO:

  • tests for equality against Rasterio
  • Test currently fails because of inconsistent axis ordering. We should ensure we return array with rasterio band ordering.

cc @geospatial-jeff

@kylebarron kylebarron changed the title feat: Fetch tile data from GeoTIFF overview feat: Fetch tile data from GeoTIFF/Overview Jan 28, 2026

# Check if the primary IFD has a mask
if len(tiff.ifds) >= 2 and is_mask_ifd(tiff.ifds[ifd_idx]): # noqa: PLR2004
object.__setattr__(self, "_mask_ifd", tiff.ifds[ifd_idx])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully remember the COG architecture, but I think at one point the Mask where stored after all the image IFD (at least when not using the COG driver)

Does async-geotiff read the ghost header https://gdal.org/en/stable/drivers/raster/cog.html#header-ghost-area ?

also might specify in the library that we don't support external overview/mask 🤷

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah. I just assumed it would always be data/mask/overview/mask overview.

No, we don't currently read the ghost header. @geospatial-jeff suggested not to in developmentseed/async-tiff#7. I think we might want to allow injecting support for it. In theory that might be something we could inject.

I think in the future, supporting external overview/mask would be possible, but no, not right now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In 8f02864 (this PR) I implemented a cleaner association of data ifds to masks:

  • First create dicts mapping from (image height, image width): (ifd index, ifd):

     data_ifds: dict[tuple[int, int], tuple[int, ImageFileDirectory]] = {}
     mask_ifds: dict[tuple[int, int], tuple[int, ImageFileDirectory]] = {}
  • Then iterate over the data ifds from largest to smallest. If there's a mask IFD of the same height and width, then associate the mask IFD with that data IFD.

@kylebarron kylebarron merged commit 98ae83b into main Jan 29, 2026
5 checks passed
@kylebarron kylebarron deleted the kyle/fetch-tiles branch January 29, 2026 17:20
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

Successfully merging this pull request may close these issues.

3 participants