Skip to content

Commit 1bba7f7

Browse files
Merge pull request #92 from johannesvollmer/api-rework
The new API (finally)
2 parents 1545833 + 29c3d1f commit 1bba7f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4351
-3302
lines changed

Cargo.lock

Lines changed: 150 additions & 152 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description = "Read and write OpenEXR files without any unsafe code"
44
keywords = ["exr", "openexr", "file", "binary", "io"]
55
categories = ["encoding", "filesystem", "graphics", "multimedia"]
66

7-
version = "0.9.0"
7+
version = "1.0.0"
88
edition = "2018"
99
authors = ["johannesvollmer <[email protected]>"]
1010

README.md

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
[![Rust Docs](https://docs.rs/exr/badge.svg)](https://docs.rs/exr)
22
[![Crate Crate](https://img.shields.io/crates/v/exr.svg)](https://crates.io/crates/exr)
3-
[![Rust Lang Version](https://img.shields.io/badge/rustc-1.43+-lightgray.svg)](https://blog.rust-lang.org/2020/04/23/Rust-1.43.0.html)
3+
[![Rust Lang Version](https://img.shields.io/badge/rustc-1.48+-lightgray.svg)](https://blog.rust-lang.org/2020/11/19/Rust-1.48.html)
44
[![Lines of Code](https://tokei.rs/b1/github/johannesvollmer/exrs?category=code)](https://tokei.rs)
55

66
# EXRS
77

88
This library is a 100% Rust and 100% safe code library for
99
reading and writing OpenEXR images.
10-
See [the examples](https://docs.rs/crate/exr/0.9.0/source/examples/) for a first impression.
10+
See [the examples](https://docs.rs/crate/exr/1.0.0/source/examples/) for a first impression.
1111

1212
[OpenEXR](http://www.openexr.com/)
1313
is the de-facto standard image format in animation, VFX, and
@@ -157,38 +157,34 @@ please leave an issue on this repository, containing the image file.
157157
Add this to your `Cargo.toml`:
158158
```toml
159159
[dependencies]
160-
exr = "0.9.0"
160+
exr = "1.0.0"
161161

162162
# also, optionally add this to your crate for smaller binary size
163163
# and better runtime performance
164164
[profile.release]
165165
lto = true
166166
```
167167

168-
The master branch of this repository is always an up-to-date version.
168+
The master branch of this repository is always an up-to-date version,
169+
so you could also link the github repository master branch.
169170

170171
### Example
171172

172-
Example: [Write a generated RGB exr file](https://github.com/johannesvollmer/exrs/blob/master/examples/1_minimal_rgb.rs).
173+
Example: [generate an rgb exr file](https://github.com/johannesvollmer/exrs/blob/master/examples/1_minimal_rgb.rs).
173174

174175
```rust
175176
extern crate exr;
176-
use exr::prelude::rgba_image::*;
177177

178178
fn main() {
179-
// generate an image with 2048*2048 pixels, converting all numbers to f16
180-
ImageInfo::rgb((2048, 2048), SampleType::F16).write_pixels_to_file(
181-
"tests/images/out/minimal_rgba.exr",
182-
write_options::high(), // higher speed, but higher memory usage
183-
184-
// generate a color for each pixel position
185-
&|position: Vec2<usize>| {
186-
Pixel::rgb(
187-
position.x() as f32 / 2048.0, // red
188-
position.y() as f32 / 2048.0, // green
189-
1.0 - (position.y() as f32 / 2048.0), // blue
190-
)
191-
}
179+
// write a file without alpha and 32-bit float precision per channel
180+
exr::prelude::write_rgb_f32_file(
181+
"tests/images/out/minimal_rgb.exr",
182+
(2048, 2048), // write an image with 2048x2048 pixels
183+
|x,y| ( // generate an f32 rgb color for each of the 2048x2048 pixels
184+
x as f32 / 2048.0, // red
185+
y as f32 / 2048.0, // green
186+
1.0 - (y as f32 / 2048.0), // blue
187+
)
192188
).unwrap();
193189
}
194190
```

examples/0_minimal_rgb_read.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
extern crate exr;
2+
3+
/// `exr` offers a few very simple functions for the most basic use cases.
4+
/// `read_first_rgba_layer_from_file` is a simple function which loads an exr file.
5+
/// To load the image, you need to specify how to create and how to update your image.
6+
fn main() {
7+
let image = exr::prelude::read_first_rgba_layer_from_file(
8+
"tests/images/out/generated_rgba.exr", // run the `1_generate_rgba` example to generate this file
9+
10+
// instantiate your image type with the size of the image file
11+
|info| {
12+
let default_pixel = [0.0, 0.0, 0.0, 0.0];
13+
let empty_line = vec![ default_pixel; info.resolution.width() ];
14+
let empty_image = vec![ empty_line; info.resolution.height() ];
15+
empty_image
16+
},
17+
18+
// transfer the colors from the file to your image type
19+
|pixel_vector, position, pixel| {
20+
pixel_vector[position.y()][position.x()] = pixel.into()
21+
},
22+
23+
).unwrap();
24+
25+
// printing all pixels might kill the console lol, so only print some meta data about the image
26+
println!("opened file generated_rgba.exr.exr: {:#?}", image.layer_data.attributes);
27+
}

examples/0_minimal_rgb_write.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
extern crate exr;
2+
3+
/// `exr` offers a few very simple functions for the most basic use cases.
4+
/// `write_rgb_f32_file` is a simple function which writes a simple exr file.
5+
/// To write the image, you need to specify how to retrieve a single pixel from it.
6+
/// The closure may capture variables or generate data on the fly.
7+
fn main() {
8+
// write a file without alpha and 32-bit float precision per channel
9+
exr::prelude::write_rgb_f32_file(
10+
"tests/images/out/minimal_rgb.exr",
11+
(2048, 2048), // write an image with 2048x2048 pixels
12+
|x,y| ( // generate an f32 rgb color for each of the 2048x2048 pixels
13+
x as f32 / 2048.0, // red
14+
y as f32 / 2048.0, // green
15+
1.0 - (y as f32 / 2048.0), // blue
16+
)
17+
).unwrap();
18+
19+
println!("created file minimal_rgb.exr");
20+
}

examples/0_read_meta.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
// exr imports
44
extern crate exr;
5-
use exr::prelude::common::*;
5+
use exr::prelude::*;
66

77
/// Print the custom meta data of a file, excluding technical encoding meta data.
8-
/// Prints compression method and tile size, but not chunk count.
8+
/// Prints compression method and tile size, but not purely technical data like chunk count.
99
fn main() {
1010
let meta_data = MetaData::read_from_file(
1111
"tests/images/valid/custom/crowskull/crow_uncompressed.exr",
12-
true // do not throw an error for invalid attributes, skipping them instead
12+
false // do not throw an error for invalid or missing attributes, skipping them instead
1313
).unwrap();
1414

1515
for (layer_index, image_layer) in meta_data.headers.iter().enumerate() {

examples/1_generate_rgba.rs

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
// exr imports
33
extern crate exr;
4-
use exr::prelude::rgba_image::*;
4+
use exr::prelude::*;
55

6-
/// Write an RGBA exr file, generating the pixel values on the fly.
6+
/// Write an rgba exr file, generating the pixel values on the fly.
77
/// This streams the generated pixel directly to the file,
88
/// never allocating the actual total pixel memory of the image.
99
fn main() {
@@ -20,34 +20,39 @@ fn main() {
2020
value.powf((position.y() as f32 / scale.y()).sin() * 0.5 + 0.5)
2121
}
2222

23-
Pixel::rgb(
23+
// return an rgba quadruple
24+
(
2425
get_sample_f32(position, 0),
2526
get_sample_f32(position, 1),
2627
get_sample_f32(position, 2),
28+
0.8
2729
)
2830
};
2931

32+
let mut attributes = LayerAttributes::named("generated rgba");
33+
attributes.comments = Some(Text::from("This image was generated as part of an example"));
34+
attributes.owner = Some(Text::from("The holy lambda function"));
3035

31-
let mut image_info = ImageInfo::rgb(
36+
let layer = Layer::new(
3237
(2*2048, 2*2048),
38+
attributes,
39+
Encoding::SMALL_FAST_LOSSY,
3340

34-
// all generated f32 values are converted to an f16 while writing the file
35-
SampleType::F16,
41+
RgbaChannels::new(
42+
// all generated f32 values are converted to an f16 while writing the file
43+
RgbaSampleTypes::RGBA_F16,
44+
generate_pixels
45+
)
3646
);
3747

38-
image_info.layer_attributes.owner = Some("Unknown Owner".try_into().unwrap());
39-
image_info.layer_attributes.comments = Some(
40-
"This image was generated as part of an example".try_into().unwrap()
41-
);
48+
// crop away black and transparent pixels from the border
49+
let layer = layer
50+
.crop_where_eq((0.0, 0.0, 0.0, 0.0))
51+
.or_crop_to_1x1_if_empty();
4252

43-
// write it to a file with all cores in parallel
44-
image_info
45-
.with_encoding(Encoding::for_compression(Compression::PIZ))
46-
.write_pixels_to_file(
47-
"tests/images/out/generated_rgba.exr",
48-
write_options::high(), // this will actually generate the pixels in parallel on all cores
49-
&generate_pixels
50-
).unwrap();
53+
let image = Image::from_single_layer(layer);
5154

55+
// write it to a file with all cores in parallel
56+
image.write().to_file("tests/images/out/generated_rgba.exr").unwrap();
5257
println!("created file generated_rgba.exr");
5358
}

examples/1_minimal_rgb.rs

Lines changed: 0 additions & 21 deletions
This file was deleted.

examples/1_rgb_exr_to_png.rs

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,44 @@ extern crate image as png;
33

44
// exr imports
55
extern crate exr;
6-
use exr::prelude::rgba_image as rgb_exr;
6+
use exr::prelude::*;
7+
use exr::prelude as exrs;
78

89
fn main() {
910

10-
// read the image from a file and keep only the png buffer
11-
let (_info, png_buffer) = rgb_exr::ImageInfo::read_pixels_from_file(
12-
"tests/images/valid/openexr/MultiResolution/Kapaa.exr",
13-
rgb_exr::read_options::high(),
14-
15-
// how to create an empty png buffer from exr image meta data (used for loading the exr image)
16-
|info: &rgb_exr::ImageInfo| -> png::RgbaImage {
17-
png::ImageBuffer::new(
18-
info.resolution.width() as u32,
19-
info.resolution.height() as u32
20-
)
21-
},
22-
23-
// set each pixel in the png buffer from the exr file
24-
|png_pixels: &mut png::RgbaImage, position: rgb_exr::Vec2<usize>, pixel: rgb_exr::Pixel| {
25-
png_pixels.put_pixel(
26-
position.x() as u32, position.y() as u32,
27-
28-
png::Rgba([
29-
tone_map(pixel.red.to_f32()),
30-
tone_map(pixel.green.to_f32()),
31-
tone_map(pixel.blue.to_f32()),
32-
(pixel.alpha_or_default().to_f32() * 255.0) as u8,
33-
])
34-
);
35-
},
36-
).unwrap();
11+
// read from the exr file directly into a new `png::RgbaImage` image without intermediate buffers
12+
let reader = exrs::read()
13+
.no_deep_data()
14+
.largest_resolution_level()
15+
.rgba_channels(
16+
|layer_info: &exrs::RgbaChannelsInfo| -> png::RgbaImage {
17+
png::ImageBuffer::new(
18+
layer_info.resolution.width() as u32,
19+
layer_info.resolution.height() as u32
20+
)
21+
},
22+
23+
// set each pixel in the png buffer from the exr file
24+
|png_pixels: &mut png::RgbaImage, position: exrs::Vec2<usize>, pixel: exrs::RgbaPixel| {
25+
png_pixels.put_pixel(
26+
position.x() as u32, position.y() as u32,
27+
28+
png::Rgba([
29+
tone_map(pixel.red.to_f32()),
30+
tone_map(pixel.green.to_f32()),
31+
tone_map(pixel.blue.to_f32()),
32+
(pixel.alpha_or_default().to_f32() * 255.0) as u8,
33+
])
34+
);
35+
}
36+
)
37+
.first_valid_layer()
38+
.all_attributes();
39+
40+
// an image that contains a single layer containing an png rgba buffer
41+
let image: Image<Layer<RgbaChannels<png::RgbaImage>>> = reader
42+
.from_file("tests/images/valid/openexr/MultiResolution/Kapaa.exr")
43+
.unwrap();
3744

3845

3946
/// compress any possible f32 into the range of [0,1].
@@ -45,6 +52,7 @@ fn main() {
4552
};
4653

4754
// save the png buffer to a png file
55+
let png_buffer = &image.layer_data.channel_data.storage;
4856
png_buffer.save("tests/images/out/rgb.png").unwrap();
4957
println!("created image rgb.png")
5058
}

0 commit comments

Comments
 (0)