I am trying to resize an image with Rmagick and if I use the resize_to_fit
method to always resize the height first, preferring that to width, but it seems as if most of my images are being resized to width first. IS there anyway using the resize_to_fit
method to tell it "prefer height over width"?
I don't understand what you mean by to resize height first. So perhaps I'm wrong with my answer.
When you resize you have three possibilities: You may keep the ratio (resize_to_fit
) or crop the picture (resize_to_fill
) or stretch/shrink the picture (scale
?)
With resize_to_fit
you can define a maximum width and optional a maximum length (default is the given width).
Example: img.resize_to_fit(300)
. Depending on your picture you get a picture with maximum width 300 or length 300. The other dimension is calculated by the ratio. A 50x100 picture becomes 150x300. A 100x50 picture becomes 300x150.
If you want a 300x400 picture you can't use img.resize_to_fit(300,400)
, it would check, which dimension does fit first and calculate the other dimension depending on it.
If your prefer height over width means, that you want a given height (e.g. 300) and the width should be calculated by the picture ratio, you may use resize_to_fit(1000000, 300)
.
Every times the height 300 will be reached before the width 1000000 is reached, your picture will get the height 300.
A few thoughts and some code.
What differences do you see? How can you tell it's width first? I don't see a case where the end result should be a different size, if it's a quality problem an example might help.
It doesn't look like the api exposes a way to stretch one way and then another but we can certainly make a method or two to give it a try. There are two approaches below, the first, two_step_resize resizes in one direction and the the other. The second, resize_with_rotate rotates the image, resizes it, and then rotates it back.
For the examples I ran it through I don't see any oddness in either solution.
require 'RMagick'
#Change the size in two steps, height first then width
def two_step_resize(img, filename, max_x, max_y)
x = img.columns
y = img.rows
#make sure it's a float w/ the 1.0*
ratio = (1.0*x)/y
new_y = max_y
new_x = ratio * new_y
if (new_x > max_x)
new_x = max_x
new_y = new_x / ratio
end
# do the change in two steps, first the height
img.resize!(x, new_y);
#then the width
img.resize!(new_x, new_y)
#save it, with the least compression to get a better image
res.write(filename){self.quality=100}
end
#spin the image before resizing
def resize_with_rotate(img, output_filename, max_x, max_y)
res = img.rotate(90).resize_to_fit(max_y, max_x).rotate(-90)
res.write(output_filename){self.quality=100}
end
img = Magick::Image.read(filename).first
two_step_resize(img, "2-step.jpg", 100, 200)
img = Magick::Image.read(filename).first
resize_with_rotate(img, "rotate.jpg", 100, 200)
You can specify the height max value and let Rmagick calculate the corresponding width by using the change_geometry method.
This can be useful in case you want to set the max height of a landscape image and do not want to specify the corresponding width to preserve the ratio:
require "rmagick"
include Magick
img = ImageList.new("<path_to_your_img>") # assuming a landscape oriented img
img.change_geometry("x395") do |cols, rows, img| # set the max height
img.resize(cols, rows)
end
Do remember you always have to pass a block to the change geometry method. You can find more information on the official documentation.
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With