ss-attachment_fu 3.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,142 @@
1
+ require 'mini_magick'
2
+ module Technoweenie # :nodoc:
3
+ module AttachmentFu # :nodoc:
4
+ module Processors
5
+ module MiniMagickProcessor
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ base.alias_method_chain :process_attachment, :processing
9
+ end
10
+
11
+ module ClassMethods
12
+ # Yields a block containing an MiniMagick Image for the given binary data.
13
+ def with_image(file, &block)
14
+ begin
15
+ binary_data = file.is_a?(MiniMagick::Image) ? file : MiniMagick::Image.open(file) unless !Object.const_defined?(:MiniMagick)
16
+ rescue
17
+ # Log the failure to load the image.
18
+ logger.debug("Exception working with image: #{$!}")
19
+ binary_data = nil
20
+ end
21
+ block.call binary_data if block && binary_data
22
+ ensure
23
+ !binary_data.nil?
24
+ end
25
+ end
26
+
27
+ protected
28
+ def process_attachment_with_processing
29
+ return unless process_attachment_without_processing
30
+ with_image do |img|
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
35
+ end if image?
36
+ end
37
+
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
+ format = img[:format]
42
+ img.combine_options do |commands|
43
+ commands.strip unless attachment_options[:keep_profile]
44
+
45
+ # GIF is not handled correctly, so we move to PNG, as in other processors…
46
+ if format == 'GIF'
47
+ img.format('PNG')
48
+ end
49
+
50
+ if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
51
+ if size.is_a?(Fixnum)
52
+ size = [size, size]
53
+ commands.resize(size.join('x'))
54
+ else
55
+ commands.resize(size.join('x') + '!')
56
+ end
57
+ # extend to thumbnail size
58
+ elsif size.is_a?(String) and size =~ /e$/
59
+ size = size.gsub(/e/, '')
60
+ commands.resize(size.to_s + '>')
61
+ commands.background('#ffffff')
62
+ commands.gravity('center')
63
+ commands.extent(size)
64
+ # crop thumbnail, the smart way
65
+ elsif size.is_a?(String) and size =~ /c$/
66
+ size = size.gsub(/c/, '')
67
+
68
+ # calculate sizes and aspect ratio
69
+ thumb_width, thumb_height = size.split("x")
70
+ thumb_width = thumb_width.to_f
71
+ thumb_height = thumb_height.to_f
72
+
73
+ thumb_aspect = thumb_width.to_f / thumb_height.to_f
74
+ image_width, image_height = img[:width].to_f, img[:height].to_f
75
+ image_aspect = image_width / image_height
76
+
77
+ # only crop if image is not smaller in both dimensions
78
+ unless image_width < thumb_width and image_height < thumb_height
79
+ command = calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
80
+
81
+ # crop image
82
+ commands.extract(command)
83
+ end
84
+
85
+ # don not resize if image is not as height or width then thumbnail
86
+ if image_width < thumb_width or image_height < thumb_height
87
+ commands.background('#ffffff')
88
+ commands.gravity('center')
89
+ commands.extent(size)
90
+ # resize image
91
+ else
92
+ commands.resize("#{size.to_s}")
93
+ end
94
+ # crop end
95
+ else
96
+ commands.resize(size.to_s)
97
+ end
98
+ end
99
+ dims = img[:dimensions]
100
+ self.width = dims[0] if respond_to?(:width)
101
+ self.height = dims[1] if respond_to?(:height)
102
+ # Has to be done this far so we get proper dimensions
103
+ if format == 'JPEG'
104
+ quality = get_jpeg_quality
105
+ img.quality(quality) if quality
106
+ end
107
+ temp_paths.unshift img
108
+ self.size = File.size(self.temp_path)
109
+ end
110
+
111
+ def calculate_offset(image_width,image_height,image_aspect,thumb_width,thumb_height,thumb_aspect)
112
+ # only crop if image is not smaller in both dimensions
113
+
114
+ # special cases, image smaller in one dimension then thumbsize
115
+ if image_width < thumb_width
116
+ offset = (image_height / 2) - (thumb_height / 2)
117
+ command = "#{image_width}x#{thumb_height}+0+#{offset}"
118
+ elsif image_height < thumb_height
119
+ offset = (image_width / 2) - (thumb_width / 2)
120
+ command = "#{thumb_width}x#{image_height}+#{offset}+0"
121
+
122
+ # normal thumbnail generation
123
+ # calculate height and offset y, width is fixed
124
+ elsif (image_aspect <= thumb_aspect or image_width < thumb_width) and image_height > thumb_height
125
+ height = image_width / thumb_aspect
126
+ offset = (image_height / 2) - (height / 2)
127
+ command = "#{image_width}x#{height}+0+#{offset}"
128
+ # calculate width and offset x, height is fixed
129
+ else
130
+ width = image_height * thumb_aspect
131
+ offset = (image_width / 2) - (width / 2)
132
+ command = "#{width}x#{image_height}+#{offset}+0"
133
+ end
134
+ # crop image
135
+ command
136
+ end
137
+
138
+
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,66 @@
1
+ require 'RMagick'
2
+ module Technoweenie # :nodoc:
3
+ module AttachmentFu # :nodoc:
4
+ module Processors
5
+ module RmagickProcessor
6
+ def self.included(base)
7
+ base.send :extend, ClassMethods
8
+ base.alias_method_chain :process_attachment, :processing
9
+ end
10
+
11
+ module ClassMethods
12
+ # Yields a block containing an RMagick Image for the given binary data.
13
+ def with_image(file, &block)
14
+ begin
15
+ binary_data = file.is_a?(Magick::Image) ? file : Magick::Image.read(file).first unless !Object.const_defined?(:Magick)
16
+ binary_data && binary_data.auto_orient!
17
+ rescue
18
+ # Log the failure to load the image. This should match ::Magick::ImageMagickError
19
+ # but that would cause acts_as_attachment to require rmagick.
20
+ logger.debug("Exception working with image: #{$!}")
21
+ binary_data = nil
22
+ end
23
+ block.call binary_data if block && binary_data
24
+ ensure
25
+ !binary_data.nil?
26
+ end
27
+ end
28
+
29
+ protected
30
+ def process_attachment_with_processing
31
+ return unless process_attachment_without_processing
32
+ with_image do |img|
33
+ resize_image_or_thumbnail! img
34
+ self.width = img.columns if respond_to?(:width)
35
+ self.height = img.rows if respond_to?(:height)
36
+ callback_with_args :after_resize, img
37
+ end if image?
38
+ end
39
+
40
+ # Performs the actual resizing operation for a thumbnail
41
+ def resize_image(img, size)
42
+ size = size.first if size.is_a?(Array) && size.length == 1 && !size.first.is_a?(Fixnum)
43
+ if size.is_a?(Fixnum) || (size.is_a?(Array) && size.first.is_a?(Fixnum))
44
+ size = [size, size] if size.is_a?(Fixnum)
45
+ img.thumbnail!(*size)
46
+ elsif size.is_a?(String) && size =~ /^c.*$/ # Image cropping - example geometry string: c75x75
47
+ dimensions = size[1..size.size].split("x")
48
+ img.crop_resized!(dimensions[0].to_i, dimensions[1].to_i)
49
+ else
50
+ img.change_geometry(size.to_s) { |cols, rows, image|
51
+ image.resize!(cols<1 ? 1 : cols, rows<1 ? 1 : rows)
52
+ }
53
+ end
54
+ self.width = img.columns if respond_to?(:width)
55
+ self.height = img.rows if respond_to?(:height)
56
+ img = img.sharpen if attachment_options[:sharpen_on_resize] && img.changed?
57
+ img.strip! unless attachment_options[:keep_profile]
58
+ quality = img.format.to_s[/JPEG/] && get_jpeg_quality
59
+ out_file = write_to_temp_file(img.to_blob { self.quality = quality if quality })
60
+ temp_paths.unshift out_file
61
+ self.size = File.size(self.temp_path)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end