views:

328

answers:

4

I want attachment_fu to resize my thumbnails in a similar way to how flickr, facebook and twitter handle this: If I want a 100x100 thumbnail I want the thumbnail to be exactly 100x100 with any excess cropped off so that the aspect ratio is preserved.

Any ideas?

+1  A: 

To set up the 100x100 thumbnails, add the following to your model:

  has_attachment :content_type => :image,
                 :storage => IMAGE_STORAGE,
                 :max_size => 20.megabytes,
                 :thumbnails => {
                   :thumb  => '100x100>',
                   :large  => '800x600>',
                 }

(In this example, I am creating a 100x100 thumbnail, and also an 800x600 'large' size, in additional to keeping the original size.)

Also, keep in mind that the thumbnail might not be exactly 100x100; it will have a maximum dimension of 100x100. This means that if the original has an aspect ration of 4:3, the thumbnail would be 100x75. I'm not exactly sure if that is what you meant by "exactly 100x100 with any excess cropped off so that the aspect ratio is preserved."

pkaeding
The > modifier simply sets the largest dimension> What I want is an image of exactly 100x100 with aspect ratio preserved, no matter what the original image dimensions.
Mike Sutton
@Mike Sutton : I'm a little confused... what if the input image is not square? How do you get an exactly 100x100 thumbnail, while preserving aspect ratio? Suppose you had an input image that was 1000x750. What should the result be?
pkaeding
The excess should be cropped off to make the image square.
Mike Sutton
Okay, so in the case of an image that is 1000 px high, and 750 px wide, the resulting image should crop off the 25% of the top? or 25% of the bottom? or 12.5% off the top and 12.5% off the bottom?
pkaeding
Top and bottom. Check out how flickr does it, for example here: http://www.flickr.com/photos/romanlily/sets/81690/
Tomas Markauskas
A: 

There's a cropping directive that can be given in the specification:

has_attachment :content_type => :image,
  :thumbnails => {
    :thumb  => '100x100#'
}

Memonic: '#' looks like the crop tool.

Edit: Correction

has_attachment :content_type => :image,
  :thumbnails => {
    :thumb  => '100x100!'
}

The previous method was for Paperclip which has a different notation.

tadman
"Unknown geometry string" error
Mike Sutton
Maybe that's where Paperclip is better than attachment_fu. Hm.
tadman
Actually, I've looked at some old attachment_fu stuff I have and I used '100x100!' to specify cropping.
tadman
! does a resize without preserving the aspect ratio.
Mike Sutton
A: 

Add this to your model

protected  

  # Override image resizing method  
  def resize_image(img, size)  
    # resize_image take size in a number of formats, we just want  
    # Strings in the form of "crop: WxH"  
    if (size.is_a?(String) && size =~ /^crop: (\d*)x(\d*)/i) ||  
        (size.is_a?(Array) && size.first.is_a?(String) &&  
          size.first =~ /^crop: (\d*)x(\d*)/i)  
      img.crop_resized!($1.to_i, $2.to_i)  
      # We need to save the resized image in the same way the  
      # orignal does.  
      self.temp_path = write_to_temp_file(img.to_blob)  
    else  
      super # Otherwise let attachment_fu handle it  
    end  
  end

and change the thumbnail size to:

:thumbnails => {:thumb => 'crop: 100x100' }

source:

http://stuff-things.net/2008/02/21/quick-and-dirty-cropping-images-with-attachment_fu/

deb
Wouldn't work in the model. I tried editing the plug in itself, but it still doesn't preserve the aspect ratio.
Mike Sutton
A: 

My solution was to delve into the attachment_fu plugin folder (vendor/plugins) and edit the rmagick_processor.rb file. First I renamed resize_image to resize_image_internal, then added:

  def resize_image(img, size)  
    # resize_image take size in a number of formats, we just want  
    # Strings in the form of "square: WxH"  
    if (size.is_a?(String) && size =~ /^square: (\d*)x(\d*)/i) ||  
        (size.is_a?(Array) && size.first.is_a?(String) &&  
          size.first =~ /^square: (\d*)x(\d*)/i)  
        iw, ih = img.columns, img.rows
        aspect = iw.to_f / ih.to_f
        if aspect > 1
            shave_off = (iw - ih) / 2
            img.shave!(shave_off, 0)
        else
            shave_off = (ih-iw) / 2
            img.shave!(0, shave_off)
        end
        resize_image_internal(img, "#{$1}x#{$2}!")
    else  
      resize_image_internal(img, size) # Otherwise let attachment_fu handle it  
    end  
  end

I can now use 'square: 100x100' as my geometry string. Note that the above code assumes the required output is square.

Mike Sutton