Skip to content

Commit 871bfd6

Browse files
authored
Cleanup and document rust code (#44)
* Cleanup and document rust code * Python compile * bump bytes * bump pyo3-bytes
1 parent 78d2876 commit 871bfd6

File tree

15 files changed

+225
-101
lines changed

15 files changed

+225
-101
lines changed

Cargo.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
[package]
22
name = "async-tiff"
3-
version = "0.1.0"
3+
version = "0.1.0-beta.1"
44
edition = "2021"
5+
authors = ["Kyle Barron <kyle@developmentseed.org>"]
6+
license = "MIT OR Apache-2.0"
7+
repository = "https://github.com/developmentseed/async-tiff"
8+
description = "Low-level asynchronous TIFF reader."
9+
readme = "README.md"
510

611
[dependencies]
712
byteorder = "1"
@@ -11,6 +16,7 @@ futures = "0.3.31"
1116
jpeg = { package = "jpeg-decoder", version = "0.3.0", default-features = false }
1217
num_enum = "0.7.3"
1318
# Match the version used by pyo3-object-store
19+
# We'll upgrade to object_store 0.12 ASAP when it comes out
1420
object_store = { git = "https://github.com/apache/arrow-rs", rev = "7a15e4b47ca97df2edef689c9f2ebd2f3888b79e" }
1521
thiserror = "1"
1622
tokio = { version = "1.43.0", optional = true }

python/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "async-tiff"
2+
name = "py-async-tiff"
33
version = "0.1.0-beta.1"
44
authors = ["Kyle Barron <kyle@developmentseed.org>"]
55
edition = "2021"
@@ -18,12 +18,13 @@ crate-type = ["cdylib"]
1818

1919
[dependencies]
2020
async-tiff = { path = "../" }
21-
bytes = "1.8"
21+
bytes = "1.10.1"
22+
# We'll upgrade to object_store 0.12 ASAP
2223
# Match the version used by pyo3-object-store
2324
object_store = { git = "https://github.com/apache/arrow-rs", rev = "7a15e4b47ca97df2edef689c9f2ebd2f3888b79e" }
2425
pyo3 = { version = "0.23.0", features = ["macros"] }
2526
pyo3-async-runtimes = "0.23"
26-
pyo3-bytes = "0.1.2"
27+
pyo3-bytes = "0.1.3"
2728
pyo3-object_store = { git = "https://github.com/developmentseed/obstore", rev = "28ba07a621c1c104f084fb47ae7f8d08b1eae3ea" }
2829
rayon = "1.10.0"
2930
tokio-rayon = "2.1.0"

python/src/decoder.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::collections::HashMap;
22
use std::sync::Arc;
33

44
use async_tiff::decoder::{Decoder, DecoderRegistry};
5-
use async_tiff::error::AiocogeoError;
5+
use async_tiff::error::{AsyncTiffError, AsyncTiffResult};
66
use async_tiff::tiff::tags::PhotometricInterpretation;
77
use bytes::Bytes;
88
use pyo3::exceptions::PyTypeError;
@@ -74,12 +74,12 @@ impl<'py> FromPyObject<'py> for PyDecoder {
7474
impl Decoder for PyDecoder {
7575
fn decode_tile(
7676
&self,
77-
buffer: bytes::Bytes,
77+
buffer: Bytes,
7878
_photometric_interpretation: PhotometricInterpretation,
7979
_jpeg_tables: Option<&[u8]>,
80-
) -> async_tiff::error::Result<bytes::Bytes> {
80+
) -> AsyncTiffResult<Bytes> {
8181
let decoded_buffer = Python::with_gil(|py| self.call(py, buffer))
82-
.map_err(|err| AiocogeoError::General(err.to_string()))?;
82+
.map_err(|err| AsyncTiffError::General(err.to_string()))?;
8383
Ok(decoded_buffer.into_inner())
8484
}
8585
}

python/src/tiff.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use async_tiff::{AsyncFileReader, COGReader, ObjectReader, PrefetchReader};
1+
use async_tiff::reader::{AsyncFileReader, ObjectReader, PrefetchReader};
2+
use async_tiff::TIFF;
23
use pyo3::prelude::*;
34
use pyo3::types::PyType;
45
use pyo3_async_runtimes::tokio::future_into_py;
@@ -7,7 +8,7 @@ use pyo3_object_store::PyObjectStore;
78
use crate::PyImageFileDirectory;
89

910
#[pyclass(name = "TIFF", frozen)]
10-
pub(crate) struct PyTIFF(COGReader);
11+
pub(crate) struct PyTIFF(TIFF);
1112

1213
#[pymethods]
1314
impl PyTIFF {
@@ -32,7 +33,7 @@ impl PyTIFF {
3233
} else {
3334
Box::new(reader)
3435
};
35-
Ok(PyTIFF(COGReader::try_open(reader).await.unwrap()))
36+
Ok(PyTIFF(TIFF::try_open(reader).await.unwrap()))
3637
})?;
3738
Ok(cog_reader)
3839
}

