diff --git a/src/async_reader.rs b/src/async_reader.rs index c6c922a..1519247 100644 --- a/src/async_reader.rs +++ b/src/async_reader.rs @@ -205,10 +205,6 @@ impl AsyncCursor { &self.reader } - pub(crate) async fn get_range(&mut self, range: Range) -> Result { - self.reader.get_bytes(range).await - } - /// Advance cursor position by a set amount pub(crate) fn advance(&mut self, amount: usize) { self.offset += amount; diff --git a/src/cog.rs b/src/cog.rs index 67bf823..abb2416 100644 --- a/src/cog.rs +++ b/src/cog.rs @@ -65,9 +65,10 @@ mod test { use object_store::local::LocalFileSystem; use tiff::decoder::{DecodingResult, Limits}; + #[ignore = "local file"] #[tokio::test] async fn tmp() { - let folder = "/Users/kyle/github/developmentseed/aiocogeo-rs/"; + let folder = "/Users/kyle/github/developmentseed/async-tiff/"; let path = object_store::path::Path::parse("m_4007307_sw_18_060_20220803.tif").unwrap(); let store = Arc::new(LocalFileSystem::new_with_prefix(folder).unwrap()); let reader = ObjectReader::new(store, path); @@ -79,10 +80,10 @@ mod test { // dbg!(tile.len()); } + #[ignore = "local file"] #[test] fn tmp_tiff_example() { - let path = - "/Users/kyle/github/developmentseed/aiocogeo-rs/m_4007307_sw_18_060_20220803.tif"; + let path = "/Users/kyle/github/developmentseed/async-tiff/m_4007307_sw_18_060_20220803.tif"; let reader = std::fs::File::open(path).unwrap(); let mut decoder = tiff::decoder::Decoder::new(BufReader::new(reader)) .unwrap() diff --git a/src/geo/affine.rs b/src/geo/affine.rs index 17bf857..875d134 100644 --- a/src/geo/affine.rs +++ b/src/geo/affine.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub struct AffineTransform(f64, f64, f64, f64, f64, f64); impl AffineTransform { diff --git a/src/ifd.rs b/src/ifd.rs index 12f0db9..e248011 100644 --- a/src/ifd.rs +++ b/src/ifd.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; use std::io::{Cursor, Read}; +use std::ops::Range; use byteorder::{LittleEndian, ReadBytesExt}; use bytes::{Buf, Bytes}; @@ -528,20 +529,22 @@ impl ImageFileDirectory { } } + fn get_tile_byte_range(&self, x: usize, y: usize) -> Range { + let idx = (y * self.tile_count().0) + x; + let offset = self.tile_offsets[idx] as usize; + // TODO: aiocogeo has a -1 here, but I think that was in error + let byte_count = self.tile_byte_counts[idx] as usize; + offset..offset + byte_count + } + pub async fn get_tile( &self, x: usize, y: usize, - reader: Box, + mut reader: Box, ) -> Result { - let mut cursor = AsyncCursor::new(reader); - - let idx = (y * self.tile_count().0) + x; - let offset = self.tile_offsets[idx] as usize; - // TODO: aiocogeo has a -1 here, but I think that was in error - let byte_count = self.tile_byte_counts[idx] as usize; - let range = offset..offset + byte_count; - let buf = cursor.get_range(range).await?; + let range = self.get_tile_byte_range(x, y); + let buf = reader.get_bytes(range).await?; decode_tile( buf, self.photometric_interpretation, @@ -550,6 +553,38 @@ impl ImageFileDirectory { ) } + pub async fn get_tiles( + &self, + x: &[usize], + y: &[usize], + mut reader: Box, + ) -> Result> { + assert_eq!(x.len(), y.len(), "x and y should have same len"); + + // 1: Get all the byte ranges for all tiles + let byte_ranges: Vec<_> = x + .iter() + .zip(y) + .map(|(x, y)| self.get_tile_byte_range(*x, *y)) + .collect(); + + // 2: Fetch using `get_ranges + let buffers = reader.get_byte_ranges(byte_ranges).await?; + + // 3: Decode tiles (in the future, separate API) + let mut decoded_tiles = vec![]; + for buf in buffers { + let decoded = decode_tile( + buf, + self.photometric_interpretation, + self.compression, + self.jpeg_tables.as_ref(), + )?; + decoded_tiles.push(decoded); + } + Ok(decoded_tiles) + } + /// Return the number of x/y tiles in the IFD pub fn tile_count(&self) -> (usize, usize) { let x_count = (self.image_width as f64 / self.tile_width as f64).ceil();