Watermark images with paperclip, rails 4

匿名 (未验证) 提交于 2019-12-03 08:57:35

问题:

I've been attempting to add watermarks to my images, following the answer listed in watermark with paperclip :

Watermark.rb:

module Paperclip   class Watermark < Processor     # Handles watermarking of images that are uploaded.     attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options, :watermark_path, :watermark_offset, :overlay, :position      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)     end      # TODO: extend watermark      # 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       dst = Tempfile.new([@basename, @format].compact.join("."))       dst.binmode        if watermark_path         command = "composite"         params = %W[-gravity #{@position}]         params += %W[-geometry '#{@watermark_offset}'] if @watermark_offset         params += %W['#{watermark_path}' '#{fromfile}']         params += transformation_command         params << "'#{tofile(dst)}'"       else         command = "convert"         params = ["'#{fromfile}'"]         params += transformation_command         params << "'#{tofile(dst)}'"       end        begin         Paperclip.run(command, params.join(' '))       rescue ArgumentError, Cocaine::CommandLineError         raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny       end        dst     end      def fromfile       File.expand_path(@file.path)     end      def tofile(destination)       File.expand_path(destination.path)     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?       trans     end   end end 

and model code:

has_attached_file :image,                    :processors => [:watermark],                    :styles => {                      :large => "640x480",                      :thumb => "100x100",                     :medium => "300x300",                         :content => {                             :geometry => '150x153',                             :watermark_path => Rails.root.join('app/assets/images/watermark.jpg'),                             :position => 'SouthWest'                         },                   },                   dependent: :allow_destroy 

I've attempted to update this to work with Rails 4 (moving attr_accessor to params in the model), but I get the error:

uninitialized constant Paperclip::Watermark::PaperclipError 

Any tips on how to get implement watermarks in a rails 4 app?

UPDATE: I was able to get past the uninitialized constant error with Graeme's suggestion below of changing:

raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny 

to:

raise Paperclip::Error.new("There was an error processing the watermark for #{@basename}") if @whiny 

I also had to remove the following from the model in order for the upload to process:

:url => "/images/:style/:id_:style.:extension",  :path => ":rails_root/app/assets/images/:style/:id_:style.:extension" 

I don't understand what the purpose of :url and :path are in this scenario, when users are uploading images?

The problem is, even though the images now get uploaded, no watermark is being displayed. Thoughts?

Update 2: In order to get the watermark displaying correctly, I had to change the model to:

has_attached_file :image,    :processors => [:watermark],    :url => "/system/:class/:attachment/:id_partition/:style/:filename",   :path => ":rails_root/public/system/:class/:attachment/:id_partition/:style/:filename",   :styles => {      :large => "640x480",      :thumb => "100x100",     :medium => {              :processors => [:watermark],             :geometry => '300x300',             :watermark_path => Rails.root.join('app/assets/images/icon.gif'),             :position => 'SouthWest'         },   },   dependent: :allow_destroy 

The key piece was removing :content => . Only remaining issue is that the watermark is scaling up to fit the entire width of the image. Any recommendations on how to stop the watermark-scaling?

回答1:

The problem with the watermark being stretched is the Imagemagick command which is combining the two images together and then resizing the result.

Effectively the command being run will be (I've abbreviated the actual filenames for clarity):

composite -gravity SouthWest icon.gif uploaded_image.gif -resize 300x300 output_image.gif 

As you see the images are joined and then resized.

The command I believe you need is:

convert uploaded_image.gif -resize 300x300 icon.gif -gravity SouthWest -composite output_image.gif 

i.e. resize the uploaded image and then add on the watermark.

I've tested this using composite and convert on the command line and it does what I believe you are looking for.

To achieve it in the code, you need to change if watermark_path statement in the make method:

def make    dst = Tempfile.new([@basename, @format].compact.join("."))   dst.binmode    if watermark_path     # -- original code --     # command = "composite"     # params = %W[-gravity #{@position}]     # params += %W[-geometry '#{@watermark_offset}'] if @watermark_offset     # params += %W['#{watermark_path}' '#{fromfile}']     # params += transformation_command     # params << "'#{tofile(dst)}'"      # -- new code --     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    begin     Paperclip.run(command, params.join(' '))   rescue ArgumentError, Cocaine::CommandLineError     raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny   end    dst end 

Disclaimer: I have not actually tested this so please forgive any errors.



回答2:

PaperclipError doesn't exist.

Try changing:

raise PaperclipError, "There was an error processing the watermark for #{@basename}" if @whiny 

to:

raise Paperclip::Error.new("There was an error processing the watermark for #{@basename}") if @whiny 


回答3:

Since you are now asking a different question I'll make a new answer.

:path is used to define where Paperclip will store the uploaded image. By default this will be :rails_root/public/system/:class/:attachment/:id_partition/:style/:filename.

:url is used to access the image later. By default this will be /system/:class/:attachment/:id_partition/:style/:filename.

(Actually, to save having to duplicate the url part, :path is really defined as :rails_root/public:url by default.)

By specifying them in the model you are changing the save location. I wouldn't recommend putting them in the assets directory as assets are really part of your application and you don't want user uploaded files to be going there.

As to why you are not seeing the watermark with the uploaded image, I guess the Imagemagick composite command is not being called correctly. Try running it on the command line, or adding the parameter -debug to see why it is failing.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!