Skip to content

Commit 82d09d6

Browse files
authored
Expose other_tags from ifd (#57)
1 parent 4a5307d commit 82d09d6

File tree

8 files changed

+211
-76
lines changed

8 files changed

+211
-76
lines changed

python/Cargo.lock

Lines changed: 136 additions & 75 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/python/async_tiff/_ifd.pyi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ from .enums import (
88
)
99
from ._geo import GeoKeyDirectory
1010

11+
Value = int | float | str | tuple[int, int] | list[Value]
12+
1113
class ImageFileDirectory:
1214
@property
1315
def new_subfile_type(self) -> int | None: ...
@@ -96,3 +98,5 @@ class ImageFileDirectory:
9698
def model_pixel_scale(self) -> list[float] | None: ...
9799
@property
98100
def model_tiepoint(self) -> list[float] | None: ...
101+
@property
102+
def other_tags(self) -> dict[int, Value]: ...

python/src/ifd.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashMap;
2+
13
use async_tiff::ImageFileDirectory;
24
use pyo3::prelude::*;
35

@@ -6,6 +8,7 @@ use crate::enums::{
68
PyResolutionUnit, PySampleFormat,
79
};
810
use crate::geo::PyGeoKeyDirectory;
11+
use crate::value::PyValue;
912

1013
#[pyclass(name = "ImageFileDirectory")]
1114
pub(crate) struct PyImageFileDirectory(ImageFileDirectory);
@@ -214,6 +217,16 @@ impl PyImageFileDirectory {
214217
pub fn model_tiepoint(&self) -> Option<&[f64]> {
215218
self.0.model_tiepoint()
216219
}
220+
221+
#[getter]
222+
pub fn other_tags(&self) -> HashMap<u16, PyValue> {
223+
let iter = self
224+
.0
225+
.other_tags()
226+
.iter()
227+
.map(|(key, val)| (key.to_u16(), val.clone().into()));
228+
HashMap::from_iter(iter)
229+
}
217230
}
218231

219232
impl From<ImageFileDirectory> for PyImageFileDirectory {

python/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod ifd;
77
mod thread_pool;
88
mod tiff;
99
mod tile;
10+
mod value;
1011

1112
use pyo3::prelude::*;
1213

python/src/value.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use async_tiff::tiff::Value;
2+
use pyo3::exceptions::PyRuntimeError;
3+
use pyo3::prelude::*;
4+
use pyo3::IntoPyObjectExt;
5+
6+
pub struct PyValue(Value);
7+
8+
impl<'py> IntoPyObject<'py> for PyValue {
9+
type Target = PyAny;
10+
type Output = Bound<'py, Self::Target>;
11+
type Error = PyErr;
12+
13+
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
14+
match self.0 {
15+
Value::Byte(val) => val.into_bound_py_any(py),
16+
Value::Short(val) => val.into_bound_py_any(py),
17+
Value::SignedByte(val) => val.into_bound_py_any(py),
18+
Value::SignedShort(val) => val.into_bound_py_any(py),
19+
Value::Signed(val) => val.into_bound_py_any(py),
20+
Value::SignedBig(val) => val.into_bound_py_any(py),
21+
Value::Unsigned(val) => val.into_bound_py_any(py),
22+
Value::UnsignedBig(val) => val.into_bound_py_any(py),
23+
Value::Float(val) => val.into_bound_py_any(py),
24+
Value::Double(val) => val.into_bound_py_any(py),
25+
Value::List(val) => val
26+
.into_iter()
27+
.map(|v| PyValue(v).into_bound_py_any(py))
28+
.collect::<PyResult<Vec<_>>>()?
29+
.into_bound_py_any(py),
30+
Value::Rational(num, denom) => (num, denom).into_bound_py_any(py),
31+
Value::RationalBig(num, denom) => (num, denom).into_bound_py_any(py),
32+
Value::SRational(num, denom) => (num, denom).into_bound_py_any(py),
33+
Value::SRationalBig(num, denom) => (num, denom).into_bound_py_any(py),
34+
Value::Ascii(val) => val.into_bound_py_any(py),
35+
Value::Ifd(_val) => Err(PyRuntimeError::new_err("Unsupported value type 'Ifd'")),
36+
Value::IfdBig(_val) => Err(PyRuntimeError::new_err("Unsupported value type 'IfdBig'")),
37+
v => Err(PyRuntimeError::new_err(format!(
38+
"Unknown value type: {:?}",
39+
v
40+
))),
41+
}
42+
}
43+
}
44+
45+
impl From<Value> for PyValue {
46+
fn from(value: Value) -> Self {
47+
Self(value)
48+
}
49+
}

src/ifd.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,11 @@ impl ImageFileDirectory {
721721
self.model_tiepoint.as_deref()
722722
}
723723

724+
/// Tags for which the tiff crate doesn't have a hard-coded enum variant.
725+
pub fn other_tags(&self) -> &HashMap<Tag, Value> {
726+
&self.other_tags
727+
}
728+
724729
/// Construct colormap from colormap tag
725730
pub fn colormap(&self) -> Option<HashMap<usize, [u8; 3]>> {
726731
fn cmap_transform(val: u16) -> u8 {

src/tiff/ifd.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Function for reading TIFF tags
22
3+
#![allow(missing_docs)]
4+
35
use std::vec;
46

57
use self::Value::{

src/tiff/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ mod ifd;
55
pub mod tags;
66

77
pub(crate) use error::{TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
8-
pub(crate) use ifd::Value;
8+
pub use ifd::Value;

0 commit comments

Comments
 (0)