g1nn13-image_science 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig ADDED
Binary file
data/History.txt CHANGED
@@ -1,3 +1,8 @@
1
+ === 1.2.6 / 2010-05-26
2
+
3
+ * Now based on ImageScience 1.2.1
4
+ * Added new method resize_with_crop
5
+
1
6
  === 1.2.5 / 2010-01-26
2
7
 
3
8
  * 1 tweak
data/README.txt CHANGED
@@ -11,6 +11,11 @@ g1nn13 fork changes:
11
11
  * added buffer() method to get image buffer for writing (to Amazon S3)
12
12
  * added fit_within() method to resize an image to fit within a specified
13
13
  height and width without changing the image's aspect ratio
14
+ * added resize_with_crop() to resize and crop images where the
15
+ target aspect ratio differs from the original aspect ratio. This is
16
+ for converting portrait to landscape and landscape to portrait.
17
+
18
+
14
19
 
15
20
  ImageScience is a clean and happy Ruby library that generates
16
21
  thumbnails -- and kicks the living crap out of RMagick. Oh, and it
data/lib/image_science.rb CHANGED
@@ -9,9 +9,11 @@ require 'inline'
9
9
  #
10
10
  # For more information or if you have build issues with FreeImage, see
11
11
  # http://seattlerb.rubyforge.org/ImageScience.html
12
+ #
13
+ # Based on ImageScience 1.2.1
12
14
 
13
15
  class ImageScience
14
- VERSION = '1.2.5'
16
+ VERSION = '1.2.6'
15
17
 
16
18
  ##
17
19
  # The top-level image loader opens +path+ and then yields the image.
@@ -55,6 +57,79 @@ class ImageScience
55
57
  def buffer(extension) # :yields: image
56
58
  end
57
59
 
60
+
61
+ ##
62
+ # Resizes an image to the specified size without stretching or
63
+ # compressing the original. If the aspect ratio of the new height/width
64
+ # does not match the aspect ratio of the original (as when converting
65
+ # portrait to landscape or landscape to portrait), the resulting
66
+ # image will be cropped. Cropping preserves the center of the image,
67
+ # with content trimmed evenly from the top and bottom and/or left and
68
+ # right edges of the image. This can cause some less than ideal
69
+ # conversions. For example, converting a portrait to a landscape can
70
+ # result in the portrait's head being cut off.
71
+
72
+ def resize_with_crop(width, height, &block)
73
+
74
+ # ---------------------------------------------------------------
75
+ # We want to adjust both height and width by the same ratio,
76
+ # so the image is not stretched. Adjust everything by the
77
+ # larger ratio, so that portrait to landscape and landscape
78
+ # to portrait transformations come out right.
79
+ # ---------------------------------------------------------------
80
+ src2target_height_ratio = height.to_f / self.height
81
+ src2target_width_ratio = width.to_f / self.width
82
+ height_ratio_is_larger = src2target_height_ratio > src2target_width_ratio
83
+ if height_ratio_is_larger
84
+ target_height = (self.height * src2target_height_ratio).round
85
+ target_width = (self.width * src2target_height_ratio).round
86
+ else
87
+ target_height = (self.height * src2target_width_ratio).round
88
+ target_width = (self.width * src2target_width_ratio).round
89
+ end
90
+
91
+ # ---------------------------------------------------------------
92
+ # Create a version of this image whose longest
93
+ # side is equal to max_dimension. We'll add two
94
+ # to this value, since floating point arithmetic
95
+ # often produces values 1-2 pixels short of what we want.
96
+ # ---------------------------------------------------------------
97
+ max_dimension = (target_height > target_width ?
98
+ target_height : target_width)
99
+
100
+ self.thumbnail(max_dimension + 2) do |img1|
101
+ top, left = 0, 0
102
+ top = (img1.height - height) / 2 unless img1.height < height
103
+ left = (img1.width - width) / 2 unless img1.width < width
104
+ right = width + left
105
+ bottom = height + top
106
+
107
+ # ---------------------------------------------------------------
108
+ # Crop the resized image evenly at top/bottom, left/right,
109
+ # so that we preserve the center.
110
+ # ---------------------------------------------------------------
111
+ result = img1.with_crop(left, top, right, bottom) do |img2|
112
+ if block_given?
113
+ yield img2
114
+ else
115
+ return img2
116
+ end
117
+ end
118
+
119
+ if result.nil?
120
+ message = "Crop/resize failed... is some dimension is out of bounds?"
121
+ message += "Original Height = #{self.height}, Width = #{self.width}"
122
+ message += "Target Height = #{height}, Width = #{width}"
123
+ message += "Actual Height = #{self.height}, Width = #{self.width}"
124
+ message += "Left=#{left}, Top=#{top}, Right=#{right}, Bottom=#{bottom}"
125
+ raise message
126
+ end
127
+
128
+
129
+ end
130
+ end
131
+
132
+
58
133
  ##
