Image: Shrinking image causes visual glitch

Created on 17 Jan 2021  路  6Comments  路  Source: image-rs/image

This happens in image::imageops::resize.

Expected

Shrinking shouldn't add visual glitch

Actual behaviour

It does happen

Reproduction steps

Input image:

yuno

// let decoded = raw RGBA buffer
// let xsize = 622;
// let ysize = 622;

let rgba = image::RgbaImage::from_raw(info.xsize, info.ysize, decoded)
    .expect("Failed to consume the decoded RGBA buffer");

rgba.save(&format!("{}\\debug.png", env!("CARGO_MANIFEST_DIR"))).unwrap();

let resized =
    image::imageops::resize(&rgba, 256, 256, image::imageops::Lanczos3);

resized.save(&format!("{}\\debug-resized.png", env!("CARGO_MANIFEST_DIR"))).unwrap();

Output image:

debug

Glitch:

image

Shrinking with image editors e.g. Paint.NET doesn't add such glitches, is this expected here?

bug

Most helpful comment

I think this might be caused by using floating point math to do the resampling. In particular, converting individual components back from floats to integers seem to truncate rather than round:
https://github.com/image-rs/image/blob/8de5cb71fa0f35f8a681b7c2abb3c45ac98dbda7/src/imageops/sample.rs#L264-L267

If the value was say 254.9999 then that could be cast to 254, and since there are two iterations of sampling (one horizontal and one vertical) some pixels might get rounded down twice to a final value of 253.

All 6 comments

Can you be more specific, i.e. give a comparison to Paint?

I think Paint.NET was already specific, but this is what Paint 3D does: (Paint doesn't support transparency so picked it instead)

yuno-256

I don't understand. We don't aim at replicating the exact behavior of a specific tool. What is the problem with the image? Artifacts that I overlook? You need to be specific with regards to the problem, not the expected result.

I guess you couldn't catch the glitch I uploaded. It's easier to see if you zoom in it with image editors, and this is what I'm saying (emphasized as black dots)

image

Now that I see the glitches have #E5FD5D while the background color is #E5FE5E. Surely hard to see 馃槄

I recognize a weird visual pattern here.

Oh, BTW it's much more visible with black background layer because somehow alpha channel is affected. In the original image the hair part consistently have opaque value 255 but after shrinking some pixels get 253-254.

I think it's the reason why I could catch the glitch in the first place.

Please open your image editor if you still don't see it.

image

I think this might be caused by using floating point math to do the resampling. In particular, converting individual components back from floats to integers seem to truncate rather than round:
https://github.com/image-rs/image/blob/8de5cb71fa0f35f8a681b7c2abb3c45ac98dbda7/src/imageops/sample.rs#L264-L267

If the value was say 254.9999 then that could be cast to 254, and since there are two iterations of sampling (one horizontal and one vertical) some pixels might get rounded down twice to a final value of 253.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

franleplant picture franleplant  路  3Comments

lovasoa picture lovasoa  路  9Comments

38 picture 38  路  9Comments

aschampion picture aschampion  路  3Comments

acidicX picture acidicX  路  4Comments