How to make Paperclip crop and NOT scale an attached image? - ruby-on-rails

I want Paperclip to crop, and not scale (see :full1 in this excerpt)
class Graphic < ActiveRecord::Base
has_attached_file :image, :styles => { :full0 => "940x1000#" #want it to scale, and crop if neccessary
:full1 => "940#", #want it to crop width, not scale
}
I want :full1 to work, but it doesn't. By "work" I mean it should crop the image's width, but do nothing to it's height. The reason is I'm uploading web screenshots, and I want them to be trimmed to 940px wide (from the center), but their height should remain intact. As far as what I research on paperclip I'm not finding how to do this.
Apparently it's quite supported by ImageMagick: http://www.imagemagick.org/Usage/crop/#crop_strip But I don't know how to jam this into paperclip on rails.
Many thanks!

Could you just set the height to something absurdly large so that it will be a non-issue?
class Graphic < ActiveRecord::Base
has_attached_file :image, :styles => { :full0 => "940x1000#" #want it to scale, and crop if neccessary
:full1 => "940x9999999#", #want it to crop width, not scale
}
I think that will crop anything wider than 940px.

You can user convert options for image process, Following will crop the image centrally.
has_attached_file :profile_picture, :storage => :s3,
:styles => { :medium => "", :thumb => ""},
:convert_options => {
:thumb => Proc.new { |instance| instance.thumnail_dimension },
:medium => Proc.new { |instance| instance.thumnail_dimension(300) }
}
def thumnail_dimension(size=100)
dimensions = Paperclip::Geometry.from_file(profile_picture.queued_for_write[:original].path)
min = dimensions.width > dimensions.height ? dimensions.height : dimensions.width
"-gravity Center -crop #{min}x#{min}+0+0 +repage -resize #{size}x#{size}^"
end

Related

How to set Paperclip to process original image?

Using Paperclip Gem in a Rails 4 project to attach an image and then clean out all exif data, like this:
has_attached_file :image,
styles: lambda{ |a|
{
large: ['800x', :png],
thumb_340: ['340x340#', :png],
thumb_180: ['180x180#', :png]
}
},
convert_options: { all: '-strip' }
Problem is, convert_options isn't getting called on the original image. What's the best method for reprocessing (or pre-processing) the original to make sure that '-strip' gets called?
try this
has_attached_file :image,
styles: lambda{ |a|
{
original: {convert_options: '-strip'},
large: ['800x', :png],
thumb_340: ['340x340#', :png],
thumb_180: ['180x180#', :png]
}
}

Rails Paperclip doesn't understand the same convert options as ImageMagick

Trying to set max width to 1280 when above 600Kb and not a .gif:
has_attached_file :main_image,
:styles => {:original => "" },
:convert_options => {
:original => lambda { |instance| (instance.main_image_file_name.index(/\.gif/,-4).nil? && instance.main_image.size > 600000) ? "-resize 1280>" : "" }
},
:path => ":rails_root/public/system/:class/:attachment/:id_:basename.:extension",
:url => "/system/:class/:attachment/:id_:basename.:extension"
Getting this in my logs:
Command :: convert '/var/folders/hn/2q5wpxh52nn_3nk9wwskr48w0000gn/T/5827912cb359afd550a72bf4f54b109020141119-76993-1i6nij6.png[0]' -auto-orient -resize 1280> '/var/folders/hn/2q5wpxh52nn_3nk9wwskr48w0000gn/T/5827912cb359afd550a72bf4f54b109020141119-76993-1i6nij620141119-76993-q0m833'
sh: 1280: Bad file descriptor
[paperclip] An error was received while processing: #<Paperclip::Error: There was an error processing the thumbnail for 5827912cb359afd550a72bf4f54b109020141119-76993-1i6nij6>
Two issues here:
Paperclip w/ Rails will often require you to add \\ in front of < or > characters, as in 1280x\\>
Also, Paperclip always needs those x's, even when just doing width (1280x\\> and not 1280\\>).
Here's my full solution for setting max width to 1280 when above 600Kb and not a .gif:
has_attached_file :main_image,
:styles => {:original => "" },
:convert_options => {
:original => lambda { |instance| (instance.main_image_file_name.index(/\.gif/,-4).nil? && instance.main_image.size > 600000) ? "-resize 1280x\\>" : "" }
},
:path => ":rails_root/public/system/:class/:attachment/:id_:basename.:extension",
:url => "/system/:class/:attachment/:id_:basename.:extension"

Limiting image dimensions based on aspect ratio within Paperclip and ImageMagick

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

Paperclip: width is 100%, height is 60% of width