59
134
  # Resizes the image to +width+ and +height+ using a cubic-bspline
60
135
  # filter and yields the new image.
@@ -121,6 +196,25 @@ class ImageScience
121
196
  end
122
197
  end
123
198
 
199
+ ##
200
+ # Creates a square thumbnail of the image cropping the longest edge
201
+ # to match the shortest edge, resizes to +size+, and yields the new
202
+ # image.
203
+
204
+ def cropped_to_fit(width, height) # :yields: image
205
+ w, h = width, height
206
+ l, t, r, b, half = 0, 0, w, h, (w - h).abs / 2
207
+
208
+ l, r = half, half + h if w > h
209
+ t, b = half, half + w if h > w
210
+
211
+ with_crop(l, t, r, b) do |img|
212
+ img.thumbnail(size) do |thumb|
213
+ yield thumb
214
+ end
215
+ end
216
+ end
217
+
124
218
  inline do |builder|
125
219
  if test ?d, "/opt/local" then
126
220
  builder.add_compile_flags "-I/opt/local/include"
@@ -138,249 +232,190 @@ class ImageScience
138
232
  builder.include '"FreeImage.h"'
139
233
 
140
234
  builder.prefix <<-"END"
141
- #define GET_BITMAP(name) Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed");
142
- END
235
+ #define GET_BITMAP(name) Data_Get_Struct(self, FIBITMAP, (name)); if (!(name)) rb_raise(rb_eTypeError, "Bitmap has already been freed");
236
+ END
143
237
 
144
238
  builder.prefix <<-"END"
145
- VALUE unload(VALUE self) {
146
- FIBITMAP *bitmap;
147
- GET_BITMAP(bitmap);
239
+ VALUE unload(VALUE self) {
240
+ FIBITMAP *bitmap;
241
+ GET_BITMAP(bitmap);
148
242
 
149
- FreeImage_Unload(bitmap);
150
- DATA_PTR(self) = NULL;
151
- return Qnil;
152
- }
153
- END
243
+ FreeImage_Unload(bitmap);
244
+ DATA_PTR(self) = NULL;
245
+ return Qnil;
246
+ }
247
+ END
154
248
 
155
249
  builder.prefix <<-"END"
156
- VALUE wrap_and_yield(FIBITMAP *image, VALUE self, FREE_IMAGE_FORMAT fif) {
157
- unsigned int self_is_class = rb_type(self) == T_CLASS;
158
- VALUE klass = self_is_class ? self : CLASS_OF(self);
159
- VALUE type = self_is_class ? INT2FIX(fif) : rb_iv_get(self, "@file_type");
160
- VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, image);
161
- rb_iv_set(obj, "@file_type", type);
162
- return rb_ensure(rb_yield, obj, unload, obj);
163
- }
164
- END
250
+ VALUE wrap_and_yield(FIBITMAP *image, VALUE self, FREE_IMAGE_FORMAT fif) {
251
+ unsigned int self_is_class = rb_type(self) == T_CLASS;
252
+ VALUE klass = self_is_class ? self : CLASS_OF(self);
253
+ VALUE type = self_is_class ? INT2FIX(fif) : rb_iv_get(self, "@file_type");
254
+ VALUE obj = Data_Wrap_Struct(klass, NULL, NULL, image);
255
+ rb_iv_set(obj, "@file_type", type);
256
+ return rb_ensure(rb_yield, obj, unload, obj);
257
+ }
258
+ END
165
259
 
166
260
  builder.prefix <<-"END"
