according to this example (http://dimaspriyanto.com/2010/06/08/image-watermarking-with-paperclip/), I try to put a watermark on every picture I upload (for now, I restrain myself to the large one).
And guess what? It doesn't work!
So in my picture model, I have
require 'paperclip_processors/watermark'
has_attached_file :image,
:styles => {:medium => "300x300^", :thumb => "150x105^",
:large => {
:geometry => "460",
:watermark_path => ":rails_root/public/images/watermark.png"
}
},
:url => "/images/:style/:id_:style.:extension",
:path => ":rails_root/public/images/:style/:id_:style.:extension"
and in /lib/paperclip_processors/watermark.rb, I have:
module Paperclip
class Watermark < Processor
attr_accessor :current_geometry, :target_geometry, :format, :whiny, :convert_options, :watermark_path, :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]
#overlay = options[:overlay].nil? ? true : false
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
end
def crop?
#crop
end
def convert_options?
not #convert_options.blank?
end
def make
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
if watermark_path
command = "composite"
params = "-gravity #{#position} #{watermark_path} #{fromfile} #{transformation_command} #{tofile(dst)}"
else
command = "convert"
params = "#{fromfile} #{transformation_command} #{tofile(dst)}"
end
begin
success = Paperclip.run(command, params)
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}" if #whiny
end
dst
end
def fromfile
"\"#{ File.expand_path(#file.path) }[0]\""
end
def tofile(destination)
"\"#{ File.expand_path(destination.path) }[0]\""
end
def transformation_command
scale, crop = #current_geometry.transformation_to(#target_geometry, crop?)
trans = "-resize \"#{scale}\""
trans << " -crop \"#{crop}\" +repage" if crop
trans << " #{convert_options}" if convert_options?
trans
end
end
end
The watermark is in /public/images/ and it doesn't crash in the process, I mean the pictures are uploaded, in every size but the large one is nude, without the watermark.
Any idea?
Here's the preprocessor that works (I use it)
https://gist.github.com/2499137
Here's sample code for you model:
has_attached_file :data,
:processors => [:watermark],
:url => "/ckeditor_assets/pictures/:id/:style_:basename.:extension",
:path => ":rails_root/public/ckeditor_assets/pictures/:id/:style_:basename.:extension",
:styles => {
:thumb => '118x100#',
:content => {
:geometry => '700>',
:watermark_path => "#{Rails.root}/public/images/watermark.png",
:position => 'SouthWest'
},
}
Related
When I'm trying to upload watermark on s3 image through paperclip then it will give error like not authorised and missing an image filename because I'm using dynamic watermark URL. It is also stored in s3
photo.rb
has_attached_file :image,
:processors => lambda {|attachment|
if attachment.class.apply_watermark
[:thumbnail,:watermark]
else
[:thumbnail]
end
},
:styles => lambda { |attachment|
{
:medium => {
:geometry => "259x259#",
:watermark_path => attachment.instance.class.watermark_thumb_url,
:position => "SouthEast",
:s3_protocol => :https
},
:thumb => {
:geometry => Proc.new { |instance| instance.resize },
},
:original => {
:geometry => '1200>',
},
}
}, default_url: "https://s3_bucket_name.s3.ap-south-1.amazonaws.com/shared_photos/missing.png",
:s3_protocol => :https
lib/paperclip_processors/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, :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? ? "center" : options[:position]
#overlay = options[:overlay].nil? ? true : false
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
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
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
command = "convert"
params = [fromfile]
params += transformation_command
params << tofile(dst)
begin
success = Paperclip.run(command, params.flatten.compact.collect{|e| "'#{e}'"}.join(" "))
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error resizing and cropping #{#basename}" if #whiny
end
if watermark_path
command = "composite"
params = %W[-gravity #{#position} #{watermark_path} #{tofile(dst)}]
params << tofile(dst)
begin
success = Paperclip.run(command, params.flatten.compact.collect{|e| "'#{e}'"}.join(" "))
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}" if #whiny
end
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
watermarks_controller.rb
def upload_watermark_on_dummy_image
Photo.apply_watermark = true
Photo.watermark_thumb_url = #watermark.photo.image.url(:thumb)
current_resource_owner.photos.create(image: File.new("public/shared_photos/dummy-image.jpg"))
end
It is giving error when try to run below command in watermark processors
command = "composite"
params = ["-gravity",
"SouthEast",
"https://s3.ap-south-1.amazonaws.com/s3_bucket_name/photos/images/000/000/025/thumb/download.png?1560325300",
"/tmp/3151d071493084e42ac1e51947ef71ce20190612-25378-1usu3ji20190612-25378-135qwqy",
"/tmp/3151d071493084e42ac1e51947ef71ce20190612-25378-1usu3ji20190612-25378-135qwqy"]
success = Paperclip.run(command, params.flatten.compact.collect{|e| "'#{e}'"}.join(" "))
It is giving below error:
Command :: composite '-gravity' 'SouthEast' 'https://s3.ap-south-1.amazonaws.com/s3_bucket_name/photos/images/000/000/026/thumb/download.png?1560328681' '/tmp/703fb0e145df584135fc841239e8aa3020190612-27615-14xprt020190612-27615-10g8hgo' '/tmp/703fb0e145df584135fc841239e8aa3020190612-27615-14xprt020190612-27615-10g8hgo'
Cocaine::ExitStatusError: Command 'composite '-gravity' 'SouthEast' 'https://s3.ap-south-1.amazonaws.com/s3_bucket_name/photos/images/000/000/026/thumb/download.png?1560328681' '/tmp/703fb0e145df584135fc841239e8aa3020190612-27615-14xprt020190612-27615-10g8hgo' '/tmp/703fb0e145df584135fc841239e8aa3020190612-27615-14xprt020190612-27615-10g8hgo'' returned 1. Expected 0
Here is the command output: STDOUT:
I try apply watermark to my paperclip, it keep show error message and unable update/upload image. It keep show **
uninitialized constant Paperclip::Watermark::PaperclipCommandLineError
**
gem file
gem "paperclip", '4.2' gem 'rails', '4.2.6' gem
'paperclip-compression'
paperclip_processors/watermark.rb
module Paperclip
class Watermark < Thumbnail
def initialize(file, options = {}, attachment = nil)
super
#watermark_path = options[:watermark_path]
#position = options[:position].nil? ? "SouthEast" : options[:position]
end
def make
src = #file
dst = Tempfile.new([#basename].compact.join("."))
dst.binmode
return super unless #watermark_path
params = "-gravity #{#position} #{transformation_command.join(" ")} #{#watermark_path} :source :dest"
begin
success = Paperclip.run("composite", params, :source => "#{File.expand_path(src.path)}[0]", :dest => File.expand_path(dst.path))
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}" if #whiny
end
dst
end
end
end
lisitng.rb
class Listing < ActiveRecord::Base
require 'paperclip_processors/watermark'
has_attached_file :image,
:processors => [:watermark],
:styles => {
:medium => {
:geometry => "300x300>",
:watermark_path => "#{Rails.root}/public/images/watermark.png"
},
:thumb => "100x100>",
}
I think you're subclassing wrong. Don't subclass Thumbnail, subclass Paperclip::Processor
module Paperclip
class Watermark < Processor
...
https://github.com/thoughtbot/paperclip/blob/master/lib/paperclip/processor.rb
Is there any way to set new dimensions to my_image and save it to AWS S3?
I have
my_image = Post.last.photo.image
geometry = Paperclip::Geometry.from_file(my_image.url)
so i want to set new geometry and save it
geometry = 'my params'
my_image.save
Of course i have my
has_attached_file :image, :styles => { :large => "220x" ..other styles}
My main goal set new dimensions during cropping photo with Jcrop
so when i receive new params like my_params=>"crop_x"=>"83", "crop_y"=>"24", "crop_w"=>"76", "crop_h"=>"76" set it as new style inside has_attached_file
You can do that easily,
Declare attribute accessors for the crop dimensions
attr_accessor :crop_x, :crop_y, :crop_w, :crop_h
Then you need to override the processor, create cropper.rb in /lib/paperclip_processors and add following code
module Paperclip
class Cropper < Thumbnail
def transformation_command
if crop_command
crop_command + super.join(' ').sub(/ -crop \S+/, '').split(' ') # super returns an array like this: ["-resize", "100x", "-crop", "100x100+0+0", "+repage"]
else
super
end
end
def crop_command
target = #attachment.instance
if target.cropping?
["-crop", "#{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y}"]
end
end
end
end
Now in the model you can do this
has_attached_file :image, styles: { large: "800X800>" }, default_url: "/images/:style/missing.png", :processors => [:cropper]
after_save :reprocess_image, if: :cropping?
def cropping?
!crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank?
end
def reprocess_image
image.assign(image)
image.save
end
Hope this helps!
My rails app uses Paperclip and ImageMagick to process uploaded photos.
I currently have it set up like this
as_attached_file :photo, :styles => { :original => "1500x1500>", :thumb => "400x400>#", :large => "1080x1080>" }, :convert_options => { :thumb => '-quality 60', :large => '-quality 60'}, :default_url => "/missing.png"
If someone uploads an image with dimension 1000x100 (10:1 aspect ratio) for example I would like to limit the aspect ratio (on the :large and :original) so that it will crop the image if the aspect ratio is too extreme.
ie: if ratio is beyond 4:1 or 1:4 then crop
The best way to do this is to implement a custom processor. That way you can implement your logic and decide when to change the image the way you want.
See an example implementation of a custom processor. In my case I needed to apply a watermark on the images.
lib/paperclip_processors/watermark.rb
module Paperclip
class Watermark < Thumbnail
attr_accessor :format, :watermark_path, :watermark_gravity, :watermark_dissolve
def initialize file, options = {}, attachment = nil
super
#file = file
#format = options[:format]
#watermark_path = options[:watermark_path]
#watermark_gravity = options[:watermark_gravity].nil? ? "center" : options[:watermark_gravity]
#watermark_dissolve = options[:watermark_dissolve].nil? ? 40 : options[:watermark_dissolve]
#current_format = File.extname(#file.path)
#basename = File.basename(#file.path, #current_format)
end
def make
return #file unless watermark_path
dst = Tempfile.new([#basename, #format].compact.join("."))
dst.binmode
command = "composite"
params = "-gravity #{#watermark_gravity} -dissolve #{#watermark_dissolve} #{watermark_path} #{fromfile} #{tofile(dst)}"
begin
success = Paperclip.run(command, params)
rescue PaperclipCommandLineError
raise PaperclipError, "There was an error processing the watermark for #{#basename}"
end
dst
end
def fromfile
"\"#{ File.expand_path(#file.path) }[0]\""
end
def tofile(destination)
"\"#{ File.expand_path(destination.path) }[0]\""
end
end
end
models/image.rb
has_attached_file :file,
processors: [:thumbnail, :watermark],
styles: {
layout: "100%",
preview: {geometry: "900x900>", watermark_path: "#{Rails.root}/app/assets/images/watermarks/watermark_200.png"},
thumbnail: "300x300>",
miniature: "150x150>"
},
convert_options: {
layout: "-units PixelsPerInch -density 100",
preview: "-units PixelsPerInch -density 72",
thumbnail: "-units PixelsPerInch -density 72",
miniature: "-units PixelsPerInch -density 72"
}
You can refer to the documentation for custom processors:
https://github.com/thoughtbot/paperclip#custom-attachment-processors
Trying to get the width and height of the uploaded image while still in the model on the initial save.
Any way to do this?
Here's the snippet of code I've been testing with from my model. Of course it fails on "instance.photo_width".
has_attached_file :photo,
:styles => {
:original => "634x471>",
:thumb => Proc.new { |instance|
ratio = instance.photo_width/instance.photo_height
min_width = 142
min_height = 119
if ratio > 1
final_height = min_height
final_width = final_height * ratio
else
final_width = min_width
final_height = final_width * ratio
end
"#{final_width}x#{final_height}"
}
},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style.:extension",
:bucket => 'foo_bucket'
So I'm basically trying to do this to get a custom thumbnail width and height based on the initial image dimensions.
Any ideas?
Ahh, figured it out. I just needed to make a proc.
Here's the code from my model:
class Submission < ActiveRecord::Base
#### Start Paperclip ####
has_attached_file :photo,
:styles => {
:original => "634x471>",
:thumb => Proc.new { |instance| instance.resize }
},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style.:extension",
:bucket => 'foo_bucket'
#### End Paperclip ####
def resize
geo = Paperclip::Geometry.from_file(photo.to_file(:original))
ratio = geo.width/geo.height
min_width = 142
min_height = 119
if ratio > 1
# Horizontal Image
final_height = min_height
final_width = final_height * ratio
"#{final_width.round}x#{final_height.round}!"
else
# Vertical Image
final_width = min_width
final_height = final_width * ratio
"#{final_height.round}x#{final_width.round}!"
end
end
end
class Asset
include Mongoid::Paperclip
before_save :extract_dimensions
field :width, type: Integer
field :height, type: Integer
has_mongoid_attached_file :data
def extract_dimensions
return unless is_image?
tempfile = data.queued_for_write[:original]
unless tempfile.nil?
geometry = Paperclip::Geometry.from_file(tempfile)
self.width = geometry.width.to_i
self.height = geometry.height.to_i
end
true # wont save if false
end
def is_image?
data_content_type =~ %r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$}
end
end