3

I am trying to create a watermark with different opacity values (from 0 opaque value to 1 totally transparent).

I have the following method for RMagick in ruby:

  # 0 = opaque (Magick::OpaqueOpacity) 1= transparent (Magick::TransparentOpacity)
  def watermark(opacity = 0.99, size = 'm')
    manipulate! do |img|
      logo = Magick::Image.read("#{Rails.root}/app/assets/images/watermark#{size}.png").first
      logo.alpha(Magick::ActivateAlphaChannel) 
      logo.opacity = (1 - opacity.to_f) * Magick::QuantumRange
      img.alpha(Magick::ActivateAlphaChannel)
      img = img.composite(logo, Magick::NorthWestGravity, 0, 0, Magick::OverCompositeOp)
    end
  end

My problem is that it seems to work, but the composite mode or the alpha composite or setting the opacity or alpha is failing, because I get a black transparency in the image. For example if my watermark is a totally transparent image with a text, that I put over a car image, then I get a more dark or nightly image with the watermark, so the background of the watermark it is not blending properly.

Any suggestions to set properly the opacity in the watermark image? Maybe some method to disolve the watermark?

EDIT: Adding image examples:

http://uppix.com/f-watermarkg53925b100016ab8e.png (watermark) http://oi62.tinypic.com/2us8rxl.jpg (base image) http://oi60.tinypic.com/2pt6mg3.jpg (composition)

shakaran
  • 10,612
  • 2
  • 29
  • 46
  • As this is image manipulation it might help to show an example with inputs (separate image, watermark) and result. Then answer can show result of doing it differently. IIRC you essentially have to build a new watermark with re-calculated alpha channel and composite that *without* an opacity setting, because opacity and pre-existing alpha channel combine in unwanted way. – Neil Slater Jun 06 '14 at 23:45
  • Updated with the input images. How do you recalculate the alpha channel in the watermark? – shakaran Jun 07 '14 at 00:08
  • You create a new, temporary, watermark image composited with a plain white canvas which has the opacity you want (composited using MultiplyCompositeOp). This new image will have the combined effect of the existing alpha and the opacity amount you wanted. – Neil Slater Jun 07 '14 at 00:13
  • Your example images not quite working for me. Especially the watermark, because the site you have used has turned it into a JPEG without alpha channel. – Neil Slater Jun 07 '14 at 00:18
  • Updated with .png image. Could you provide some example with code? I am trying this now without result: http://pastebin.com/fJAiyXRP – shakaran Jun 07 '14 at 00:25
  • I try follow your recommendation with plain white canvas and MultiplyCompositeOp, but I have the same result, here the code http://pastebin.com/Rus3Jy6r what I am doing wrong? – shakaran Jun 07 '14 at 00:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/55236/discussion-between-shakaran-and-neil-slater). – shakaran Jun 07 '14 at 00:43
  • Where you have `logo.opacity = 0.5` change to `white_canvas.opacity = 0.5` – Neil Slater Jun 07 '14 at 11:36
  • Thanks Neil! It works now, but not as I expected. It seems than only opacity the blank colour and not the black color. This is a result image now http://uppix.com/f-grande_opacity5392ffa00016ac80.jpg Maybe should I change to background none or background black? – shakaran Jun 07 '14 at 12:04

1 Answers1

6

Thanks to Neil Slater, I finally found the right solution. I need a combination of composite operation of DstIn + Over in my finalt result:

  def watermark(opacity = 0.99, size = 'm')
    manipulate! do |img|
      logo = Magick::Image.read("#{Rails.root}/app/assets/images/watermark#{size}.png").first
      logo.alpha(Magick::ActivateAlphaChannel) 

      white_canvas = Magick::Image.new(logo.columns, logo.rows) { self.background_color = "none" }
      white_canvas.alpha(Magick::ActivateAlphaChannel)
      white_canvas.opacity = Magick::QuantumRange - (Magick::QuantumRange * opacity)

      # Important: DstIn composite operation (white canvas + watermark)
      logo_opacity = logo.composite(white_canvas, Magick::NorthWestGravity, 0, 0, Magick::DstInCompositeOp)
      logo_opacity.alpha(Magick::ActivateAlphaChannel)

      # Important: Over composite operation (original image + white canvas watermarked)
      img = img.composite(logo_opacity, Magick::NorthWestGravity, 0, 0, Magick::OverCompositeOp)
    end
  end
shakaran
  • 10,612
  • 2
  • 29
  • 46