167
- void copy_icc_profile(VALUE self, FIBITMAP *from, FIBITMAP *to) {
168
- FREE_IMAGE_FORMAT fif = FIX2INT(rb_iv_get(self, "@file_type"));
169
- if (fif != FIF_PNG && FreeImage_FIFSupportsICCProfiles(fif)) {
170
- FIICCPROFILE *profile = FreeImage_GetICCProfile(from);
171
- if (profile && profile->data) {
172
- FreeImage_CreateICCProfile(to, profile->data, profile->size);
173
- }
174
- }
175
- }
176
- END
261
+ void copy_icc_profile(VALUE self, FIBITMAP *from, FIBITMAP *to) {
262
+ FREE_IMAGE_FORMAT fif = FIX2INT(rb_iv_get(self, "@file_type"));
263
+ if (fif != FIF_PNG && FreeImage_FIFSupportsICCProfiles(fif)) {
264
+ FIICCPROFILE *profile = FreeImage_GetICCProfile(from);
265
+ if (profile && profile->data) {
266
+ FreeImage_CreateICCProfile(to, profile->data, profile->size);
267
+ }
268
+ }
269
+ }
270
+ END
177
271
 
178
272
  builder.prefix <<-"END"
179
- void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
180
- rb_raise(rb_eRuntimeError,
181
- "FreeImage exception for type %s: %s",
182
- (fif == FIF_UNKNOWN) ? "???" : FreeImage_GetFormatFromFIF(fif),
183
- message);
184
- }
185
- END
273
+ void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
274
+ rb_raise(rb_eRuntimeError,
275
+ "FreeImage exception for type %s: %s",
276
+ (fif == FIF_UNKNOWN) ? "???" : FreeImage_GetFormatFromFIF(fif),
277
+ message);
278
+ }
279
+ END
186
280
 
187
281
  builder.add_to_init "FreeImage_SetOutputMessage(FreeImageErrorHandler);"
188
282
 
189
283
  builder.c_singleton <<-"END"
190
- VALUE with_image(char * input) {
191
- FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
192
- int flags;
193
-
194
- fif = FreeImage_GetFileType(input, 0);
195
- if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(input);
196
- if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
197
- FIBITMAP *bitmap;
198
- VALUE result = Qnil;
199
- flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
200
- if (bitmap = FreeImage_Load(fif, input, flags)) {
201
- FITAG *tagValue = NULL;
202
- FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Orientation", &tagValue);
203
- switch (tagValue == NULL ? 0 : *((short *) FreeImage_GetTagValue(tagValue))) {
204
- case 6:
205
- bitmap = FreeImage_RotateClassic(bitmap, 270);
206
- break;
207
- case 3:
208
- bitmap = FreeImage_RotateClassic(bitmap, 180);
209
- break;
210
- case 8:
211
- bitmap = FreeImage_RotateClassic(bitmap, 90);
212
- break;
213
- default:
214
- break;
215
- }
216
-
217
- result = wrap_and_yield(bitmap, self, fif);
218
- }
219
- return result;
220
- }
221
- rb_raise(rb_eTypeError, "Unknown file format");
222
- }
223
- END
284
+ VALUE with_image(char * input) {
285
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
286
+ int flags;
287
+
288
+ fif = FreeImage_GetFileType(input, 0);
289
+ if (fif == FIF_UNKNOWN) fif = FreeImage_GetFIFFromFilename(input);
290
+ if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
291
+ FIBITMAP *bitmap;
292
+ VALUE result = Qnil;
293
+ flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
294
+ if (bitmap = FreeImage_Load(fif, input, flags)) {
295
+ FITAG *tagValue = NULL;
296
+ FreeImage_GetMetadata(FIMD_EXIF_MAIN, bitmap, "Orientation", &tagValue);
297
+ switch (tagValue == NULL ? 0 : *((short *) FreeImage_GetTagValue(tagValue))) {
298
+ case 6:
299
+ bitmap = FreeImage_RotateClassic(bitmap, 270);
300
+ break;
301
+ case 3:
302
+ bitmap = FreeImage_RotateClassic(bitmap, 180);
303
+ break;
304
+ case 8:
305
+ bitmap = FreeImage_RotateClassic(bitmap, 90);
306
+ break;
307
+ default:
308
+ break;
309
+ }
310
+
311
+ result = wrap_and_yield(bitmap, self, fif);
312
+ }
313
+ return result;
314
+ }
315
+ rb_raise(rb_eTypeError, "Unknown file format");
316
+ }
317
+ END
224
318
 
