I recently needed to find out the geometry of the image being uploaded via CarrierWave. Images come in many different sizes and shapes. What I want is to have a “best” image and store its actual size along with my image model.
Define a Best Image
First, lets define a “best” version of the image. That’s one that’s not being resized, only converted into JPG.
class ArtworkUploader < CarrierWave::Uploader::Base
version :best do
process convert: 'jpg'
end
end
Fetch Geometry on Upload
Notice the process declarations above: both resize_to_limit and convert are methods of the uploader class. We can therefore add a new read_geometry function and store the geometry of the uploaded image with this version.
class ArtworkUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
version :best do
process convert: 'jpg'
process :read_geometry
attr_reader :geometry
end
def read_geometry
return unless @file
img = ::Magick::Image.read(@file.file).first
@geometry = [img.columns, img.rows]
end
end
Save Geometry
Finally, we would like to store best_width and best_height with the Image model. We use Mongoid, so we can fetch the geometry before_save.
class Image
field :best_width
field :best_height
before_save :saving
def saving
geometry = image.best.geometry
return if geometry.nil?
self.best_width = geometry[0]
self.best_height = geometry[1]
end
end
I think image geometry should be a built-in function and property of CarrierWave. Maybe this can be improved further and make it into the library?
