So I know how both imageMagik
and carrierwave
work but the question is can they do exact resize of image. I tried with process resize_to_fit: [100, 100]
and uploaded a 800*200
image which resulted in 100*27
instead of 100*100
. resize_to_fill
does it but crops the image which should not be. Is there any way to resize to exact width and height in Ruby on Rails
using the carrierwave
.
Carrierwave passes a block with resize_to_fit and resize_to_limit to the manipulate!
method to crop the image.
By changing this block, you can change the cropping/resizing. Carrierwave
calls on instance Magick::Image
the method change_geometry
at this line.
The
change_geometry
method supports resizing a method by specifying constraints. For example, you can specify that the image should be resized such that the aspect ratio should be retained but the resulting image should be no larger than 640 pixels wide and 480 pixels tall.The argument may be either a geometry string or a Geometry object. Change_geometry yields to the block, passing new width and height values based on the argument with respect to self. The return value is the return value of the block.
You need to pass a block to manipulate!
similar to the below example:
def resize_no_crop(width, height)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
# change the below geometry object to achieve your effect
# geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
new_img = img.change_geometry(geometry) do |new_width, new_height|
img.resize(new_width, new_height)
end
destroy_image(img)
new_img = yield(new_img) if block_given?
new_img
end
end
Set the geometry
object as per your desires
geometry = Magick::Geometry.new(width, height, 0, 0, !)
as I read in the docs, the last parameters !
has the following effect
!
Use this flag when you want to force the new image to have exactly the size specified by the the width and height attributes.
ImageMagick
command line tool and Rmagick api docs provide more information.
Carrierwave
uses miniMagick
to perform the resizing process.
The ImageProcessing gem uses MiniMagick, a mini replacement for RMagick that uses ImageMagick command-line tools, to build a "convert" command that performs the processing.
This is how the resize_to_limit
method works, it may help you building your own method using the Rmagick
and ImageMagick
command line tools.
module MiniMagick
extend ActiveSupport::Concern
included do
require "image_processing/mini_magick"
end
module ClassMethods
def convert(format)
process :convert => format
end
def resize_to_limit(width, height)
process :resize_to_limit => [width, height]
end
end
end
The method
manipulates the images using the ImageMagick
command line tool and Rmagick. You can visit the above websites to read their documentation.
As you can read below resize_to_limit
manipulates the image by creating a new instance of Magick::Geometry
and passing a width
,height
, x,y
and flag
def resize_to_limit(width, height)
width = dimension_from width
height = dimension_from height
manipulate! do |img|
# Read The Explanation below
end
end
Carrierwave
created their own manipulate!
method which will iterate with the yield statement and crop/resize the image
image.each_with_index do |frame, index|
frame = yield(*[frame, index, options].take(block.arity)) if block_given?
frames << frame if frame
end
The method each_with_index
will iterate between manipulate! do ... end
with the yield statement.
*[frame, index, options].take(block.arity)
, .take(block.arity)
will pass only frame
as it is called with only one parameter.
The frame
variable will equal the new_image
returned.
geometry = Magick::Geometry.new(width, height, 0, 0, Magick::GreaterGeometry)
new_img = img.change_geometry(geometry) do |new_width, new_height|
img.resize(new_width, new_height)
end
destroy_image(img)
new_img = yield(new_img) if block_given?
new_img
You can read more about Image::Magick class and on rmagick.github.io to better understand how the process of frame selection works.