sharp icon indicating copy to clipboard operation
sharp copied to clipboard

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

Open davidecantoni opened this issue 8 years ago • 14 comments

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.

davidecantoni avatar Nov 02 '16 06:11 davidecantoni

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

lovell avatar Nov 02 '16 07:11 lovell

@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?

davidecantoni avatar Nov 02 '16 08:11 davidecantoni

https://github.com/janosgyerik/cheatsheets/wiki/ImageMagick-cheat-sheet

lovell avatar Nov 02 '16 09:11 lovell

@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.

davidecantoni avatar Nov 02 '16 09:11 davidecantoni

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.

lovell avatar Nov 02 '16 10:11 lovell

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 avatar Jan 05 '18 20:01 samlin86

@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.

lovell avatar Jan 06 '18 10:01 lovell

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 *= {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.

jcupitt avatar Jul 25 '19 15:07 jcupitt

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();

Colkadome avatar Sep 17 '19 16:09 Colkadome

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!!!

tinypoint avatar Nov 24 '19 04:11 tinypoint

Coming back to the original request, how to blend a watermark with transparency over a base image? From previous comment, I can't tell if 'source' is watermark or base, nor couldn't figure out how to combine the two. Thanks

mariusa avatar Dec 05 '21 10:12 mariusa

Has this feature ever been added to Sharp?

It seems like it'd be a relatively common image-manipulation task.

I'm using the following code an can't for the life of me figure out how I'd apply the logo watermark at a variable-based opacity level. (the logo opacity will be user-selected, so I can't just modify the logo png.

           overlayImg = await Sharp(sourceImage.Body)
				.composite([{ 
					input: './lambdas/processNewImage/logos/white.png', 
					gravity: 'southeast',
					
				}])
				.toFormat('jpeg').toBuffer();

jfederer avatar Feb 15 '22 04:02 jfederer

@jfederer This issue is a future possible enhancement. A PR to implement it is welcome, if you're able.

lovell avatar Feb 15 '22 10:02 lovell

Is it not currently possible (even if there isn't an 'easy' way to do it?)? I'm trying to stay with Sharp but I'll have to leave (an re-write a lot of code) for a different library if it doesn't have this functionality.

jfederer avatar Feb 15 '22 14:02 jfederer