//! Read an exr image. //! //! For great flexibility and customization, use the `read()` function. //! The return value of the `read()` function must be further customized before reading a file. //! //! For very simple applications, you can alternatively use one of these functions: //! //! 1. `read_first_rgba_layer_from_file(path, your_constructor, your_pixel_setter)`: //! You specify how to store the pixels. //! The first layer containing rgba channels is then loaded from the file. //! Fails if no rgba layer can be found. //! //! 1. `read_all_rgba_layers_from_file(path, your_constructor, your_pixel_setter)`: //! You specify how to store the pixels. //! All layers containing rgba channels are then loaded from the file. //! Fails if any layer in the image does not contain rgba channels. //! //! 1. `read_first_flat_layer_from_file(path)`: //! The first layer containing non-deep data with arbitrary channels is loaded from the file. //! Fails if no non-deep layer can be found. //! //! 1. `read_all_flat_layers_from_file(path)`: //! All layers containing non-deep data with arbitrary channels are loaded from the file. //! Fails if any layer in the image contains deep data. //! //! 1. `read_all_data_from_file(path)`: //! All layers with arbitrary channels and all resolution levels are extracted from the file. //! //! Note: Currently does not support deep data, and currently fails //! if any layer in the image contains deep data. //! // The following three stages are internally used to read an image. // 1. `ReadImage` - The specification. Contains everything the user wants to tell us about loading an image. // The data in this structure will be instantiated and might be borrowed. // 2. `ImageReader` - The temporary reader. Based on the specification of the blueprint, // a reader is instantiated, once for each layer. // This data structure accumulates the image data from the file. // It also owns temporary data and references the blueprint. // 3. `Image` - The clean image. The accumulated data from the Reader // is converted to the clean image structure, without temporary data. pub mod image; pub mod layers; pub mod any_channels; pub mod levels; pub mod samples; pub mod specific_channels; use crate::error::{Result}; use crate::image::read::samples::{ReadFlatSamples}; use std::path::Path; use crate::image::{AnyImage, AnyChannels, FlatSamples, Image, Layer, FlatImage, PixelLayersImage, RgbaChannels}; use crate::image::read::image::ReadLayers; use crate::image::read::layers::ReadChannels; use crate::math::Vec2; use crate::prelude::{PixelImage}; use crate::block::samples::FromNativeSample; /// All resolution levels, all channels, all layers. /// Does not support deep data yet. Uses parallel decompression and relaxed error handling. /// Inspect the source code of this function if you need customization. pub fn read_all_data_from_file(path: impl AsRef) -> Result { read() .no_deep_data() // TODO deep data .all_resolution_levels() .all_channels() .all_layers() .all_attributes() .from_file(path) } // FIXME do not throw error on deep data but just skip it! /// No deep data, no resolution levels, all channels, all layers. /// Uses parallel decompression and relaxed error handling. /// Inspect the source code of this function if you need customization. pub fn read_all_flat_layers_from_file(path: impl AsRef) -> Result { read() .no_deep_data() .largest_resolution_level() .all_channels() .all_layers() .all_attributes() .from_file(path) } /// No deep data, no resolution levels, all channels, first layer. /// Uses parallel decompression and relaxed error handling. /// Inspect the source code of this function if you need customization. pub fn read_first_flat_layer_from_file(path: impl AsRef) -> Result>>> { read() .no_deep_data() .largest_resolution_level() .all_channels() .first_valid_layer() .all_attributes() .from_file(path) } /// No deep data, no resolution levels, rgba channels, all layers. /// If a single layer does not contain rgba data, this method returns an error. /// Uses parallel decompression and relaxed error handling. /// `Create` and `Set` can be closures, see the examples for more information. /// Inspect the source code of this function if you need customization. /// The alpha channel will contain the value `1.0` if no alpha channel can be found in the image. /// /// Using two closures, define how to store the pixels. /// The first closure creates an image, and the second closure inserts a single pixel. /// The type of the pixel can be defined by the second closure; /// it must be a tuple containing four values, each being either `f16`, `f32`, `u32` or `Sample`. // FIXME Set and Create should not need to be static pub fn read_all_rgba_layers_from_file( path: impl AsRef, create: Create, set_pixel: Set ) -> Result> where R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample, Create: Fn(Vec2, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels, Set: Fn(&mut Pixels, Vec2, (R,G,B,A)), { read() .no_deep_data() .largest_resolution_level() .rgba_channels(create, set_pixel) .all_layers() .all_attributes() .from_file(path) } /// No deep data, no resolution levels, rgba channels, choosing the first layer with rgba channels. /// Uses parallel decompression and relaxed error handling. /// `Create` and `Set` can be closures, see the examples for more information. /// Inspect the source code of this function if you need customization. /// The alpha channel will contain the value `1.0` if no alpha channel can be found in the image. /// /// Using two closures, define how to store the pixels. /// The first closure creates an image, and the second closure inserts a single pixel. /// The type of the pixel can be defined by the second closure; /// it must be a tuple containing four values, each being either `f16`, `f32`, `u32` or `Sample`. // FIXME Set and Create should not need to be static pub fn read_first_rgba_layer_from_file( path: impl AsRef, create: Create, set_pixel: Set ) -> Result> where R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample, Create: Fn(Vec2, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels, Set: Fn(&mut Pixels, Vec2, (R,G,B,A)), { read() .no_deep_data() .largest_resolution_level() .rgba_channels(create, set_pixel) .first_valid_layer() .all_attributes() .from_file(path) } /// Utilizes the builder pattern to configure an image reader. This is the initial struct. #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct ReadBuilder; /// Create a reader which can be used to load an exr image. /// Allows you to exactly specify how to load the image, for example: /// /// ```no_run /// use exr::prelude::*; /// /// // the type of the this image depends on the chosen options /// let image = read() /// .no_deep_data() // (currently required) /// .largest_resolution_level() // or `all_resolution_levels()` /// .all_channels() // or `rgba_channels(constructor, setter)` /// .all_layers() // or `first_valid_layer()` /// .all_attributes() // (currently required) /// .on_progress(|progress| println!("progress: {:.1}", progress*100.0)) // optional /// .from_file("image.exr").unwrap(); // or `from_buffered(my_byte_slice)` /// ``` /// /// You can alternatively use one of the following simpler functions: /// 1. `read_first_flat_layer_from_file` /// 1. `read_all_rgba_layers_from_file` /// 1. `read_all_flat_layers_from_file` /// 1. `read_all_data_from_file` /// // TODO not panic but skip deep layers! pub fn read() -> ReadBuilder { ReadBuilder } impl ReadBuilder { /// Specify to handle only one sample per channel, disabling "deep data". // TODO not panic but skip deep layers! pub fn no_deep_data(self) -> ReadFlatSamples { ReadFlatSamples } // pub fn any_resolution_levels() -> ReadBuilder<> {} // TODO // e. g. `let sum = reader.any_channels_with(|sample, sum| sum += sample)` // e. g. `let floats = reader.any_channels_with(|sample, f32_samples| f32_samples[index] = sample as f32)` // pub fn no_deep_data_with (self, storage: S) -> FlatSamplesWith { } // pub fn flat_and_deep_data(self) -> ReadAnySamples { ReadAnySamples } }