Module: FileColumn::MagickExtension

Defined in:
lib/magick_file_column.rb

Overview

If you are using file_column to upload images, you can directly process the images with RMagick, a ruby extension for accessing the popular imagemagick libraries. You can find more information about RMagick at rmagick.rubyforge.org.

You can control what to do by adding a :magick option to your options hash. All operations are performed immediately after a new file is assigned to the file_column attribute (i.e., when a new file has been uploaded).

Resizing images

To resize the uploaded image according to an imagemagick geometry string, just use the :size option:

file_column :image, :magick => {:size => "800x600>"}

If the uploaded file cannot be loaded by RMagick, file_column will signal a validation error for the corresponding attribute. If you want to allow non-image files to be uploaded in a column that uses the :magick option, you can set the :image_required attribute to false:

file_column :image, :magick => {:size => "800x600>",
                                :image_required => false }

Multiple versions

You can also create additional versions of your image, for example thumb-nails, like this:

file_column :image, :magick => {:versions => {
     :thumb => {:size => "50x50"},
     :medium => {:size => "640x480>"}
   }

These versions will be stored in separate sub-directories, named like the symbol you used to identify the version. So in the previous example, the image versions will be stored in “thumb”, “screen” and “widescreen” directories, resp. A name different from the symbol can be set via the :name option.

These versions can be accessed via FileColumnHelper's url_for_image_column method like this:

<%= url_for_image_column "entry", "image", :thumb %>

Cropping images

If you wish to crop your images with a size ratio before scaling them according to your version geometry, you can use the :crop directive.

file_column :image, :magick => {:versions => {
     :square => {:crop => "1:1", :size => "50x50", :name => "thumb"},
     :screen => {:crop => "4:3", :size => "640x480>"},
     :widescreen => {:crop => "16:9", :size => "640x360!"},
   }
}

Custom attributes

To change some of the image properties like compression level before they are saved you can set the :attributes option. For a list of available attributes go to www.simplesystems.org/RMagick/doc/info.html

file_column :image, :magick => { :attributes => { :quality => 30 } }

Custom transformations

To perform custom transformations on uploaded images, you can pass a callback to file_column:

file_column :image, :magick => 
   Proc.new { |image| image.quantize(256, Magick::GRAYColorspace) }

The callback you give, receives one argument, which is an instance of Magick::Image, the RMagick image class. It should return a transformed image. Instead of passing a Proc object, you can also give a Symbol, the name of an instance method of your model.

Custom transformations can be combined via the standard :size and :crop features, by using the :transformation option:

file_column :image, :magick => {
   :transformation => Proc.new { |image| ... },
   :size => "640x480"
 }

In this case, the standard resizing operations will be performed after the custom transformation.

Of course, custom transformations can be used in versions, as well.

Note: You'll need the RMagick extension being installed in order to use file_column's imagemagick integration.

Class Method Summary collapse

Class Method Details

.file_column(klass, attr, options) ⇒ Object

:nodoc:


212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/magick_file_column.rb', line 212

def self.file_column(klass, attr, options) # :nodoc:
  require 'RMagick'
  options[:magick] = process_options(options[:magick],false) if options[:magick]
  if options[:magick][:versions]
    options[:magick][:versions].each_pair do |name, value|
      options[:magick][:versions][name] = process_options(value, name.to_s)
    end
  end
  state_method = "#{attr}_state".to_sym
  after_assign_method = "#{attr}_magick_after_assign".to_sym
  
  klass.send(:define_method, after_assign_method) do
    self.send(state_method).transform_with_magick
  end
  
  options[:after_upload] ||= []
  options[:after_upload] << after_assign_method
  
  klass.validate do |record|
    state = record.send(state_method)
    if state.has_magick_errors?
      state.magick_errors.each do |error|
        record.errors.add attr, error
      end
    end
  end
end

.process_options(options, create_name = true) ⇒ Object


241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/magick_file_column.rb', line 241

def self.process_options(options,create_name=true)
  case options
  when String then options = {:size => options}
  when Proc, Symbol then options = {:transformation => options }
  end
  if options[:geometry]
    options[:size] = options.delete(:geometry)
  end
  options[:image_required] = true unless options.key?(:image_required)
  if options[:name].nil? and create_name
    if create_name == true
      hash = 0
      for key in [:size, :crop]
        hash = hash ^ options[key].hash if options[key]
      end
      options[:name] = hash.abs.to_s(36)
    else
      options[:name] = create_name
    end
  end
  options
end