
extern crate image as png;

// exr imports
extern crate exr;

/// Converts one rgba exr with one layer to one png, or fail.
fn main() {
    use exr::prelude::*;
    use exr::prelude as exrs;

    // read from the exr file directly into a new `png::RgbaImage` image without intermediate buffers
    let reader = exrs::read()
        .no_deep_data()
        .largest_resolution_level()
        .rgba_channels(
        |resolution, _channels: &RgbaChannels| -> png::RgbaImage {
                png::ImageBuffer::new(
                    resolution.width() as u32,
                    resolution.height() as u32
                )
            },

            // set each pixel in the png buffer from the exr file
            |png_pixels, position, (r,g,b,a): (f32,f32,f32,f32)| { // TODO implicit argument types!
                png_pixels.put_pixel(
                    position.x() as u32, position.y() as u32,
                    png::Rgba([tone_map(r), tone_map(g), tone_map(b), (a * 255.0) as u8])
                );
            }
        )
        .first_valid_layer()
        .all_attributes();

    // an image that contains a single layer containing an png rgba buffer
    let image: Image<Layer<SpecificChannels<png::RgbaImage, RgbaChannels>>> = reader
        .from_file("generated_rgba.exr")
        .expect("run the `1_write_rgba` example to generate the required file");


    /// compress any possible f32 into the range of [0,1].
    /// and then convert it to an unsigned byte.
    fn tone_map(linear: f32) -> u8 {
        // TODO does the `image` crate expect gamma corrected data?
        let clamped = (linear - 0.5).tanh() * 0.5 + 0.5;
        (clamped * 255.0) as u8
    }

    // save the png buffer to a png file
    let png_buffer = &image.layer_data.channel_data.pixels;
    png_buffer.save("rgb.png").unwrap();
    println!("created image rgb.png")
}