Skip to content

Tile request coalescing #11

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 4 commits into from
Feb 21, 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
4 changes: 0 additions & 4 deletions src/async_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,6 @@ impl AsyncCursor {
&self.reader
}

pub(crate) async fn get_range(&mut self, range: Range<usize>) -> Result<Bytes> {
self.reader.get_bytes(range).await
}

/// Advance cursor position by a set amount
pub(crate) fn advance(&mut self, amount: usize) {
self.offset += amount;
Expand Down
7 changes: 4 additions & 3 deletions src/cog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions src/geo/affine.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[derive(Debug)]
pub struct AffineTransform(f64, f64, f64, f64, f64, f64);

impl AffineTransform {
Expand Down
53 changes: 44 additions & 9 deletions src/ifd.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -528,20 +529,22 @@ impl ImageFileDirectory {
}
}

fn get_tile_byte_range(&self, x: usize, y: usize) -> Range<usize> {
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<dyn AsyncFileReader>,
mut reader: Box<dyn AsyncFileReader>,
) -> Result<Bytes> {
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,
Expand All @@ -550,6 +553,38 @@ impl ImageFileDirectory {
)
}

pub async fn get_tiles(
&self,
x: &[usize],
y: &[usize],
mut reader: Box<dyn AsyncFileReader>,
) -> Result<Vec<Bytes>> {
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();
Expand Down
Loading