Search code examples
rubyruby-on-rails-3rmagickcarrierwave

Scale down image until one side reaches goal dimension


How do you scale down an image until one side reaches it's goal dimension with Carrierwave and rmagick?

Example:

Goal dimensions: 600x400

Picture being uploaded: 700x450

I want this image to be scaled down until the height reaches 400 pixels keeping the original aspect ratio.

That would result in a image with the following dimensions: 622x400


Solution

  • You might take a look at resize_to_limit. From the carrierwave docs:

    Resize the image to fit within the specified dimensions while retaining the original aspect ratio. Will only resize the image if it is larger than the specified dimensions. The resulting image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.

    So you could do something like this in your uploader:

    process :resize_to_fill => [600, 400]
    

    If you don't mind to crop the image, you could go for resize_to_fit instead, and use the gravity value that you desire:

    From the RMagick documentation: “Resize the image to fit within the specified dimensions while retaining the original aspect ratio. The image may be shorter or narrower than specified in the smaller dimension but will not be larger than the specified values.“

    Edit: You can read the documentation for these processors for more options on resizing

    For a resize_to_min implementation that would only enforce minimum dimensions for your width and height, you can take resize_to_limit as base and just modify the geometry setting to MinimumGeometry to create a custom processor:

      process :resize_to_min => [600, 400]
    
      def resize_to_min(width, height)
        manipulate! do |img|
          geometry = Magick::Geometry.new(width, height, 0, 0, Magick::MinimumGeometry)
          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