225
319
  builder.c_singleton <<-"END"
226
- VALUE with_image_from_memory(VALUE image_data) {
227
- FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
228
-
229
- Check_Type(image_data, T_STRING);
230
- BYTE *image_data_ptr = (BYTE*)RSTRING_PTR(image_data);
231
- DWORD image_data_length = RSTRING_LEN(image_data);
232
- FIMEMORY *stream = FreeImage_OpenMemory(image_data_ptr, image_data_length);
233
-
234
- if (NULL == stream) {
235
- rb_raise(rb_eTypeError, "Unable to open image_data");
236
- }
237
-
238
- fif = FreeImage_GetFileTypeFromMemory(stream, 0);
239
- if ((fif == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading(fif)) {
240
- rb_raise(rb_eTypeError, "Unknown file format");
241
- }
242
-
243
- FIBITMAP *bitmap = NULL;
244
- VALUE result = Qnil;
245
- int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
246
- bitmap = FreeImage_LoadFromMemory(fif, stream, flags);
247
- FreeImage_CloseMemory(stream);
248
- if (bitmap) {
249
- result = wrap_and_yield(bitmap, self, fif);
250
- }
251
- return result;
252
- }
253
- END
320
+ VALUE with_image_from_memory(VALUE image_data) {
321
+ FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
322
+
323
+ Check_Type(image_data, T_STRING);
324
+ BYTE *image_data_ptr = (BYTE*)RSTRING_PTR(image_data);
325
+ DWORD image_data_length = RSTRING_LEN(image_data);
326
+ FIMEMORY *stream = FreeImage_OpenMemory(image_data_ptr, image_data_length);
327
+
328
+ if (NULL == stream) {
329
+ rb_raise(rb_eTypeError, "Unable to open image_data");
330
+ }
331
+
332
+ fif = FreeImage_GetFileTypeFromMemory(stream, 0);
333
+ if ((fif == FIF_UNKNOWN) || !FreeImage_FIFSupportsReading(fif)) {
334
+ rb_raise(rb_eTypeError, "Unknown file format");
335
+ }
336
+
337
+ FIBITMAP *bitmap = NULL;
338
+ VALUE result = Qnil;
339
+ int flags = fif == FIF_JPEG ? JPEG_ACCURATE : 0;
340
+ bitmap = FreeImage_LoadFromMemory(fif, stream, flags);
341
+ FreeImage_CloseMemory(stream);
342
+ if (bitmap) {
343
+ result = wrap_and_yield(bitmap, self, fif);
344
+ }
345
+ return result;
346
+ }
347
+ END
254
348
 
255
349
  builder.c <<-"END"
256
- VALUE with_crop(int l, int t, int r, int b) {
257
- FIBITMAP *copy, *bitmap;
258
- VALUE result = Qnil;
259
- GET_BITMAP(bitmap);
260
-
261
- if (copy = FreeImage_Copy(bitmap, l, t, r, b)) {
262
- copy_icc_profile(self, bitmap, copy);
263
- result = wrap_and_yield(copy, self, 0);
264
- }
265
- return result;
266
- }
267
- END
350
+ VALUE with_crop(int l, int t, int r, int b) {
351
+ FIBITMAP *copy, *bitmap;
352
+ VALUE result = Qnil;
353
+ GET_BITMAP(bitmap);
354
+
355
+ if (copy = FreeImage_Copy(bitmap, l, t, r, b)) {
356
+ copy_icc_profile(self, bitmap, copy);
357
+ result = wrap_and_yield(copy, self, 0);
358
+ }
359
+ return result;
360
+ }
361
+ END
268
362
 
269
363
  builder.c <<-"END"
270
- int height() {
271
- FIBITMAP *bitmap;
272
- GET_BITMAP(bitmap);
364
+ int height() {
365
+ FIBITMAP *bitmap;
366
+ GET_BITMAP(bitmap);
273
367
 
274
- return FreeImage_GetHeight(bitmap);
275
- }
276
- END
368
+ return FreeImage_GetHeight(bitmap);
369
+ }
370
+ END
277
371
 
278
372
  builder.c <<-"END"
279
- int width() {
280
- FIBITMAP *bitmap;
281
- GET_BITMAP(bitmap);
373
+ int width() {
374
+ FIBITMAP *bitmap;
375
+ GET_BITMAP(bitmap);
282
376
 
283
- return FreeImage_GetWidth(bitmap);
284
- }
285
- END
286
-
287
- builder.c <<-"END"
288
- VALUE resize(long w, long h) {
289
- FIBITMAP *bitmap, *image;
290
- if (w <= 0) rb_raise(rb_eArgError, "Width <= 0");
291
- if (h <= 0) rb_raise(rb_eArgError, "Height <= 0");
292
- GET_BITMAP(bitmap);
293
- image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
294
- if (image) {
295
- copy_icc_profile(self, bitmap, image);
296
- return wrap_and_yield(image, self, 0);
297
- }
298
- return Qnil;
299
- }
300
- END
377
+ return FreeImage_GetWidth(bitmap);
378
+ }
379
+ END
301
380
 
302
381
  builder.c <<-"END"
303
- VALUE save(char * output) {
304
- int flags;
305
- FIBITMAP *bitmap;
306
- FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(output);
307
- if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
308
- if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
309
- GET_BITMAP(bitmap);
310
- flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
311
- BOOL result = 0, unload = 0;
312
-
313
- if (fif == FIF_PNG) FreeImage_DestroyICCProfile(bitmap);
314
- if (fif == FIF_JPEG && FreeImage_GetBPP(bitmap) != 24)
315
- bitmap = FreeImage_ConvertTo24Bits(bitmap), unload = 1; // sue me
316
-
317
- result = FreeImage_Save(fif, bitmap, output, flags);
318
-
319
- if (unload) FreeImage_Unload(bitmap);
320
-
321
- return result ? Qtrue : Qfalse;
322
- }
323
- rb_raise(rb_eTypeError, "Unknown file format");
324
- }
325
- END
382
+ VALUE resize(long w, long h) {
383
+ FIBITMAP *bitmap, *image;
384
+ if (w <= 0) rb_raise(rb_eArgError, "Width <= 0");
385
+ if (h <= 0) rb_raise(rb_eArgError, "Height <= 0");
386
+ GET_BITMAP(bitmap);
387
+ image = FreeImage_Rescale(bitmap, w, h, FILTER_CATMULLROM);
388
+ if (image) {
389
+ copy_icc_profile(self, bitmap, image);
390
+ return wrap_and_yield(image, self, 0);
391
+ }
392
+ return Qnil;
393
+ }
394
+ END
326
395
 
