Is there a simple way to get image dimensions in Ruby?
libimage-size is a Ruby library for calculating image sizes for a wide variety of graphical formats. A gem is available, or you can download the source tarball and extract the image_size.rb
file.
Get the width and height of an image without downloading it
You will most likely not be able to do so without actually downloading the image (as in using the bandwidth).
That being said, you can use the FastImage gem to do this for you.
require 'fastimage'
FastImage.size("http://stephensykes.com/images/ss.com_x.gif")
=> [266, 56] # width, height
How to check the height and width of a image in rails before update?
You can use the mini magic gem
require 'mini_magick'
image = MiniMagick::Image.open(user.avatar) # or user.avatar.path
image[:width] > image[:height]
Getting the dimensions of the image in ruby
Since you already use an external library (ImageMagick), you could use its Ruby wrapper RMagick:
require 'RMagick'
img = Magick::Image::read('image.png').first
arr = [img.columns, img.rows]
Here's an example of a very simple PNG parser:
data = File.binread('image.png', 100) # read first 100 bytes
if data[0, 8] == [137, 80, 78, 71, 13, 10, 26, 10].pack("C*")
# file has a PNG file signature, let's get the image header chunk
length, chunk_type = data[8, 8].unpack("l>a4")
raise "unknown format, expecting image header" unless chunk_type == "IHDR"
chunk_data = data[16, length].unpack("l>l>CCCCC")
width = chunk_data[0]
height = chunk_data[1]
bit_depth = chunk_data[2]
color_type = chunk_data[3]
compression_method = chunk_data[4]
filter_method = chunk_data[5]
interlace_method = chunk_data[6]
puts "image size: #{width}x#{height}"
else
# handle other formats
end
Get image dimensions using Refile
@russellb's comment almost got me there, but wasn't quite correct. If you have a Refile::File called @file, you need to:
fileIO = @file.to_io.to_io
mm = MiniMagick::Image.open(fileIO)
mm.width # image width
mm.height # image height
Yes, that's two calls to #to_io >...< The first to_io gives you a Tempfile, which isn't what MiniMagick wants. Hope this helps someone!
-- update --
Additional wrinkle: this will fail if the file is very small (<~20kb, from: ruby-forum.com/topic/106583) because you won't get a tempfile from to_io, but a StringIO. You need to fork your code if you get a StringIO and do:
mm = MiniMagick::Image.read(fileio.read)
So my full code is now:
# usually this is a Tempfile; but if the image is small, it will be
# a StringIO instead >:[
fileio = file.to_io
if fileio.is_a?(StringIO)
mm = MiniMagick::Image.read(fileio.read)
else
file = fileio.to_io
mm = MiniMagick::Image.open(file)
end
Fast way to get remote image dimensions
I think this gem does what you want https://github.com/sdsykes/fastimage
FastImage finds the size or type of an
image given its uri by fetching as
little as needed
Ruby on Rails - Carrierwave get the image dimension width and height
You have to install ImageMagick, RMagick or MiniMagick. Then you open the file (image) before you can find out its height.
Example: https://github.com/jnicklas/carrierwave#conditional-versions (see the is_landscape? method), copied here:
def is_landscape? picture
image = MiniMagick::Image.open(picture.path)
image[:width] > image[:height]
end
Or this other related question:
Carrierwave and mini_magick finding widths & height
Extracting image dimensions in the background with Shrine
The way I got this to work is by making use of :refresh_metadata
plugin, instead of :restore_cached_data
which I used originally. Thanks to Janko for pointing me in the right direction.
Reading into the source code provided some useful insights. :store_dimensions
plugin by itself doesn't extract dimensions - it adds width and height to the metadata hash so that when Shrine's base class requests metadata, they get extracted too.
By using :restore_cached_data
, this was being done on every assignment. :restore_cached_data
uses :refresh_metadata
internally so we can use that knowledge to only call it when the file is promoted to the store.
I have :backgrounding
and :store_dimensions
set up in the initializer so the final uploader can be simplified to this:
class ImageUploader < Shrine
plugin :refresh_metadata
plugin :processing
process(:store) do |io, context|
io.refresh_metadata!(context)
io
end
end
This way persisting data we get from Uppy is super fast and we let the background job extract dimensions when the file is promoted to the store, so they can be used later.
Finally, should you have questions related to Shrine, I highly recommend its dedicated Google Group. Kudos to Janko for not only creating an amazing piece of software (seriously, go read the source), but also for his dedication to supporting the community.
Getting width and height of image in model in the Ruby Paperclip GEM
Ahh, figured it out. I just needed to make a proc.
Here's the code from my model:
class Submission < ActiveRecord::Base
#### Start Paperclip ####
has_attached_file :photo,
:styles => {
:original => "634x471>",
:thumb => Proc.new { |instance| instance.resize }
},
:storage => :s3,
:s3_credentials => "#{RAILS_ROOT}/config/s3.yml",
:path => ":attachment/:id/:style.:extension",
:bucket => 'foo_bucket'
#### End Paperclip ####
def resize
geo = Paperclip::Geometry.from_file(photo.to_file(:original))
ratio = geo.width/geo.height
min_width = 142
min_height = 119
if ratio > 1
# Horizontal Image
final_height = min_height
final_width = final_height * ratio
"#{final_width.round}x#{final_height.round}!"
else
# Vertical Image
final_width = min_width
final_height = final_width * ratio
"#{final_height.round}x#{final_width.round}!"
end
end
end
Related Topics
What's the Best Way to Talk to a Database While Using Sinatra
Is There a Literal Notation for an Array of Symbols
Access Instance Variable from Outside the Class
Convert an Array of Integers into an Array of Strings in Ruby
Nested Object Creation with JSON in Rails
How to Set Up Cascade Deleting in Rails
Skip Over Iteration in Enumerable#Collect
Difference Between Plugins and Ruby Gems
Getting Only New Mail from an Imap Server
Count Number of Days Between Two Dates
How to Return Something Early from a Block
How to Check If a Class Is Defined
How to Sort a String's Characters Alphabetically
How to Add a New Action to the Existing Controller
Undefined Instance Method "Respond_To" in Rails 5 API Controller