src/cog.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
use crate::async_reader::AsyncCursor;
2-
use crate::error::Result;
1+
use crate::error::AsyncTiffResult;
32
use crate::ifd::ImageFileDirectories;
3+
use crate::reader::{AsyncCursor, AsyncFileReader};
44
use crate::tiff::{TiffError, TiffFormatError};
5-
use crate::AsyncFileReader;
65

7-
#[derive(Debug)]
8-
pub struct COGReader {
9-
#[allow(dead_code)]
10-
cursor: AsyncCursor,
6+
/// A TIFF file.
7+
#[derive(Debug, Clone)]
8+
pub struct TIFF {
119
ifds: ImageFileDirectories,
1210
}
1311

14-
impl COGReader {
15-
pub async fn try_open(reader: Box<dyn AsyncFileReader>) -> Result<Self> {
12+
impl TIFF {
13+
/// Open a new TIFF file.
14+
///
15+
/// This will read all the Image File Directories (IFDs) in the file.
16+
pub async fn try_open(reader: Box<dyn AsyncFileReader>) -> AsyncTiffResult<Self> {
1617
let mut cursor = AsyncCursor::try_open_tiff(reader).await?;
1718
let version = cursor.read_u16().await?;
1819

@@ -44,9 +45,10 @@ impl COGReader {
4445

4546
let ifds = ImageFileDirectories::open(&mut cursor, first_ifd_location, bigtiff).await?;
4647

47-
Ok(Self { cursor, ifds })
48+
Ok(Self { ifds })
4849
}
4950

51+
/// Access the underlying Image File Directories.
5052
pub fn ifds(&self) -> &ImageFileDirectories {
5153
&self.ifds
5254
}
@@ -58,7 +60,7 @@ mod test {
5860
use std::sync::Arc;
5961

6062
use crate::decoder::DecoderRegistry;
61-
use crate::ObjectReader;
63+
use crate::reader::ObjectReader;
6264

6365
use super::*;
6466
use object_store::local::LocalFileSystem;
@@ -72,7 +74,7 @@ mod test {
7274
let store = Arc::new(LocalFileSystem::new_with_prefix(folder).unwrap());
7375
let reader = ObjectReader::new(store, path);
7476

75-
let cog_reader = COGReader::try_open(Box::new(reader.clone())).await.unwrap();
77+
let cog_reader = TIFF::try_open(Box::new(reader.clone())).await.unwrap();
7678

7779
let ifd = &cog_reader.ifds.as_ref()[1];
7880
let decoder_registry = DecoderRegistry::default();

src/decoder.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1+
//! Decoders for different TIFF compression methods.
2+
13
use std::collections::HashMap;
24
use std::fmt::Debug;
35
use std::io::{Cursor, Read};
46

57
use bytes::Bytes;
68
use flate2::bufread::ZlibDecoder;
79

8-
use crate::error::Result;
10+
use crate::error::AsyncTiffResult;
911
use crate::tiff::tags::{CompressionMethod, PhotometricInterpretation};
1012
use crate::tiff::{TiffError, TiffUnsupportedError};
1113

@@ -46,14 +48,16 @@ impl Default for DecoderRegistry {
4648

4749
/// A trait to decode a TIFF tile.
4850
pub trait Decoder: Debug + Send + Sync {
51+
/// Decode a TIFF tile.
4952
fn decode_tile(
5053
&self,
5154
buffer: Bytes,
5255
photometric_interpretation: PhotometricInterpretation,
5356
jpeg_tables: Option<&[u8]>,
54-
) -> Result<Bytes>;
57+
) -> AsyncTiffResult<Bytes>;
5558
}
5659

60+
/// A decoder for the Deflate compression method.
5761
#[derive(Debug, Clone)]
5862
pub struct DeflateDecoder;
5963

@@ -63,14 +67,15 @@ impl Decoder for DeflateDecoder {
6367
buffer: Bytes,
6468
_photometric_interpretation: PhotometricInterpretation,
6569
_jpeg_tables: Option<&[u8]>,
66-
) -> Result<Bytes> {
70+
) -> AsyncTiffResult<Bytes> {
6771
let mut decoder = ZlibDecoder::new(Cursor::new(buffer));
6872
let mut buf = Vec::new();
6973
decoder.read_to_end(&mut buf)?;
7074
Ok(buf.into())
7175
}
7276
}
7377

78+
/// A decoder for the JPEG compression method.
7479
#[derive(Debug, Clone)]
7580
pub struct JPEGDecoder;
7681

@@ -80,11 +85,12 @@ impl Decoder for JPEGDecoder {
8085
buffer: Bytes,
8186
photometric_interpretation: PhotometricInterpretation,
8287
jpeg_tables: Option<&[u8]>,
83-
) -> Result<Bytes> {
88+
) -> AsyncTiffResult<Bytes> {
8489
decode_modern_jpeg(buffer, photometric_interpretation, jpeg_tables)
8590
}
8691
}
8792

93+
/// A decoder for the LZW compression method.
8894
#[derive(Debug, Clone)]
8995
pub struct LZWDecoder;
9096

@@ -94,14 +100,15 @@ impl Decoder for LZWDecoder {
94100
buffer: Bytes,
95101
_photometric_interpretation: PhotometricInterpretation,
96102
_jpeg_tables: Option<&[u8]>,
97-
) -> Result<Bytes> {
103+
) -> AsyncTiffResult<Bytes> {
98104
// https://github.com/image-rs/image-tiff/blob/90ae5b8e54356a35e266fb24e969aafbcb26e990/src/decoder/stream.rs#L147
99105
let mut decoder = weezl::decode::Decoder::with_tiff_size_switch(weezl::BitOrder::Msb, 8);
100106
let decoded = decoder.decode(&buffer).expect("failed to decode LZW data");
101107
Ok(decoded.into())
102108
}
103109
}
104110

111+
/// A decoder for uncompressed data.
105112
#[derive(Debug, Clone)]
106113
pub struct UncompressedDecoder;
107114

@@ -111,7 +118,7 @@ impl Decoder for UncompressedDecoder {
111118
buffer: Bytes,
112119
_photometric_interpretation: PhotometricInterpretation,
113120
_jpeg_tables: Option<&[u8]>,
114-
) -> Result<Bytes> {
121+
) -> AsyncTiffResult<Bytes> {
115122
Ok(buffer)
116123
}
117124
}
@@ -121,7 +128,7 @@ fn decode_modern_jpeg(
121128
buf: Bytes,
122129
photometric_interpretation: PhotometricInterpretation,
123130
jpeg_tables: Option<&[u8]>,
124-
) -> Result<Bytes> {
131+
) -> AsyncTiffResult<Bytes> {
125132
// Construct new jpeg_reader wrapping a SmartReader.
126133
//
127134
// JPEG compression in TIFF allows saving quantization and/or huffman tables in one central

src/error.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,36 @@
1+
//! Error handling.
2+
13
use std::fmt::Debug;
24
use thiserror::Error;
35

46
/// Enum with all errors in this crate.
57
#[derive(Error, Debug)]
68
#[non_exhaustive]
7-
pub enum AiocogeoError {
9+
pub enum AsyncTiffError {
10+
/// End of file error.
811
#[error("End of File: expected to read {0} bytes, got {1}")]
912
EndOfFile(usize, usize),
1013

1114
/// General error.
1215
#[error("General error: {0}")]
1316
General(String),
1417

18+
/// IO Error.
1519
#[error(transparent)]
1620
IOError(#[from] std::io::Error),
1721

22+
/// Error while decoding JPEG data.
1823
#[error(transparent)]
1924
JPEGDecodingError(#[from] jpeg::Error),
2025

26+
/// Error while fetching data using object store.
2127
#[error(transparent)]
2228
ObjectStore(#[from] object_store::Error),
2329

30+
/// An error during TIFF tag parsing.
2431
#[error(transparent)]
2532
InternalTIFFError(#[from] crate::tiff::TiffError),
2633
}
2734

2835
/// Crate-specific result type.
29-
pub type Result<T> = std::result::Result<T, AiocogeoError>;
36+
pub type AsyncTiffResult<T> = std::result::Result<T, AsyncTiffError>;

src/geo/affine.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,37 @@ use crate::ImageFileDirectory;
55
pub struct AffineTransform(f64, f64, f64, f64, f64, f64);
66

77
impl AffineTransform {
8+
/// Construct a new Affine Transform
89
pub fn new(a: f64, b: f64, xoff: f64, d: f64, e: f64, yoff: f64) -> Self {
910
Self(a, b, xoff, d, e, yoff)
1011
}
1112

13+
/// a
1214
pub fn a(&self) -> f64 {
1315
self.0
1416
}
1517

18+
/// b
1619
pub fn b(&self) -> f64 {
1720
self.1
1821
}
1922

23+
/// c
2024
pub fn c(&self) -> f64 {
2125
self.2
2226
}
2327

28+
/// d
2429
pub fn d(&self) -> f64 {
2530
self.3
2631
}
2732

33+
/// e
2834
pub fn e(&self) -> f64 {
2935
self.4
3036
}
3137

38+
/// f
3239
pub fn f(&self) -> f64 {
3340
self.5
3441
}

src/geo/geo_key_directory.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![allow(dead_code)]
2+
#![allow(missing_docs)]
23

34
use std::collections::HashMap;
45

0 commit comments

Comments
 (0)