rszr 0.4.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/README.md +129 -12
- data/Rakefile +6 -0
- data/ext/rszr/errors.c +68 -0
- data/ext/rszr/errors.h +15 -0
- data/ext/rszr/extconf.rb +18 -0
- data/ext/rszr/image.c +482 -0
- data/ext/rszr/image.h +12 -0
- data/ext/rszr/rszr.c +17 -0
- data/ext/rszr/rszr.h +11 -0
- data/lib/rszr/batch_transformation.rb +24 -0
- data/lib/rszr/buffered.rb +25 -0
- data/lib/rszr/identification.rb +60 -0
- data/lib/rszr/image.rb +151 -98
- data/lib/rszr/image_processing.rb +82 -0
- data/lib/rszr/orientation.rb +107 -0
- data/lib/rszr/stream.rb +61 -0
- data/lib/rszr/version.rb +1 -1
- data/lib/rszr.rb +21 -7
- metadata +27 -114
- data/lib/rszr/base.rb +0 -29
- data/lib/rszr/errors.rb +0 -42
- data/lib/rszr/handle.rb +0 -37
- data/lib/rszr/lib.rb +0 -73
- data/lib/rszr/lock.rb +0 -23
data/ext/rszr/image.c
ADDED
@@ -0,0 +1,482 @@
|
|
1
|
+
#ifndef RUBY_RSZR_IMAGE
|
2
|
+
#define RUBY_RSZR_IMAGE
|
3
|
+
|
4
|
+
#include "rszr.h"
|
5
|
+
#include "image.h"
|
6
|
+
#include "errors.h"
|
7
|
+
|
8
|
+
VALUE cImage = Qnil;
|
9
|
+
|
10
|
+
|
11
|
+
static void rszr_free_image(Imlib_Image image)
|
12
|
+
{
|
13
|
+
imlib_context_set_image(image);
|
14
|
+
imlib_free_image();
|
15
|
+
}
|
16
|
+
|
17
|
+
|
18
|
+
static void rszr_image_deallocate(rszr_image_handle * handle)
|
19
|
+
{
|
20
|
+
// fprintf(stderr, "rszr_image_deallocate");
|
21
|
+
if (handle->image) {
|
22
|
+
// fprintf(stderr, ": freeing");
|
23
|
+
rszr_free_image(handle->image);
|
24
|
+
handle->image = NULL;
|
25
|
+
}
|
26
|
+
free(handle);
|
27
|
+
// fprintf(stderr, "\n");
|
28
|
+
}
|
29
|
+
|
30
|
+
static VALUE rszr_image_s_allocate(VALUE klass)
|
31
|
+
{
|
32
|
+
rszr_image_handle * handle = calloc(1, sizeof(rszr_image_handle));
|
33
|
+
return Data_Wrap_Struct(klass, NULL, rszr_image_deallocate, handle);
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
static VALUE rszr_image_initialize(VALUE self, VALUE rb_width, VALUE rb_height)
|
38
|
+
{
|
39
|
+
rszr_image_handle * handle;
|
40
|
+
|
41
|
+
Check_Type(rb_width, T_FIXNUM);
|
42
|
+
Check_Type(rb_height, T_FIXNUM);
|
43
|
+
|
44
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
45
|
+
|
46
|
+
handle->image = imlib_create_image(FIX2INT(rb_width), FIX2INT(rb_height));
|
47
|
+
|
48
|
+
return self;
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
static VALUE rszr_image_s__load(VALUE klass, VALUE rb_path)
|
53
|
+
{
|
54
|
+
rszr_image_handle * handle;
|
55
|
+
Imlib_Image image;
|
56
|
+
char * path;
|
57
|
+
Imlib_Load_Error error;
|
58
|
+
VALUE oImage;
|
59
|
+
|
60
|
+
path = StringValueCStr(rb_path);
|
61
|
+
|
62
|
+
imlib_set_cache_size(0);
|
63
|
+
image = imlib_load_image_without_cache(path);
|
64
|
+
|
65
|
+
if (!image) {
|
66
|
+
image = imlib_load_image_with_error_return(path, &error);
|
67
|
+
|
68
|
+
if (!image) {
|
69
|
+
rszr_raise_load_error(error);
|
70
|
+
return Qnil;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
imlib_context_set_image(image);
|
75
|
+
imlib_image_set_irrelevant_format(0);
|
76
|
+
|
77
|
+
oImage = rszr_image_s_allocate(cImage);
|
78
|
+
Data_Get_Struct(oImage, rszr_image_handle, handle);
|
79
|
+
handle->image = image;
|
80
|
+
return oImage;
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
static VALUE rszr_image__format_get(VALUE self)
|
85
|
+
{
|
86
|
+
rszr_image_handle * handle;
|
87
|
+
char * format;
|
88
|
+
|
89
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
90
|
+
|
91
|
+
imlib_context_set_image(handle->image);
|
92
|
+
format = imlib_image_format();
|
93
|
+
|
94
|
+
if (format) {
|
95
|
+
return rb_str_new2(format);
|
96
|
+
} else {
|
97
|
+
return Qnil;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
static VALUE rszr_image__format_set(VALUE self, VALUE rb_format)
|
103
|
+
{
|
104
|
+
rszr_image_handle * handle;
|
105
|
+
char * format = StringValueCStr(rb_format);
|
106
|
+
|
107
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
108
|
+
|
109
|
+
imlib_context_set_image(handle->image);
|
110
|
+
imlib_image_set_format(format);
|
111
|
+
|
112
|
+
return self;
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
static VALUE rszr_image_width(VALUE self)
|
117
|
+
{
|
118
|
+
rszr_image_handle * handle;
|
119
|
+
int width;
|
120
|
+
|
121
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
122
|
+
|
123
|
+
imlib_context_set_image(handle->image);
|
124
|
+
width = imlib_image_get_width();
|
125
|
+
|
126
|
+
return INT2NUM(width);
|
127
|
+
}
|
128
|
+
|
129
|
+
|
130
|
+
static VALUE rszr_image_height(VALUE self)
|
131
|
+
{
|
132
|
+
rszr_image_handle * handle;
|
133
|
+
int height;
|
134
|
+
|
135
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
136
|
+
|
137
|
+
imlib_context_set_image(handle->image);
|
138
|
+
height = imlib_image_get_height();
|
139
|
+
|
140
|
+
return INT2NUM(height);
|
141
|
+
}
|
142
|
+
|
143
|
+
/*
|
144
|
+
static VALUE rszr_image_get_quality(VALUE self)
|
145
|
+
{
|
146
|
+
rszr_image_handle * handle;
|
147
|
+
int quality;
|
148
|
+
|
149
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
150
|
+
|
151
|
+
imlib_context_set_image(handle->image);
|
152
|
+
quality = imlib_image_get_attached_value("quality");
|
153
|
+
|
154
|
+
if (quality) {
|
155
|
+
return INT2NUM(quality);
|
156
|
+
} else {
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
}
|
160
|
+
|
161
|
+
static VALUE rszr_image_set_quality(VALUE self, VALUE rb_quality)
|
162
|
+
{
|
163
|
+
rszr_image_handle * handle;
|
164
|
+
int quality;
|
165
|
+
|
166
|
+
Check_Type(rb_quality, T_FIXNUM);
|
167
|
+
quality = FIX2INT(rb_quality);
|
168
|
+
if (quality <= 0) {
|
169
|
+
rb_raise(rb_eArgError, "quality must be >= 0");
|
170
|
+
return Qnil;
|
171
|
+
}
|
172
|
+
|
173
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
174
|
+
|
175
|
+
imlib_context_set_image(handle->image);
|
176
|
+
imlib_image_attach_data_value("quality", NULL, quality, NULL);
|
177
|
+
|
178
|
+
return INT2NUM(quality);
|
179
|
+
}
|
180
|
+
*/
|
181
|
+
|
182
|
+
static VALUE rszr_image_dup(VALUE self)
|
183
|
+
{
|
184
|
+
rszr_image_handle * handle;
|
185
|
+
rszr_image_handle * cloned_handle;
|
186
|
+
Imlib_Image cloned_image;
|
187
|
+
VALUE oClonedImage;
|
188
|
+
|
189
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
190
|
+
|
191
|
+
imlib_context_set_image(handle->image);
|
192
|
+
cloned_image = imlib_clone_image();
|
193
|
+
|
194
|
+
if (!cloned_image) {
|
195
|
+
rb_raise(eRszrTransformationError, "error cloning image");
|
196
|
+
return Qnil;
|
197
|
+
}
|
198
|
+
|
199
|
+
oClonedImage = rszr_image_s_allocate(cImage);
|
200
|
+
Data_Get_Struct(oClonedImage, rszr_image_handle, cloned_handle);
|
201
|
+
cloned_handle->image = cloned_image;
|
202
|
+
|
203
|
+
return oClonedImage;
|
204
|
+
}
|
205
|
+
|
206
|
+
|
207
|
+
static VALUE rszr_image__turn_bang(VALUE self, VALUE orientation)
|
208
|
+
{
|
209
|
+
rszr_image_handle * handle;
|
210
|
+
|
211
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
212
|
+
|
213
|
+
imlib_context_set_image(handle->image);
|
214
|
+
imlib_image_orientate(NUM2INT(orientation));
|
215
|
+
|
216
|
+
return self;
|
217
|
+
}
|
218
|
+
|
219
|
+
|
220
|
+
static VALUE rszr_image_flop_bang(VALUE self)
|
221
|
+
{
|
222
|
+
rszr_image_handle * handle;
|
223
|
+
|
224
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
225
|
+
|
226
|
+
imlib_context_set_image(handle->image);
|
227
|
+
imlib_image_flip_horizontal();
|
228
|
+
|
229
|
+
return self;
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
static VALUE rszr_image_flip_bang(VALUE self)
|
234
|
+
{
|
235
|
+
rszr_image_handle * handle;
|
236
|
+
|
237
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
238
|
+
|
239
|
+
imlib_context_set_image(handle->image);
|
240
|
+
imlib_image_flip_vertical();
|
241
|
+
|
242
|
+
return self;
|
243
|
+
}
|
244
|
+
|
245
|
+
|
246
|
+
static VALUE rszr_image__rotate(VALUE self, VALUE bang, VALUE rb_angle)
|
247
|
+
{
|
248
|
+
rszr_image_handle * handle;
|
249
|
+
rszr_image_handle * rotated_handle;
|
250
|
+
Imlib_Image rotated_image;
|
251
|
+
VALUE oRotatedImage;
|
252
|
+
double angle;
|
253
|
+
|
254
|
+
angle = NUM2DBL(rb_angle);
|
255
|
+
|
256
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
257
|
+
|
258
|
+
imlib_context_set_image(handle->image);
|
259
|
+
rotated_image = imlib_create_rotated_image(angle);
|
260
|
+
|
261
|
+
if (!rotated_image) {
|
262
|
+
rb_raise(eRszrTransformationError, "error rotating image");
|
263
|
+
return Qnil;
|
264
|
+
}
|
265
|
+
|
266
|
+
if (RTEST(bang)) {
|
267
|
+
rszr_free_image(handle->image);
|
268
|
+
handle->image = rotated_image;
|
269
|
+
|
270
|
+
return self;
|
271
|
+
}
|
272
|
+
else {
|
273
|
+
oRotatedImage = rszr_image_s_allocate(cImage);
|
274
|
+
Data_Get_Struct(oRotatedImage, rszr_image_handle, rotated_handle);
|
275
|
+
rotated_handle->image = rotated_image;
|
276
|
+
|
277
|
+
return oRotatedImage;
|
278
|
+
}
|
279
|
+
}
|
280
|
+
|
281
|
+
|
282
|
+
static VALUE rszr_image_filter_bang(VALUE self, VALUE rb_filter_expr)
|
283
|
+
{
|
284
|
+
rszr_image_handle * handle;
|
285
|
+
char * filter_expr;
|
286
|
+
|
287
|
+
filter_expr = StringValueCStr(rb_filter_expr);
|
288
|
+
|
289
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
290
|
+
|
291
|
+
imlib_context_set_image(handle->image);
|
292
|
+
imlib_apply_filter(filter_expr);
|
293
|
+
|
294
|
+
return self;
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
static VALUE rszr_image__sharpen_bang(VALUE self, VALUE rb_radius)
|
299
|
+
{
|
300
|
+
rszr_image_handle * handle;
|
301
|
+
int radius;
|
302
|
+
|
303
|
+
radius = NUM2INT(rb_radius);
|
304
|
+
|
305
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
306
|
+
|
307
|
+
imlib_context_set_image(handle->image);
|
308
|
+
|
309
|
+
if (radius >= 0) {
|
310
|
+
imlib_image_sharpen(radius);
|
311
|
+
} else {
|
312
|
+
imlib_image_blur(radius);
|
313
|
+
}
|
314
|
+
|
315
|
+
return self;
|
316
|
+
}
|
317
|
+
|
318
|
+
|
319
|
+
static Imlib_Image rszr_create_cropped_scaled_image(const Imlib_Image image, VALUE rb_src_x, VALUE rb_src_y, VALUE rb_src_w, VALUE rb_src_h, VALUE rb_dst_w, VALUE rb_dst_h)
|
320
|
+
{
|
321
|
+
Imlib_Image resized_image;
|
322
|
+
|
323
|
+
int src_x = NUM2INT(rb_src_x);
|
324
|
+
int src_y = NUM2INT(rb_src_y);
|
325
|
+
int src_w = NUM2INT(rb_src_w);
|
326
|
+
int src_h = NUM2INT(rb_src_h);
|
327
|
+
int dst_w = NUM2INT(rb_dst_w);
|
328
|
+
int dst_h = NUM2INT(rb_dst_h);
|
329
|
+
|
330
|
+
// TODO: raise if <= 0
|
331
|
+
|
332
|
+
imlib_context_set_image(image);
|
333
|
+
imlib_context_set_anti_alias(1);
|
334
|
+
resized_image = imlib_create_cropped_scaled_image(src_x, src_y, src_w, src_h, dst_w, dst_h);
|
335
|
+
|
336
|
+
if (!resized_image) {
|
337
|
+
rb_raise(eRszrTransformationError, "error resizing image");
|
338
|
+
return NULL;
|
339
|
+
}
|
340
|
+
|
341
|
+
return resized_image;
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
static VALUE rszr_image__resize(VALUE self, VALUE bang, VALUE rb_src_x, VALUE rb_src_y, VALUE rb_src_w, VALUE rb_src_h, VALUE rb_dst_w, VALUE rb_dst_h)
|
346
|
+
{
|
347
|
+
rszr_image_handle * handle;
|
348
|
+
Imlib_Image resized_image;
|
349
|
+
rszr_image_handle * resized_handle;
|
350
|
+
VALUE oResizedImage;
|
351
|
+
|
352
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
353
|
+
|
354
|
+
resized_image = rszr_create_cropped_scaled_image(handle->image, rb_src_x, rb_src_y, rb_src_w, rb_src_h, rb_dst_w, rb_dst_h);
|
355
|
+
if (!resized_image) return Qfalse;
|
356
|
+
|
357
|
+
if (RTEST(bang)) {
|
358
|
+
rszr_free_image(handle->image);
|
359
|
+
handle->image = resized_image;
|
360
|
+
|
361
|
+
return self;
|
362
|
+
}
|
363
|
+
else {
|
364
|
+
oResizedImage = rszr_image_s_allocate(cImage);
|
365
|
+
Data_Get_Struct(oResizedImage, rszr_image_handle, resized_handle);
|
366
|
+
resized_handle->image = resized_image;
|
367
|
+
|
368
|
+
return oResizedImage;
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
|
373
|
+
static Imlib_Image rszr_create_cropped_image(const Imlib_Image image, VALUE rb_x, VALUE rb_y, VALUE rb_w, VALUE rb_h)
|
374
|
+
{
|
375
|
+
Imlib_Image cropped_image;
|
376
|
+
|
377
|
+
int x = NUM2INT(rb_x);
|
378
|
+
int y = NUM2INT(rb_y);
|
379
|
+
int w = NUM2INT(rb_w);
|
380
|
+
int h = NUM2INT(rb_h);
|
381
|
+
|
382
|
+
imlib_context_set_image(image);
|
383
|
+
cropped_image = imlib_create_cropped_image(x, y, w, h);
|
384
|
+
|
385
|
+
if (!cropped_image) {
|
386
|
+
rb_raise(eRszrTransformationError, "error cropping image");
|
387
|
+
return NULL;
|
388
|
+
}
|
389
|
+
|
390
|
+
return cropped_image;
|
391
|
+
}
|
392
|
+
|
393
|
+
|
394
|
+
static VALUE rszr_image__crop(VALUE self, VALUE bang, VALUE rb_x, VALUE rb_y, VALUE rb_w, VALUE rb_h)
|
395
|
+
{
|
396
|
+
rszr_image_handle * handle;
|
397
|
+
Imlib_Image cropped_image;
|
398
|
+
rszr_image_handle * cropped_handle;
|
399
|
+
VALUE oCroppedImage;
|
400
|
+
|
401
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
402
|
+
|
403
|
+
cropped_image = rszr_create_cropped_image(handle->image, rb_x, rb_y, rb_w, rb_h);
|
404
|
+
if (!cropped_image) return Qfalse;
|
405
|
+
|
406
|
+
if (RTEST(bang)) {
|
407
|
+
rszr_free_image(handle->image);
|
408
|
+
handle->image = cropped_image;
|
409
|
+
|
410
|
+
return self;
|
411
|
+
}
|
412
|
+
else {
|
413
|
+
oCroppedImage = rszr_image_s_allocate(cImage);
|
414
|
+
Data_Get_Struct(oCroppedImage, rszr_image_handle, cropped_handle);
|
415
|
+
cropped_handle->image = cropped_image;
|
416
|
+
|
417
|
+
return oCroppedImage;
|
418
|
+
}
|
419
|
+
}
|
420
|
+
|
421
|
+
|
422
|
+
static VALUE rszr_image__save(VALUE self, VALUE rb_path, VALUE rb_format, VALUE rb_quality)
|
423
|
+
{
|
424
|
+
rszr_image_handle * handle;
|
425
|
+
char * path;
|
426
|
+
char * format;
|
427
|
+
int quality;
|
428
|
+
Imlib_Load_Error save_error;
|
429
|
+
|
430
|
+
path = StringValueCStr(rb_path);
|
431
|
+
format = StringValueCStr(rb_format);
|
432
|
+
quality = (NIL_P(rb_quality)) ? 0 : FIX2INT(rb_quality);
|
433
|
+
|
434
|
+
Data_Get_Struct(self, rszr_image_handle, handle);
|
435
|
+
|
436
|
+
imlib_context_set_image(handle->image);
|
437
|
+
imlib_image_set_format(format);
|
438
|
+
if (quality)
|
439
|
+
imlib_image_attach_data_value("quality", NULL, quality, NULL);
|
440
|
+
imlib_save_image_with_error_return(path, &save_error);
|
441
|
+
|
442
|
+
if (save_error) {
|
443
|
+
rszr_raise_save_error(save_error);
|
444
|
+
return Qfalse;
|
445
|
+
}
|
446
|
+
|
447
|
+
return Qtrue;
|
448
|
+
}
|
449
|
+
|
450
|
+
void Init_rszr_image()
|
451
|
+
{
|
452
|
+
cImage = rb_define_class_under(mRszr, "Image", rb_cObject);
|
453
|
+
rb_define_alloc_func(cImage, rszr_image_s_allocate);
|
454
|
+
|
455
|
+
// Class methods
|
456
|
+
rb_define_private_method(rb_singleton_class(cImage), "_load", rszr_image_s__load, 1);
|
457
|
+
|
458
|
+
// Instance methods
|
459
|
+
rb_define_method(cImage, "initialize", rszr_image_initialize, 2);
|
460
|
+
rb_define_method(cImage, "width", rszr_image_width, 0);
|
461
|
+
rb_define_method(cImage, "height", rszr_image_height, 0);
|
462
|
+
rb_define_method(cImage, "dup", rszr_image_dup, 0);
|
463
|
+
rb_define_method(cImage, "filter!", rszr_image_filter_bang, 1);
|
464
|
+
rb_define_method(cImage, "flop!", rszr_image_flop_bang, 0);
|
465
|
+
rb_define_method(cImage, "flip!", rszr_image_flip_bang, 0);
|
466
|
+
|
467
|
+
// rb_define_method(cImage, "quality", rszr_image_get_quality, 0);
|
468
|
+
// rb_define_method(cImage, "quality=", rszr_image_set_quality, 1);
|
469
|
+
|
470
|
+
rb_define_protected_method(cImage, "_format", rszr_image__format_get, 0);
|
471
|
+
rb_define_protected_method(cImage, "_format=", rszr_image__format_set, 1);
|
472
|
+
|
473
|
+
rb_define_private_method(cImage, "_resize", rszr_image__resize, 7);
|
474
|
+
rb_define_private_method(cImage, "_crop", rszr_image__crop, 5);
|
475
|
+
rb_define_private_method(cImage, "_turn!", rszr_image__turn_bang, 1);
|
476
|
+
rb_define_private_method(cImage, "_rotate", rszr_image__rotate, 2);
|
477
|
+
rb_define_private_method(cImage, "_sharpen!", rszr_image__sharpen_bang, 1);
|
478
|
+
|
479
|
+
rb_define_private_method(cImage, "_save", rszr_image__save, 3);
|
480
|
+
}
|
481
|
+
|
482
|
+
#endif
|
data/ext/rszr/image.h
ADDED
data/ext/rszr/rszr.c
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef RUBY_RSZR
|
2
|
+
#define RUBY_RSZR
|
3
|
+
|
4
|
+
#include "rszr.h"
|
5
|
+
#include "image.h"
|
6
|
+
#include "errors.h"
|
7
|
+
|
8
|
+
VALUE mRszr = Qnil;
|
9
|
+
|
10
|
+
void Init_rszr()
|
11
|
+
{
|
12
|
+
mRszr = rb_define_module("Rszr");
|
13
|
+
Init_rszr_errors();
|
14
|
+
Init_rszr_image();
|
15
|
+
}
|
16
|
+
|
17
|
+
#endif
|
data/ext/rszr/rszr.h
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Rszr
|
2
|
+
class BatchTransformation
|
3
|
+
attr_reader :transformations, :image
|
4
|
+
|
5
|
+
def initialize(path, **opts)
|
6
|
+
puts "INITIALIZED BATCH for #{path}"
|
7
|
+
@image = path.is_a?(Image) ? path : Image.load(path, **opts)
|
8
|
+
@transformations = []
|
9
|
+
end
|
10
|
+
|
11
|
+
Image::Transformations.instance_methods.grep(/\w\z/) do |method|
|
12
|
+
define_method method do |*args|
|
13
|
+
transformations << [method, args]
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def call
|
19
|
+
transformations.each { |method, args| image.public_send("#{method}!", *args) }
|
20
|
+
image
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rszr
|
2
|
+
module Buffered
|
3
|
+
def self.included(base)
|
4
|
+
base.extend Buffered
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def with_tempfile(format, data = nil)
|
10
|
+
raise ArgumentError, 'format is required' unless format
|
11
|
+
result = nil
|
12
|
+
Tempfile.create(['rszr-buffer', ".#{format}"], encoding: 'BINARY') do |file|
|
13
|
+
if data
|
14
|
+
file.binmode
|
15
|
+
file << data
|
16
|
+
file.fsync
|
17
|
+
file.rewind
|
18
|
+
end
|
19
|
+
result = yield(file)
|
20
|
+
end
|
21
|
+
result
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Type reader adapted from fastimage
|
2
|
+
# https://github.com/sdsykes/fastimage/
|
3
|
+
|
4
|
+
module Rszr
|
5
|
+
module Identification
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def identify(data)
|
10
|
+
case data[0, 2]
|
11
|
+
when 'BM'
|
12
|
+
:bmp
|
13
|
+
when 'GI'
|
14
|
+
:gif
|
15
|
+
when 0xff.chr + 0xd8.chr
|
16
|
+
:jpeg
|
17
|
+
when 0x89.chr + 'P'
|
18
|
+
:png
|
19
|
+
when 'II', 'MM'
|
20
|
+
case data[0, 11][8..10] # @stream.peek(11)[8..10]
|
21
|
+
when 'APC', "CR\002"
|
22
|
+
nil # do not recognise CRW or CR2 as tiff
|
23
|
+
else
|
24
|
+
:tiff
|
25
|
+
end
|
26
|
+
when '8B'
|
27
|
+
:psd
|
28
|
+
when "\0\0"
|
29
|
+
case data[0, 3].bytes.last #@stream.peek(3).bytes.to_a.last
|
30
|
+
when 0
|
31
|
+
# http://www.ftyps.com/what.html
|
32
|
+
# HEIC is composed of nested "boxes". Each box has a header composed of
|
33
|
+
# - Size (32 bit integer)
|
34
|
+
# - Box type (4 chars)
|
35
|
+
# - Extended size: only if size === 1, the type field is followed by 64 bit integer of extended size
|
36
|
+
# - Payload: Type-dependent
|
37
|
+
case data[0, 12][4..-1] #@stream.peek(12)[4..-1]
|
38
|
+
when 'ftypheic'
|
39
|
+
:heic
|
40
|
+
when 'ftypmif1'
|
41
|
+
:heif
|
42
|
+
end
|
43
|
+
# ico has either a 1 (for ico format) or 2 (for cursor) at offset 3
|
44
|
+
when 1 then :ico
|
45
|
+
when 2 then :cur
|
46
|
+
end
|
47
|
+
when 'RI'
|
48
|
+
:webp if data[0, 12][8..11] == 'WEBP' #@stream.peek(12)[8..11] == "WEBP"
|
49
|
+
when "<s"
|
50
|
+
:svg if data[0, 4] == '<svg' #@stream.peek(4) == "<svg"
|
51
|
+
when /\s\s|\s<|<[?!]/, 0xef.chr + 0xbb.chr
|
52
|
+
# Peek 10 more chars each time, and if end of file is reached just raise
|
53
|
+
# unknown. We assume the <svg tag cannot be within 10 chars of the end of
|
54
|
+
# the file, and is within the first 250 chars.
|
55
|
+
:svg if (1..25).detect { |n| data[0, 10 * n]&.include?('<svg') }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|