Sharp: Multiply alpha channel (was: Imagemagick's dissolve option)

Created on 2 Nov 2016  路  10Comments  路  Source: lovell/sharp

Hi @lovell,
Does sharp support the option to dissolve a transparent image?
I was looking for something similar to imagemagick's dissolve option.
I took a look at the docs but could not find anything.
What i wanna achieve is to overlay a watermark, which works well but i would also like to dissolve it by ~35%.

return sharp(watermark)
    .resize(width)
    .toBuffer()
    .then((outputBuffer) => {
      return stream.overlayWith(outputBuffer);
    });

stream is the streamed base image and watermark is the watermark png file which i would like to dissolve.

enhancement help wanted

Most helpful comment

You can multiply the alpha channel using this, where opacity is the alpha channel (0-255).

await sharp(source)
  .composite([{
    input: Buffer.from([255,255,255,128]),
    raw: {
      width: 1,
      height: 1,
      channels: 4
    },
    tile: true,
    blend: 'dest-in'
  }])
  .toBuffer();

All 10 comments

Hello, have you tried adding an alpha transparency channel of the desired opacity to the watermark?

@lovell thank you for your quick answer!

I tried but wasn't successful, this is the current outcome.

download-1

How can i add an alpha transparency channel of the desired opacity to the watermark?

@lovell thank you for the link but i wanna add the opacity via sharpjs and not on the watermark input file itself. The idea behind it is that the watermark can be reused with different dissolve percentages.

If this module were to provide the ability to multiply alpha channel values then it would make sense to allow this for any images, not just those supplied to overlayWith.

I'm happy to accept a PR to implement such an operation and can help with API design. It would need to pretty much do what the *magick command is doing, which is detach the alpha channel, multiply its pixels by a specified value (clipped to a maximum value based on 8 vs 16 bits-per-channel), then re-attach to the original image.

Seeing that libvips has released v8.6 at the end of November, I see there was a commit to master that uses this.

What are the chances that an opacity option (1-100%) is available to the overlayWith function? Or is this already available, and if so, how would I access this?

@samlin86 The overlayWith operation will be switching to use the new vips_composite as part of #728 and that will include all the new blend modes.

It would need to pretty much do what the *magick command is doing, which is detach the alpha channel, multiply its pixels by a specified value (clipped to a maximum value based on 8 vs 16 bits-per-channel), then re-attach to the original image.

libvips has aslightly neater way of doing this: you can multiply by a vector, with 1.0 for bands you want to leave alone.

In C++ you can write:

rgba_image = rgba_image * {1.0, 1.0, 1.0, opacity};

I think (?) that'll work in C++11. You might need a cast in there. You'd obviously need to check that it was an RGBA image somewhere.

You can multiply the alpha channel using this, where opacity is the alpha channel (0-255).

await sharp(source)
  .composite([{
    input: Buffer.from([255,255,255,128]),
    raw: {
      width: 1,
      height: 1,
      channels: 4
    },
    tile: true,
    blend: 'dest-in'
  }])
  .toBuffer();

You can multiply the alpha channel using this, where opacity is the alpha channel (0-255).

await sharp(source)
  .composite([{
    input: Buffer.from([255,255,255,128]),
    raw: {
      width: 1,
      height: 1,
      channels: 4
    },
    tile: true,
    blend: 'dest-in'
  }])
  .toBuffer();

It works!!!

Was this page helpful?
0 / 5 - 0 ratings