Rails ActiveStorage - crop and resize image variant
Today I've Learned postActive Storage image variants can run on two different engines: MiniMagic/Imagemagic or ruby-vips/libvips
which variant options have different syntax. The following will work for MiniMagic/Imagemagic setup:
tested on Rails 6.0.3.2 Ruby 2.7.1 on 2020-09-29
class Medium < ApplicationRecord
has_one_attached :image
end
Let say we upload an image
medium = Medium.create(params.require(:medium).permit(:image))
Here is the original image. Size is
1024x4246
medium.image.variant(resize: "400x300^", crop: '400x300+0+0')
Order of combine options does matter !!! If I swap resize and crop this will happen
medium.image.variant(crop: '400x300+0+0', resize: "400x300^")
If you want to center
medium.image.variant(:gravity=>"Center", resize: "400x300^", crop: '400x300+0+0')
If you need to rotate/auto-orient image:
medium.image.variant(auto_orient: true, rotate: 0, resize: "400x300^", crop: '400x300+0+0')
Need some blur ?
medium.image.variant(auto_orient: true, rotate: 0, resize: "400x300^", crop: '400x300+0+0', gaussian_blur: ['0x1.5'])
libvips
As For libvips
yes you can do the same thing but I don’t have code to
paste here. I’ll update this article once I have time to test it out.
combine_options is depreciated and will be removed in Rails 6.1
In Rails 6.1 :combine_options
will not be supported anymore
Rails warn message:
DEPRECATION WARNING: Active Storage's ImageProcessing transformer doesn't support :combine_options, as it always generates a single ImageMagick command. Passing :combine_options will not be supported in Rails 6.1.
So this will no longer work in future:
# this is now depricated !!
medium.image.variant({:combine_options=>{:gravity=>"Center", :resize=>"400x300^", :crop=>"400x300+0+0" }})
# this is now depricated !!
How to debug this ?
One thing to realize is that it takes quite some time to get the options right. It’s a pain to always reload web-browser with the Active Storage blob variant endpoint.
What I do instead: I just look up how the images are generated in test environment looking them up with file manager.
note: no this NOT how to test generated images! This is how to debug right variant options
# app/models/medium.rb
class Medium < ApplicationRecord
has_one_attached :image
def thumb
image.variant(auto_orient: true, rotate: 0, resize: "400x300^", crop: '400x300+0+0')
end
end
# spec/model/medium_spec.rb
require 'rails_helper'
RSpec.describe Medium, type: :model do
it 'should not throw error' do
medium = create :medium, :with_typed_image # How to do FactoryBot traits with file attachement, check out: https://blog.eq8.eu/til/factory-bot-trait-for-active-storange-has_attached.html
if medium.image.attached?
puts "\n"
k = medium.image.key.slice(0..3)
folders = [k[0..1], k[2..4]].join('/')
puts Rails.root.join('tmp', 'storage', folders).to_s
# => "/home/myuser/name_of_my_rails_project/tmp/storage/ks/cl"
variant = medium.thumb.processed # `.processed` is important!
## ...or if you want to play with options inside test:
# variant = medium.variant(auto_orient: true, rotate: 0, resize: "400x300^", crop: '400x300+0+0').processed
puts Rails.root.join('tmp', 'storage', 'va', 'ri', variant.key).to_s
# => /home/myuser/name_of_my_rails_project/tmp/storage/va/ri/variants/y0u5bhq109zzi1h3n8pa5v7p5f7u/500b88c14897d627f68fdd949ec32081f48593b82bdff4b4efed2fb1194d10d4
binding.irb # to stop the execution as your project may be set up to wipe out images after test finish
else
raise 'image was not attached?'
end
end
end
This way I’m able to open up the image easily with my file manager. E.g.
in ubuntu I open up nautilus
with
nautilus /home/myuser/name_of_my_rails_project/tmp/storage/va/ri/variants/y0u5bhq109zzi1h3n8pa5v7p5f7u/500b88c14897d627f68fdd949ec32081f48593b82bdff4b4efed2fb1194d10d4
I just check what was generated by my eye.
Once I’m done I just comment out this test.
Sources
Related articles
Discussion
Entire blog website and all the articles can be forked from this Github Repo