327
396
  builder.c <<-"END"
328
- VALUE buffer(char * extension) {
329
- VALUE str;
330
- int flags;
331
- FIBITMAP *bitmap;
332
- FIMEMORY *mem = NULL;
333
- long file_size;
334
- BYTE *mem_buffer = NULL;
335
- DWORD size_in_bytes = 0;
336
- char message[1024];
337
- FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(extension);
338
-
339
- if (fif == FIF_UNKNOWN) {
340
- fif = FIX2INT(rb_iv_get(self, "@file_type"));
341
- }
342
- if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
343
- GET_BITMAP(bitmap);
344
- flags = (fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0);
345
- BOOL result = 0, unload = 0;
346
- FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(extension);
347
-
348
- // create a memory stream and save to it
349
- bitmap = FreeImage_ConvertTo24Bits(bitmap);
350
- unload = 1;
351
- mem = FreeImage_OpenMemory(0,0);
352
- result = FreeImage_SaveToMemory(fif, bitmap, mem, flags);
353
-
354
- // get the buffer from the memory stream
355
- FreeImage_AcquireMemory(mem, &mem_buffer, &size_in_bytes);
356
-
357
- // convert to ruby string
358
- str = rb_str_new((char *) mem_buffer, size_in_bytes);
359
-
360
- // clean up
361
- if (unload) FreeImage_Unload(bitmap);
362
- FreeImage_CloseMemory(mem);
363
-
364
- // yield the string, or return it
365
- if (rb_block_given_p()) {
366
- if (result && str) {
367
- rb_yield(str);
368
- } else {
369
- rb_yield(Qnil);
370
- }
371
- }
372
- if (result && str) {
373
- return str;
374
- } else {
375
- return Qnil;
376
- }
377
- }
378
- snprintf(message,
379
- 1023,
380
- "Unknown file format: %s",
381
- extension);
382
- rb_raise(rb_eTypeError, message);
383
- }
384
- END
397
+ VALUE save(char * output) {
398
+ int flags;
399
+ FIBITMAP *bitmap;
400
+ FREE_IMAGE_FORMAT fif = FreeImage_GetFIFFromFilename(output);
401
+ if (fif == FIF_UNKNOWN) fif = FIX2INT(rb_iv_get(self, "@file_type"));
402
+ if ((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsWriting(fif)) {
403
+ GET_BITMAP(bitmap);
404
+ flags = fif == FIF_JPEG ? JPEG_QUALITYSUPERB : 0;
405
+ BOOL result = 0, unload = 0;
406
+
407
+ if (fif == FIF_PNG) FreeImage_DestroyICCProfile(bitmap);
408
+ if (fif == FIF_JPEG && FreeImage_GetBPP(bitmap) != 24)
409
+ bitmap = FreeImage_ConvertTo24Bits(bitmap), unload = 1; // sue me
410
+
411
+ result = FreeImage_Save(fif, bitmap, output, flags);
412
+
413
+ if (unload) FreeImage_Unload(bitmap);
414
+
415
+ return result ? Qtrue : Qfalse;
416
+ }
417
+ rb_raise(rb_eTypeError, "Unknown file format");
418
+ }
419
+ END
385
420
  end
386
421
  end
@@ -61,11 +61,11 @@ class TestImageScience < MiniTest::Unit::TestCase
61
61
 
62
62
  def test_class_with_image_missing_with_img_extension
63
63
 
64
- # assert_raises RuntimeError do
64
+ assert_raises RuntimeError do
65
65
  assert_nil ImageScience.with_image("nope#{@pix}") do |img|
66
66
  flunk
67
67
  end
68
- # end
68
+ end
69
69
  end
70
70
 
71
71
  def test_class_with_image_from_memory
@@ -114,7 +114,10 @@ class TestImageScience < MiniTest::Unit::TestCase
114
114
  def test_buffer_return
115
115
  ImageScience.with_image @pix do |img|
116
116
  img.resize(25, 25) do |thumb|
117
- assert thumb.buffer('.jpg')
117
+ # assert thumb.buffer('.jpg')
118
+ thumb.buffer('.jpg') do |buffer|
119
+ assert buffer
120
+ end
118
121
  end
119
122
  end
120
123
  end
@@ -315,4 +318,23 @@ class TestImageScience < MiniTest::Unit::TestCase
315
318
  end
316
319
  }
