2 module Technoweenie # :nodoc:
3 module AttachmentFu # :nodoc:
5 module MiniMagickProcessor
6 def self.included(base)
7 base.send :extend, ClassMethods
8 base.alias_method_chain :process_attachment, :processing
12 # Yields a block containing an MiniMagick Image for the given binary data.
13 def with_image(file, &block)
15 binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.from_file(file) unless !Object.const_defined?(:MiniMagick)
17 # Log the failure to load the image.
18 logger.debug("Exception working with image: #{$!}")
21 block.call binary_data if block && binary_data
28 def process_attachment_with_processing
29 return unless process_attachment_without_processing
31 resize_image_or_thumbnail! img
32 self.width = img[:width] if respond_to?(:width)
33 self.height = img[:height] if respond_to?(:height)
34 callback_with_args :after_resize, img
38 # Performs the actual resizing operation for a thumbnail
39 def resize_image(img, size)
40 size = size.first if size.is_a?(Array) && size.length == 1
41 img.combine_options do |commands|
42 commands.strip unless attachment_options[:keep_profile]
44 # gif are not handled correct, this is a hack, but it seems to work.
45 if img.output =~ / GIF /
49 if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
52 commands.resize(size.join('x'))
54 commands.resize(size.join('x') + '!')
56 # extend to thumbnail size
57 elsif size.is_a?(String) and size =~ /e$/
58 size = size.gsub(/e/, '')
59 commands.resize(size.to_s + '>')
60 commands.background('#ffffff')
61 commands.gravity('center')
63 # crop thumbnail, the smart way
64 elsif size.is_a?(String) and size =~ /c$/
65 size = size.gsub(/c/, '')
67 # calculate sizes and aspect ratio
68 thumb_width, thumb_height = size.split("x")
69 thumb_width = thumb_width.to_f
70 thumb_height = thumb_height.to_f
72 thumb_aspect = thumb_width.to_f / thumb_height.to_f
73 image_width, image_height = img[:width].to_f, img[:height].to_f
74 image_aspect = image_width / image_height
76 # only crop if image is not smaller in both dimensions
77 unless image_width < thumb_width and image_height < thumb_height
78 command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
81 commands.extract(command)
84 # don not resize if image is not as height or width then thumbnail
85 if image_width < thumb_width or image_height < thumb_height
86 commands.background('#ffffff')
87 commands.gravity('center')
91 commands.resize("#{size.to_s}")
95 commands.resize(size.to_s)
98 temp_paths.unshift img
101 def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
102 # only crop if image is not smaller in both dimensions
104 # special cases, image smaller in one dimension then thumbsize
105 if image_width < thumb_width
106 offset = (image_height / 2) - (thumb_height / 2)
107 command = "#{image_width}x#{thumb_height}+0+#{offset}"
108 elsif image_height < thumb_height
109 offset = (image_width / 2) - (thumb_width / 2)
110 command = "#{thumb_width}x#{image_height}+#{offset}+0"
112 # normal thumbnail generation
113 # calculate height and offset y, width is fixed
114 elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
115 height = image_width / thumb_aspect
116 offset = (image_height / 2) - (height / 2)
117 command = "#{image_width}x#{height}+0+#{offset}"
118 # calculate width and offset x, height is fixed
120 width = image_height * thumb_aspect
121 offset = (image_width / 2) - (width / 2)
122 command = "#{width}x#{image_height}+#{offset}+0"