Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get image dimensions using Refile

Using the Refile gem to handle file uploading in Rails, what is the best way to determine image height and width during / after it has been uploaded? There is no built in support for this AFAIK, and I can't figure out how to do it using MiniMagick.

like image 504
Chris Edwards Avatar asked Feb 21 '16 21:02

Chris Edwards


People also ask

How to find the size of my uploaded image?

Image Size Finder helps to find three different size details of your uploaded image. (1) Size of Image: To check Height and Width dimension of the uploaded images. Displays the size of the image in Pixel (px), Centimeter (cm) and Inches (in) scales.

How to find the original width and height of an image?

The naturalWidth and naturalHeight are read-only properties, and they are used to find out the original width and height of an image. We may use the width and height elements of the img tag to change the height and width of an image shown on our webpage.

How to get the size of an image using JavaScript?

Get image size with JavaScript (modern browsers, IE9+ ) function getMeta(url){ var img = new Image(); img.addEventListener("load", function(){ alert( this.naturalWidth +' '+ this.naturalHeight ); }); img.src = url; }

How to get the dimensions of an image in a document?

9 1 Unless you need to obtain the dimensions synchronously. In that case you just have to insert the image to the document (using an absolute position somewhere outside the viewport) - then the dimensions are available right after calling document.appendChild(). – JustAndrei Apr 7 '15 at 10:51


2 Answers

@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
like image 68
Mike V Avatar answered Oct 11 '22 01:10

Mike V


Refile attachments have a to_io method (see Refile::File docs) which returns an IO object that you can pass to MiniMagick.

Assuming you have an Image model with a file attachment (id stored in a file_id string column) and width and height columns you can use the following callback:

class Image < ActiveRecord::Base

  attachment :file

  before_save :set_dimensions, if: :file_id_changed?

  def set_dimensions
    image = MiniMagick::Image.open(file.to_io)
    self.width = image.width
    self.height = image.height
  end

end

Hope that helps.

like image 33
russellb Avatar answered Oct 10 '22 23:10

russellb