Entries Tagged as 'ruby on rails'

Cropped thumbnails in attachment_fu using mini_magick

I’m in the process of building a ruby on rails application that allows people to upload images. The application then takes these images and creates a series of thumbnails that are used throughout the site.

Having opted to use attachment_fu and mini_magick as my respective file upload plugin and image processor, I found an excellent post by Khamsouk Souvanlasy explaining how to create the upload form using AJAX.

The difficultly came when I wanted to make one of the custom thumbnails measure 100px x 100px, and crop the source image appropriately:

Example of ratio cropping

Thankfully Andy Croll had written how he patched attachment_fu to enable it to do just that, only using ImageScience as it’s image processor.

Therefore, I’ve extended this patch to allow you to use a ! flag to create an aspect ratio cropped image, using mini_magick as your processor.

Step 1

Modify attachment_fu/lib/geometry.rb, as suggested by Andy in cropped thumbnails in attachment_fu using imagescience. This ensures the ! flag is interpretted correctly in attachment_fu.

Step 2

Modify the resize_image function of attachment_fu/processors/mini_magick_processor.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def resize_image(img, size)
  size = size.first if size.is_a?(Array) && size.length == 1
  if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
    if size.is_a?(Fixnum)
      size = [size, size]
      img.resize(size.join('x'))
    else
      img.resize(size.join('x') + '!')
    end
  else
    n_size = [img[:width], img[:height]] / size.to_s
    if size.ends_with? "!"
      aspect = n_size[0].to_f / n_size[1].to_f
      ih, iw = img[:height], img[:width]
      w, h = (ih * aspect), (iw / aspect)
      w = [iw, w].min.to_i
      h = [ih, h].min.to_i
      if ih > h
        shave_off =  ((ih - h) / 2).round
        img.shave("0x#{shave_off}")
      end
      if iw > w
        shave_off = ((iw - w ) / 2).round
        img.shave("#{shave_off}x0")
      end
      img.resize(size.to_s)
    else
      img.resize(size.to_s)
    end
    self.temp_path = img
  end
end

Step 3

Modify your model, using the new ! flag to force a cropped aspect ratio:

has_attachment  :storage => :file_system,
                :max_size => 2.megabytes,
                :thumbnails => { :thumb => '100x100!', :medium => '470x470' },
                :processor => :MiniMagick

I think this is an excellent solution. Thanks to everyone I’ve link to here, they’ve done the real work!