async-tiff 0.5.0b2__cp311-abi3-musllinux_1_2_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
async_tiff/__init__.py ADDED
@@ -0,0 +1,31 @@
1
+ from . import enums, store
2
+ from ._async_tiff import (
3
+ TIFF,
4
+ Array,
5
+ Colormap,
6
+ DecoderRegistry,
7
+ GeoKeyDirectory,
8
+ ImageFileDirectory,
9
+ ThreadPool,
10
+ Tile,
11
+ ___version, # noqa: F403 # pyright:ignore[reportAttributeAccessIssue]
12
+ )
13
+ from ._decoder_runtime import Decoder
14
+ from ._input import ObspecInput
15
+
16
+ __version__: str = ___version()
17
+
18
+ __all__ = [
19
+ "enums",
20
+ "store",
21
+ "Array",
22
+ "Colormap",
23
+ "Decoder",
24
+ "DecoderRegistry",
25
+ "GeoKeyDirectory",
26
+ "ImageFileDirectory",
27
+ "ThreadPool",
28
+ "TIFF",
29
+ "ObspecInput",
30
+ "Tile",
31
+ ]
async_tiff/_array.pyi ADDED
@@ -0,0 +1,45 @@
1
+ import sys
2
+
3
+ if sys.version_info >= (3, 12):
4
+ from collections.abc import Buffer
5
+ else:
6
+ from typing_extensions import Buffer
7
+
8
+ class Array(Buffer):
9
+ """A 3D array that implements Python's buffer protocol.
10
+
11
+ This allows zero-copy interoperability with numpy via `np.asarray(arr)`.
12
+ The array is immutable and exposes a read-only buffer.
13
+
14
+ Example:
15
+
16
+ ```python
17
+ import numpy as np
18
+ from async_tiff import Array
19
+
20
+ # Create from raw bytes
21
+ data = bytes([1, 2, 3, 4, 5, 6])
22
+ arr = Array(data, shape=(1, 2, 3), format="<B") # 1x2x3 uint8 array
23
+
24
+ # Convert to numpy (zero-copy view)
25
+ np_arr = np.asarray(arr)
26
+ assert np_arr.shape == (1, 2, 3)
27
+ assert np_arr.dtype == np.uint8
28
+ ```
29
+ """
30
+
31
+ # This is intended only for tests
32
+ # def __init__(
33
+ # self, data: Buffer, shape: tuple[int, int, int], format: str
34
+ # ) -> None: ...
35
+ def __buffer__(self, flags: int) -> memoryview[int]: ...
36
+ @property
37
+ def shape(self) -> tuple[int, int, int]:
38
+ """The shape of the array.
39
+
40
+ The interpretation depends on the PlanarConfiguration:
41
+
42
+ - PlanarConfiguration=1 (chunky): (height, width, bands)
43
+ - PlanarConfiguration=2 (planar): (bands, height, width)
44
+ """
45
+ ...
Binary file
@@ -0,0 +1,19 @@
1
+ from ._array import Array
2
+ from ._colormap import Colormap
3
+ from ._decoder import DecoderRegistry
4
+ from ._geo import GeoKeyDirectory
5
+ from ._ifd import ImageFileDirectory
6
+ from ._thread_pool import ThreadPool
7
+ from ._tiff import TIFF
8
+ from ._tile import Tile
9
+
10
+ __all__ = [
11
+ "Array",
12
+ "Colormap",
13
+ "DecoderRegistry",
14
+ "GeoKeyDirectory",
15
+ "ImageFileDirectory",
16
+ "ThreadPool",
17
+ "TIFF",
18
+ "Tile",
19
+ ]
@@ -0,0 +1,14 @@
1
+ import sys
2
+
3
+ if sys.version_info >= (3, 12):
4
+ from collections.abc import Buffer
5
+ else:
6
+ from typing_extensions import Buffer
7
+
8
+ class Colormap(Buffer):
9
+ """A 1D array of u16 values representing a TIFF colormap.
10
+
11
+ Implements Python's buffer protocol for zero-copy access via `np.asarray()`.
12
+ """
13
+ def __buffer__(self, flags: int) -> memoryview[int]: ...
14
+ def __len__(self) -> int: ...
@@ -0,0 +1,19 @@
1
+ from ._decoder_runtime import Decoder
2
+ from .enums import Compression
3
+
4
+ class DecoderRegistry:
5
+ """A registry holding multiple decoder methods."""
6
+ def __init__(
7
+ self, custom_decoders: dict[Compression | int, Decoder] | None = None
8
+ ) -> None:
9
+ """Construct a new decoder registry.
10
+
11
+ By default, pure-Rust decoders will be used for any recognized and supported
12
+ compression types. Only the supplied decoders will override Rust-native
13
+ decoders.
14
+
15
+ Args:
16
+ custom_decoders: any custom decoder methods to use. This will be applied
17
+ _after_ (and override) any default provided Rust decoders. Defaults to
18
+ None.
19
+ """
@@ -0,0 +1,21 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import TYPE_CHECKING, Protocol
5
+
6
+ if TYPE_CHECKING:
7
+ if sys.version_info >= (3, 12):
8
+ from collections.abc import Buffer
9
+ else:
10
+ from typing_extensions import Buffer
11
+
12
+
13
+ class Decoder(Protocol):
14
+ """A custom Python-provided decompression algorithm."""
15
+
16
+ # In the future, we could pass in photometric interpretation and jpeg tables as
17
+ # well.
18
+ @staticmethod
19
+ def __call__(buffer: Buffer) -> Buffer:
20
+ """A callback to decode compressed data."""
21
+ ...
async_tiff/_geo.pyi ADDED
@@ -0,0 +1,102 @@
1
+ from collections.abc import Iterable
2
+ from typing import Any
3
+
4
+ class GeoKeyDirectory:
5
+ def keys(self) -> list[str]:
6
+ """A list of string keys representing the GeoKey fields."""
7
+ def __eq__(self, value: object) -> bool: ...
8
+ def __iter__(self) -> Iterable[str]:
9
+ """An iterable of string keys representing the GeoKey fields."""
10
+ def __getitem__(self, key: str) -> Any:
11
+ """Access GeoKey fields by string key."""
12
+
13
+ @property
14
+ def model_type(self) -> int | None: ...
15
+ @property
16
+ def raster_type(self) -> int | None: ...
17
+ @property
18
+ def citation(self) -> str | None: ...
19
+ @property
20
+ def geographic_type(self) -> int | None: ...
21
+ @property
22
+ def geog_citation(self) -> str | None: ...
23
+ @property
24
+ def geog_geodetic_datum(self) -> int | None: ...
25
+ @property
26
+ def geog_prime_meridian(self) -> int | None: ...
27
+ @property
28
+ def geog_linear_units(self) -> int | None: ...
29
+ @property
30
+ def geog_linear_unit_size(self) -> float | None: ...
31
+ @property
32
+ def geog_angular_units(self) -> int | None: ...
33
+ @property
34
+ def geog_angular_unit_size(self) -> float | None: ...
35
+ @property
36
+ def geog_ellipsoid(self) -> int | None: ...
37
+ @property
38
+ def geog_semi_major_axis(self) -> float | None: ...
39
+ @property
40
+ def geog_semi_minor_axis(self) -> float | None: ...
41
+ @property
42
+ def geog_inv_flattening(self) -> float | None: ...
43
+ @property
44
+ def geog_azimuth_units(self) -> int | None: ...
45
+ @property
46
+ def geog_prime_meridian_long(self) -> float | None: ...
47
+ @property
48
+ def projected_type(self) -> int | None: ...
49
+ @property
50
+ def proj_citation(self) -> str | None: ...
51
+ @property
52
+ def projection(self) -> int | None: ...
53
+ @property
54
+ def proj_coord_trans(self) -> int | None: ...
55
+ @property
56
+ def proj_linear_units(self) -> int | None: ...
57
+ @property
58
+ def proj_linear_unit_size(self) -> float | None: ...
59
+ @property
60
+ def proj_std_parallel1(self) -> float | None: ...
61
+ @property
62
+ def proj_std_parallel2(self) -> float | None: ...
63
+ @property
64
+ def proj_nat_origin_long(self) -> float | None: ...
65
+ @property
66
+ def proj_nat_origin_lat(self) -> float | None: ...
67
+ @property
68
+ def proj_false_easting(self) -> float | None: ...
69
+ @property
70
+ def proj_false_northing(self) -> float | None: ...
71
+ @property
72
+ def proj_false_origin_long(self) -> float | None: ...
73
+ @property
74
+ def proj_false_origin_lat(self) -> float | None: ...
75
+ @property
76
+ def proj_false_origin_easting(self) -> float | None: ...
77
+ @property
78
+ def proj_false_origin_northing(self) -> float | None: ...
79
+ @property
80
+ def proj_center_long(self) -> float | None: ...
81
+ @property
82
+ def proj_center_lat(self) -> float | None: ...
83
+ @property
84
+ def proj_center_easting(self) -> float | None: ...
85
+ @property
86
+ def proj_center_northing(self) -> float | None: ...
87
+ @property
88
+ def proj_scale_at_nat_origin(self) -> float | None: ...
89
+ @property
90
+ def proj_scale_at_center(self) -> float | None: ...
91
+ @property
92
+ def proj_azimuth_angle(self) -> float | None: ...
93
+ @property
94
+ def proj_straight_vert_pole_long(self) -> float | None: ...
95
+ @property
96
+ def vertical(self) -> int | None: ...
97
+ @property
98
+ def vertical_citation(self) -> str | None: ...
99
+ @property
100
+ def vertical_datum(self) -> int | None: ...
101
+ @property
102
+ def vertical_units(self) -> int | None: ...
async_tiff/_ifd.pyi ADDED
@@ -0,0 +1,150 @@
1
+ from collections.abc import Iterable, Sequence
2
+ from typing import Any
3
+
4
+ from ._colormap import Colormap
5
+ from ._geo import GeoKeyDirectory
6
+ from ._tile import Tile
7
+ from .enums import (
8
+ Compression,
9
+ PhotometricInterpretation,
10
+ PlanarConfiguration,
11
+ Predictor,
12
+ ResolutionUnit,
13
+ SampleFormat,
14
+ )
15
+
16
+ Value = int | float | str | tuple[int, int] | list[Value]
17
+
18
+ class ImageFileDirectory:
19
+ def keys(self) -> list[str]:
20
+ """A list of string keys representing the IFD fields."""
21
+ def __eq__(self, value: object) -> bool: ...
22
+ def __iter__(self) -> Iterable[str]:
23
+ """An iterable of string keys representing the IFD fields."""
24
+ def __getitem__(self, key: str) -> Any:
25
+ """Access IFD fields by string key."""
26
+
27
+ @property
28
+ def new_subfile_type(self) -> int | None: ...
29
+ @property
30
+ def image_width(self) -> int:
31
+ """The number of columns in the image, i.e., the number of pixels per row."""
32
+
33
+ @property
34
+ def image_height(self) -> int:
35
+ """The number of rows of pixels in the image."""
36
+
37
+ @property
38
+ def bits_per_sample(self) -> list[int]: ...
39
+ @property
40
+ def compression(self) -> Compression | int:
41
+ """Access the compression tag.
42
+
43
+ An `int` will be returned if the compression is not one of the values in
44
+ `Compression`.
45
+ """
46
+ @property
47
+ def photometric_interpretation(self) -> PhotometricInterpretation: ...
48
+ @property
49
+ def document_name(self) -> str | None: ...
50
+ @property
51
+ def image_description(self) -> str | None: ...
52
+ @property
53
+ def strip_offsets(self) -> list[int] | None: ...
54
+ @property
55
+ def orientation(self) -> int | None: ...
56
+ @property
57
+ def samples_per_pixel(self) -> int:
58
+ """
59
+ The number of components per pixel.
60
+
61
+ SamplesPerPixel is usually 1 for bilevel, grayscale, and palette-color images.
62
+ SamplesPerPixel is usually 3 for RGB images. If this value is higher,
63
+ ExtraSamples should give an indication of the meaning of the additional
64
+ channels.
65
+ """
66
+
67
+ @property
68
+ def rows_per_strip(self) -> int | None: ...
69
+ @property
70
+ def strip_byte_counts(self) -> int | None: ...
71
+ @property
72
+ def min_sample_value(self) -> int | None: ...
73
+ @property
74
+ def max_sample_value(self) -> int | None: ...
75
+ @property
76
+ def x_resolution(self) -> float | None:
77
+ """The number of pixels per ResolutionUnit in the ImageWidth direction."""
78
+
79
+ @property
80
+ def y_resolution(self) -> float | None:
81
+ """The number of pixels per ResolutionUnit in the ImageLength direction."""
82
+
83
+ @property
84
+ def planar_configuration(self) -> PlanarConfiguration: ...
85
+ @property
86
+ def resolution_unit(self) -> ResolutionUnit | None: ...
87
+ @property
88
+ def software(self) -> str | None: ...
89
+ @property
90
+ def date_time(self) -> str | None: ...
91
+ @property
92
+ def artist(self) -> str | None: ...
93
+ @property
94
+ def host_computer(self) -> str | None: ...
95
+ @property
96
+ def predictor(self) -> Predictor | None: ...
97
+ @property
98
+ def tile_width(self) -> int | None: ...
99
+ @property
100
+ def tile_height(self) -> int | None: ...
101
+ @property
102
+ def tile_offsets(self) -> list[int] | None: ...
103
+ @property
104
+ def tile_byte_counts(self) -> list[int] | None: ...
105
+ @property
106
+ def extra_samples(self) -> list[int] | None: ...
107
+ @property
108
+ def sample_format(self) -> list[SampleFormat]: ...
109
+ @property
110
+ def jpeg_tables(self) -> bytes | None: ...
111
+ @property
112
+ def copyright(self) -> str | None: ...
113
+ @property
114
+ def geo_key_directory(self) -> GeoKeyDirectory | None: ...
115
+ @property
116
+ def model_pixel_scale(self) -> list[float] | None: ...
117
+ @property
118
+ def model_tiepoint(self) -> list[float] | None: ...
119
+ @property
120
+ def model_transformation(self) -> list[float] | None: ...
121
+ @property
122
+ def gdal_nodata(self) -> str | None: ...
123
+ @property
124
+ def gdal_metadata(self) -> str | None: ...
125
+ @property
126
+ def other_tags(self) -> dict[int, Value]: ...
127
+ @property
128
+ def colormap(self) -> Colormap | None:
129
+ """The colormap for palette-color images."""
130
+ ...
131
+ async def fetch_tile(self, x: int, y: int) -> Tile:
132
+ """Fetch a single tile.
133
+
134
+ Args:
135
+ x: The column index within the ifd to read from.
136
+ y: The row index within the ifd to read from.
137
+
138
+ Returns:
139
+ Tile response.
140
+ """
141
+ async def fetch_tiles(self, x: Sequence[int], y: Sequence[int]) -> list[Tile]:
142
+ """Fetch multiple tiles concurrently.
143
+
144
+ Args:
145
+ x: The column indexes within the ifd to read from.
146
+ y: The row indexes within the ifd to read from.
147
+
148
+ Returns:
149
+ Tile responses.
150
+ """
async_tiff/_input.py ADDED
@@ -0,0 +1,8 @@
1
+ from typing import Protocol
2
+
3
+ # Fix exports
4
+ from obspec._get import GetRangeAsync, GetRangesAsync
5
+
6
+
7
+ class ObspecInput(GetRangeAsync, GetRangesAsync, Protocol):
8
+ """Supported obspec input to reader."""
@@ -0,0 +1,4 @@
1
+ class ThreadPool:
2
+ """A Rust-managed thread pool."""
3
+ def __init__(self, num_threads: int) -> None:
4
+ """Construct a new ThreadPool with the given number of threads."""
async_tiff/_tiff.pyi ADDED
@@ -0,0 +1,78 @@
1
+ from typing import Sequence
2
+
3
+ from ._ifd import ImageFileDirectory
4
+ from ._input import ObspecInput
5
+ from ._tile import Tile
6
+ from .enums import Endianness
7
+ from .store import ObjectStore
8
+
9
+ class TIFF:
10
+ @classmethod
11
+ async def open(
12
+ cls,
13
+ path: str,
14
+ *,
15
+ store: ObjectStore | ObspecInput,
16
+ prefetch: int = 32768,
17
+ multiplier: int | float = 2.0,
18
+ ) -> TIFF:
19
+ """Open a new TIFF.
20
+
21
+ Args:
22
+ path: The path within the store to read from.
23
+ store: The backend to use for data fetching.
24
+ prefetch: The number of initial bytes to read up front.
25
+ multiplier: The multiplier to use for readahead size growth. Must be
26
+ greater than 1.0. For example, for a value of `2.0`, the first metadata
27
+ read will be of size `prefetch`, and then the next read will be of size
28
+ `prefetch * 2`.
29
+
30
+ Returns:
31
+ A TIFF instance.
32
+ """
33
+
34
+ @property
35
+ def endianness(self) -> Endianness:
36
+ """The endianness of this TIFF file."""
37
+
38
+ def ifd(self, index: int) -> ImageFileDirectory:
39
+ """Access a specific IFD by index.
40
+
41
+ Args:
42
+ index: The IFD index to access.
43
+
44
+ Returns:
45
+ The requested IFD.
46
+ """
47
+
48
+ @property
49
+ def ifds(self) -> list[ImageFileDirectory]:
50
+ """Access the underlying IFDs of this TIFF.
51
+
52
+ Each ImageFileDirectory (IFD) represents one of the internal "sub images" of
53
+ this file.
54
+ """
55
+ async def fetch_tile(self, x: int, y: int, z: int) -> Tile:
56
+ """Fetch a single tile.
57
+
58
+ Args:
59
+ x: The column index within the ifd to read from.
60
+ y: The row index within the ifd to read from.
61
+ z: The IFD index to read from.
62
+
63
+ Returns:
64
+ Tile response.
65
+ """
66
+ async def fetch_tiles(
67
+ self, x: Sequence[int], y: Sequence[int], z: int
68
+ ) -> list[Tile]:
69
+ """Fetch multiple tiles concurrently.
70
+
71
+ Args:
72
+ x: The column indexes within the ifd to read from.
73
+ y: The row indexes within the ifd to read from.
74
+ z: The IFD index to read from.
75
+
76
+ Returns:
77
+ Tile responses.
78
+ """
async_tiff/_tile.pyi ADDED
@@ -0,0 +1,58 @@
1
+ from collections.abc import Buffer
2
+
3
+ from ._array import Array
4
+ from ._decoder import DecoderRegistry
5
+ from ._thread_pool import ThreadPool
6
+ from .enums import Compression
7
+
8
+ class Tile:
9
+ """A representation of a TIFF image tile."""
10
+ @property
11
+ def x(self) -> int:
12
+ """The column index this tile represents."""
13
+ @property
14
+ def y(self) -> int:
15
+ """The row index this tile represents."""
16
+ @property
17
+ def compressed_bytes(self) -> Buffer:
18
+ """The compressed bytes underlying this tile."""
19
+ @property
20
+ def compression_method(self) -> Compression | int:
21
+ """The compression method used by this tile."""
22
+ def decode_sync(
23
+ self,
24
+ *,
25
+ decoder_registry: DecoderRegistry | None = None,
26
+ ) -> Array:
27
+ """Decode this tile's data.
28
+
29
+ **Note**: This is a blocking function and will perform the tile decompression on
30
+ the current thread. Prefer using the asynchronous `decode` method, which will
31
+ offload decompression to a thread pool.
32
+
33
+ Keyword Args:
34
+ decoder_registry: the decoders to use for decompression. Defaults to None, in which case a default decoder registry is used.
35
+
36
+ Returns:
37
+ Decoded tile data as an Array instance.
38
+ """
39
+
40
+ async def decode(
41
+ self,
42
+ *,
43
+ decoder_registry: DecoderRegistry | None = None,
44
+ pool: ThreadPool | None = None,
45
+ ) -> Array:
46
+ """Decode this tile's data.
47
+
48
+ This is an asynchronous function that will offload the tile decompression to a
49
+ thread pool.
50
+
51
+ Keyword Args:
52
+ decoder_registry: the decoders to use for decompression. Defaults to None, in which case a default decoder registry is used.
53
+ pool: the thread pool on which to run decompression. Defaults to None, in
54
+ which case, a default thread pool is used.
55
+
56
+ Returns:
57
+ Decoded tile data as an Array instance.
58
+ """
async_tiff/enums.py ADDED
@@ -0,0 +1,64 @@
1
+ from enum import IntEnum
2
+
3
+
4
+ class Compression(IntEnum):
5
+ """
6
+ See [TIFF compression
7
+ tags](https://www.awaresystems.be/imaging/tiff/tifftags/compression.html) for
8
+ reference.
9
+ """
10
+
11
+ Uncompressed = 1
12
+ Huffman = 2
13
+ Fax3 = 3
14
+ Fax4 = 4
15
+ LZW = 5
16
+ JPEG = 6
17
+ # // "Extended JPEG" or "new JPEG" style
18
+ ModernJPEG = 7
19
+ Deflate = 8
20
+ OldDeflate = 0x80B2
21
+ PackBits = 0x8005
22
+ WebP = 50001
23
+ JPEG2k = 34712
24
+ ZSTD = 0xC350
25
+
26
+
27
+ class Endianness(IntEnum):
28
+ LittleEndian = 0
29
+ BigEndian = 1
30
+
31
+
32
+ class PhotometricInterpretation(IntEnum):
33
+ WhiteIsZero = 0
34
+ BlackIsZero = 1
35
+ RGB = 2
36
+ RGBPalette = 3
37
+ TransparencyMask = 4
38
+ CMYK = 5
39
+ YCbCr = 6
40
+ CIELab = 8
41
+
42
+
43
+ class PlanarConfiguration(IntEnum):
44
+ Chunky = 1
45
+ Planar = 2
46
+
47
+
48
+ class Predictor(IntEnum):
49
+ Unknown = 1
50
+ Horizontal = 2
51
+ FloatingPoint = 3
52
+
53
+
54
+ class ResolutionUnit(IntEnum):
55
+ Unknown = 1
56
+ Inch = 2
57
+ Centimeter = 3
58
+
59
+
60
+ class SampleFormat(IntEnum):
61
+ Uint = 1
62
+ Int = 2
63
+ Float = 3
64
+ Void = 4
async_tiff/py.typed ADDED
File without changes
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: async-tiff
3
+ Version: 0.5.0b2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Requires-Dist: obspec>=0.1.0
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
10
+
11
+ # async-tiff
12
+
13
+ [![PyPI][pypi_badge]][pypi_link]
14
+
15
+ [pypi_badge]: https://badge.fury.io/py/async-tiff.svg
16
+ [pypi_link]: https://pypi.org/project/async-tiff/
17
+
18
+ Fast, low-level async TIFF reader for Python.
19
+
20
+ This documentation is for the Python bindings. [Refer here for the Rust crate documentation](https://docs.rs/async-tiff).
21
+
22
+ For a higher-level API to read GeoTIFF files, visit [`async-geotiff`][async-geotiff].
23
+
24
+ [async-geotiff]: https://developmentseed.org/async-geotiff
25
+
26
+ ## Examples
27
+
28
+ ### Reading NAIP
29
+
30
+ ```py
31
+ from async_tiff import TIFF
32
+ from async_tiff.store import S3Store
33
+
34
+ # You'll also need to provide credentials to access a requester pays bucket
35
+ store = S3Store("naip-visualization", region="us-west-2", request_payer=True)
36
+ path = "ny/2022/60cm/rgb/40073/m_4007307_sw_18_060_20220803.tif"
37
+
38
+ tiff = await TIFF.open(path, store=store)
39
+ primary_ifd = tiff.ifds[0]
40
+
41
+ primary_ifd.geo_key_directory.citation
42
+ # 'NAD83 / UTM zone 18N'
43
+
44
+ primary_ifd.geo_key_directory.projected_type
45
+ # 26918
46
+ # (EPSG code)
47
+
48
+ primary_ifd.sample_format
49
+ # [<SampleFormat.Uint: 1>, <SampleFormat.Uint: 1>, <SampleFormat.Uint: 1>]
50
+
51
+ primary_ifd.bits_per_sample
52
+ # [8, 8, 8]
53
+
54
+ tile = await tiff.fetch_tile(0, 0, 4)
55
+ array = await tile.decode()
56
+
57
+ # Use rasterio and matplotlib for visualization
58
+ import numpy as np
59
+ from rasterio.plot import reshape_as_raster, show
60
+
61
+ # Zero-copy conversion of the rust array into a numpy array
62
+ np_array = np.asarray(array)
63
+
64
+ # Then we need to reshape the "image" axes into "raster" axes
65
+ # https://rasterio.readthedocs.io/en/stable/topics/image_processing.html
66
+ show(reshape_as_raster(np_array), adjust=True)
67
+ ```
68
+
69
+ ![](assets/naip-example.jpg)
70
+
71
+
72
+ ### Reading Sentinel 2 L2A
73
+
74
+ ```py
75
+ import numpy as np
76
+ from async_tiff import TIFF
77
+ from async_tiff.store import S3Store
78
+
79
+ store = S3Store("sentinel-cogs", region="us-west-2", skip_signature=True)
80
+ path = "sentinel-s2-l2a-cogs/12/S/UF/2022/6/S2B_12SUF_20220609_0_L2A/B04.tif"
81
+
82
+ tiff = await TIFF.open(path, store=store)
83
+ primary_ifd = tiff.ifds[0]
84
+ # Text readable citation
85
+ primary_ifd.geo_key_directory.citation
86
+ # EPSG code
87
+ primary_ifd.geo_key_directory.projected_type
88
+
89
+ primary_ifd.sample_format[0]
90
+ # <SampleFormat.Uint: 1>
91
+ primary_ifd.bits_per_sample[0]
92
+ # 16
93
+
94
+ tile = await tiff.fetch_tile(0, 0, 0)
95
+ array = await tile.decode()
96
+
97
+ # Zero-copy conversion of the rust array into a numpy array
98
+ np_array = np.asarray(array)
99
+ np_array.shape
100
+ # (1024, 1024, 1)
101
+ ```
102
+
103
+
@@ -0,0 +1,19 @@
1
+ async_tiff/__init__.py,sha256=hFou5CyaCeqAHIpsxyfNv28t15tehoFv7iLbgchVW54,579
2
+ async_tiff/_array.pyi,sha256=muitV2BmObMPBF1O1mgo9a89posx7-ubsl4XftG5WO4,1257
3
+ async_tiff/_async_tiff.abi3.so,sha256=d196ogZJQgtl3U20dyE8yL2kPSRpb-bV11txPtzClzU,9519873
4
+ async_tiff/_async_tiff.pyi,sha256=I0Z9ey5GYZYfjJB4ZEyPUzHTsw0GcA5KBrAbTiThMc8,410
5
+ async_tiff/_colormap.pyi,sha256=NrXLqUq3U81bI0zG8OLgQwv_JM0YS-MrVgx-1nD6j3g,402
6
+ async_tiff/_decoder.pyi,sha256=tRHzZbZj1V6lDireFpNQ-f2h2tPFqh2ExYu4L6v0Cqc,709
7
+ async_tiff/_decoder_runtime.py,sha256=N2IC7XTgC1TmGmB7ZXCJbrVVSbn6G85cWgJ6k87XpT8,553
8
+ async_tiff/_geo.pyi,sha256=h71Y9zZ5vYxXaXAR4QAYmBJ0FOhLfXMMJA85p474eTE,3451
9
+ async_tiff/_ifd.pyi,sha256=eKH2FAboDE3B5kK2U45j0RsN5MwD3cUeDVF5WTgu0as,4755
10
+ async_tiff/_input.py,sha256=f6FCam4uyKaWXy-npUQ-nePaXeOsWMdXt2WcyH5fhq0,203
11
+ async_tiff/_thread_pool.pyi,sha256=fbDu9kbo8RNlq7bBBxuuu_6ub20L5cAfXBM-J7Y0PC8,181
12
+ async_tiff/_tiff.pyi,sha256=8MtZcmOPjr72lo8ohNuSwRi9N8YRZBtcjZwwJxEAO0Q,2249
13
+ async_tiff/_tile.pyi,sha256=NBUciMH6nan6qQLt30p9msUiY4BKh4ZmW4r9CsqtYho,1961
14
+ async_tiff/enums.py,sha256=C1XnevNtV_Hp5gTU7pLZRsNAfNx-4nu_f1NpbE1dN0U,1030
15
+ async_tiff/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ async_tiff-0.5.0b2.dist-info/METADATA,sha256=50rXi50a5Ku3aism82VG4fsq0XisM-DsVDykkRdjGWQ,2741
17
+ async_tiff-0.5.0b2.dist-info/WHEEL,sha256=TYQL8ukwJ_ep9kIEzr9pEuvjwsu8H5iF24nWE7u_TGo,107
18
+ async_tiff.libs/libgcc_s-f685abf1.so.1,sha256=rZiUpi-nw8tNSOJeN-vr3RTEAMCMaHf73gTNGVqRdKs,536145
19
+ async_tiff-0.5.0b2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.11.5)
3
+ Root-Is-Purelib: false
4
+ Tag: cp311-abi3-musllinux_1_2_x86_64
Binary file