317
320
  end
321
+
322
+ def test_resize_with_crop
323
+ images = [@pix, @bearry, @biggie, @godzilla, @landscape, @portrait]
324
+ heights = [50, 450]
325
+ widths = [80, 725]
326
+ images.each do |image_file|
327
+ ImageScience.with_image(image_file) do |img|
328
+ heights.each_with_index do |height, index|
329
+ width = widths[index]
330
+ img.resize_with_crop(width, height) do |resized_image|
331
+ assert(resized_image.nil? == false)
332
+ assert_equal(height, resized_image.height)
333
+ assert_equal(width, resized_image.width)
334
+ end
335
+ end
336
+ end
337
+ end
338
+ end
339
+
318
340
  end
metadata CHANGED
@@ -1,103 +1,152 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: g1nn13-image_science
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 2
8
+ - 6
9
+ version: 1.2.6
5
10
  platform: ruby
6
11
  authors:
7
12
  - jim nist
8
13
  autorequire:
9
14
  bindir: bin
10
- cert_chain: []
15
+ cert_chain:
16
+ - |
17
+ -----BEGIN CERTIFICATE-----
18
+ MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQwwCgYDVQQDDANqaW0x
19
+ HDAaBgoJkiaJk/IsZAEZFgxob3RlbGljb3B0ZXIxEzARBgoJkiaJk/IsZAEZFgNj
20
+ b20wHhcNMTAwNTI2MTYwNTM5WhcNMTEwNTI2MTYwNTM5WjBBMQwwCgYDVQQDDANq
21
+ aW0xHDAaBgoJkiaJk/IsZAEZFgxob3RlbGljb3B0ZXIxEzARBgoJkiaJk/IsZAEZ
22
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzbudw4TyxDTEj
23
+ /UMsEt2LFWmDiEKmyKHnHiPdjINn/wY8yYw1oujRj2c2iXlaon68u8G+1qacfyd0
24
+ gpHPFQfqBFKLDtPgPffzAkY8fvW4MgjRYFcymdpiVGpHCoTgvhO9Efsrd/d8Ja4n
25
+ oeEPNHdXr/bHwLhgIAup6JYQAZSL1DY77co3rbvY1xqovbc6tg/M7cbXPp1lmONS
26
+ XwIHPWjsl3mL1IWEQPt2dmPy6ZLYliKowdGlDUblupXuVlO9cS67yf3MlJp874mY
27
+ yH1qAwSK/Toe2L39TTi/Hyx6HMFECTmkLUT/4X2z6zWUlK0e5Hr8ViBCzh2BTOyO
28
+ jojoYo7tAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
29
+ BBQ1LMdE7DCtf+7x6tJAqGRMKMtVXDANBgkqhkiG9w0BAQUFAAOCAQEAIu7ygDoV
30
+ g5wdi3wWR//1yK86vQe36luyolo3GL+Z0FmIIA+tdAPZtMAlnFasOSfLVDdkxb3O
31
+ J2MLyH5KHY5asc27J+Y/zUofGWj5JgQZIg+gAGcDuq94kr4NXgFTL4khE3zhI4uH
32
+ 65+zkHrnetmZPilpTbFjzvM1SfuzrU9t+ugEu7R1vmAQdhdcgSwXr0MYPy5oZWgQ
33
+ eayeSBRjd6tzceXRmaZYWDH2wra509l63UgJw6dsNgWzQH1XQ1XzqJXX/J8FRgDI
34
+ n3ugwImcS/YB+ZQ3TQ3uKX8E5Ikos7YH0Pc/WRQnMzcjBmNtx7GsV9MC9Qx/i+YC
35
+ UHHftgnvI+YPGw==
36
+ -----END CERTIFICATE-----
11
37
 
