async_tiff/
cog.rs

1use crate::error::AsyncTiffResult;
2use crate::ifd::ImageFileDirectories;
3use crate::reader::{AsyncCursor, AsyncFileReader};
4use crate::tiff::{TiffError, TiffFormatError};
5
6/// A TIFF file.
7#[derive(Debug, Clone)]
8pub struct TIFF {
9    ifds: ImageFileDirectories,
10}
11
12impl 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> {
17        let mut cursor = AsyncCursor::try_open_tiff(reader).await?;
18        let version = cursor.read_u16().await?;
19
20        let bigtiff = match version {
21            42 => false,
22            43 => {
23                // Read bytesize of offsets (in bigtiff it's alway 8 but provide a way to move to 16 some day)
24                if cursor.read_u16().await? != 8 {
25                    return Err(
26                        TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
27                    );
28                }
29                // This constant should always be 0
30                if cursor.read_u16().await? != 0 {
31                    return Err(
32                        TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
33                    );
34                }
35                true
36            }
37            _ => return Err(TiffError::FormatError(TiffFormatError::TiffSignatureInvalid).into()),
38        };
39
40        let first_ifd_location = if bigtiff {
41            cursor.read_u64().await?
42        } else {
43            cursor.read_u32().await?.into()
44        };
45
46        let ifds = ImageFileDirectories::open(&mut cursor, first_ifd_location, bigtiff).await?;
47
48        Ok(Self { ifds })
49    }
50
51    /// Access the underlying Image File Directories.
52    pub fn ifds(&self) -> &ImageFileDirectories {
53        &self.ifds
54    }
55}
56
57#[cfg(test)]
58mod test {
59    use std::io::BufReader;
60    use std::sync::Arc;
61
62    use crate::decoder::DecoderRegistry;
63    use crate::reader::ObjectReader;
64
65    use super::*;
66    use object_store::local::LocalFileSystem;
67    use tiff::decoder::{DecodingResult, Limits};
68
69    #[ignore = "local file"]
70    #[tokio::test]
71    async fn tmp() {
72        let folder = "/Users/kyle/github/developmentseed/async-tiff/";
73        let path = object_store::path::Path::parse("m_4007307_sw_18_060_20220803.tif").unwrap();
74        let store = Arc::new(LocalFileSystem::new_with_prefix(folder).unwrap());
75        let reader = ObjectReader::new(store, path);
76
77        let cog_reader = TIFF::try_open(Box::new(reader.clone())).await.unwrap();
78
79        let ifd = &cog_reader.ifds.as_ref()[1];
80        let decoder_registry = DecoderRegistry::default();
81        let tile = ifd.fetch_tile(0, 0, &reader).await.unwrap();
82        let tile = tile.decode(&decoder_registry).unwrap();
83        std::fs::write("img.buf", tile).unwrap();
84    }
85
86    #[ignore = "local file"]
87    #[test]
88    fn tmp_tiff_example() {
89        let path = "/Users/kyle/github/developmentseed/async-tiff/m_4007307_sw_18_060_20220803.tif";
90        let reader = std::fs::File::open(path).unwrap();
91        let mut decoder = tiff::decoder::Decoder::new(BufReader::new(reader))
92            .unwrap()
93            .with_limits(Limits::unlimited());
94        let result = decoder.read_image().unwrap();
95        match result {
96            DecodingResult::U8(content) => std::fs::write("img_from_tiff.buf", content).unwrap(),
97            _ => todo!(),
98        }
99    }
100}