From 4cf89058b98d1cd3d049176b363816d595110b56 Mon Sep 17 00:00:00 2001 From: Radzivon Bartoshyk Date: Tue, 26 Nov 2024 13:31:32 +0000 Subject: [PATCH 1/2] Fix YUV 4:2:0, 4:2:2 large strides --- src/codecs/avif/yuv.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/codecs/avif/yuv.rs b/src/codecs/avif/yuv.rs index c0d6c414e1..e0c70174e6 100644 --- a/src/codecs/avif/yuv.rs +++ b/src/codecs/avif/yuv.rs @@ -521,13 +521,23 @@ fn process_halved_chroma_row< let max_value = (1 << BIT_DEPTH) - 1; + // If the stride is larger than the plane size, + // it might contain junk data beyond the actual valid region. + // To avoid processing artifacts when working with odd-sized images, + // the buffer is reshaped to its actual size, + // preventing accidental use of invalid values from the trailing region. + + let y_plane = &image.y_plane[0..image.width]; + let chroma_size = (image.width + 1) / 2; + let u_plane = &image.u_plane[0..chroma_size]; + let v_plane = &image.v_plane[0..chroma_size]; + let rgba = &mut rgba[0..image.width * CHANNELS]; + let bias_y = range.bias_y as i32; let bias_uv = range.bias_uv as i32; - let y_iter = image.y_plane.chunks_exact(2); + let y_iter = y_plane.chunks_exact(2); let rgb_chunks = rgba.chunks_exact_mut(CHANNELS * 2); - for (((y_src, &u_src), &v_src), rgb_dst) in - y_iter.zip(image.u_plane).zip(image.v_plane).zip(rgb_chunks) - { + for (((y_src, &u_src), &v_src), rgb_dst) in y_iter.zip(u_plane).zip(v_plane).zip(rgb_chunks) { let y_value: i32 = (y_src[0].as_() - bias_y) * y_coef; let cb_value: i32 = u_src.as_() - bias_uv; let cr_value: i32 = v_src.as_() - bias_uv; @@ -571,13 +581,13 @@ fn process_halved_chroma_row< // Process remainder if width is odd. if image.width & 1 != 0 { - let y_left = image.y_plane.chunks_exact(2).remainder(); + let y_left = y_plane.chunks_exact(2).remainder(); let rgb_chunks = rgba .chunks_exact_mut(CHANNELS * 2) .into_remainder() .chunks_exact_mut(CHANNELS); - let u_iter = image.u_plane.iter().rev(); - let v_iter = image.v_plane.iter().rev(); + let u_iter = u_plane.iter().rev(); + let v_iter = v_plane.iter().rev(); for (((y_src, u_src), v_src), rgb_dst) in y_left.iter().zip(u_iter).zip(v_iter).zip(rgb_chunks) From 45767eeb4ea162e8c6807e39c7b927477e185bef Mon Sep 17 00:00:00 2001 From: Radzivon Bartoshyk Date: Tue, 26 Nov 2024 15:45:59 +0000 Subject: [PATCH 2/2] Update src/codecs/avif/yuv.rs Co-authored-by: Andreas Molzer --- src/codecs/avif/yuv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codecs/avif/yuv.rs b/src/codecs/avif/yuv.rs index e0c70174e6..29167342a4 100644 --- a/src/codecs/avif/yuv.rs +++ b/src/codecs/avif/yuv.rs @@ -528,7 +528,7 @@ fn process_halved_chroma_row< // preventing accidental use of invalid values from the trailing region. let y_plane = &image.y_plane[0..image.width]; - let chroma_size = (image.width + 1) / 2; + let chroma_size = image.width.div_ceil(2); let u_plane = &image.u_plane[0..chroma_size]; let v_plane = &image.v_plane[0..chroma_size]; let rgba = &mut rgba[0..image.width * CHANNELS];