How would I write a Paperclip style to keep the width of the uploaded image at 100% but crop only the height to 60% of the width?
Something like this:
has_attached_file :image, :styles => { :cropped => "100%x[60% of height]" }
has_attached_file :image, :styles => {
:original => "100x60>",
:thumb => Proc.new { |instance| instance.resize }
}
#### End Paperclip ####
def resize
geo = Paperclip::Geometry.from_file(image.to_file(:original))
height = (geo.width.to_i * 60)/100
width = geo.width
"#{width.round}x#{height.round}!"
end
Hope this could help you
has_attached_file :image, :styles => after_save :save_image_dimensions
def save_image_dimensions
geo = Paperclip::Geometry.from_file(image.path)
self.image_height = (geo.height.to_i * 60)/100
end
If you have problem on extract dimension From below you can get a good help
https://github.com/thoughtbot/paperclip/wiki/Extracting-image-dimensions
Please look into this link for cropping images using paperclip
http://viget.com/extend/manual-cropping-with-paperclip
Thanks

Paperclip obtain real image size

My problem is the next:
I am trying resize a image size depending a proportial size. Example If i have a image whose size is 1440*1000 its new size will be 648*440 (I use a proportion depending a max_size)
NOTE: Then i post my code so you will understand the size relations.
Ok. so I am reading this stackoverflow post:
Getting width and height of image in model in the Ruby Paperclip GEM
Now i post my code and then i will describe my problem.
class ProductImage < ActiveRecord::Base
belongs_to :product, :dependent => :destroy
MAXIMUM_SIZE = 650
has_attached_file :photo, :url => "/:attachment/:class/:id/:style_:basename.:extension", :styles => {:real_size => Proc.new { |instance| instance.real_size }, :original => "400x400>", :medium => "300x300>", :principal => "240x240>", :thumb => "100x100>", :small => "80x50>"}
def real_size
#image = Paperclip::Geometry.from_file(photo.to_file(:maximum_size))
#OBTAIN REAL IMAGE SIZE, NOT ATTACHMENT SIZES
if image_less_than_maximum_size?
return "#{image.width}x#{image.height}"
else
return adjust_image_size(self.width, self.height)
end
end
def adjust_image_size(image_width, image_height)
ratio = (image_width/image_height).to_f
difference_between_size = (image_width - image_height).abs
percentage_difference = ratio > 1 ? difference_between_size * 100.0 / image_width : difference_between_size * 100.0 / image_height
difference_respect_maximum_size = ratio > 1 ? MAXIMUM_SIZE * 100.0 / image_width : MAXIMUM_SIZE * 100.0 / image_height
width = height = 0.0
if ratio > 1
#USE 101.0 FOR INCREMENT OR DECREMENT THE VALUE A LITTLE BIT
width = image_width * difference_respect_maximum_size / 101.0
height = width - (percentage_difference * width / 101.0)
else
heigth = image_height * difference_respect_maximum_size / 101.0
width = height - (percentage_difference * height / 101.0)
end
return "#{width}x#{height}"
end
def image_less_than_maximum_size?
if self.width > self.height
return self.width < MAXIMUM_SIZE
else
return self.height < MAXIMUM_SIZE
end
end
end
My problem is how could i obtain the "real_size"?.
i.e, if image size is "1440*1000" to obtain this size (no attachment size)
UPDATE:
I am thinking a solution. So i think in declare two temp variable to ProductImage model and during initialize method use a before_post_process paperclip callback.
class ProductImage < ActiveRecord::Base
belongs_to :product, :dependent => :destroy
attr_accessor :height, :width
MAXIMUM_SIZE = 650
has_attached_file :photo, :url => "/:attachment/:class/:id/:style_:basename.:extension", :styles => {:real_size => Proc.new { |instance| instance.real_size }, :original => "400x400>", :medium => "300x300>", :principal => "240x240>", :thumb => "100x100>", :small => "80x50>"}
before_post_process :image?
before_post_process :assign_size
...
def assign_size
#width = Paperclip::Geometry.from_file(remote_original_photo_path).width
#height = Paperclip::Geometry.from_file(remote_original_photo_path).height
end
end
Then i could use this size in the other method.
My new problem is how could I determine the remote_original_photo_path in model?
in controller i use the params[:product][:product_images_attributes][index][:photo].
I could save the temp path in model. However because my real_size method during initilize i donĀ“t know how to pass the params info.
Thanks in advance again
With using a gem like image_size ?
[EDIT]
To determine the original upload path may be you can use :
remote_original_photo_path = File.basename(upload['datafile'].original_path)

Resources