g1nn13-image_science 1.2.5 → 1.2.6
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.tar.gz.sig +0 -0
- data/History.txt +5 -0
- data/README.txt +5 -0
- data/lib/image_science.rb +253 -218
- data/test/test_image_science.rb +25 -3
- metadata +96 -45
- metadata.gz.sig +5 -0
data.tar.gz.sig
ADDED
Binary file
|
data/History.txt
CHANGED
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.
|
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
|
-
|
142
|
-
|
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
|
-
|
146
|
-
|
147
|
-
|
239
|
+
VALUE unload(VALUE self) {
|
240
|
+
FIBITMAP *bitmap;
|
241
|
+
GET_BITMAP(bitmap);
|
148
242
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
243
|
+
FreeImage_Unload(bitmap);
|
244
|
+
DATA_PTR(self) = NULL;
|
245
|
+
return Qnil;
|
246
|
+
}
|
247
|
+
END
|
154
248
|
|
155
249
|
builder.prefix <<-"END"
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
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
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
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
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
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
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
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
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
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
|
-
|
271
|
-
|
272
|
-
|
364
|
+
int height() {
|
365
|
+
FIBITMAP *bitmap;
|
366
|
+
GET_BITMAP(bitmap);
|
273
367
|
|
274
|
-
|
275
|
-
|
276
|
-
|
368
|
+
return FreeImage_GetHeight(bitmap);
|
369
|
+
}
|
370
|
+
END
|
277
371
|
|
278
372
|
builder.c <<-"END"
|
279
|
-
|
280
|
-
|
281
|
-
|
373
|
+
int width() {
|
374
|
+
FIBITMAP *bitmap;
|
375
|
+
GET_BITMAP(bitmap);
|
282
376
|
|
283
|
-
|
284
|
-
|
285
|
-
|
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
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
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
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
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
|
data/test/test_image_science.rb
CHANGED
@@ -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
|
-
|
64
|
+
assert_raises RuntimeError do
|
65
65
|
assert_nil ImageScience.with_image("nope#{@pix}") do |img|
|
66
66
|
flunk
|
67
67
|
end
|
68
|
-
|
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
|
-
|
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-
|
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
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id002
|
45
69
|
- !ruby/object:Gem::Dependency
|
46
70
|
name: hoe-doofus
|
47
|
-
|
48
|
-
|
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
|
-
|
81
|
+
type: :development
|
82
|
+
version_requirements: *id003
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: hoe-git
|
57
|
-
|
58
|
-
|
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
|
-
|
95
|
+
type: :development
|
96
|
+
version_requirements: *id004
|
65
97
|
- !ruby/object:Gem::Dependency
|
66
98
|
name: hoe-telicopter
|
67
|
-
|
68
|
-
|
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
|
-
|
109
|
+
type: :development
|
110
|
+
version_requirements: *id005
|
75
111
|
- !ruby/object:Gem::Dependency
|
76
112
|
name: minitest
|
77
|
-
|
78
|
-
|
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
|
-
|
123
|
+
type: :development
|
124
|
+
version_requirements: *id006
|
85
125
|
- !ruby/object:Gem::Dependency
|
86
126
|
name: hoe
|
87
|
-
|
88
|
-
|
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
|
-
|
94
|
-
|
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.
|
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
|
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
|