Daniel Doubrovkine bio photo

Daniel Doubrovkine

aka dB., @awscloud, former CTO @artsy, +@vestris, NYC

Email Twitter LinkedIn Github Strava
Creative Commons License

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 get_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 :get_geometry

    def geometry
      @geometry
    end
  end

  def get_geometry
    if (@file)
      img = ::Magick::Image::read(@file.file).first
      @geometry = [img.columns, img.rows]
    end
  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 = self.image.best.geometry
    if (! geometry.nil?)
      self.best_width = geometry[0]
      self.best_height = geometry[1]
    end
  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?