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
45pub mod image;
46pub mod layers;
47pub mod any_channels;
48pub mod levels;
49pub mod samples;
50pub mod specific_channels;
51
52use crate::error::{Result};
53use crate::image::read::samples::{ReadFlatSamples};
54use std::path::Path;
55use crate::image::{AnyImage, AnyChannels, FlatSamples, Image, Layer, FlatImage, PixelLayersImage, RgbaChannels};
56use crate::image::read::image::ReadLayers;
57use crate::image::read::layers::ReadChannels;
58use crate::math::Vec2;
59use crate::prelude::{PixelImage};
60use 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.
66pub 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.
80pub 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.
93pub 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
115pub 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
144pub 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)]
165pub 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!
191pub fn read() -> ReadBuilder { ReadBuilder }
192
193impl 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