etemesi254/zune-image

Composite does not work correctly when the destination image is transparent

Closed this issue · 3 comments

CompositeMethod::Over does not affect the destination image's alpha channel.

E.g. composite any opaque source image over a totally transparent destination image (with every alpha value equals zero) will end up with a totally transparent image. In reality we would like to see that the composition area of the destination image being replaced by the content of the source image, i.e. the resulting alpha should be calculated as src_alpha + (1 - src_alpha) * dst_alpha (where the alpha values are normalized).

Hi, could you share the images used?

The following code demonstrates this issue. It composites an opaque image onto a transparent image. We expect the result image to be opaque.

use zune_image::{image::Image, traits::OperationsTrait};
use zune_imageprocs::composite::{Composite, CompositeMethod};

fn main() {
    let mut transparent_image = Image::from_fn(
        1usize,
        1usize,
        zune_core::colorspace::ColorSpace::RGBA,
        |_y, _x, pixels| {
            pixels[0] = 0u8;
            pixels[1] = 0u8;
            pixels[2] = 0u8;
            pixels[3] = 0u8;
        },
    );

    let opaque_image = Image::from_fn(
        1usize,
        1usize,
        zune_core::colorspace::ColorSpace::RGBA,
        |_y, _x, pixels| {
            pixels[0] = 0u8;
            pixels[1] = 0u8;
            pixels[2] = 0u8;
            pixels[3] = 0xffu8;
        },
    );

    let composite = Composite::new(&opaque_image, CompositeMethod::Over, (0usize, 0usize));

    composite.execute(&mut transparent_image).unwrap();

    unsafe {
        transparent_image.channels_ref(false)[3]
            .alias()
            .iter()
            .for_each(|x| {
                assert_eq!(*x, 0xffu8);
            });
    }
}

Thank you, added a test which is the example code you gave.