attachment_zen 1.0.1

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,47 @@
1
+ module RedArtisan
2
+ module CoreImage
3
+ module Filters
4
+ module Scale
5
+
6
+ def resize(width, height)
7
+ create_core_image_context(width, height)
8
+
9
+ scale_x, scale_y = scale(width, height)
10
+
11
+ @original.affine_clamp :inputTransform => OSX::NSAffineTransform.transform do |clamped|
12
+ clamped.lanczos_scale_transform :inputScale => scale_x > scale_y ? scale_x : scale_y, :inputAspectRatio => scale_x / scale_y do |scaled|
13
+ scaled.crop :inputRectangle => vector(0, 0, width, height) do |cropped|
14
+ @target = cropped
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def thumbnail(width, height)
21
+ create_core_image_context(width, height)
22
+
23
+ transform = OSX::NSAffineTransform.transform
24
+ transform.scaleXBy_yBy *scale(width, height)
25
+
26
+ @original.affine_transform :inputTransform => transform do |scaled|
27
+ @target = scaled
28
+ end
29
+ end
30
+
31
+ def fit(size)
32
+ original_size = @original.extent.size
33
+ scale = size.to_f / (original_size.width > original_size.height ? original_size.width : original_size.height)
34
+ resize (original_size.width * scale).to_i, (original_size.height * scale).to_i
35
+ end
36
+
37
+ private
38
+
39
+ def scale(width, height)
40
+ original_size = @original.extent.size
41
+ return width.to_f / original_size.width.to_f, height.to_f / original_size.height.to_f
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ module RedArtisan
2
+ module CoreImage
3
+ module Filters
4
+ module Watermark
5
+
6
+ def watermark(watermark_image, tile = false, strength = 0.1)
7
+ create_core_image_context(@original.extent.size.width, @original.extent.size.height)
8
+
9
+ if watermark_image.respond_to? :to_str
10
+ watermark_image = OSX::CIImage.from(watermark_image.to_str)
11
+ end
12
+
13
+ if tile
14
+ tile_transform = OSX::NSAffineTransform.transform
15
+ tile_transform.scaleXBy_yBy 1.0, 1.0
16
+
17
+ watermark_image.affine_tile :inputTransform => tile_transform do |tiled|
18
+ tiled.crop :inputRectangle => vector(0, 0, @original.extent.size.width, @original.extent.size.height) do |tiled_watermark|
19
+ watermark_image = tiled_watermark
20
+ end
21
+ end
22
+ end
23
+
24
+ @original.dissolve_transition :inputTargetImage => watermark_image, :inputTime => strength do |watermarked|
25
+ @target = watermarked
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,122 @@
1
+ require 'osx/cocoa'
2
+ require 'active_support'
3
+
4
+ require 'red_artisan/core_image/filters/scale'
5
+ require 'red_artisan/core_image/filters/color'
6
+ require 'red_artisan/core_image/filters/watermark'
7
+ require 'red_artisan/core_image/filters/quality'
8
+ require 'red_artisan/core_image/filters/perspective'
9
+ require 'red_artisan/core_image/filters/effects'
10
+
11
+ # Generic image processor for scaling images based on CoreImage via RubyCocoa.
12
+ #
13
+ # Example usage:
14
+ #
15
+ # p = Processor.new OSX::CIImage.from(path_to_image)
16
+ # p.resize(640, 480)
17
+ # p.render do |result|
18
+ # result.save('resized.jpg', OSX::NSJPEGFileType)
19
+ # end
20
+ #
21
+ # This will resize the image to the given dimensions exactly, if you'd like to ensure that aspect ratio is preserved:
22
+ #
23
+ # p = Processor.new OSX::CIImage.from(path_to_image)
24
+ # p.fit(640)
25
+ # p.render do |result|
26
+ # result.save('resized.jpg', OSX::NSJPEGFileType)
27
+ # end
28
+ #
29
+ # fit(size) will attempt its best to resize the image so that the longest width/height (depending on image orientation) will match
30
+ # the given size. The second axis will be calculated automatically based on the aspect ratio.
31
+ #
32
+ # Scaling is performed by first clamping the image so that its external bounds become infinite, this helps when scaling so that any
33
+ # rounding discrepencies in dimensions don't affect the resultant image. We then perform a Lanczos transform on the image which scales
34
+ # it to the target size. We then crop the image to the traget dimensions.
35
+ #
36
+ # If you are generating smaller images such as thumbnails where high quality rendering isn't as important, an additional method is
37
+ # available:
38
+ #
39
+ # p = Processor.new OSX::CIImage.from(path_to_image)
40
+ # p.thumbnail(100, 100)
41
+ # p.render do |result|
42
+ # result.save('resized.jpg', OSX::NSJPEGFileType)
43
+ # end
44
+ #
45
+ # This will perform a straight affine transform and scale the X and Y boundaries to the requested size. Generally, this will be faster
46
+ # than a lanczos scale transform, but with a scaling quality trade.
47
+ #
48
+ # More than welcome to intregrate any patches, improvements - feel free to mail me with ideas.
49
+ #
50
+ # Thanks to
51
+ # * Satoshi Nakagawa for working out that OCObjWrapper needs inclusion when aliasing method_missing on existing OSX::* classes.
52
+ # * Vasantha Crabb for general help and inspiration with Cocoa
53
+ # * Ben Schwarz for example image data and collaboration during performance testing
54
+ #
55
+ # Copyright (c) Marcus Crafter <crafterm@redartisan.com> released under the MIT license
56
+ #
57
+ module RedArtisan
58
+ module CoreImage
59
+ class Processor
60
+
61
+ def initialize(original)
62
+ if original.respond_to? :to_str
63
+ @original = OSX::CIImage.from(original.to_str)
64
+ else
65
+ @original = original
66
+ end
67
+ end
68
+
69
+ def render(&block)
70
+ raise "unprocessed image: #{@original}" unless @target
71
+ block.call @target
72
+ end
73
+
74
+ include Filters::Scale, Filters::Color, Filters::Watermark, Filters::Quality, Filters::Perspective, Filters::Effects
75
+
76
+ private
77
+
78
+ def create_core_image_context(width, height)
79
+ output = OSX::NSBitmapImageRep.alloc.initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(nil, width, height, 8, 4, true, false, OSX::NSDeviceRGBColorSpace, 0, 0)
80
+ context = OSX::NSGraphicsContext.graphicsContextWithBitmapImageRep(output)
81
+ OSX::NSGraphicsContext.setCurrentContext(context)
82
+ @ci_context = context.CIContext
83
+ end
84
+
85
+ def vector(x, y, w, h)
86
+ OSX::CIVector.vectorWithX_Y_Z_W(x, y, w, h)
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ module OSX
93
+ class CIImage
94
+ include OCObjWrapper
95
+
96
+ def method_missing_with_filter_processing(sym, *args, &block)
97
+ f = OSX::CIFilter.filterWithName("CI#{sym.to_s.camelize}")
98
+ return method_missing_without_filter_processing(sym, *args, &block) unless f
99
+
100
+ f.setDefaults if f.respond_to? :setDefaults
101
+ f.setValue_forKey(self, 'inputImage')
102
+ options = args.last.is_a?(Hash) ? args.last : {}
103
+ options.each { |k, v| f.setValue_forKey(v, k.to_s) }
104
+
105
+ block.call f.valueForKey('outputImage')
106
+ end
107
+
108
+ alias_method_chain :method_missing, :filter_processing
109
+
110
+ def save(target, format = OSX::NSJPEGFileType, properties = nil)
111
+ bitmapRep = OSX::NSBitmapImageRep.alloc.initWithCIImage(self)
112
+ blob = bitmapRep.representationUsingType_properties(format, properties)
113
+ blob.writeToFile_atomically(target, false)
114
+ end
115
+
116
+ def self.from(filepath)
117
+ raise Errno::ENOENT, "No such file or directory - #{filepath}" unless File.exists?(filepath)
118
+ OSX::CIImage.imageWithContentsOfURL(OSX::NSURL.fileURLWithPath(filepath))
119
+ end
120
+ end
121
+ end
122
+
metadata ADDED
@@ -0,0 +1,255 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: attachment_zen
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Technoweenie
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 3.2.21
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 4.3.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.21
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 4.3.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: actionpack
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bump
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: wwtd
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: mocha
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: mysql
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: mini_magick
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: 3.6.0
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: 3.6.0
131
+ - !ruby/object:Gem::Dependency
132
+ name: minitest
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: minitest-rg
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: aws-sdk-v1
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ - !ruby/object:Gem::Dependency
174
+ name: cloudfiles
175
+ requirement: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ type: :development
181
+ prerelease: false
182
+ version_requirements: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ - !ruby/object:Gem::Dependency
188
+ name: byebug
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ">="
199
+ - !ruby/object:Gem::Version
200
+ version: '0'
201
+ description: Adds has_attachment (file store) properties to ActiveRecord. Supports
202
+ local file, file-in-db, S3 and Cloudfiles backends.
203
+ email:
204
+ executables: []
205
+ extensions: []
206
+ extra_rdoc_files: []
207
+ files:
208
+ - CHANGELOG
209
+ - README.md
210
+ - lib/attachment_fu.rb
211
+ - lib/technoweenie/attachment_fu.rb
212
+ - lib/technoweenie/attachment_fu/backends/backend_delegator.rb
213
+ - lib/technoweenie/attachment_fu/backends/cloud_file_backend.rb
214
+ - lib/technoweenie/attachment_fu/backends/db_file_backend.rb
215
+ - lib/technoweenie/attachment_fu/backends/file_system_backend.rb
216
+ - lib/technoweenie/attachment_fu/backends/mogile_fs_backend.rb
217
+ - lib/technoweenie/attachment_fu/backends/s3_backend.rb
218
+ - lib/technoweenie/attachment_fu/geometry.rb
219
+ - lib/technoweenie/attachment_fu/processors/core_image_processor.rb
220
+ - lib/technoweenie/attachment_fu/processors/gd2_processor.rb
221
+ - lib/technoweenie/attachment_fu/processors/image_science_processor.rb
222
+ - lib/technoweenie/attachment_fu/processors/mini_magick_processor.rb
223
+ - lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
224
+ - vendor/red_artisan/core_image/filters/color.rb
225
+ - vendor/red_artisan/core_image/filters/effects.rb
226
+ - vendor/red_artisan/core_image/filters/perspective.rb
227
+ - vendor/red_artisan/core_image/filters/quality.rb
228
+ - vendor/red_artisan/core_image/filters/scale.rb
229
+ - vendor/red_artisan/core_image/filters/watermark.rb
230
+ - vendor/red_artisan/core_image/processor.rb
231
+ homepage: https://github.com/zendesk/attachment_fu
232
+ licenses: []
233
+ metadata: {}
234
+ post_install_message:
235
+ rdoc_options: []
236
+ require_paths:
237
+ - lib
238
+ - vendor
239
+ required_ruby_version: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ required_rubygems_version: !ruby/object:Gem::Requirement
245
+ requirements:
246
+ - - ">="
247
+ - !ruby/object:Gem::Version
248
+ version: '0'
249
+ requirements: []
250
+ rubyforge_project:
251
+ rubygems_version: 2.2.2
252
+ signing_key:
253
+ specification_version: 4
254
+ summary: Adds has_attachment properties to ActiveRecord
255
+ test_files: []