12
- date: 2010-01-26 00:00:00 -05:00
38
+ date: 2010-05-26 00:00:00 -04:00
13
39
  default_executable:
14
40
  dependencies:
15
41
  - !ruby/object:Gem::Dependency
16
42
  name: hoe
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
43
+ prerelease: false
44
+ requirement: &id001 !ruby/object:Gem::Requirement
20
45
  requirements:
21
46
  - - ">="
22
47
  - !ruby/object:Gem::Version
48
+ segments:
49
+ - 2
50
+ - 5
51
+ - 0
23
52
  version: 2.5.0
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: gemcutter
27
53
  type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 0.3.0
34
- version:
54
+ version_requirements: *id001
35
55
  - !ruby/object:Gem::Dependency
36
56
  name: gemcutter
37
- type: :development
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
57
+ prerelease: false
58
+ requirement: &id002 !ruby/object:Gem::Requirement
40
59
  requirements:
41
60
  - - ">="
42
61
  - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ - 3
65
+ - 0
43
66
  version: 0.3.0
44
- version:
67
+ type: :runtime
68
+ version_requirements: *id002
45
69
  - !ruby/object:Gem::Dependency
46
70
  name: hoe-doofus
47
- type: :development
48
- version_requirement:
49
- version_requirements: !ruby/object:Gem::Requirement
71
+ prerelease: false
72
+ requirement: &id003 !ruby/object:Gem::Requirement
50
73
  requirements:
51
74
  - - ">="
52
75
  - !ruby/object:Gem::Version
76
+ segments:
77
+ - 1
78
+ - 0
79
+ - 0
53
80
  version: 1.0.0
54
- version:
81
+ type: :development
82
+ version_requirements: *id003
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: hoe-git
57
- type: :development
58
- version_requirement:
59
- version_requirements: !ruby/object:Gem::Requirement
85
+ prerelease: false
86
+ requirement: &id004 !ruby/object:Gem::Requirement
60
87
  requirements:
61
88
  - - ">="
62
89
  - !ruby/object:Gem::Version
90
+ segments:
91
+ - 1
92
+ - 3
93
+ - 0
63
94
  version: 1.3.0
64
- version:
95
+ type: :development
96
+ version_requirements: *id004
65
97
  - !ruby/object:Gem::Dependency
66
98
  name: hoe-telicopter
