image_resizer 0.1.4
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.
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +45 -0
- data/LICENSE +22 -0
- data/README.md +56 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/image_resizer.gemspec +93 -0
- data/lib/image_resizer/analyzer.rb +51 -0
- data/lib/image_resizer/configurable.rb +206 -0
- data/lib/image_resizer/encoder.rb +55 -0
- data/lib/image_resizer/has_filename.rb +24 -0
- data/lib/image_resizer/loggable.rb +28 -0
- data/lib/image_resizer/processor.rb +220 -0
- data/lib/image_resizer/shell.rb +48 -0
- data/lib/image_resizer/temp_object.rb +216 -0
- data/lib/image_resizer/utils.rb +44 -0
- data/lib/image_resizer.rb +10 -0
- data/samples/DSC02119.JPG +0 -0
- data/samples/a.jp2 +0 -0
- data/samples/beach.jpg +0 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/landscape.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/samples/white pixel.png +0 -0
- data/spec/image_resizer/analyzer_spec.rb +78 -0
- data/spec/image_resizer/configurable_spec.rb +479 -0
- data/spec/image_resizer/encoder_spec.rb +41 -0
- data/spec/image_resizer/has_filename_spec.rb +88 -0
- data/spec/image_resizer/loggable_spec.rb +80 -0
- data/spec/image_resizer/processor_spec.rb +590 -0
- data/spec/image_resizer/shell_spec.rb +34 -0
- data/spec/image_resizer/temp_object_spec.rb +442 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +58 -0
- data/spec/support/simple_matchers.rb +53 -0
- data/tmp/test_file +1 -0
- metadata +147 -0
@@ -0,0 +1,590 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ImageResizer::Processor do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@image = ImageResizer::TempObject.new(SAMPLES_DIR.join('beach.png')) # 280x355
|
7
|
+
@processor = ImageResizer::Processor.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "_resize" do
|
11
|
+
|
12
|
+
it "should work correctly with xNN" do
|
13
|
+
image = @processor._resize(@image, 'x30')
|
14
|
+
image.should have_width(24)
|
15
|
+
image.should have_height(30)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should work correctly with NNx" do
|
19
|
+
image = @processor._resize(@image, '30x')
|
20
|
+
image.should have_width(30)
|
21
|
+
image.should have_height(38)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should work correctly with NNxNN" do
|
25
|
+
image = @processor._resize(@image, '30x30')
|
26
|
+
image.should have_width(24)
|
27
|
+
image.should have_height(30)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should work correctly with NNxNN!" do
|
31
|
+
image = @processor._resize(@image, '30x30!')
|
32
|
+
image.should have_width(30)
|
33
|
+
image.should have_height(30)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should work correctly with NNxNN%" do
|
37
|
+
image = @processor._resize(@image, '25x50%')
|
38
|
+
image.should have_width(70)
|
39
|
+
image.should have_height(178)
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "NNxNN>" do
|
43
|
+
|
44
|
+
it "should not resize if the image is smaller than specified" do
|
45
|
+
image = @processor._resize(@image, '1000x1000>')
|
46
|
+
image.should have_width(280)
|
47
|
+
image.should have_height(355)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should resize if the image is larger than specified" do
|
51
|
+
image = @processor._resize(@image, '30x30>')
|
52
|
+
image.should have_width(24)
|
53
|
+
image.should have_height(30)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "NNxNN<" do
|
59
|
+
|
60
|
+
it "should not resize if the image is larger than specified" do
|
61
|
+
image = @processor._resize(@image, '10x10<')
|
62
|
+
image.should have_width(280)
|
63
|
+
image.should have_height(355)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should resize if the image is smaller than specified" do
|
67
|
+
image = @processor._resize(@image, '400x400<')
|
68
|
+
image.should have_width(315)
|
69
|
+
image.should have_height(400)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "crop" do # Difficult to test here other than dimensions
|
77
|
+
|
78
|
+
it "should not crop if no args given" do
|
79
|
+
image = @processor.crop(@image)
|
80
|
+
image.should have_width(280)
|
81
|
+
image.should have_height(355)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should crop using the offset given" do
|
85
|
+
image = @processor.crop(@image, :x => '7', :y => '12')
|
86
|
+
image.should have_width(273)
|
87
|
+
image.should have_height(343)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should crop using the dimensions given" do
|
91
|
+
image = @processor.crop(@image, :width => '10', :height => '20')
|
92
|
+
image.should have_width(10)
|
93
|
+
image.should have_height(20)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should crop in one dimension if given" do
|
97
|
+
image = @processor.crop(@image, :width => '10')
|
98
|
+
image.should have_width(10)
|
99
|
+
image.should have_height(355)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should take into account the gravity given" do
|
103
|
+
image1 = @processor.crop(@image, :width => '10', :height => '10', :gravity => 'nw')
|
104
|
+
image2 = @processor.crop(@image, :width => '10', :height => '10', :gravity => 'se')
|
105
|
+
image1.should_not equal_image(image2)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "should clip bits of the image outside of the requested crop area when not nw gravity" do
|
109
|
+
# Rmagick was previously throwing an error when the cropping area was outside the image size, when
|
110
|
+
# using a gravity other than nw
|
111
|
+
image = @processor.crop(@image, :width => '500', :height => '1000', :x => '100', :y => '200', :gravity => 'se')
|
112
|
+
image.should have_width(180)
|
113
|
+
image.should have_height(155)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should crop twice in a row correctly" do
|
117
|
+
image1 = @processor.crop(@image, :x => '10', :y => '10', :width => '100', :height => '100')
|
118
|
+
image2 = @processor.crop(ImageResizer::TempObject.new(image1), :x => '0' , :y => '0' , :width => '50' , :height => '50' )
|
119
|
+
image2.should have_width(50)
|
120
|
+
image2.should have_height(50)
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should crop twice in a row while consciously keeping page geometry" do
|
124
|
+
# see http://www.imagemagick.org/Usage/crop/#crop_page
|
125
|
+
# it explains how cropping multiple times without resetting geometry behaves
|
126
|
+
image1 = @processor.crop(@image, :x => '10', :y => '10', :width => '100', :height => '100', :repage => false)
|
127
|
+
image2 = @processor.crop(ImageResizer::TempObject.new(image1), :x => '0' , :y => '0' , :width => '50' , :height => '50')
|
128
|
+
image2.should have_width(40)
|
129
|
+
image2.should have_height(40)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
describe "#resize(temp_object, width, height)" do
|
136
|
+
context "when both the width and the height are non-zero" do
|
137
|
+
it "should crop and scale to the specified dimensions" do
|
138
|
+
@processor.should_receive(:resize_and_crop).with(@image, :width => 77, :height => 33, :gravity => 'c')
|
139
|
+
@processor.resize(@image, :width => 77, :height => 33)
|
140
|
+
end
|
141
|
+
|
142
|
+
context "with the crop_from_top_if_portrait option" do
|
143
|
+
context "with a portrait oriented image" do
|
144
|
+
it "should resize and crop with a gravity of 'n'" do
|
145
|
+
@processor.should_receive(:resize_and_crop).with(@image, :width => 77, :height => 33, :gravity => 'n')
|
146
|
+
@processor.resize(@image, :width => 77, :height => 33, :crop_from_top_if_portrait => true)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "with a landscape oriented image" do
|
151
|
+
it "should resize and crop with a gravity of 'c'" do
|
152
|
+
@image = ImageResizer::TempObject.new(SAMPLES_DIR.join('landscape.png')) # 355x280
|
153
|
+
@processor.should_receive(:resize_and_crop).with(@image, :width => 77, :height => 33, :gravity => 'c')
|
154
|
+
@processor.resize(@image, :width => 77, :height => 33, :crop_from_top_if_portrait => true)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context "when the height is 0, nil, or not present" do
|
161
|
+
it "should restrict only in the horizontal dimension" do
|
162
|
+
@processor.should_receive(:_resize).with(@image, '77x').exactly(3).times
|
163
|
+
@processor.resize(@image, :width => 77, :height => 0)
|
164
|
+
@processor.resize(@image, :width => 77, :height => nil)
|
165
|
+
@processor.resize(@image, :width => 77)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "when the width is 0, nil, or not present" do
|
170
|
+
it "should restrict only in the vertical dimension" do
|
171
|
+
@processor.should_receive(:_resize).with(@image, 'x33').exactly(3).times
|
172
|
+
@processor.resize(@image, :width => 0, :height => 33)
|
173
|
+
@processor.resize(@image, :width => nil, :height => 33)
|
174
|
+
@processor.resize(@image, :height => 33)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "when both height and width are 0, nil, or not present" do
|
179
|
+
it "should return the original image file" do
|
180
|
+
@image.should_receive(:file).exactly(3).times
|
181
|
+
@processor.should_not_receive(:_resize)
|
182
|
+
@processor.resize(@image, :width => 0, :height => 0)
|
183
|
+
@processor.resize(@image, :width => nil, :height => nil)
|
184
|
+
@processor.resize(@image)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
describe "#resize_and_crop_around_point(:point => [x%, y%], :width => w, :height => h" do
|
193
|
+
context "when the source image is portrait, but the requested ratio is landscape" do
|
194
|
+
it "should call crop_to_frame_and_resize with a frame that is vertically centered on the focus point" do
|
195
|
+
# original is 280px x 355px
|
196
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
197
|
+
:width => 100,
|
198
|
+
:height => 60,
|
199
|
+
:upper_left => [0.0, 0.5 - 280 * 0.6 / 355 / 2.0],
|
200
|
+
:lower_right => [1.0, 0.5 + 280 * 0.6 / 355 / 2.0])
|
201
|
+
@processor.resize_and_crop_around_point(@image,
|
202
|
+
:point => [0.5, 0.5],
|
203
|
+
:width => 100,
|
204
|
+
:height => 60
|
205
|
+
)
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when the focus point is too close to the top to be the vertical center" do
|
209
|
+
it "should call crop_to_frame_and_resize with a frame that is pinned at the top of the image" do
|
210
|
+
# original is 280px x 355px
|
211
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
212
|
+
:width => 100,
|
213
|
+
:height => 60,
|
214
|
+
:upper_left => [0.0, 0.0],
|
215
|
+
:lower_right => [1.0, 280 * 0.6 / 355])
|
216
|
+
@processor.resize_and_crop_around_point(@image,
|
217
|
+
:point => [0.5, 0.1],
|
218
|
+
:width => 100,
|
219
|
+
:height => 60
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context "when the focus point is too close to the bottom to be the vertical center" do
|
225
|
+
it "should call crop_to_frame_and_resize with a frame that is pinned at the bottom of the image" do
|
226
|
+
# original is 280px x 355px
|
227
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
228
|
+
:width => 100,
|
229
|
+
:height => 60,
|
230
|
+
:upper_left => [0.0, 1 - 280 * 0.6 / 355],
|
231
|
+
:lower_right => [1.0, 1.0])
|
232
|
+
@processor.resize_and_crop_around_point(@image,
|
233
|
+
:point => [0.5, 0.9],
|
234
|
+
:width => 100,
|
235
|
+
:height => 60
|
236
|
+
)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "when the source image is landscape, but the requested ratio is portrait" do
|
242
|
+
before(:each) do
|
243
|
+
@image = ImageResizer::TempObject.new(SAMPLES_DIR.join('landscape.png')) # 355x280
|
244
|
+
end
|
245
|
+
|
246
|
+
it "should call crop_to_frame_and_resize with a frame that is vertically centered on the focus point" do
|
247
|
+
# original is 355px x 280px
|
248
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
249
|
+
:width => 60,
|
250
|
+
:height => 100,
|
251
|
+
:upper_left => [0.5 - 280 * 0.6 / 355 / 2.0, 0.0],
|
252
|
+
:lower_right => [0.5 + 280 * 0.6 / 355 / 2.0, 1.0])
|
253
|
+
@processor.resize_and_crop_around_point(@image,
|
254
|
+
:point => [0.5, 0.5],
|
255
|
+
:width => 60,
|
256
|
+
:height => 100
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
context "when the focus point is too close to the left to be the vertical center" do
|
261
|
+
it "should call crop_to_frame_and_resize with a frame that is pinned at the left of the image" do
|
262
|
+
# original is 355px x 280px
|
263
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
264
|
+
:width => 60,
|
265
|
+
:height => 100,
|
266
|
+
:upper_left => [0.0, 0.0],
|
267
|
+
:lower_right => [280 * 0.6 / 355, 1.0])
|
268
|
+
@processor.resize_and_crop_around_point(@image,
|
269
|
+
:point => [0.1, 0.5],
|
270
|
+
:width => 60,
|
271
|
+
:height => 100
|
272
|
+
)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
context "when the focus point is too close to the right to be the vertical center" do
|
277
|
+
it "should call crop_to_frame_and_resize with a frame that is pinned at the right of the image" do
|
278
|
+
# original is 355px x 280px
|
279
|
+
@processor.should_receive(:crop_to_frame_and_resize ).with(@image,
|
280
|
+
:width => 60,
|
281
|
+
:height => 100,
|
282
|
+
:upper_left => [1.0 - 280 * 0.6 / 355, 0.0],
|
283
|
+
:lower_right => [1.0, 1.0])
|
284
|
+
@processor.resize_and_crop_around_point(@image,
|
285
|
+
:point => [0.9, 0.5],
|
286
|
+
:width => 60,
|
287
|
+
:height => 100
|
288
|
+
)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
context "when the specified width is 0" do
|
294
|
+
it "should not raise an exception" do
|
295
|
+
lambda {
|
296
|
+
@processor.resize_and_crop_around_point(@image,
|
297
|
+
:point => [0.20, 0.30],
|
298
|
+
:width => 0,
|
299
|
+
:height => 80
|
300
|
+
)
|
301
|
+
}.should_not raise_error
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
context "when the specified height is 0" do
|
306
|
+
it "should not raise an exception" do
|
307
|
+
lambda {
|
308
|
+
@processor.resize_and_crop_around_point(@image,
|
309
|
+
:point => [0.20, 0.30],
|
310
|
+
:width => 80,
|
311
|
+
:height => 0
|
312
|
+
)
|
313
|
+
}.should_not raise_error
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
describe "#crop_to_frame_and_resize(:upper_left => [x%, y%], :lower_right => [x%, y%], :width => w, :height => h" do
|
319
|
+
it "should call #crop with the :x & :y and :width & :height expressed in pixels and :width and :height determined by the frame bounds (not the width and height we pass in), and :resize expressed as widthxheight" do
|
320
|
+
# original is 280px x 355px
|
321
|
+
@processor.should_receive(:convert).with(@image, "-crop 140x178+56+107 -resize 70x89 +repage")
|
322
|
+
@processor.crop_to_frame_and_resize(@image,
|
323
|
+
:upper_left => [0.20, 0.30],
|
324
|
+
:lower_right => [0.70, 0.80],
|
325
|
+
:width => 70,
|
326
|
+
:height => 89
|
327
|
+
)
|
328
|
+
end
|
329
|
+
|
330
|
+
context "when width is 0, nil, or not present as an option" do
|
331
|
+
it "should use the ratio defined by the upper_left and lower_right points to determine the width from the height" do
|
332
|
+
# original is 280px x 355px
|
333
|
+
@processor.should_receive(:convert).with(@image, "-crop 140x178+56+107 -resize 70x89 +repage").exactly(3).times
|
334
|
+
@processor.crop_to_frame_and_resize(@image,
|
335
|
+
:upper_left => [0.20, 0.30],
|
336
|
+
:lower_right => [0.70, 0.80],
|
337
|
+
:width => 0,
|
338
|
+
:height => 89
|
339
|
+
)
|
340
|
+
|
341
|
+
@processor.crop_to_frame_and_resize(@image,
|
342
|
+
:upper_left => [0.20, 0.30],
|
343
|
+
:lower_right => [0.70, 0.80],
|
344
|
+
:width => nil,
|
345
|
+
:height => 89
|
346
|
+
)
|
347
|
+
|
348
|
+
@processor.crop_to_frame_and_resize(@image,
|
349
|
+
:upper_left => [0.20, 0.30],
|
350
|
+
:lower_right => [0.70, 0.80],
|
351
|
+
:height => 89
|
352
|
+
)
|
353
|
+
end
|
354
|
+
|
355
|
+
end
|
356
|
+
|
357
|
+
context "when height is 0, nil, or not present as an option" do
|
358
|
+
it "should use the ratio defined by the upper_left and lower_right points to determine the height from the width" do
|
359
|
+
# original is 280px x 355px
|
360
|
+
@processor.should_receive(:convert).with(@image, "-crop 140x178+56+107 -resize 70x89 +repage").exactly(3).times
|
361
|
+
@processor.crop_to_frame_and_resize(@image,
|
362
|
+
:upper_left => [0.20, 0.30],
|
363
|
+
:lower_right => [0.70, 0.80],
|
364
|
+
:width => 70,
|
365
|
+
:height => 0
|
366
|
+
)
|
367
|
+
|
368
|
+
@processor.crop_to_frame_and_resize(@image,
|
369
|
+
:upper_left => [0.20, 0.30],
|
370
|
+
:lower_right => [0.70, 0.80],
|
371
|
+
:width => 70,
|
372
|
+
:height => nil
|
373
|
+
)
|
374
|
+
|
375
|
+
@processor.crop_to_frame_and_resize(@image,
|
376
|
+
:upper_left => [0.20, 0.30],
|
377
|
+
:lower_right => [0.70, 0.80],
|
378
|
+
:width => 70
|
379
|
+
)
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
context "when both width and heigth are 0 or nil" do
|
384
|
+
it "should not raise an exception" do
|
385
|
+
lambda {
|
386
|
+
@processor.crop_to_frame_and_resize(@image,
|
387
|
+
:upper_left => [0.20, 0.30],
|
388
|
+
:lower_right => [0.70, 0.80],
|
389
|
+
:width => 0,
|
390
|
+
:height => 0
|
391
|
+
)
|
392
|
+
}.should_not raise_error
|
393
|
+
|
394
|
+
lambda {
|
395
|
+
@processor.crop_to_frame_and_resize(@image,
|
396
|
+
:upper_left => [0.20, 0.30],
|
397
|
+
:lower_right => [0.70, 0.80]
|
398
|
+
)
|
399
|
+
}.should_not raise_error
|
400
|
+
end
|
401
|
+
|
402
|
+
context "when the frame specifies a width of 0" do
|
403
|
+
it "should not raise an exception" do
|
404
|
+
lambda {
|
405
|
+
@processor.crop_to_frame_and_resize(@image,
|
406
|
+
:upper_left => [0.20, 0.30],
|
407
|
+
:lower_right => [0.20, 0.80],
|
408
|
+
:width => 0,
|
409
|
+
:height => 0
|
410
|
+
)
|
411
|
+
}.should_not raise_error
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
context "when the frame specifies a height of 0" do
|
416
|
+
it "should not raise an exception" do
|
417
|
+
lambda {
|
418
|
+
@processor.crop_to_frame_and_resize(@image,
|
419
|
+
:upper_left => [0.20, 0.30],
|
420
|
+
:lower_right => [0.70, 0.30],
|
421
|
+
:width => 0,
|
422
|
+
:height => 0
|
423
|
+
)
|
424
|
+
}.should_not raise_error
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|
430
|
+
|
431
|
+
describe "greyscale" do
|
432
|
+
it "should not raise an error" do
|
433
|
+
# Bit tricky to test
|
434
|
+
@processor.greyscale(@image)
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
describe "resize_and_crop" do
|
439
|
+
|
440
|
+
it "should do nothing if no args given" do
|
441
|
+
image = @processor.resize_and_crop(@image)
|
442
|
+
image.should have_width(280)
|
443
|
+
image.should have_height(355)
|
444
|
+
end
|
445
|
+
|
446
|
+
it "should do nothing if called without width and height" do
|
447
|
+
image = @processor.resize_and_crop(@image)
|
448
|
+
image.should have_width(280)
|
449
|
+
image.should have_height(355)
|
450
|
+
image.should eq @image
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should crop to the correct dimensions" do
|
454
|
+
image = @processor.resize_and_crop(@image, :width => '100', :height => '100')
|
455
|
+
image.should have_width(100)
|
456
|
+
image.should have_height(100)
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should actually resize before cropping" do
|
460
|
+
image1 = @processor.resize_and_crop(@image, :width => '100', :height => '100')
|
461
|
+
image2 = @processor.crop(@image, :width => '100', :height => '100', :gravity => 'c')
|
462
|
+
image1.should_not equal_image(image2)
|
463
|
+
end
|
464
|
+
|
465
|
+
it "should allow cropping in one dimension" do
|
466
|
+
image = @processor.resize_and_crop(@image, :width => '100')
|
467
|
+
image.should have_width(100)
|
468
|
+
image.should have_height(355)
|
469
|
+
end
|
470
|
+
|
471
|
+
it "should take into account the gravity given" do
|
472
|
+
image1 = @processor.resize_and_crop(@image, :width => '10', :height => '10', :gravity => 'nw')
|
473
|
+
image2 = @processor.resize_and_crop(@image, :width => '10', :height => '10', :gravity => 'se')
|
474
|
+
image1.should_not equal_image(image2)
|
475
|
+
end
|
476
|
+
|
477
|
+
end
|
478
|
+
|
479
|
+
describe "rotate" do
|
480
|
+
|
481
|
+
it "should rotate by 90 degrees" do
|
482
|
+
image = @processor.rotate(@image, 90)
|
483
|
+
image.should have_width(355)
|
484
|
+
image.should have_height(280)
|
485
|
+
end
|
486
|
+
|
487
|
+
it "should not rotate given a larger height and the '>' qualifier" do
|
488
|
+
image = @processor.rotate(@image, 90, :qualifier => '>')
|
489
|
+
image.should have_width(280)
|
490
|
+
image.should have_height(355)
|
491
|
+
end
|
492
|
+
|
493
|
+
it "should rotate given a larger height and the '<' qualifier" do
|
494
|
+
image = @processor.rotate(@image, 90, :qualifier => '<')
|
495
|
+
image.should have_width(355)
|
496
|
+
image.should have_height(280)
|
497
|
+
end
|
498
|
+
|
499
|
+
end
|
500
|
+
|
501
|
+
describe "strip" do
|
502
|
+
it "should strip exif data" do
|
503
|
+
jpg = ImageResizer::TempObject.new(SAMPLES_DIR.join('taj.jpg'))
|
504
|
+
image = @processor.strip(jpg)
|
505
|
+
image.should have_width(300)
|
506
|
+
image.should have_height(300)
|
507
|
+
image.size.should < jpg.size
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
describe "thumb" do
|
512
|
+
it "should call resize if the correct string given" do
|
513
|
+
@processor.should_receive(:resize).with(@image, '30x40').and_return(image = mock)
|
514
|
+
@processor.thumb(@image, '30x40').should == image
|
515
|
+
end
|
516
|
+
it "should call resize_and_crop if the correct string given" do
|
517
|
+
@processor.should_receive(:resize_and_crop).with(@image, :width => '30', :height => '40', :gravity => 'se').and_return(image = mock)
|
518
|
+
@processor.thumb(@image, '30x40#se').should == image
|
519
|
+
end
|
520
|
+
it "should call crop if x and y given" do
|
521
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => '+10', :y => '+20', :gravity => nil).and_return(image = mock)
|
522
|
+
@processor.thumb(@image, '30x40+10+20').should == image
|
523
|
+
end
|
524
|
+
it "should call crop if just gravity given" do
|
525
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => nil, :y => nil, :gravity => 'sw').and_return(image = mock)
|
526
|
+
@processor.thumb(@image, '30x40sw').should == image
|
527
|
+
end
|
528
|
+
it "should call crop if x, y and gravity given" do
|
529
|
+
@processor.should_receive(:crop).with(@image, :width => '30', :height => '40', :x => '-10', :y => '-20', :gravity => 'se').and_return(image = mock)
|
530
|
+
@processor.thumb(@image, '30x40-10-20se').should == image
|
531
|
+
end
|
532
|
+
it "should raise an argument error if an unrecognized string is given" do
|
533
|
+
lambda{ @processor.thumb(@image, '30x40#ne!') }.should raise_error(ArgumentError)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
|
537
|
+
describe "auto-orient" do
|
538
|
+
it "should rotate an image according to exif information" do
|
539
|
+
@image = ImageResizer::TempObject.new(SAMPLES_DIR.join('beach.jpg'))
|
540
|
+
@image.should have_width(355)
|
541
|
+
@image.should have_height(280)
|
542
|
+
image = @processor.auto_orient(@image)
|
543
|
+
image.should have_width(280)
|
544
|
+
image.should have_height(355)
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
describe "flip" do
|
549
|
+
it "should flip the image, leaving the same dimensions" do
|
550
|
+
image = @processor.flip(@image)
|
551
|
+
image.should have_width(280)
|
552
|
+
image.should have_height(355)
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
describe "flop" do
|
557
|
+
it "should flop the image, leaving the same dimensions" do
|
558
|
+
image = @processor.flop(@image)
|
559
|
+
image.should have_width(280)
|
560
|
+
image.should have_height(355)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
describe "convert" do
|
565
|
+
it "should allow for general convert commands" do
|
566
|
+
image = @processor.convert(@image, '-scale 56x71')
|
567
|
+
image.should have_width(56)
|
568
|
+
image.should have_height(71)
|
569
|
+
end
|
570
|
+
|
571
|
+
it "should allow for general convert commands with added format" do
|
572
|
+
image, extra = @processor.convert(@image, '-scale 56x71', :gif)
|
573
|
+
image.should have_width(56)
|
574
|
+
image.should have_height(71)
|
575
|
+
image.should have_format('gif')
|
576
|
+
extra[:format].should == :gif
|
577
|
+
end
|
578
|
+
|
579
|
+
it "should work for commands with parenthesis" do
|
580
|
+
image = @processor.convert(@image, "\\( +clone -sparse-color Barycentric '0,0 black 0,%[fx:h-1] white' -function polynomial 2,-2,0.5 \\) -compose Blur -set option:compose:args 15 -composite")
|
581
|
+
image.should have_width(280)
|
582
|
+
end
|
583
|
+
|
584
|
+
it "should work for files with spaces in the name" do
|
585
|
+
image = ImageResizer::TempObject.new(SAMPLES_DIR.join('white pixel.png'))
|
586
|
+
@processor.convert(image, "-resize 2x2!").should have_width(2)
|
587
|
+
end
|
588
|
+
end
|
589
|
+
|
590
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ImageResizer::Shell do
|
4
|
+
|
5
|
+
include ImageResizer::Shell
|
6
|
+
|
7
|
+
it "should raise an error if the identify command isn't found" do
|
8
|
+
suppressing_stderr do
|
9
|
+
lambda{
|
10
|
+
run "non-existent-command"
|
11
|
+
}.should raise_error(ImageResizer::Shell::CommandFailed)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "escaping args" do
|
16
|
+
{
|
17
|
+
%q(hello) => %q('hello'),
|
18
|
+
%q("hello") => %q('hello'),
|
19
|
+
%q('hello') => %q('hello'),
|
20
|
+
%q(he\'llo) => %q('he'\''llo'),
|
21
|
+
%q('he'\''llo') => %q('he'\''llo'),
|
22
|
+
%q("he'llo") => %q('he'\''llo'),
|
23
|
+
%q(hel$(lo)) => %q('hel$(lo)'),
|
24
|
+
%q(hel\$(lo)) => %q('hel$(lo)'),
|
25
|
+
%q('hel\$(lo)') => %q('hel\$(lo)')
|
26
|
+
}.each do |args, escaped_args|
|
27
|
+
it "should escape #{args.inspect} -> #{escaped_args.inspect}" do
|
28
|
+
pending "not applicable to windows" if running_on_windows?
|
29
|
+
escape_args(args).should == escaped_args
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|