aboutsummaryrefslogtreecommitdiff
path: root/vendor/exr/GUIDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/exr/GUIDE.md')
-rw-r--r--vendor/exr/GUIDE.md588
1 files changed, 0 insertions, 588 deletions
diff --git a/vendor/exr/GUIDE.md b/vendor/exr/GUIDE.md
deleted file mode 100644
index 4f3cfaa..0000000
--- a/vendor/exr/GUIDE.md
+++ /dev/null
@@ -1,588 +0,0 @@
-# Guide
-
-This document talks about the capabilities of OpenEXR and outlines the design of this library.
-In addition to reading this guide, you should also have a look at the examples.
-
-Contents:
-- Wording
-- Why this is complicated
-- One-liners for reading and writing simple images
-- Reading a complex image
-- The Image data structure
-- Writing a complex image
-
-## Wording
-Some names in this library differ from the classic OpenEXR conventions.
-For example, an OpenEXR "multipart" is called a file with multiple "layers" in this library.
-The old OpenEXR "layers" are called "grouped channels" instead.
-
-- `Image` Contains everything that an `.exr` file can contain. Includes metadata and multiple layers.
-- `Layer` A grid of pixels that can be placed anywhere on the two-dimensional canvas
-- `Channel` All samples of a single color component, such as red or blue. Also contains metadata.
-- `Pixel` The color at an exact location in the image. Contains one sample for each channel.
-- `Sample` The value (either f16, f32 or u32) of one channel at an exact location in the image.
- Usually a simple number, such as the red value of the bottom left pixel.
-- `Grouped Channels` Multiple channels may be grouped my prepending the same prefix to the name.
- This behaviour is opt-in; it has to be enabled explicitly:
- By default, channels are stored in a plain list, and channel names are unmodified.
-- `pedantic: bool` When reading, pedantic being false will generally ignore
- invalid information instead of aborting the reading process where possible.
- When writing, pedantic being false will generally skip some expensive image validation checks.
-
-## OpenEXR | Complexity
-This image format supports some features that you won't find in other image formats.
-As a consequence, an exr file cannot necessarily be converted to other formats,
-even when the loss of precision is acceptable. Furthermore,
-an arbitrary exr image may include possibly unwanted data.
-Supporting deep data, for example, might be unnecessary for some applications.
-
-To read an image, `exrs` must know which parts of an image you want to end up with,
-and which parts of the file should be skipped. That's why you need
-a little more code to read an exr file, compared to simpler file formats.
-
-### Possibly Undesired Features
-- Arbitrary Channels:
- `CMYK`, `YCbCr`, `LAB`, `XYZ` channels might not be interesting for you,
- maybe you only want to accept `RGBA` images
-- Deep Data: Multiple colors per pixel might not be interesting for you
-- Resolution Levels: Mip Maps or Rip Maps might be unnecessary and can be skipped,
- loading only the full resolution image instead
-<!-- - TODO: Meta Data: Skip reading meta data -->
-
-# Simple Reading and Writing
-There are a few very simple functions for the most common use cases.
-For decoding an image file, use one of these functions
-from the `exr::image::read` module (data structure complexity increasing):
-
-1. `read_first_rgba_layer_from_file(path, your_constructor, your_pixel_setter)`
-1. `read_all_rgba_layers_from_file(path, your_constructor, your_pixel_setter)`
-1. `read_first_flat_layer_from_file(path)`
-1. `read_all_flat_layers_from_file(path)`
-1. `read_all_data_from_file(path)`
-
-If you don't have a file path, or want to load any other channels than `rgba`,
-then these simple functions will not suffice. The more complex approaches are
-described later in this document.
-
-For encoding an image file, use one of these functions in the `exr::image::write` module:
-
-1. `write_rgba_file(path, width, height, |x,y| my_image.get_rgb_at(x,y))`
-1. `write_rgb_file(path, width, height, |x,y| my_image.get_rgba_at(x,y))`
-
-These functions are only syntactic sugar. If you want to customize the data type,
-the compression method, or write multiple layers, these simple functions will not suffice.
-Again, the more complex approaches are described in the following paragraph.
-
-# Reading an Image
-
-Reading an image involves three steps:
-1. Specify how to load an image by constructing an image reader.
- 1. Start with `read()`
- 1. Chain method calls to customize the reader
-1. Call `from_file(path)`, `from_buffered(bytes)`, or `from_unbuffered(bytes)`
- on the reader to actually load an image
-1. Process the resulting image data structure or the error in your application
-
-The type of the resulting image depends on the reader you constructed. For example,
-if you configure the reader to load mip map levels, the resulting image type
-will contain an additional vector with the mip map levels.
-
-### Deep Data
-The first choice to be made is whether you want to load deep data or not.
-Deep data is where multiple colors are stored in one pixel at the same location.
-Currently, deep data is not supported yet, so we always call `no_deep_data()`.
-
-```rust
-fn main(){
- use exr::prelude::*;
- let reader = read().no_deep_data();
-}
-```
-
-### Resolution Levels
-Decide whether you want to load the largest resolution level, or all Mip Maps from the file.
-Loading only the largest level actually skips portions of the image, which should be faster.
-
-Calling `largest_resolution_level()` will result in a single image (`FlatSamples`),
-whereas calling `all_resolution_levels()` will result in multiple levels `Levels<FlatSamples>`.
-
-```rust
-fn main(){
- use exr::prelude::*;
- let reader = read().no_deep_data().largest_resolution_level();
- let reader = read().no_deep_data().all_resolution_levels();
-}
-```
-
-### Channels
-Decide whether you want to load all channels in a dynamic list, or only load a fixed set of channels.
-
-Calling `all_channels()` will result in a `Vec<Channel<_>>`.
-
-```rust
-fn main(){
- use exr::prelude::*;
- let reader = read().no_deep_data().largest_resolution_level().all_channels();
-}
-```
-
-The alternative, `specific_channels()` allows you to exactly specify which channels should be loaded.
-The usage follows the same builder pattern as the rest of the library.
-
-First, call `specific_channels()`. Then, for each channel you desire,
-call either `required(channel_name)` or `optional(channel_name, default_value)`.
-At last, call `collect_pixels()` to define how the pixels should be stored in an image.
-This additional mechanism will not simply store the pixels in a `Vec<Pixel>`, but instead
-works with a closure. This allows you to instantiate your own existing image type with
-the pixel data from the file.
-
-```rust
-fn main(){
- use exr::prelude::*;
-
- let reader = read()
- .no_deep_data().largest_resolution_level()
-
- // load LAB channels, with chroma being optional
- .specific_channels().required("L").optional("A", 0.0).optional("B", 0.0).collect_pixels(
-
- // create our image based on the resolution of the file
- |resolution: Vec2<usize>, (l,a,b): &(ChannelDescription, Option<ChannelDescription>, Option<ChannelDescription>)|{
- if a.is_some() && b.is_some() { MyImage::new_lab(resolution) }
- else { MyImage::new_luma(resolution) }
- },
-
- // insert a single pixel into out image
- |my_image: &mut MyImage, position: Vec<usize>, (l,a,b): (f32, f16, f16)|{
- my_image.set_pixel_at(position.x(), position.y(), (l, a, b));
- }
-
- );
-}
-```
-
-The first closure is the constructor of your image, and the second closure is the setter for a single pixel in your image.
-The tuple containing the channel descriptions and the pixel tuple depend on the channels that you defined earlier.
-In this example, as we defined to load L,A and B, each pixel has three values. The arguments of the closure
-can usually be inferred, so you don't need to declare the type of your image and the `Vec2<usize>`.
-However, the type of the pixel needs to be defined. In this example, we define the pixel type to be `(f32, f16, f16)`.
-All luma values will be converted to `f32` and all chroma values will be converted to `f16`.
-The pixel type can be any combination of `f16`, `f32`, `u32` or `Sample` values, in a tuple with as many entries as there are channels.
-The `Sample` type is a dynamic enum over the other types, which allows you to keep the original sample type of each image.
-
-_Note: Currently, up to 32 channels are supported, which is an implementation problem.
-Open an issue if this is not enough for your use case. Alternatively,
-you can always use `all_channels()`, which has no limitations._
-
-####RGBA Channels
-For rgba images, there is a predefined simpler alternative to `specific_channels` called `rgb_channels` and `rgba_channels`.
-It works just the same as `specific_channels` and , but you don't need to specify the names of the channels explicitly.
-
-```rust
-fn main(){
- use exr::prelude::*;
-
- let reader = read()
- .no_deep_data().largest_resolution_level()
-
- // load rgba channels
- // with alpha being optional, defaulting to 1.0
- .rgba_channels(
-
- // create our image based on the resolution of the file
- |resolution, &(r,g,b,a)|{
- if a.is_some() { MyImage::new_with_alpha(resolution.x(), resolution.y()) }
- else { MyImage::new_without_alpha(resolution.x(), resolution.y()) }
- },
-
- // insert a single pixel into out image
- |my_image, position, (r,g,b,a): (f32, f32, f32, f16)|{
- my_image.set_pixel_at(position.x(), position.y(), (r,g,b,a));
- }
-
- );
-}
-```
-
-
-### Layers
-Use `all_layers()` to load a `Vec<Layer<_>>` or use `first_valid_layer()` to only load
-the first `Layer<_>` that matches the previously defined requirements
-(for example, the first layer without deep data and cmyk channels).
-
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- let image = read()
- .no_deep_data().largest_resolution_level()
- .all_channels().all_layers();
-
- let image = read()
- .no_deep_data().largest_resolution_level()
- .all_channels().first_valid_layer();
-}
-```
-
-### Attributes
-Currently, the only option is to load all attributes by calling `all_attributes()`.
-
-### Progress Notification
-This library allows you to listen for the file reading progress by calling `on_progress(callback)`.
-If you don't need this, you can just omit this call.
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- let image = read().no_deep_data().largest_resolution_level()
- .all_channels().first_valid_layer().all_attributes()
- .on_progress(|progress: f64| println!("progress: {:.3}", progress));
-}
-```
-
-### Parallel Decompression
-By default, this library uses all the available CPU cores if the pixels are compressed.
-You can disable this behaviour by additionally calling `non_parallel()`.
-
-```rust
-fn main() {
-use exr::prelude::*;
-
- let image = read().no_deep_data().largest_resolution_level()
- .all_channels().first_valid_layer().all_attributes()
- .non_parallel();
-}
-```
-
-### Byte Sources
-Any `std::io::Read` byte source can be used as input. However, this library also offers a simplification for files.
-Call `from_file(path)` to load an image from a file. Internally, this wraps the file in a buffered reader.
-Alternatively, you can call `from_buffered` or `from_unbuffered` (which wraps your reader in a buffered reader) to read an image.
-
-```rust
-fn main() {
-use exr::prelude::*;
-
- let read = read().no_deep_data().largest_resolution_level()
- .all_channels().first_valid_layer().all_attributes();
-
- let image = read.clone().from_file("D:/images/file.exr"); // also accepts `Path` and `PathBuf` and `String`
- let image = read.clone().from_unbuffered(web_socket);
- let image = read.clone().from_buffered(Cursor::new(byte_vec));
-}
-```
-
-### Results and Errors
-The type of image returned depends on the options you picked.
-The image is wrapped in a `Result<..., exr::error::Error>`.
-This error type allows you to differentiate between three types of errors:
-- `Error::Io(std::io::Error)` for file system errors (for example, "file does not exist" or "missing access rights")
-- `Error::NotSupported(str)` for files that may be valid but contain features that are not supported yet
-- `Error::Invalid(str)` for files that do not contain a valid exr image (files that are not exr or damaged exr)
-
-## Full Example
-Loading all channels from the file:
-```rust
-fn main() {
- 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` or `specific_channels() ...`
- .all_layers() // or `first_valid_layer()`
- .all_attributes() // (currently required)
- .on_progress(|progress| println!("progress: {:.1}", progress * 100.0)) // optional
- //.non_parallel() // optional. discouraged. just leave this line out
- .from_file("image.exr").unwrap(); // or `from_buffered(my_byte_slice)`
-}
-```
-
-
-# The `Image` Data Structure
-
-For great flexibility, this crate does not offer a plain data structure to represent an exr image.
-Instead, the `Image` data type has a generic parameter, allowing for different image contents.
-
-```rust
-fn main(){
- // this image contains only a single layer
- let single_layer_image: Image<Layer<_>> = Image::from_layer(my_layer);
-
- // this image contains an arbitrary number of layers (notice the S for plural on `Layers`)
- let multi_layer_image: Image<Layers<_>> = Image::new(attributes, smallvec![ layer1, layer2 ]);
-
- // this image can contain the compile-time specified channels
- let single_layer_rgb_image : Image<Layer<SpecificChannels<_, _>>> = Image::from_layer(Layer::new(
- dimensions, attributes, encoding,
- RgbaChannels::new(sample_types, rgba_pixels)
- ));
-
- // this image can contain all channels from a file, even unexpected ones
- let single_layer_image : Image<Layer<AnyChannels<_>>> = Image::from_layer(Layer::new(
- dimensions, attributes, encoding,
- AnyChannels::sort(smallvec![ channel_x, channel_y, channel_z ])
- ));
-
-}
-```
-
-The following pseudo code illustrates the image data structure.
-The image should always be constructed using the constructor functions such as `Image::new(...)`,
-because these functions watch out for invalid image contents.
-
-```
-Image {
- attributes: ImageAttributes,
-
- // the layer data can be either a single layer a list of layers
- layer_data: Layer | SmallVec<Layer> | Vec<Layer> | &[Layer] (writing only),
-}
-
-Layer {
-
- // the channel data can either be a fixed set of known channels, or a dynamic list of arbitrary channels
- channel_data: SpecificChannels | AnyChannels,
-
- attributes: LayerAttributes,
- size: Vec2<usize>,
- encoding: Encoding,
-}
-
-SpecificChannels {
- channels: [any tuple containing `ChannelDescription` or `Option<ChannelDescription>`],
-
- // the storage is usually a closure or a custom type which implements the `GetPixel` trait
- storage: impl GetPixel | impl Fn(Vec2<usize>) -> Pixel,
- where Pixel = any tuple containing f16 or f32 or u32 values
-}
-
-AnyChannels {
- list: SmallVec<AnyChannel>
-}
-
-AnyChannel {
- name: Text,
- sample_data: FlatSamples | Levels,
- quantize_linearly: bool,
- sampling: Vec2<usize>,
-}
-
-Levels = Singular(FlatSamples) | Mip(FlatSamples) | Rip(FlatSamples)
-FlatSamples = F16(Vec<f16>) | F32(Vec<f32>) | U32(Vec<u32>)
-```
-
-As a consequence, one of the simpler image types is `Image<Layer<AnyChannels<FlatSamples>>>`. If you
-enable loading multiple resolution levels, you will instead get the type `Image<Layer<AnyChannels<Levels<FlatSamples>>>>`.
-
-While you can put anything inside an image,
-it can only be written if the content of the image implements certain traits.
-This allows you to potentially write your own channel storage system.
-
-
-# Writing an Image
-
-Writing an image involves three steps:
-1. Construct the image data structure, starting with an `exrs::image::Image`
-1. Call `image_data.write()` to obtain an image writer
-1. Customize the writer, for example in order to listen for the progress
-1. Write the image by calling `to_file(path)`, `to_buffered(bytes)`, or `to_unbuffered(bytes)` on the reader
-
-
-### Image
-You will currently need an `Image<_>` at the top level. The type parameter is the type of layer.
-
-The following variants are recommended:
-- `Image::from_channels(resolution, channels)` where the pixel data must be `SpecificChannels` or `AnyChannels`.
-- `Image::from_layer(layer)` where the layer data must be one `Layer`.
-- `Image::empty(attributes).with_layer(layer1).with_layer(layer2)...` where the two layers can have different types
-- `Image::new(image_attributes, layer_data)` where the layer data can be `Layers` or `Layer`.
-- `Image::from_layers(image_attributes, layer_vec)` where the layer data can be `Layers`.
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- // single layer constructors
- let image = Image::from_layer(layer);
- let image = Image::from_channels(resolution, channels);
-
- // use this if the layers have different types
- let image = Image::empty(attributes).with_layer(layer1).with_layer(layer2);
-
- // use this if the layers have the same type and the above method does not work for you
- let image = Image::from_layers(attributes, smallvec![ layer1, layer2 ]);
-
- // this constructor accepts any layers object if it implements a certain trait, use this for custom layers
- let image = Image::new(attributes, layers);
-
-
- // create an image writer
- image.write()
-
- // print progress (optional, you can remove this line)
- .on_progress(|progress:f64| println!("progress: {:.3}", progress))
-
- // use only a single cpu (optional, you should remove this line)
- // .non_parallel()
-
- // alternatively call to_buffered() or to_unbuffered()
- // the file path can be str, String, Path, PathBuf
- .to_file(path);
-}
-```
-
-### Layers
-The simple way to create layers is to use `Layers<_>` or `Layer<_>`.
-The type parameter is the type of channels.
-
-Use `Layer::new(resolution, attributes, encoding, channels)` to create a layer.
-Alternatively, use `smallvec![ layer1, layer2 ]` to create `Layers<_>`, which is a type alias for a list of layers.
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- let layer = Layer::new(
- (1024, 800),
- LayerAttributes::named("first layer"), // name required, other attributes optional
- Encoding::FAST_LOSSLESS, // or Encoding { .. } or Encoding::default()
- channels
- );
-
- let image = Image::from_layer(layer);
-}
-```
-
-
-### Channels
-You can create either `SpecificChannels` to write a fixed set of channels, or `AnyChannels` for a dynamic list of channels.
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- let channels = AnyChannels::sort(smallvec![ channel1, channel2, channel3 ]);
- let image = Image::from_channels((1024, 800), channels);
-}
-```
-
-Alternatively, write specific channels. Start with `SpecificChannels::build()`,
-then call `with_channel(name)` as many times as desired, then call `collect_pixels(..)` to define the colors.
-You need to provide a closure that defines the content of the channels: Given the pixel location,
-return a tuple with one element per channel. The tuple can contain `f16`, `f32` or `u32` values,
-which then will be written to the file, without converting any value to a different type.
-
-```rust
-fn main() {
- use exr::prelude::*;
-
- let channels = SpecificChannels::build()
- .with_channel("L").with_channel("B")
- .with_pixel_fn(|position: Vec2<usize>| {
- let (l, b) = my_image.lookup_color_at(position.x(), position.y());
- (l as f32, f16::from_f32(b))
- });
-
- let image = Image::from_channels((1024, 800), channels);
-}
-```
-
-#### RGB, RGBA
-There is an even simpler alternative for rgba images, namely `SpecificChannels::rgb` and `SpecificChannels::rgba`:
-This is mostly the same as the `SpecificChannels::build` option.
-
-The rgb method works with three channels per pixel,
-whereas the rgba method works with four channels per pixel. The default alpha value of `1.0` will be used
-if the image does not contain alpha.
-```rust
-fn main() {
- use exr::prelude::*;
-
- let channels = SpecificChannels::rgba(|_position|
- (0.4_f32, 0.2_f32, 0.1_f32, f16::ONE)
- );
-
- let channels = SpecificChannels::rgb(|_position|
- (0.4_f32, 0.2_f32, 0.1_f32)
- );
-
- let image = Image::from_channels((1024, 800), channels);
-}
-```
-
-### Channel
-The type `AnyChannel` can describe every possible channel and contains all its samples for this layer.
-Use `AnyChannel::new(channel_name, sample_data)` or `AnyChannel { .. }`.
-The samples can currently only be `FlatSamples` or `Levels<FlatSamples>`, and in the future might be `DeepSamples`.
-
-### Samples
-Currently, only flat samples are supported. These do not contain deep data.
-Construct flat samples directly using `FlatSamples::F16(samples_vec)`, `FlatSamples::F32(samples_vec)`, or `FlatSamples::U32(samples_vec)`.
-The vector contains all samples of the layer, row by row (from top to bottom), from left to right.
-
-### Levels
-Optionally include Mip Maps or Rip Maps.
-Construct directly using `Levels::Singular(flat_samples)` or `Levels::Mip { .. }` or `Levels::Rip { .. }`.
-Put this into the channel, for example`AnyChannel::new("R", Levels::Singular(FlatSamples::F32(vec)))`.
-
-## Full example
-Writing a flexible list of channels:
-```rust
-fn main(){
- // construct an image to write
- let image = Image::from_layer(
- Layer::new( // the only layer in this image
- (1920, 1080), // resolution
- LayerAttributes::named("main-rgb-layer"), // the layer has a name and other properties
- Encoding::FAST_LOSSLESS, // compress slightly
- AnyChannels::sort(smallvec![ // the channels contain the actual pixel data
- AnyChannel::new("R", FlatSamples::F32(vec![0.6; 1920*1080 ])), // this channel contains all red values
- AnyChannel::new("G", FlatSamples::F32(vec![0.7; 1920*1080 ])), // this channel contains all green values
- AnyChannel::new("B", FlatSamples::F32(vec![0.9; 1920*1080 ])), // this channel contains all blue values
- ]),
- )
- );
-
- image.write()
- .on_progress(|progress| println!("progress: {:.1}", progress*100.0)) // optional
- .to_file("image.exr").unwrap();
-}
-```
-
-
-### Pixel Closures
-When working with specific channels, the data is not stored directly.
-Instead, you provide a closure that stores or loads pixels in your existing image data structure.
-
-If you really do not want to provide your own storage, you can use the predefined structures from
-`exr::image::pixel_vec`, such as `PixelVec<(f32,f32,f16)>` or `create_pixel_vec`.
-Use this only if you don't already have a pixel storage.
-
-```rust
-fn main(){
- let read = read()
- .no_deep_data().largest_resolution_level()
- .rgba_channels(
- PixelVec::<(f32,f32,f32,f16)>::constructor, // how to create an image
- PixelVec::set_pixel, // how to update a single pixel in the image
- )/* ... */;
-}
-```
-
-
-## Low Level Operations
-The image abstraction builds up on some low level code.
-You can use this low level directly,
-as shown in the examples `custom_write.rs` and `custom_read.rs`.
-This allows you to work with
-raw OpenEXR pixel blocks and chunks directly,
-or use custom parallelization mechanisms.
-
-You can find these low level operations in the `exr::block` module.
-Start with the `block::read(...)`
-and `block::write(...)` functions.
-