67
- type: :development
68
- version_requirement:
69
- version_requirements: !ruby/object:Gem::Requirement
99
+ prerelease: false
100
+ requirement: &id005 !ruby/object:Gem::Requirement
70
101
  requirements:
71
102
  - - ">="
72
103
  - !ruby/object:Gem::Version
104
+ segments:
105
+ - 1
106
+ - 0
107
+ - 0
73
108
  version: 1.0.0
74
- version:
109
+ type: :development
110
+ version_requirements: *id005
75
111
  - !ruby/object:Gem::Dependency
76
112
  name: minitest
77
- type: :development
78
- version_requirement:
79
- version_requirements: !ruby/object:Gem::Requirement
113
+ prerelease: false
114
+ requirement: &id006 !ruby/object:Gem::Requirement
80
115
  requirements:
81
116
  - - ">="
82
117
  - !ruby/object:Gem::Version
118
+ segments:
119
+ - 1
120
+ - 5
121
+ - 0
83
122
  version: 1.5.0
84
- version:
123
+ type: :development
124
+ version_requirements: *id006
85
125
  - !ruby/object:Gem::Dependency
86
126
  name: hoe
87
- type: :development
88
- version_requirement:
89
- version_requirements: !ruby/object:Gem::Requirement
127
+ prerelease: false
128
+ requirement: &id007 !ruby/object:Gem::Requirement
90
129
  requirements:
91
130
  - - ">="
92
131
  - !ruby/object:Gem::Version
93
- version: 2.5.0
94
- version:
132
+ segments:
133
+ - 2
134
+ - 6
135
+ - 0
136
+ version: 2.6.0
137
+ type: :development
138
+ version_requirements: *id007
95
139
  description: |-
96
140
  g1nn13 fork changes:
97
141
 
98
142
  * added buffer() method to get image buffer for writing (to Amazon S3)
99
143
  * added fit_within() method to resize an image to fit within a specified
100
144
  height and width without changing the image's aspect ratio
145
+ * added resize_with_crop() to resize and crop images where the
146
+ target aspect ratio differs from the original aspect ratio. This is
147
+ for converting portrait to landscape and landscape to portrait.
148
+
149
+
101
150
 
102
151
  ImageScience is a clean and happy Ruby library that generates
103
152
  thumbnails -- and kicks the living crap out of RMagick. Oh, and it
@@ -138,20 +187,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
187
  requirements:
139
188
  - - ">="
140
189
  - !ruby/object:Gem::Version
190
+ segments:
191
+ - 0
141
192
  version: "0"
142
- version:
143
193
  required_rubygems_version: !ruby/object:Gem::Requirement
144
194
  requirements:
145
195
  - - ">="
146
196
  - !ruby/object:Gem::Version
197
+ segments:
198
+ - 0
147
199
  version: "0"
148
- version:
149
200
  requirements: []
150
201
 
151
202
  rubyforge_project: g1nn13-image_science
152
- rubygems_version: 1.3.5
203
+ rubygems_version: 1.3.6
153
204
  signing_key:
154
205
  specification_version: 3
155
- summary: "g1nn13 fork changes: * added buffer() method to get image buffer for writing (to Amazon S3) * added fit_within() method to resize an image to fit within a specified height and width without changing the image's aspect ratio ImageScience is a clean and happy Ruby library that generates thumbnails -- and kicks the living crap out of RMagick"
206
+ summary: "g1nn13 fork changes: * added buffer() method to get image buffer for writing (to Amazon S3) * added fit_within() method to resize an image to fit within a specified height and width without changing the image's aspect ratio * added resize_with_crop() to resize and crop images where the target aspect ratio differs from the original aspect ratio"
156
207
  test_files:
157
208
  - test/test_image_science.rb
metadata.gz.sig ADDED
@@ -0,0 +1,5 @@
1
+ Pl\3N��>KA���C��y{�[ZT��}��ͻC�ه?��M��ƅs�#�):��
2
+ C����B�du�9��
3
+ xܩ�DH�@e��P8���X��e<mm��-�m��N�b��4�Î`b�]����
4
+ �WZ�rO�.!�~2nB
5
+ �!;w(t}�e�0Fh#[��t�͎7(�ő�?�*!�ӛ^�Q��j��s���Q��8�O���; �+gg��v��%�u �t}����Ǧ]�� E�ʞ]�&����_