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_pixels: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_pixels: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 | |