Is There a Simple Way to Get Image Dimensions in Ruby

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



Leave a reply



Submit