Skip to content

Commit

Permalink
make some minimal changes on the api
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesvollmer committed Oct 8, 2023
1 parent 48fe94f commit 05670f5
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 26 deletions.
20 changes: 13 additions & 7 deletions examples/9_read_blocks_on_demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,36 +38,42 @@ fn main() {
let mut chunk_reader = exr::block::read(file, true).unwrap()
.on_demand_chunks().unwrap();

let header_index = 0; // only load pixels from the first header (assumes first layer has rgb channels)
let layer_index = 0; // only load pixels from the first "header" (assumes first layer has rgb channels)
let mip_level = (0, 0); // only load largest mip map
println!("loading header #0 from {:#?}", chunk_reader.meta_data());

let exr_info = &chunk_reader.meta_data().clone();
let layer_info = &exr_info.headers[layer_index];
let channel_info = &layer_info.channels;
println!("loading header #0 from {:#?}", exr_info);

// this object can decode packed exr blocks to simple rgb (can be shared or cloned across threads)
let rgb_from_block_extractor = read_specific_channels()
.required("R").required("G").required("B")
.optional("A", 1.0)
.create_recursive_reader(&chunk_reader.header(header_index).channels).unwrap(); // this will fail if the image does not contain rgb channels
.create_recursive_reader(channel_info).unwrap(); // this will fail if the image does not contain rgb channels


// ...
// later in your app, maybe when the view changed:
when_new_pixel_section_must_be_loaded(move |pixel_section| {

// todo: only load blocks that are not loaded yet. maybe an additional filter? or replace this with a more modular filtering architecture?
let compressed_chunks = chunk_reader
.load_all_chunks_for_display_space_section(header_index, mip_level, pixel_section)
.load_all_chunks_for_display_space_section(layer_index, mip_level, pixel_section)

// in this example, we use .flatten(), this simply discards all errors and only continues with the successfully loaded chunks
// in this example, we collect here due to borrowing meta data
.flatten().collect::<Vec<Chunk>>();

// this could be done in parallel, e.g. by using rayon par_iter
let packed_pixel_blocks = compressed_chunks.into_iter()
.map(|chunk| UncompressedBlock::decompress_chunk(chunk, chunk_reader.meta_data(), true))
.map(|chunk| UncompressedBlock::decompress_chunk(chunk, exr_info, true))
.flatten();

// the exr blocks may contain arbitrary channels, but we are only interested in rgba.
// so we convert each exr block to an rgba block (vec of [f32; 4])
let rgba_blocks = packed_pixel_blocks.map(|block| {
let header = &chunk_reader.meta_data().headers[block.index.layer];
assert_eq!(block.index.layer, layer_index);

let position = block.index.pixel_position;
let size = block.index.pixel_size;
Expand All @@ -76,7 +82,7 @@ fn main() {
// decode individual pixels into our f32 buffer
// automatically converts f16 samples to f32 if required
// ignores all other channel data
rgb_from_block_extractor.read_block_pixels(header, block, |position, (r,g,b,a)|{
rgb_from_block_extractor.read_pixels_from_block(channel_info, block, |position, (r,g,b,a)|{
rgba_buffer[position.flat_index_for_size(size)] = [r,g,b,a];
});

Expand Down
12 changes: 0 additions & 12 deletions src/block/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -659,18 +659,6 @@ impl<R: Read + Seek> OnDemandChunksReader<R> {
.collect()
}

/*pub fn find_seek_position_for_block(&self, layer_index: usize, filter_blocks: impl Fn(TileIndices) -> bool) -> impl Iterator<> {
let header = &self.meta_data.headers[layer_index];
// TODO: directly compute the block index based on mip level and resolution??
let increasing_y_block_index_in_header = header.blocks_increasing_y_order()
.position(filter_blocks); // todo: this is a vec internally, save it in the reader and look it up at this point
let offset_table = &self.offset_tables[layer_index];
offset_table[increasing_y_block_index_in_header]
}*/


/// Reads the specified chunks by seeking the file. In the order as they appear in the file, so it might be arbitrary.
pub fn load_chunks(&mut self, mut chunks: Vec<u64>) -> impl '_ + Iterator<Item = Result<Chunk>> {
// sorting the file access should improve read performance, especially on HDDs
Expand Down
14 changes: 7 additions & 7 deletions src/image/read/specific_channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ pub trait RecursivePixelReader {

// TODO dedup with SpecificChannelsReader::read_block(..)?
/// Note: The (x,y) coordinates are in block space. You will have to add `block.index.pixel_position` for the pixel position in the layer.
fn read_block_pixels<Pixel>(
&self, header: &Header, block: UncompressedBlock,
mut set_pixel: impl FnMut(Vec2<usize>, Pixel)
fn read_pixels_from_block<PixelTuple>(
&self, channels: &ChannelList, block: UncompressedBlock,
mut set_pixel: impl FnMut(Vec2<usize>, PixelTuple)
)
where Self::RecursivePixel: IntoTuple<Pixel>
where Self::RecursivePixel: IntoTuple<PixelTuple>
{
let mut one_line_of_recursive_pixels = vec![Self::RecursivePixel::default(); block.index.pixel_size.width()];

let byte_lines = block.data.chunks_exact(header.channels.bytes_per_pixel * block.index.pixel_size.width());
let byte_lines = block.data.chunks_exact(channels.bytes_per_pixel * block.index.pixel_size.width());
debug_assert_eq!(byte_lines.len(), block.index.pixel_size.height(), "invalid block lines split");

for (y_offset, line_bytes) in byte_lines.enumerate() { // TODO sampling
Expand Down Expand Up @@ -211,8 +211,8 @@ ChannelsReader for SpecificChannelsReader<PixelStorage, SetPixel, PxReader, Pixe
let (storage, set_pixel, reader) = (&mut self.pixel_storage, &mut self.set_pixel, &self.pixel_reader);
let block_position = block.index.pixel_position;

reader.read_block_pixels(
header, block,
reader.read_pixels_from_block(
&header.channels, block,
|pos, px| set_pixel(storage, pos + block_position, px)
);

Expand Down

0 comments on commit 05670f5

Please sign in to comment.