1use crate::error::AsyncTiffResult;
2use crate::ifd::ImageFileDirectories;
3use crate::reader::{AsyncCursor, AsyncFileReader};
4use crate::tiff::{TiffError, TiffFormatError};
5
6#[derive(Debug, Clone)]
8pub struct TIFF {
9 ifds: ImageFileDirectories,
10}
11
12impl TIFF {
13 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 if cursor.read_u16().await? != 8 {
25 return Err(
26 TiffError::FormatError(TiffFormatError::TiffSignatureNotFound).into(),
27 );
28 }
29 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 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}