image-rs / image

Encoding and decoding images in Rust
Apache License 2.0
4.86k stars 597 forks source link

Floating point image generates incorrect thumbnail #2273

Open gyk opened 2 months ago

gyk commented 2 months ago

The rounding code doesn't work with color types like Rgba32F.

Reproduction code

Test image: https://github.com/johannesvollmer/exrs/blob/master/tests/images/valid/custom/compression_methods/f32/b44a.exr

use image::GenericImageView;

fn main() -> anyhow::Result<()> {
    let args: Vec<String> = ::std::env::args().collect();
    let path = &args[1];

    let im = image::open(path)?;

    println!("Get pixel at (0, 0):\n");
    println!("Original = {:?}", im.get_pixel(0, 0));
    println!("Original (raw) = {:?}", im.as_rgba32f().unwrap().get_pixel(0, 0));

    let thumbnail = im.thumbnail(im.width(), im.height());
    println!("Thumbnail (same size) = {:?}", thumbnail.get_pixel(0, 0));
    println!("Thumbnail (same size, raw) = {:?}", thumbnail.as_rgba32f().unwrap().get_pixel(0, 0));
    let thumbnail = im.thumbnail(im.width() / 2, im.height() / 2);
    println!("Thumbnail (scale down) = {:?}", thumbnail.get_pixel(0, 0));
    let thumbnail = im.thumbnail(im.width() * 2, im.height() * 2);
    println!("Thumbnail (scale up) = {:?}", thumbnail.get_pixel(0, 0));

    Ok(())
}

The output:

Get pixel at (0, 0):

Original = Rgba([5, 6, 8, 255])
Original (raw) = Rgba([0.018939972, 0.022951007, 0.033104062, 1.0])
Thumbnail (same size) = Rgba([132, 133, 136, 255])
Thumbnail (same size, raw) = Rgba([0.51894, 0.522951, 0.53310406, 1.5])
Thumbnail (scale down) = Rgba([132, 133, 136, 255])
Thumbnail (scale up) = Rgba([132, 133, 136, 255])