Search code examples
rubyimageimagemagickrmagickwatermark

Rmagick setting opacity in watermark with transparency


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)


Solution

  • 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