diff options
Diffstat (limited to 'vendor/exr/examples/8_read_raw_blocks.rs')
-rw-r--r-- | vendor/exr/examples/8_read_raw_blocks.rs | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/vendor/exr/examples/8_read_raw_blocks.rs b/vendor/exr/examples/8_read_raw_blocks.rs new file mode 100644 index 0000000..4864c98 --- /dev/null +++ b/vendor/exr/examples/8_read_raw_blocks.rs @@ -0,0 +1,129 @@ + +extern crate rand; +extern crate half; + +use std::io::{BufReader}; +use std::fs::File; +use exr::block::reader::ChunksReader; + +// exr imports +extern crate exr; + + +/// Collects the average pixel value for each channel. +/// Does not load the whole image into memory at once: only processes the image block by block. +/// On my machine, this program analyzes a 3GB file while only allocating 1.1MB. +fn main() { + use exr::prelude::*; + + let file = BufReader::new( + File::open("3GB.exr") + .expect("run example `7_write_raw_blocks` to generate this image file") + ); + + + // -- the following structs will hold the collected data from the image -- + + /// Collect averages for each layer in the image + #[derive(Debug)] + struct Layer { + #[allow(unused)] // note: is used in Debug impl + layer_name: Option<Text>, + + data_window: IntegerBounds, + + /// Collect one average float per channel in the layer + channels: Vec<Channel>, + } + + /// A single channel in the layer, holds a single average value + #[derive(Debug)] + struct Channel { + #[allow(unused)] // note: is used in Debug impl + channel_name: Text, + + sample_type: SampleType, // f32, u32, or f16 + average: f32, + } + + let start_time = ::std::time::Instant::now(); + + + // -- read the file, summing up the average pixel values -- + + // start reading the file, extracting the meta data of the image + let reader = exr::block::read(file, true).unwrap(); + + // print progress only if it advances more than 1% + let mut current_progress_percentage = 0; + + // create the empty data structure that will collect the analyzed results, + // based on the extracted meta data of the file + let mut averages = reader.headers().iter() + // create a layer for each header in the file + .map(|header| Layer { + layer_name: header.own_attributes.layer_name.clone(), + data_window: header.data_window(), + + // create a averaging channel for each channel in the file + channels: header.channels.list.iter() + .map(|channel| Channel { + channel_name: channel.name.clone(), + sample_type: channel.sample_type, + average: 0.0 + }) + .collect() + }) + .collect::<Vec<_>>(); + + // create a reader that loads only relevant chunks from the file, and also prints something on progress + let reader = reader + + // do not worry about multi-resolution levels or deep data + .filter_chunks(true, |meta_data, tile, block| { + let header = &meta_data.headers[block.layer]; + !header.deep && tile.is_largest_resolution_level() + }).unwrap() + + .on_progress(|progress|{ + let new_progress = (progress * 100.0) as usize; + if new_progress != current_progress_percentage { + current_progress_percentage = new_progress; + println!("progress: {}%", current_progress_percentage) + } + }); + + // read all pixel blocks from the image, decompressing in parallel + reader.decompress_parallel(true, |meta_data, block|{ + let header = &meta_data.headers[block.index.layer]; + + // collect all pixel values from the pixel block + for line in block.lines(&header.channels) { + let layer = &mut averages[line.location.layer]; + let channel = &mut layer.channels[line.location.channel]; + let channel_sample_count = layer.data_window.size.area() as f32; + + // now sum the average based on the values in this line section of pixels + match channel.sample_type { + SampleType::F16 => for value in line.read_samples::<f16>() { + channel.average += value?.to_f32() / channel_sample_count; + }, + + SampleType::F32 => for value in line.read_samples::<f32>() { + channel.average += value? / channel_sample_count; + }, + + SampleType::U32 => for value in line.read_samples::<u32>() { + channel.average += (value? as f32) / channel_sample_count; + }, + } + } + + Ok(()) + }).unwrap(); + + println!("average values: {:#?}", averages); + + // warning: highly unscientific benchmarks ahead! + println!("\nprocessed file in {:?}s", start_time.elapsed().as_secs_f32()); +}
\ No newline at end of file |