|
2 | 2 |
|
3 | 3 | from dataclasses import dataclass, field |
4 | 4 | from functools import cached_property |
5 | | -from typing import TYPE_CHECKING, Literal, Self |
| 5 | +from typing import TYPE_CHECKING, Self |
6 | 6 |
|
7 | 7 | from affine import Affine |
8 | 8 | from async_tiff import TIFF |
9 | 9 | from async_tiff.enums import PhotometricInterpretation |
10 | 10 |
|
11 | 11 | from async_geotiff._crs import crs_from_geo_keys |
12 | 12 | from async_geotiff._overview import Overview |
| 13 | +from async_geotiff._transform import TransformMixin |
13 | 14 | from async_geotiff.enums import Compression, Interleaving |
14 | 15 |
|
15 | 16 | if TYPE_CHECKING: |
16 | | - from collections.abc import Callable |
17 | | - |
18 | 17 | import pyproj |
19 | 18 | from async_tiff import GeoKeyDirectory, ImageFileDirectory, ObspecInput |
20 | 19 | from async_tiff.store import ObjectStore # type: ignore # noqa: PGH003 |
21 | 20 |
|
22 | 21 |
|
23 | 22 | @dataclass(frozen=True, init=False, kw_only=True, repr=False) |
24 | | -class GeoTIFF: |
| 23 | +class GeoTIFF(TransformMixin): |
25 | 24 | """A class representing a GeoTIFF image.""" |
26 | 25 |
|
27 | 26 | _tiff: TIFF |
@@ -222,27 +221,6 @@ def height(self) -> int: |
222 | 221 | """The height (number of rows) of the full image.""" |
223 | 222 | return self._primary_ifd.image_height |
224 | 223 |
|
225 | | - def index( |
226 | | - self, |
227 | | - x: float, |
228 | | - y: float, |
229 | | - op: Callable[[float, float], tuple[int, int]] | None = None, |
230 | | - ) -> tuple[int, int]: |
231 | | - """Get the (row, col) index of the pixel containing (x, y). |
232 | | -
|
233 | | - Args: |
234 | | - x: x value in coordinate reference system |
235 | | - y: y value in coordinate reference system |
236 | | - op: function, optional (default: numpy.floor) |
237 | | - Function to convert fractional pixels to whole numbers |
238 | | - (floor, ceiling, round) |
239 | | -
|
240 | | - Returns: |
241 | | - (row index, col index) |
242 | | -
|
243 | | - """ |
244 | | - raise NotImplementedError |
245 | | - |
246 | 224 | def indexes(self) -> list[int]: |
247 | 225 | """Return the 1-based indexes of each band in the dataset. |
248 | 226 |
|
@@ -283,7 +261,7 @@ def photometric(self) -> PhotometricInterpretation | None: |
283 | 261 | # https://rasterio.readthedocs.io/en/stable/api/rasterio.enums.html#rasterio.enums.PhotometricInterp |
284 | 262 | raise NotImplementedError |
285 | 263 |
|
286 | | - @cached_property |
| 264 | + @property |
287 | 265 | def res(self) -> tuple[float, float]: |
288 | 266 | """Return the (width, height) of pixels in the units of its CRS.""" |
289 | 267 | transform = self.transform |
@@ -344,46 +322,6 @@ def width(self) -> int: |
344 | 322 | """The width (number of columns) of the full image.""" |
345 | 323 | return self._primary_ifd.image_width |
346 | 324 |
|
347 | | - def xy( |
348 | | - self, |
349 | | - row: int, |
350 | | - col: int, |
351 | | - offset: Literal["center", "ul", "ur", "ll", "lr"] | str = "center", |
352 | | - ) -> tuple[float, float]: |
353 | | - """Get the coordinates x, y of a pixel at row, col. |
354 | | -
|
355 | | - The pixel's center is returned by default, but a corner can be returned |
356 | | - by setting `offset` to one of `"ul"`, `"ur"`, `"ll"`, `"lr"`. |
357 | | -
|
358 | | - Args: |
359 | | - row: Pixel row. |
360 | | - col: Pixel column. |
361 | | - offset: Determines if the returned coordinates are for the center of the |
362 | | - pixel or for a corner. |
363 | | -
|
364 | | - """ |
365 | | - transform = self.transform |
366 | | - |
367 | | - if offset == "center": |
368 | | - c = col + 0.5 |
369 | | - r = row + 0.5 |
370 | | - elif offset == "ul": |
371 | | - c = col |
372 | | - r = row |
373 | | - elif offset == "ur": |
374 | | - c = col + 1 |
375 | | - r = row |
376 | | - elif offset == "ll": |
377 | | - c = col |
378 | | - r = row + 1 |
379 | | - elif offset == "lr": |
380 | | - c = col + 1 |
381 | | - r = row + 1 |
382 | | - else: |
383 | | - raise ValueError(f"Invalid offset value: {offset}") |
384 | | - |
385 | | - return transform * (c, r) |
386 | | - |
387 | 325 |
|
388 | 326 | def has_geokeys(ifd: ImageFileDirectory) -> bool: |
389 | 327 | """Check if an IFD has GeoTIFF keys. |
|
0 commit comments