Skip to content

Commit 5987b80

Browse files
authored
BigTIFF support (#30)
* Add bigtiff support * add open helper * Remove underlying tiff dependency
1 parent 8978a5d commit 5987b80

17 files changed

+1210
-157
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ num_enum = "0.7.3"
1313
# Match the version used by pyo3-object-store
1414
object_store = { git = "https://github.com/apache/arrow-rs", rev = "7a15e4b47ca97df2edef689c9f2ebd2f3888b79e" }
1515
thiserror = "1"
16-
tiff = "0.9"
1716
tokio = { version = "1.43.0", optional = true }
1817
weezl = "0.1.0"
1918

2019
[dev-dependencies]
20+
tiff = "0.9.1"
2121
tokio = { version = "1.9", features = ["macros", "fs", "rt-multi-thread"] }

src/async_reader.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ pub enum Endianness {
169169
#[derive(Debug)]
170170
pub(crate) struct AsyncCursor {
171171
reader: Box<dyn AsyncFileReader>,
172-
offset: usize,
172+
offset: u64,
173173
endianness: Endianness,
174174
}
175175

@@ -212,7 +212,7 @@ impl AsyncCursor {
212212
}
213213

214214
/// Read the given number of bytes, advancing the internal cursor state by the same amount.
215-
pub(crate) async fn read(&mut self, length: usize) -> Result<EndianAwareReader> {
215+
pub(crate) async fn read(&mut self, length: u64) -> Result<EndianAwareReader> {
216216
let range = self.offset as _..(self.offset + length) as _;
217217
self.offset += length;
218218
let bytes = self.reader.get_bytes(range).await?;
@@ -281,15 +281,15 @@ impl AsyncCursor {
281281
}
282282

283283
/// Advance cursor position by a set amount
284-
pub(crate) fn advance(&mut self, amount: usize) {
284+
pub(crate) fn advance(&mut self, amount: u64) {
285285
self.offset += amount;
286286
}
287287

288-
pub(crate) fn seek(&mut self, offset: usize) {
288+
pub(crate) fn seek(&mut self, offset: u64) {
289289
self.offset = offset;
290290
}
291291

292-
pub(crate) fn position(&self) -> usize {
292+
pub(crate) fn position(&self) -> u64 {
293293
self.offset
294294
}
295295
}

src/cog.rs

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,56 @@
11
use crate::async_reader::AsyncCursor;
22
use crate::error::Result;
33
use crate::ifd::ImageFileDirectories;
4+
use crate::tiff::{TiffError, TiffFormatError};
45
use crate::AsyncFileReader;
56

67
#[derive(Debug)]
78
pub struct COGReader {
89
#[allow(dead_code)]
910
cursor: AsyncCursor,
1011
ifds: ImageFileDirectories,
12+
#[allow(dead_code)]
13+
bigtiff: bool,
1114
}
1215

1316
impl COGReader {
1417
pub async fn try_open(reader: Box<dyn AsyncFileReader>) -> Result<Self> {
1518
let mut cursor = AsyncCursor::try_open_tiff(reader).await?;
1619
let version = cursor.read_u16().await?;
1720

18-
// Assert it's a standard non-big tiff
19-
assert_eq!(version, 42);
20-
21-
let first_ifd_location = cursor.read_u32().await?;
22-
23-
let ifds = ImageFileDirectories::open(&mut cursor, first_ifd_location as usize).await?;
24-
25-
Ok(Self { cursor, ifds })
21+
let bigtiff = match version {
22+
42 => false,
23+
43 => {
24+
// Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
25+
if cursor.read_u16().await? != 8 {
26+
return Err(
27+
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
28+
);
29+
}
30+
// This constant should always be 0
31+
if cursor.read_u16().await? != 0 {
32+
return Err(
33+
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
34+
);
35+
}
36+
true
37+
}
38+
_ => return Err(TiffError::FormatError(TiffFormatError::TiffSignatureInvalid).into()),
39+
};
40+
41+
let first_ifd_location = if bigtiff {
42+
cursor.read_u64().await?
43+
} else {
44+
cursor.read_u32().await?.into()
45+
};
46+
47+
let ifds = ImageFileDirectories::open(&mut cursor, first_ifd_location, bigtiff).await?;
48+
49+
Ok(Self {
50+
cursor,
51+
ifds,
52+
bigtiff,
53+
})
2654
}
2755

2856
pub fn ifds(&self) -> &ImageFileDirectories {

src/decoder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use std::io::{Cursor, Read};
44

55
use bytes::Bytes;
66
use flate2::bufread::ZlibDecoder;
7-
use tiff::tags::{CompressionMethod, PhotometricInterpretation};
8-
use tiff::{TiffError, TiffUnsupportedError};
97

108
use crate::error::Result;
9+
use crate::tiff::tags::{CompressionMethod, PhotometricInterpretation};
10+
use crate::tiff::{TiffError, TiffUnsupportedError};
1111

1212
/// A registry of decoders.
1313
#[derive(Debug)]

src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub enum AiocogeoError {
2222
ObjectStore(#[from] object_store::Error),
2323

2424
#[error(transparent)]
25-
TIFFError(#[from] tiff::TiffError),
25+
InternalTIFFError(#[from] crate::tiff::TiffError),
2626
}
2727

2828
/// Crate-specific result type.

src/geo/geo_key_directory.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
use std::collections::HashMap;
44

55
use num_enum::{IntoPrimitive, TryFromPrimitive};
6-
use tiff::decoder::ifd::Value;
7-
use tiff::{TiffError, TiffResult};
6+
7+
use crate::tiff::Value;
8+
use crate::tiff::{TiffError, TiffResult};
89

910
/// Geospatial TIFF tag variants
1011
#[derive(Clone, Copy, Debug, PartialEq, TryFromPrimitive, IntoPrimitive, Eq, Hash)]

0 commit comments

Comments
 (0)