| 1 |
|
| 2 | //! Read an exr image.
|
| 3 | //!
|
| 4 | //! For great flexibility and customization, use the `read()` function.
|
| 5 | //! The return value of the `read()` function must be further customized before reading a file.
|
| 6 |
|
| 7 | //!
|
| 8 | //! For very simple applications, you can alternatively use one of these functions:
|
| 9 | //!
|
| 10 | //! 1. `read_first_rgba_layer_from_file(path, your_constructor, your_pixel_setter)`:
|
| 11 | //! You specify how to store the pixels.
|
| 12 | //! The first layer containing rgba channels is then loaded from the file.
|
| 13 | //! Fails if no rgba layer can be found.
|
| 14 | //!
|
| 15 | //! 1. `read_all_rgba_layers_from_file(path, your_constructor, your_pixel_setter)`:
|
| 16 | //! You specify how to store the pixels.
|
| 17 | //! All layers containing rgba channels are then loaded from the file.
|
| 18 | //! Fails if any layer in the image does not contain rgba channels.
|
| 19 | //!
|
| 20 | //! 1. `read_first_flat_layer_from_file(path)`:
|
| 21 | //! The first layer containing non-deep data with arbitrary channels is loaded from the file.
|
| 22 | //! Fails if no non-deep layer can be found.
|
| 23 | //!
|
| 24 | //! 1. `read_all_flat_layers_from_file(path)`:
|
| 25 | //! All layers containing non-deep data with arbitrary channels are loaded from the file.
|
| 26 | //! Fails if any layer in the image contains deep data.
|
| 27 | //!
|
| 28 | //! 1. `read_all_data_from_file(path)`:
|
| 29 | //! All layers with arbitrary channels and all resolution levels are extracted from the file.
|
| 30 | //!
|
| 31 | //! Note: Currently does not support deep data, and currently fails
|
| 32 | //! if any layer in the image contains deep data.
|
| 33 | //!
|
| 34 |
|
| 35 | // The following three stages are internally used to read an image.
|
| 36 | // 1. `ReadImage` - The specification. Contains everything the user wants to tell us about loading an image.
|
| 37 | // The data in this structure will be instantiated and might be borrowed.
|
| 38 | // 2. `ImageReader` - The temporary reader. Based on the specification of the blueprint,
|
| 39 | // a reader is instantiated, once for each layer.
|
| 40 | // This data structure accumulates the image data from the file.
|
| 41 | // It also owns temporary data and references the blueprint.
|
| 42 | // 3. `Image` - The clean image. The accumulated data from the Reader
|
| 43 | // is converted to the clean image structure, without temporary data.
|
| 44 |
|
| 45 | pub mod image;
|
| 46 | pub mod layers;
|
| 47 | pub mod any_channels;
|
| 48 | pub mod levels;
|
| 49 | pub mod samples;
|
| 50 | pub mod specific_channels;
|
| 51 |
|
| 52 | use crate::error::{Result};
|
| 53 | use crate::image::read::samples::{ReadFlatSamples};
|
| 54 | use std::path::Path;
|
| 55 | use crate::image::{AnyImage, AnyChannels, FlatSamples, Image, Layer, FlatImage, PixelLayersImage, RgbaChannels};
|
| 56 | use crate::image::read::image::ReadLayers;
|
| 57 | use crate::image::read::layers::ReadChannels;
|
| 58 | use crate::math::Vec2;
|
| 59 | use crate::prelude::{PixelImage};
|
| 60 | use crate::block::samples::FromNativeSample;
|
| 61 |
|
| 62 |
|
| 63 | /// All resolution levels, all channels, all layers.
|
| 64 | /// Does not support deep data yet. Uses parallel decompression and relaxed error handling.
|
| 65 | /// Inspect the source code of this function if you need customization.
|
| 66 | pub fn read_all_data_from_file(path: impl AsRef<Path>) -> Result<AnyImage> {
|
| 67 | readReadImage>()
|
| 68 | .no_deep_data() // TODO deep data
|
| 69 | .all_resolution_levels()
|
| 70 | .all_channels()
|
| 71 | .all_layers()
|
| 72 | .all_attributes()
|
| 73 | .from_file(path)
|
| 74 | }
|
| 75 |
|
| 76 | // FIXME do not throw error on deep data but just skip it!
|
| 77 | /// No deep data, no resolution levels, all channels, all layers.
|
| 78 | /// Uses parallel decompression and relaxed error handling.
|
| 79 | /// Inspect the source code of this function if you need customization.
|
| 80 | pub fn read_all_flat_layers_from_file(path: impl AsRef<Path>) -> Result<FlatImage> {
|
| 81 | readReadImage>()
|
| 82 | .no_deep_data()
|
| 83 | .largest_resolution_level()
|
| 84 | .all_channels()
|
| 85 | .all_layers()
|
| 86 | .all_attributes()
|
| 87 | .from_file(path)
|
| 88 | }
|
| 89 |
|
| 90 | /// No deep data, no resolution levels, all channels, first layer.
|
| 91 | /// Uses parallel decompression and relaxed error handling.
|
| 92 | /// Inspect the source code of this function if you need customization.
|
| 93 | pub fn read_first_flat_layer_from_file(path: impl AsRef<Path>) -> Result<Image<Layer<AnyChannels<FlatSamples>>>> {
|
| 94 | readReadImage>()
|
| 95 | .no_deep_data()
|
| 96 | .largest_resolution_level()
|
| 97 | .all_channels()
|
| 98 | .first_valid_layer()
|
| 99 | .all_attributes()
|
| 100 | .from_file(path)
|
| 101 | }
|
| 102 |
|
| 103 | /// No deep data, no resolution levels, rgba channels, all layers.
|
| 104 | /// If a single layer does not contain rgba data, this method returns an error.
|
| 105 | /// Uses parallel decompression and relaxed error handling.
|
| 106 | /// `Create` and `Set` can be closures, see the examples for more information.
|
| 107 | /// Inspect the source code of this function if you need customization.
|
| 108 | /// The alpha channel will contain the value `1.0` if no alpha channel can be found in the image.
|
| 109 | ///
|
| 110 | /// Using two closures, define how to store the pixels.
|
| 111 | /// The first closure creates an image, and the second closure inserts a single pixel.
|
| 112 | /// The type of the pixel can be defined by the second closure;
|
| 113 | /// it must be a tuple containing four values, each being either `f16`, `f32`, `u32` or `Sample`.
|
| 114 | // FIXME Set and Create should not need to be static
|
| 115 | pub fn read_all_rgba_layers_from_file<R,G,B,A, Set:'static, Create:'static, Pixels: 'static>(
|
| 116 | path: impl AsRef<Path>, create: Create, set_pixel: Set
|
| 117 | )
|
| 118 | -> Result<PixelLayersImage<Pixels, RgbaChannels>>
|
| 119 | where
|
| 120 | R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample,
|
| 121 | Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels<Pixels=Pixels>,
|
| 122 | Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B,A)),
|
| 123 | {
|
| 124 | readReadImage>()
|
| 125 | .no_deep_data()
|
| 126 | .largest_resolution_level()
|
| 127 | .rgba_channels(create, set_pixel)
|
| 128 | .all_layers()
|
| 129 | .all_attributes()
|
| 130 | .from_file(path)
|
| 131 | }
|
| 132 |
|
| 133 | /// No deep data, no resolution levels, rgba channels, choosing the first layer with rgba channels.
|
| 134 | /// Uses parallel decompression and relaxed error handling.
|
| 135 | /// `Create` and `Set` can be closures, see the examples for more information.
|
| 136 | /// Inspect the source code of this function if you need customization.
|
| 137 | /// The alpha channel will contain the value `1.0` if no alpha channel can be found in the image.
|
| 138 | ///
|
| 139 | /// Using two closures, define how to store the pixels.
|
| 140 | /// The first closure creates an image, and the second closure inserts a single pixel.
|
| 141 | /// The type of the pixel can be defined by the second closure;
|
| 142 | /// it must be a tuple containing four values, each being either `f16`, `f32`, `u32` or `Sample`.
|
| 143 | // FIXME Set and Create should not need to be static
|
| 144 | pub fn read_first_rgba_layer_from_file<R,G,B,A, Set:'static, Create:'static, Pixels: 'static>(
|
| 145 | path: impl AsRef<Path>, create: Create, set_pixel: Set
|
| 146 | )
|
| 147 | -> Result<PixelImage<Pixels, RgbaChannels>>
|
| 148 | where
|
| 149 | R: FromNativeSample, G: FromNativeSample, B: FromNativeSample, A: FromNativeSample,
|
| 150 | Create: Fn(Vec2<usize>, &RgbaChannels) -> Pixels, // TODO type alias? CreateRgbaPixels<Pixels=Pixels>,
|
| 151 | Set: Fn(&mut Pixels, Vec2<usize>, (R,G,B,A)),
|
| 152 | {
|
| 153 | readReadImage>()
|
| 154 | .no_deep_data()
|
| 155 | .largest_resolution_level()
|
| 156 | .rgba_channels(create, set_pixel)
|
| 157 | .first_valid_layer()
|
| 158 | .all_attributes()
|
| 159 | .from_file(path)
|
| 160 | }
|
| 161 |
|
| 162 |
|
| 163 | /// Utilizes the builder pattern to configure an image reader. This is the initial struct.
|
| 164 | #[derive (Copy, Clone, Debug, Eq, PartialEq)]
|
| 165 | pub struct ReadBuilder;
|
| 166 |
|
| 167 | /// Create a reader which can be used to load an exr image.
|
| 168 | /// Allows you to exactly specify how to load the image, for example:
|
| 169 | ///
|
| 170 | /// ```no_run
|
| 171 | /// use exr::prelude::*;
|
| 172 | ///
|
| 173 | /// // the type of the this image depends on the chosen options
|
| 174 | /// let image = read()
|
| 175 | /// .no_deep_data() // (currently required)
|
| 176 | /// .largest_resolution_level() // or `all_resolution_levels()`
|
| 177 | /// .all_channels() // or `rgba_channels(constructor, setter)`
|
| 178 | /// .all_layers() // or `first_valid_layer()`
|
| 179 | /// .all_attributes() // (currently required)
|
| 180 | /// .on_progress(|progress| println!("progress: {:.1}" , progress*100.0)) // optional
|
| 181 | /// .from_file("image.exr" ).unwrap(); // or `from_buffered(my_byte_slice)`
|
| 182 | /// ```
|
| 183 | ///
|
| 184 | /// You can alternatively use one of the following simpler functions:
|
| 185 | /// 1. `read_first_flat_layer_from_file`
|
| 186 | /// 1. `read_all_rgba_layers_from_file`
|
| 187 | /// 1. `read_all_flat_layers_from_file`
|
| 188 | /// 1. `read_all_data_from_file`
|
| 189 | ///
|
| 190 | // TODO not panic but skip deep layers!
|
| 191 | pub fn read() -> ReadBuilder { ReadBuilder }
|
| 192 |
|
| 193 | impl ReadBuilder {
|
| 194 |
|
| 195 | /// Specify to handle only one sample per channel, disabling "deep data".
|
| 196 | // TODO not panic but skip deep layers!
|
| 197 | pub fn no_deep_data(self) -> ReadFlatSamples { ReadFlatSamples }
|
| 198 |
|
| 199 | // pub fn any_resolution_levels() -> ReadBuilder<> {}
|
| 200 |
|
| 201 | // TODO
|
| 202 | // e. g. `let sum = reader.any_channels_with(|sample, sum| sum += sample)`
|
| 203 | // e. g. `let floats = reader.any_channels_with(|sample, f32_samples| f32_samples[index] = sample as f32)`
|
| 204 | // pub fn no_deep_data_with <S> (self, storage: S) -> FlatSamplesWith<S> { }
|
| 205 |
|
| 206 | // pub fn flat_and_deep_data(self) -> ReadAnySamples { ReadAnySamples }
|
| 207 | }
|
| 208 | |