Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/async_geotiff/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from ._geotiff import GeoTIFF
from ._overview import Overview
from ._version import __version__

__all__ = ["GeoTIFF", "__version__"]
__all__ = ["GeoTIFF", "Overview", "__version__"]
15 changes: 14 additions & 1 deletion src/async_geotiff/_geotiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from affine import Affine
from async_tiff import TIFF

from async_geotiff._overview import Overview
from async_geotiff.enums import Compression, Interleaving, PhotometricInterp

if TYPE_CHECKING:
Expand All @@ -15,7 +16,7 @@


class GeoTIFF:
"""A class representing a GeoTIFF dataset."""
"""A class representing a GeoTIFF image."""

_tiff: TIFF
"""The underlying async-tiff TIFF instance that we wrap.
Expand All @@ -31,6 +32,10 @@ class GeoTIFF:
"""The GeoKeyDirectory of the primary IFD.
"""

_overviews: list[Overview]
"""A list of overviews for the GeoTIFF.
"""

def __init__(self, tiff: TIFF) -> None:
"""Create a GeoTIFF from an existing TIFF instance."""

Expand All @@ -48,6 +53,9 @@ def __init__(self, tiff: TIFF) -> None:
self._primary_ifd = first_ifd
self._gkd = gkd

# TODO: populate overviews
self._overviews = []

@classmethod
async def open(
cls,
Expand Down Expand Up @@ -214,6 +222,11 @@ def nodata(self) -> float | None:

return float(nodata)

@property
def overviews(self) -> list[Overview]:
"""A list of overview levels for the dataset."""
return self._overviews

@property
def photometric(self) -> PhotometricInterp | None:
"""The photometric interpretation of the dataset."""
Expand Down
71 changes: 71 additions & 0 deletions src/async_geotiff/_overview.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from __future__ import annotations

from functools import cached_property
from typing import TYPE_CHECKING, Literal, Self

from affine import Affine
from async_tiff import TIFF

from async_geotiff.enums import Compression, Interleaving, PhotometricInterp

if TYPE_CHECKING:
from async_tiff import GeoKeyDirectory, ImageFileDirectory

from async_geotiff import GeoTIFF


class Overview:
"""An overview level of a Cloud-Optimized GeoTIFF image."""

_geotiff: GeoTIFF
"""A reference to the parent GeoTIFF object.
"""

_gkd: GeoKeyDirectory
"""The GeoKeyDirectory of the primary IFD.
"""

_ifd: ImageFileDirectory
"""The IFD for this overview level.
"""

_mask_ifd: ImageFileDirectory | None
"""The IFD for the mask associated with this overview level, if any.
"""

_overview_idx: int
"""The overview level (0 is the full resolution image, 1 is the first overview, etc).
"""

def __init__(
self,
geotiff: GeoTIFF,
gkd: GeoKeyDirectory,
ifd: ImageFileDirectory,
mask_ifd: ImageFileDirectory | None,
overview_idx: int,
) -> None:
self._geotiff = geotiff
self._gkd = gkd
self._ifd = ifd
self._mask_ifd = mask_ifd
self._overview_idx = overview_idx

@cached_property
def transform(self) -> Affine:
"""The affine transform mapping pixel coordinates to geographic coordinates.

Returns:
Affine: The affine transform.
"""
full_transform = self._geotiff.transform

overview_width = self._ifd.image_width
full_width = self._geotiff.width
overview_height = self._ifd.image_height
full_height = self._geotiff.height

scale_x = full_width / overview_width
scale_y = full_height / overview_height

return full_transform * Affine.scale(scale_x, scale_y)
Loading