/
mini_magick_processor.rb
132 lines (117 loc) · 5.11 KB
/
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
require 'mini_magick'
module Technoweenie # :nodoc:
module AttachmentFu # :nodoc:
module Processors
module MiniMagickProcessor
def self.included(base)
base.send :extend, ClassMethods
base.alias_method_chain :process_attachment, :processing
end
module ClassMethods
# Yields a block containing an MiniMagick Image for the given binary data.
def with_image(file, &block)
begin
binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.from_file(file) unless !Object.const_defined?(:MiniMagick)
rescue
# Log the failure to load the image.
logger.debug("Exception working with image: #{$!}")
binary_data = nil
end
block.call binary_data if block && binary_data
ensure
!binary_data.nil?
end
end
protected
def process_attachment_with_processing
return unless process_attachment_without_processing
with_image do |img|
resize_image_or_thumbnail! img
self.width = img[:width] if respond_to?(:width)
self.height = img[:height] if respond_to?(:height)
callback_with_args :after_resize, img
end if image?
end
# Performs the actual resizing operation for a thumbnail
def resize_image(img, size)
size = size.first if size.is_a?(Array) && size.length == 1
img.combine_options do |commands|
commands.strip unless attachment_options[:keep_profile]
# gif are not handled correct, this is a hack, but it seems to work.
if img.output =~ / GIF /
img.format("png")
end
if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
if size.is_a?(Fixnum)
size = [size, size]
commands.resize(size.join('x'))
else
commands.resize(size.join('x') + '!')
end
# extend to thumbnail size
elsif size.is_a?(String) and size =~ /e$/
size = size.gsub(/e/, '')
commands.resize(size.to_s + '>')
commands.background('#ffffff')
commands.gravity('center')
commands.extent(size)
# crop thumbnail, the smart way
elsif size.is_a?(String) and size =~ /c$/
size = size.gsub(/c/, '')
# calculate sizes and aspect ratio
thumb_width, thumb_height = size.split("x")
thumb_width = thumb_width.to_f
thumb_height = thumb_height.to_f
thumb_aspect = thumb_width.to_f / thumb_height.to_f
image_width, image_height = img[:width].to_f, img[:height].to_f
image_aspect = image_width / image_height
# only crop if image is not smaller in both dimensions
unless image_width < thumb_width and image_height < thumb_height
command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
# crop image
commands.extract(command)
end
# don not resize if image is not as height or width then thumbnail
if image_width < thumb_width or image_height < thumb_height
commands.background('#ffffff')
commands.gravity('center')
commands.extent(size)
# resize image
else
commands.resize("#{size.to_s}")
end
# crop end
else
commands.resize(size.to_s)
end
end
temp_paths.unshift img
end
def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
# only crop if image is not smaller in both dimensions
# special cases, image smaller in one dimension then thumbsize
if image_width < thumb_width
offset = (image_height / 2) - (thumb_height / 2)
command = "#{image_width}x#{thumb_height}+0+#{offset}"
elsif image_height < thumb_height
offset = (image_width / 2) - (thumb_width / 2)
command = "#{thumb_width}x#{image_height}+#{offset}+0"
# normal thumbnail generation
# calculate height and offset y, width is fixed
elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
height = image_width / thumb_aspect
offset = (image_height / 2) - (height / 2)
command = "#{image_width}x#{height}+0+#{offset}"
# calculate width and offset x, height is fixed
else
width = image_height * thumb_aspect
offset = (image_width / 2) - (width / 2)
command = "#{width}x#{image_height}+#{offset}+0"
end
# crop image
command
end
end
end
end
end