All threads / Paperclip - Watermarking for dynamic image sizes

Ask A Question

Notifications

You’re not receiving notifications from this thread.

Paperclip - Watermarking for dynamic image sizes

Michael Victor asked in Gems / Libraries

I'm looking to add watermarks to all images that are uploaded to my application. They can be of several sizes and this is where I'm running into trouble.

This is my watermark processor:

module Paperclip
  class Watermark < Processor
    def initialize(file, options = {}, attachment = nil)
      super
      geometry = options[:geometry]
      @file = file
      @crop = geometry[-1,1] == '#'
      @target_geometry = Geometry.parse geometry
      @current_geometry = Geometry.from_file @file
      @convert_options = options[:convert_options]
      @whiny = options[:whiny].nil? ? true : options[:whiny]
      @format = options[:format]
      @watermark_path = options[:watermark_path]
      @position = options[:position].nil? ? "SouthEast" : options[:position]
      @watermark_offset = options[:watermark_offset]
      @overlay = options[:overlay].nil? ? true : false
      @current_format = File.extname(@file.path)
      @basename = File.basename(@file.path, @current_format)
      Rails.logger.info "watermark initialized"
    end

     # Returns true if the +target_geometry+ is meant to crop.
    def crop?
      @crop
    end

    # Returns true if the image is meant to make use of additional convert options.
    def convert_options?
      not @convert_options.blank?
    end

    # Performs the conversion of the +file+ into a watermark. Returns the Tempfile
    # that contains the new image.

    def make
      Rails.logger.info "watermark make method"
      src = @file
      dst = Tempfile.new([@basename].compact.join("."))
      dst.binmode


      if @watermark_path.present?
        command = "convert"
        params  = %W['#{fromfile}']
        params += transformation_command
        params += %W['#{@watermark_path}' -gravity #{@position} -composite]
        params << "'#{tofile(dst)}'"
      else
        command = "convert"
        params = ["'#{fromfile}'"]
        params += transformation_command
        params << "'#{tofile(dst)}'"
      end

      Rails.logger.info 'params:' + params.to_s

      begin
        Paperclip.run(command, params.join(' '))
      rescue ArgumentError, Cocaine::CommandLineError
        raise Paperclip::Error.new("There was an error processing the watermark for #{@basename}") if @whiny
      end

      dst
    end

    def transformation_command
      scale, crop = @current_geometry.transformation_to(@target_geometry, crop?)
      trans = %W[-resize '#{scale}']
      trans += %W[-crop '#{crop}' +repage] if crop
      trans << @convert_options if @convert_options.present?
      trans
    end

    def fromfile
      File.expand_path(@file.path)
    end

    def tofile(destination)
      File.expand_path(destination.path)
    end
  end
end

I'm wondering what strategies I can use to get this done or if there are some good gems around I can use.

Things I have thought of

Resizing the watermark image to 10% of the image size before placing it on top of the image (seems the best option right now)
Adding a transparent image with the watermark on the bottom right already taking up 10% of the space. (but this might not really work since I can't for sure specify what kind of aspect ratio is being uploaded)
Model File for reference:

class Picture < ActiveRecord::Base
    #Associations
    belongs_to :picturable, polymorphic: true

    #Gem Functions
    acts_as_paranoid

    #Paperclip
    has_attached_file :picture_file,
                        styles: {
                          medium: {
                            processors: [:watermark],
                            geometry:       "268*222",
                            watermark_path: "#{Rails.root}/app/assets/images/watermark.jpeg",
                            convert_options: { } #or whatever options you want
                          },
                          original_watermarked: {
                            processors: [:watermark],
                            watermark_path: "#{Rails.root}/app/assets/images/watermark.jpeg",
                            convert_options: { } #or whatever options you want
                            },
                          thumb: "100x100>",
                        }
    validates_attachment_content_type :picture_file, content_type: /\Aimage\/.*\Z/
end
Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 35,699+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.