Last active
September 24, 2024 09:17
-
-
Save maxivak/3924976 to your computer and use it in GitHub Desktop.
Crop and resize an image using MiniMagick in Ruby on Rails. Two approaches.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def resize_nocrop_noscale(image, w,h) | |
w_original = image[:width].to_f | |
h_original = image[:height].to_f | |
if w_original < w && h_original < h | |
return image | |
end | |
# resize | |
image.resize("#{w}x#{h}") | |
return image | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def resize_with_crop(img, w, h, options = {}) | |
gravity = options[:gravity] || :center | |
w_original, h_original = [img[:width].to_f, img[:height].to_f] | |
op_resize = '' | |
# check proportions | |
if w_original * h < h_original * w | |
op_resize = "#{w.to_i}x" | |
w_result = w | |
h_result = (h_original * w / w_original) | |
else | |
op_resize = "x#{h.to_i}" | |
w_result = (w_original * h / h_original) | |
h_result = h | |
end | |
w_offset, h_offset = crop_offsets_by_gravity(gravity, [w_result, h_result], [ w, h]) | |
img.combine_options do |i| | |
i.resize(op_resize) | |
i.gravity(gravity) | |
i.crop "#{w.to_i}x#{h.to_i}+#{w_offset}+#{h_offset}!" | |
end | |
img | |
end | |
# from http://www.dweebd.com/ruby/resizing-and-cropping-images-to-fixed-dimensions/ | |
GRAVITY_TYPES = [ :north_west, :north, :north_east, :east, :south_east, :south, :south_west, :west, :center ] | |
def crop_offsets_by_gravity(gravity, original_dimensions, cropped_dimensions) | |
raise(ArgumentError, "Gravity must be one of #{GRAVITY_TYPES.inspect}") unless GRAVITY_TYPES.include?(gravity.to_sym) | |
raise(ArgumentError, "Original dimensions must be supplied as a [ width, height ] array") unless original_dimensions.kind_of?(Enumerable) && original_dimensions.size == 2 | |
raise(ArgumentError, "Cropped dimensions must be supplied as a [ width, height ] array") unless cropped_dimensions.kind_of?(Enumerable) && cropped_dimensions.size == 2 | |
original_width, original_height = original_dimensions | |
cropped_width, cropped_height = cropped_dimensions | |
vertical_offset = case gravity | |
when :north_west, :north, :north_east then 0 | |
when :center, :east, :west then [ ((original_height - cropped_height) / 2.0).to_i, 0 ].max | |
when :south_west, :south, :south_east then (original_height - cropped_height).to_i | |
end | |
horizontal_offset = case gravity | |
when :north_west, :west, :south_west then 0 | |
when :center, :north, :south then [ ((original_width - cropped_width) / 2.0).to_i, 0 ].max | |
when :north_east, :east, :south_east then (original_width - cropped_width).to_i | |
end | |
return [ horizontal_offset, vertical_offset ] | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# see details - http://maxivak.com/crop-and-resize-an-image-using-minimagick-ruby-on-rails | |
def resize_with_nocrop(image, w, h) | |
w_original = image[:width].to_f | |
h_original = image[:height].to_f | |
if (w_original*h != h_original * w) | |
if w_original*h >= h_original * w | |
# long width | |
w_result = w | |
h_result = w_result * (h_original / w_original) | |
elsif w_original*h <= h_original * w | |
# long height | |
h_result = h | |
w_result = h_result * (w_original / h_original) | |
end | |
else | |
# good proportions | |
h_result = h | |
w_result = w | |
end | |
# | |
image.resize("#{w_result}x#{h_result}") | |
return image | |
end | |
Awesome script, thanks.
Btw, this didn’t maintain the correct gravity orientation for me when I used this exact code for the resize_with_crop function.
I needed to remove the:
i.gravity(gravity)
line of code to make it work.
Doesn't work properly. Two strings works wrong in my case. Should be:
when :center, :east, :west then [ ((original_height - cropped_height) / 2.0).to_i, 0 ].min
when :center, :north, :south then [ ((original_width - cropped_width) / 2.0).to_i, 0 ].min
@Sinozet THANK YOU
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@maxivak I believe that in the resize_with_crop method, there is a mistake respect to the original code that you mentioned.
The fact that the line 23 in the gravity function there is not always 'Northwest' but the option gravity that we pass, mess up the cropping region. Effectively if you try your code without gravity option, it will set it up that to :center, and the cropping result will be just not around the center but starting from the bottom of the image, and that is weird.
What do you think?
Actually I just think that condition is completely wrong. It shouldn't have any gravity before crop (the gravity anyway is used to calculate the offset). Using a gravity flag that is not fixed as for example the original code 'NorthWest', will just create a lot of trouble in the image cropping: e.g. don't give option will set the option gravity to center, and with the gravity as center before the crop image, it will move it to the bottom.
I believe that you can be without any gravity before the crop, or if you want one just put it as fixed value as 'NorthWest'.
My 2 cents!
Cheers