async-tiff 0.5.0b1__cp310-cp310-musllinux_1_2_armv7l.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,32 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from ._async_tiff import (
4
+ TIFF,
5
+ Array,
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
+ if TYPE_CHECKING:
17
+ from . import store
18
+
19
+ __version__: str = ___version()
20
+
21
+ __all__ = [
22
+ "store",
23
+ "Array",
24
+ "Decoder",
25
+ "DecoderRegistry",
26
+ "GeoKeyDirectory",
27
+ "ImageFileDirectory",
28
+ "ThreadPool",
29
+ "TIFF",
30
+ "ObspecInput",
31
+ "Tile",
32
+ ]
async_tiff/_array.pyi ADDED
@@ -0,0 +1,40 @@
1
+ from collections.abc import Buffer
2
+
3
+ class Array(Buffer):
4
+ """A 3D array that implements Python's buffer protocol.
5
+
6
+ This allows zero-copy interoperability with numpy via `np.asarray(arr)`.
7
+ The array is immutable and exposes a read-only buffer.
8
+
9
+ Example:
10
+
11
+ ```python
12
+ import numpy as np
13
+ from async_tiff import Array
14
+
15
+ # Create from raw bytes
16
+ data = bytes([1, 2, 3, 4, 5, 6])
17
+ arr = Array(data, shape=(1, 2, 3), format="<B") # 1x2x3 uint8 array
18
+
19
+ # Convert to numpy (zero-copy view)
20
+ np_arr = np.asarray(arr)
21
+ assert np_arr.shape == (1, 2, 3)
22
+ assert np_arr.dtype == np.uint8
23
+ ```
24
+ """
25
+
26
+ # This is intended only for tests
27
+ # def __init__(
28
+ # self, data: Buffer, shape: tuple[int, int, int], format: str
29
+ # ) -> None: ...
30
+ def __buffer__(self, flags: int) -> memoryview[int]: ...
31
+ @property
32
+ def shape(self) -> tuple[int, int, int]:
33
+ """The shape of the array.
34
+
35
+ The interpretation depends on the PlanarConfiguration:
36
+
37
+ - PlanarConfiguration=1 (chunky): (height, width, bands)
38
+ - PlanarConfiguration=2 (planar): (bands, height, width)
39
+ """
40
+ ...
@@ -0,0 +1,17 @@
1
+ from ._array import Array
2
+ from ._decoder import DecoderRegistry
3
+ from ._geo import GeoKeyDirectory
4
+ from ._ifd import ImageFileDirectory
5
+ from ._thread_pool import ThreadPool
6
+ from ._tiff import TIFF
7
+ from ._tile import Tile
8
+
9
+ __all__ = [
10
+ "Array",
11
+ "DecoderRegistry",
12
+ "GeoKeyDirectory",
13
+ "ImageFileDirectory",
14
+ "ThreadPool",
15
+ "TIFF",
16
+ "Tile",
17
+ ]
@@ -0,0 +1,19 @@
1
+ from ._decoder_runtime import Decoder
2
+ from .enums import CompressionMethod
3
+
4
+ class DecoderRegistry:
5
+ """A registry holding multiple decoder methods."""
6
+ def __init__(
7
+ self, custom_decoders: dict[CompressionMethod | 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,124 @@
1
+ from collections.abc import Iterable
2
+ from typing import Any
3
+
4
+ from ._geo import GeoKeyDirectory
5
+ from .enums import (
6
+ CompressionMethod,
7
+ PhotometricInterpretation,
8
+ PlanarConfiguration,
9
+ Predictor,
10
+ ResolutionUnit,
11
+ SampleFormat,
12
+ )
13
+
14
+ Value = int | float | str | tuple[int, int] | list[Value]
15
+
16
+ class ImageFileDirectory:
17
+ def keys(self) -> list[str]:
18
+ """A list of string keys representing the IFD fields."""
19
+ def __eq__(self, value: object) -> bool: ...
20
+ def __iter__(self) -> Iterable[str]:
21
+ """An iterable of string keys representing the IFD fields."""
22
+ def __getitem__(self, key: str) -> Any:
23
+ """Access IFD fields by string key."""
24
+
25
+ @property
26
+ def new_subfile_type(self) -> int | None: ...
27
+ @property
28
+ def image_width(self) -> int:
29
+ """The number of columns in the image, i.e., the number of pixels per row."""
30
+
31
+ @property
32
+ def image_height(self) -> int:
33
+ """The number of rows of pixels in the image."""
34
+
35
+ @property
36
+ def bits_per_sample(self) -> list[int]: ...
37
+ @property
38
+ def compression(self) -> CompressionMethod | int:
39
+ """Access the compression tag.
40
+
41
+ An `int` will be returned if the compression is not one of the values in
42
+ `CompressionMethod`.
43
+ """
44
+ @property
45
+ def photometric_interpretation(self) -> PhotometricInterpretation: ...
46
+ @property
47
+ def document_name(self) -> str | None: ...
48
+ @property
49
+ def image_description(self) -> str | None: ...
50
+ @property
51
+ def strip_offsets(self) -> list[int] | None: ...
52
+ @property
53
+ def orientation(self) -> int | None: ...
54
+ @property
55
+ def samples_per_pixel(self) -> int:
56
+ """
57
+ The number of components per pixel.
58
+
59
+ SamplesPerPixel is usually 1 for bilevel, grayscale, and palette-color images.
60
+ SamplesPerPixel is usually 3 for RGB images. If this value is higher,
61
+ ExtraSamples should give an indication of the meaning of the additional
62
+ channels.
63
+ """
64
+
65
+ @property
66
+ def rows_per_strip(self) -> int | None: ...
67
+ @property
68
+ def strip_byte_counts(self) -> int | None: ...
69
+ @property
70
+ def min_sample_value(self) -> int | None: ...
71
+ @property
72
+ def max_sample_value(self) -> int | None: ...
73
+ @property
74
+ def x_resolution(self) -> float | None:
75
+ """The number of pixels per ResolutionUnit in the ImageWidth direction."""
76
+
77
+ @property
78
+ def y_resolution(self) -> float | None:
79
+ """The number of pixels per ResolutionUnit in the ImageLength direction."""
80
+
81
+ @property
82
+ def planar_configuration(self) -> PlanarConfiguration: ...
83
+ @property
84
+ def resolution_unit(self) -> ResolutionUnit | None: ...
85
+ @property
86
+ def software(self) -> str | None: ...
87
+ @property
88
+ def date_time(self) -> str | None: ...
89
+ @property
90
+ def artist(self) -> str | None: ...
91
+ @property
92
+ def host_computer(self) -> str | None: ...
93
+ @property
94
+ def predictor(self) -> Predictor | None: ...
95
+ @property
96
+ def tile_width(self) -> int | None: ...
97
+ @property
98
+ def tile_height(self) -> int | None: ...
99
+ @property
100
+ def tile_offsets(self) -> list[int] | None: ...
101
+ @property
102
+ def tile_byte_counts(self) -> list[int] | None: ...
103
+ @property
104
+ def extra_samples(self) -> list[int] | None: ...
105
+ @property
106
+ def sample_format(self) -> list[SampleFormat]: ...
107
+ @property
108
+ def jpeg_tables(self) -> bytes | None: ...
109
+ @property
110
+ def copyright(self) -> str | None: ...
111
+ @property
112
+ def geo_key_directory(self) -> GeoKeyDirectory | None: ...
113
+ @property
114
+ def model_pixel_scale(self) -> list[float] | None: ...
115
+ @property
116
+ def model_tiepoint(self) -> list[float] | None: ...
117
+ @property
118
+ def model_transformation(self) -> list[float] | None: ...
119
+ @property
120
+ def gdal_nodata(self) -> str | None: ...
121
+ @property
122
+ def gdal_metadata(self) -> str | None: ...
123
+ @property
124
+ def other_tags(self) -> dict[int, Value]: ...
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,63 @@
1
+ from ._ifd import ImageFileDirectory
2
+ from ._input import ObspecInput
3
+ from ._tile import Tile
4
+ from .enums import Endianness
5
+ from .store import ObjectStore
6
+
7
+ class TIFF:
8
+ @classmethod
9
+ async def open(
10
+ cls,
11
+ path: str,
12
+ *,
13
+ store: ObjectStore | ObspecInput,
14
+ prefetch: int = 32768,
15
+ multiplier: int | float = 2.0,
16
+ ) -> TIFF:
17
+ """Open a new TIFF.
18
+
19
+ Args:
20
+ path: The path within the store to read from.
21
+ store: The backend to use for data fetching.
22
+ prefetch: The number of initial bytes to read up front.
23
+ multiplier: The multiplier to use for readahead size growth. Must be
24
+ greater than 1.0. For example, for a value of `2.0`, the first metadata
25
+ read will be of size `prefetch`, and then the next read will be of size
26
+ `prefetch * 2`.
27
+
28
+ Returns:
29
+ A TIFF instance.
30
+ """
31
+
32
+ @property
33
+ def endianness(self) -> Endianness:
34
+ """The endianness of this TIFF file."""
35
+ @property
36
+ def ifds(self) -> list[ImageFileDirectory]:
37
+ """Access the underlying IFDs of this TIFF.
38
+
39
+ Each ImageFileDirectory (IFD) represents one of the internal "sub images" of
40
+ this file.
41
+ """
42
+ async def fetch_tile(self, x: int, y: int, z: int) -> Tile:
43
+ """Fetch a single tile.
44
+
45
+ Args:
46
+ x: The column index within the ifd to read from.
47
+ y: The row index within the ifd to read from.
48
+ z: The IFD index to read from.
49
+
50
+ Returns:
51
+ Tile response.
52
+ """
53
+ async def fetch_tiles(self, x: list[int], y: list[int], z: int) -> list[Tile]:
54
+ """Fetch multiple tiles concurrently.
55
+
56
+ Args:
57
+ x: The column indexes within the ifd to read from.
58
+ y: The row indexes within the ifd to read from.
59
+ z: The IFD index to read from.
60
+
61
+ Returns:
62
+ Tile responses.
63
+ """
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 CompressionMethod
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) -> CompressionMethod | 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,61 @@
1
+ from enum import IntEnum
2
+
3
+
4
+ class CompressionMethod(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
+
23
+
24
+ class Endianness(IntEnum):
25
+ LittleEndian = 0
26
+ BigEndian = 1
27
+
28
+
29
+ class PhotometricInterpretation(IntEnum):
30
+ WhiteIsZero = 0
31
+ BlackIsZero = 1
32
+ RGB = 2
33
+ RGBPalette = 3
34
+ TransparencyMask = 4
35
+ CMYK = 5
36
+ YCbCr = 6
37
+ CIELab = 8
38
+
39
+
40
+ class PlanarConfiguration(IntEnum):
41
+ Chunky = 1
42
+ Planar = 2
43
+
44
+
45
+ class Predictor(IntEnum):
46
+ Unknown = 1
47
+ Horizontal = 2
48
+ FloatingPoint = 3
49
+
50
+
51
+ class ResolutionUnit(IntEnum):
52
+ Unknown = 1
53
+ Inch = 2
54
+ Centimeter = 3
55
+
56
+
57
+ class SampleFormat(IntEnum):
58
+ Uint = 1
59
+ Int = 2
60
+ Float = 3
61
+ Void = 4
async_tiff/py.typed ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: async-tiff
3
+ Version: 0.5.0b1
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
@@ -0,0 +1,18 @@
1
+ async_tiff/__init__.py,sha256=EAs0ZXh393JFZeO_mpt69rDHQdv-cnZkU4rgqvUGf7A,586
2
+ async_tiff/_array.pyi,sha256=uuJLjpoGF6wk_VS4kfTJIS_mhQ29RBEYGyy40cn5E28,1162
3
+ async_tiff/_async_tiff.cpython-310-arm-linux-gnueabihf.so,sha256=sDQ5D_Mf0WWdECwxZWwNatTgxfofFeJG50nZ74pYB74,8241681
4
+ async_tiff/_async_tiff.pyi,sha256=9Jbj2DFNpmo4BqBUU9p9-Z-8Ea_warzn-LPE2m3SzBM,362
5
+ async_tiff/_decoder.pyi,sha256=T1600oX7eWwzulo3uxWvqZ0CFwcMgQ_iAA7NzaQc5Hg,721
6
+ async_tiff/_decoder_runtime.py,sha256=N2IC7XTgC1TmGmB7ZXCJbrVVSbn6G85cWgJ6k87XpT8,553
7
+ async_tiff/_geo.pyi,sha256=h71Y9zZ5vYxXaXAR4QAYmBJ0FOhLfXMMJA85p474eTE,3451
8
+ async_tiff/_ifd.pyi,sha256=X6eAFIc6jBIR9nnLnjQFNVFnQ6fr9zoUJeQjZAdv494,3981
9
+ async_tiff/_input.py,sha256=f6FCam4uyKaWXy-npUQ-nePaXeOsWMdXt2WcyH5fhq0,203
10
+ async_tiff/_thread_pool.pyi,sha256=fbDu9kbo8RNlq7bBBxuuu_6ub20L5cAfXBM-J7Y0PC8,181
11
+ async_tiff/_tiff.pyi,sha256=aR7qtsfKBqYcdF-Jf6weZl9CE1owM9GgXu5gU2nAlIo,1980
12
+ async_tiff/_tile.pyi,sha256=1JlhrXGq4xB9gbSrmMt4aUR5Bufr1LhFCFwOCdgf5X8,1973
13
+ async_tiff/enums.py,sha256=uz6EUnLeLpbtD40vxXsd4VnFNQBMaC_o5bslqF8gJv0,982
14
+ async_tiff/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ async_tiff-0.5.0b1.dist-info/METADATA,sha256=3zbqc79Cw47NzYr09ctYrByaCgrL5QhlOzlLBp-CW2s,291
16
+ async_tiff-0.5.0b1.dist-info/WHEEL,sha256=oQl0jSFLrJ7cOk5P3a35ueLgmfTP5J-oZPtOD9iCKBY,108
17
+ async_tiff.libs/libgcc_s-262c4f60.so.1,sha256=xPsZgCvL7EO-llmjqc5bm96baehLsO4avBqUhih0xZg,2810501
18
+ async_tiff-0.5.0b1.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: cp310-cp310-musllinux_1_2_armv7l
Binary file