lovell / sharp

High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, AVIF and TIFF images. Uses the libvips library.
https://sharp.pixelplumbing.com
Apache License 2.0
29k stars 1.29k forks source link

Enhancement: add support to recomb for 4x4 recombination matrices #4145

Closed ton11797 closed 1 month ago

ton11797 commented 3 months ago

Question about an existing feature

What are you trying to achieve?

I want to multiply the Alpha channel with an opacity value. This is what I came up with in my code

    async multiplyAlphaChannel(layerImage: Sharp, multiply: number) {
        const layerMetadata = await layerImage.metadata();
        const channels: Array<{ data: Buffer }> = await Promise.all([
            layerImage.extractChannel(0).raw().toBuffer({ resolveWithObject: true }),
            layerImage.extractChannel(1).raw().toBuffer({ resolveWithObject: true }),
            layerImage.extractChannel(2).raw().toBuffer({ resolveWithObject: true }),
            layerImage.extractChannel(3).raw().toBuffer({ resolveWithObject: true })
        ]);

        const pixelArray = new Uint8ClampedArray(channels[0].data.length * 4);

        for (let i = 0; i < channels[0].data.length; i++) {
            pixelArray[i * 4] = channels[0].data[i]; // Red
            pixelArray[i * 4 + 1] = channels[1].data[i]; // Green
            pixelArray[i * 4 + 2] = channels[2].data[i]; // Blue
            pixelArray[i * 4 + 3] = channels[3].data[i] * multiply; // Alpha
        }

        return await sharp(pixelArray, {
            raw: {
                width: layerMetadata.width,
                height: layerMetadata.height,
                channels: 4
            }
        }).png();
    }

Question

Are there any more efficient or simplified methods to achieve this using the Sharp library?

lovell commented 3 months ago

This is a scenario that matrix multiplication via the recomb operation should allow but currently it only supports a 3x3 matrix for non-alpha channels.

Let's tag this as an enhancement for 4x4 matrix support.

// Proposed API to support 4x4 matrix - NOT YET AVAILABLE
const alphaMultiplication = 1.1;
const output = await sharp(input)
  .recomb([
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, alphaMultiplication
  ])
  .toBuffer();
lovell commented 1 month ago

v0.33.5 now available, thank you for implementing this feature.