Home > Mobile >  How do I create a non-trivial ActiveStorage variant for watermarking images?
How do I create a non-trivial ActiveStorage variant for watermarking images?

Time:04-15

I have written the following ImageMagick command which takes a watermark image, scales it, and composites it over a base image, tiling it:

convert image.png \( watermark.png -resize 5% -write mpr:watermark  delete \) \(  clone -tile mpr:watermark -draw "color 0,0 reset" \)  -compose over -composite watermarked_image.png

I want to define this as an Active Storage variant, so that I can watermark images in certain contexts, but I am coming up short. I can only find very simple transformation examples. Is this possible as an Active Storage variant?

CodePudding user response:

I finally figured this out and wanted to share the answer in case anyone else lands here looking for help. I found the following article, which explains the basic premise. From there it was only a matter of translating the ImageMagick command into the correct MiniMagick API calls.

require "image_processing"

module ImageProcessing
  module MiniMagick
    module Processing
      extend ActiveSupport::Concern

      included do
        def watermark(scale: 0.5, opacity: 0.5)
          watermark_path = Rails.root.join('lib', 'watermark.png')
          formatted_scale = "%0.0f%%" % [scale* 100]

          magick.stack do |stack|
            stack << watermark_path

            stack.alpha('on')
            stack.channel('a')
            stack.evaluate('multiply', opacity.to_f)
            stack.channel. 

            stack.resize(formatted_scale)
            stack.write('mpr:watermark')
            stack.delete. 
          end

          magick.stack do |stack|
            stack.clone. 
            stack.tile('mpr:watermark')
            stack.draw('color 0,0 reset')
          end

          magick.compose('over')
          magick.composite
        end
      end
    end
  end
end

ImageProcessing::MiniMagick::Processor.include(
  ImageProcessing::MiniMagick::Processing
) 

Then, assuming you have a model with an image attachment, just call the new watermark variant with:

design.image.variant(
  watermark: { scale: 0.25, opacity: 0.2 },
)

  • Related