Skip to content

BigTIFF support #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ num_enum = "0.7.3"
# Match the version used by pyo3-object-store
object_store = { git = "https://github.com/apache/arrow-rs", rev = "7a15e4b47ca97df2edef689c9f2ebd2f3888b79e" }
thiserror = "1"
tiff = "0.9"
tokio = { version = "1.43.0", optional = true }
weezl = "0.1.0"

[dev-dependencies]
tiff = "0.9.1"
tokio = { version = "1.9", features = ["macros", "fs", "rt-multi-thread"] }
10 changes: 5 additions & 5 deletions src/async_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ pub enum Endianness {
#[derive(Debug)]
pub(crate) struct AsyncCursor {
reader: Box<dyn AsyncFileReader>,
offset: usize,
offset: u64,
endianness: Endianness,
}

Expand Down Expand Up @@ -212,7 +212,7 @@ impl AsyncCursor {
}

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

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

pub(crate) fn seek(&mut self, offset: usize) {
pub(crate) fn seek(&mut self, offset: u64) {
self.offset = offset;
}

pub(crate) fn position(&self) -> usize {
pub(crate) fn position(&self) -> u64 {
self.offset
}
}
Expand Down
44 changes: 36 additions & 8 deletions src/cog.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
use crate::async_reader::AsyncCursor;
use crate::error::Result;
use crate::ifd::ImageFileDirectories;
use crate::tiff::{TiffError, TiffFormatError};
use crate::AsyncFileReader;

#[derive(Debug)]
pub struct COGReader {
#[allow(dead_code)]
cursor: AsyncCursor,
ifds: ImageFileDirectories,
#[allow(dead_code)]
bigtiff: bool,
}

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

// Assert it's a standard non-big tiff
assert_eq!(version, 42);

let first_ifd_location = cursor.read_u32().await?;

let ifds = ImageFileDirectories::open(&mut cursor, first_ifd_location as usize).await?;

Ok(Self { cursor, ifds })
let bigtiff = match version {
42 => false,
43 => {
// Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
if cursor.read_u16().await? != 8 {
return Err(
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
);
}
// This constant should always be 0
if cursor.read_u16().await? != 0 {
return Err(
TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
);
}
true
}
_ => return Err(TiffError::FormatError(TiffFormatError::TiffSignatureInvalid).into()),
};

let first_ifd_location = if bigtiff {
cursor.read_u64().await?
} else {
cursor.read_u32().await?.into()
};

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

Ok(Self {
cursor,
ifds,
bigtiff,
})
}

pub fn ifds(&self) -> &ImageFileDirectories {
Expand Down
4 changes: 2 additions & 2 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use std::io::{Cursor, Read};

use bytes::Bytes;
use flate2::bufread::ZlibDecoder;
use tiff::tags::{CompressionMethod, PhotometricInterpretation};
use tiff::{TiffError, TiffUnsupportedError};

use crate::error::Result;
use crate::tiff::tags::{CompressionMethod, PhotometricInterpretation};
use crate::tiff::{TiffError, TiffUnsupportedError};

/// A registry of decoders.
#[derive(Debug)]
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub enum AiocogeoError {
ObjectStore(#[from] object_store::Error),

#[error(transparent)]
TIFFError(#[from] tiff::TiffError),
InternalTIFFError(#[from] crate::tiff::TiffError),
}

/// Crate-specific result type.
Expand Down
5 changes: 3 additions & 2 deletions src/geo/geo_key_directory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
use std::collections::HashMap;

use num_enum::{IntoPrimitive, TryFromPrimitive};
use tiff::decoder::ifd::Value;
use tiff::{TiffError, TiffResult};

use crate::tiff::Value;
use crate::tiff::{TiffError, TiffResult};

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