oil 0.1.1 → 0.1.2
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.rdoc +0 -6
- data/Rakefile +1 -1
- data/ext/oil/jpeg.c +115 -29
- data/ext/oil/png.c +110 -64
- data/ext/oil/yscaler.c +29 -0
- data/ext/oil/yscaler.h +3 -1
- data/lib/oil.rb +59 -33
- data/test/helper.rb +0 -16
- data/test/test_jpeg.rb +101 -17
- data/test/test_png.rb +20 -15
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b39dd91704802e2731a0f67da4743ae67c0535ed
|
4
|
+
data.tar.gz: 9f7767d654f542c11a9fec84f3dc4c097004755c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a862073a15ee977727398689263311dd9868c6c66d518cc840a1e5c7a81f638246b62b1d5d32a4dc2a28d8205a36f4327463a025b4dcb67f491711c19f5d2d5
|
7
|
+
data.tar.gz: 14da2b6aea208767826869a19c6fe8ba4824f15fba435ca1e8862adfe8d19603ce3e7e5a48e66cd693a3afa65c9ee923f6834ac49515c7a6751cd8f23b4e12dd
|
data/README.rdoc
CHANGED
@@ -27,8 +27,6 @@ performance and low memory use.
|
|
27
27
|
|
28
28
|
== REQUIREMENTS:
|
29
29
|
|
30
|
-
These requirements do not apply to the JRuby gem.
|
31
|
-
|
32
30
|
* libjpeg-turbo
|
33
31
|
* libpng
|
34
32
|
|
@@ -48,10 +46,6 @@ Valgrind should not complain (ruby-1.9.3p125, compiled with -O3):
|
|
48
46
|
$ valgrind /path/to/ruby -Iext:test test/test_jpeg.rb
|
49
47
|
$ valgrind /path/to/ruby -Iext:test test/test_png.rb
|
50
48
|
|
51
|
-
Tests should not leak memory:
|
52
|
-
|
53
|
-
$ ruby -Iext:test -e "require 'test_jpeg.rb'; require 'test_png.rb'; loop{ MiniTest.run }"
|
54
|
-
|
55
49
|
Changes to the interpolator should be analyzed using ResampleScope:
|
56
50
|
|
57
51
|
https://github.com/jsummers/resamplescope
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ Rake::ExtensionTask.new('oil') do |ext|
|
|
6
6
|
ext.lib_dir = 'lib/oil'
|
7
7
|
end
|
8
8
|
|
9
|
-
s = Gem::Specification.new('oil', '0.1.
|
9
|
+
s = Gem::Specification.new('oil', '0.1.2') do |s|
|
10
10
|
s.license = 'MIT'
|
11
11
|
s.summary = 'Resize JPEG and PNG images.'
|
12
12
|
s.description = 'Resize JPEG and PNG images, aiming for fast performance and low memory use.'
|
data/ext/oil/jpeg.c
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
#define READ_SIZE 1024
|
8
8
|
#define WRITE_SIZE 1024
|
9
9
|
|
10
|
-
static ID id_GRAYSCALE, id_RGB, id_YCbCr, id_CMYK, id_YCCK, id_UNKNOWN;
|
10
|
+
static ID id_GRAYSCALE, id_RGB, id_YCbCr, id_CMYK, id_YCCK, id_RGBX, id_UNKNOWN;
|
11
11
|
static ID id_APP0, id_APP1, id_APP2, id_APP3, id_APP4, id_APP5, id_APP6,
|
12
12
|
id_APP7, id_APP8, id_APP9, id_APP10, id_APP11, id_APP12, id_APP13,
|
13
13
|
id_APP14, id_APP15, id_COM;
|
@@ -49,6 +49,8 @@ static J_COLOR_SPACE sym_to_j_color_space(VALUE sym)
|
|
49
49
|
return JCS_CMYK;
|
50
50
|
} else if (rb == id_YCCK) {
|
51
51
|
return JCS_YCCK;
|
52
|
+
} else if (rb == id_RGBX) {
|
53
|
+
return JCS_EXT_RGBX;
|
52
54
|
}
|
53
55
|
rb_raise(rb_eRuntimeError, "Color space not recognized.");
|
54
56
|
}
|
@@ -293,10 +295,11 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
|
293
295
|
*/
|
294
296
|
if (reader->source_io) {
|
295
297
|
jpeg_abort_decompress(dinfo);
|
298
|
+
} else {
|
299
|
+
jpeg_create_decompress(dinfo);
|
296
300
|
}
|
297
301
|
|
298
|
-
|
299
|
-
reader->dinfo.src = &reader->mgr;
|
302
|
+
dinfo->src = &reader->mgr;
|
300
303
|
|
301
304
|
rb_scan_args(argc, argv, "11", &io, &markers);
|
302
305
|
reader->source_io = io;
|
@@ -305,13 +308,16 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
|
305
308
|
if(!NIL_P(markers)) {
|
306
309
|
Check_Type(markers, T_ARRAY);
|
307
310
|
for (i=0; i<RARRAY_LEN(markers); i++) {
|
311
|
+
if (!SYMBOL_P(RARRAY_PTR(markers)[i])) {
|
312
|
+
rb_raise(rb_eTypeError, "Marker code is not a symbol.");
|
313
|
+
}
|
308
314
|
marker_code = sym_to_marker_code(RARRAY_PTR(markers)[i]);
|
309
315
|
jpeg_save_markers(dinfo, marker_code, 0xFFFF);
|
310
316
|
}
|
311
317
|
}
|
312
318
|
|
313
319
|
/* Be warned that this can raise a ruby exception and longjmp away. */
|
314
|
-
jpeg_read_header(
|
320
|
+
jpeg_read_header(dinfo, TRUE);
|
315
321
|
|
316
322
|
jpeg_calc_output_dimensions(dinfo);
|
317
323
|
|
@@ -320,12 +326,16 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
|
|
320
326
|
|
321
327
|
/*
|
322
328
|
* call-seq:
|
323
|
-
* reader.
|
329
|
+
* reader.num_components -> number
|
324
330
|
*
|
325
|
-
* Retrieve the number of components as
|
331
|
+
* Retrieve the number of components per pixel as indicated by the image
|
332
|
+
* header.
|
333
|
+
*
|
334
|
+
* This may differ from the number of components that will be returned by the
|
335
|
+
* decompressor if we ask for a color space transformation.
|
326
336
|
*/
|
327
337
|
|
328
|
-
static VALUE
|
338
|
+
static VALUE num_components(VALUE self)
|
329
339
|
{
|
330
340
|
struct jpeg_decompress_struct * dinfo;
|
331
341
|
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
@@ -334,18 +344,53 @@ static VALUE components(VALUE self)
|
|
334
344
|
|
335
345
|
/*
|
336
346
|
* call-seq:
|
337
|
-
* reader.
|
347
|
+
* reader.output_components -> number
|
348
|
+
*
|
349
|
+
* Retrieve the number of bytes per pixel that will be in the output image.
|
338
350
|
*
|
339
|
-
*
|
351
|
+
* Not all bytes will necessarily have data, since some color spaces have
|
352
|
+
* padding.
|
353
|
+
*/
|
354
|
+
|
355
|
+
static VALUE output_components(VALUE self)
|
356
|
+
{
|
357
|
+
struct jpeg_decompress_struct * dinfo;
|
358
|
+
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
359
|
+
return INT2FIX(dinfo->output_components);
|
360
|
+
}
|
361
|
+
|
362
|
+
/*
|
363
|
+
* call-seq:
|
364
|
+
* reader.out_color_components -> number
|
340
365
|
*
|
341
|
-
*
|
342
|
-
*
|
366
|
+
* Retrieve the number of components in the output color space.
|
367
|
+
*
|
368
|
+
* Some color spaces have padding, so this may not accurately represent the
|
369
|
+
* size of output pixels.
|
370
|
+
*/
|
371
|
+
|
372
|
+
static VALUE out_color_components(VALUE self)
|
373
|
+
{
|
374
|
+
struct jpeg_decompress_struct * dinfo;
|
375
|
+
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
376
|
+
return INT2FIX(dinfo->out_color_components);
|
377
|
+
}
|
378
|
+
|
379
|
+
/*
|
380
|
+
* call-seq:
|
381
|
+
* reader.jpeg_color_space -> symbol
|
382
|
+
*
|
383
|
+
* Returns a symbol representing the color model in which the JPEG is stored,
|
384
|
+
* as indicated by the image header.
|
343
385
|
*
|
344
386
|
* Possible color models are: :GRAYSCALE, :RGB, :YCbCr, :CMYK, and :YCCK. This
|
345
387
|
* method will return :UNKNOWN if the color model is not recognized.
|
388
|
+
*
|
389
|
+
* This may differ from the color space that will be returned by the
|
390
|
+
* decompressor if we ask for a color space transformation.
|
346
391
|
*/
|
347
392
|
|
348
|
-
static VALUE
|
393
|
+
static VALUE jpeg_color_space(VALUE self)
|
349
394
|
{
|
350
395
|
struct jpeg_decompress_struct * dinfo;
|
351
396
|
ID id;
|
@@ -370,7 +415,7 @@ static VALUE out_color_space(VALUE self)
|
|
370
415
|
ID id;
|
371
416
|
|
372
417
|
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
373
|
-
id = j_color_space_to_id(dinfo->
|
418
|
+
id = j_color_space_to_id(dinfo->out_color_space);
|
374
419
|
|
375
420
|
return ID2SYM(id);
|
376
421
|
}
|
@@ -379,7 +424,7 @@ static VALUE out_color_space(VALUE self)
|
|
379
424
|
* call-seq:
|
380
425
|
* reader.out_color_space = symbol
|
381
426
|
*
|
382
|
-
* Set the color model to which
|
427
|
+
* Set the color model to which the image will be converted on decompress.
|
383
428
|
*/
|
384
429
|
|
385
430
|
static VALUE set_out_color_space(VALUE self, VALUE cs)
|
@@ -389,19 +434,22 @@ static VALUE set_out_color_space(VALUE self, VALUE cs)
|
|
389
434
|
Data_Get_Struct(self, struct readerdata, reader);
|
390
435
|
raise_if_locked(reader);
|
391
436
|
|
392
|
-
reader->dinfo.
|
437
|
+
reader->dinfo.out_color_space = sym_to_j_color_space(cs);
|
393
438
|
jpeg_calc_output_dimensions(&reader->dinfo);
|
394
439
|
return cs;
|
395
440
|
}
|
396
441
|
|
397
442
|
/*
|
398
443
|
* call-seq:
|
399
|
-
* reader.
|
444
|
+
* reader.image_width -> number
|
400
445
|
*
|
401
|
-
*
|
446
|
+
* The width of the of the image as indicated by the header.
|
447
|
+
*
|
448
|
+
* This may differ from the width of the image that will be returned by the
|
449
|
+
* decompressor if we request DCT scaling.
|
402
450
|
*/
|
403
451
|
|
404
|
-
static VALUE
|
452
|
+
static VALUE image_width(VALUE self)
|
405
453
|
{
|
406
454
|
struct jpeg_decompress_struct * dinfo;
|
407
455
|
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
@@ -410,18 +458,49 @@ static VALUE width(VALUE self)
|
|
410
458
|
|
411
459
|
/*
|
412
460
|
* call-seq:
|
413
|
-
* reader.
|
461
|
+
* reader.image_height -> number
|
462
|
+
*
|
463
|
+
* The height of the image as indicated by the header.
|
414
464
|
*
|
415
|
-
*
|
465
|
+
* This may differ from the height of the image that will be returned by the
|
466
|
+
* decompressor if we request DCT scaling.
|
416
467
|
*/
|
417
468
|
|
418
|
-
static VALUE
|
469
|
+
static VALUE image_height(VALUE self)
|
419
470
|
{
|
420
471
|
struct jpeg_decompress_struct * dinfo;
|
421
472
|
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
422
473
|
return INT2FIX(dinfo->image_height);
|
423
474
|
}
|
424
475
|
|
476
|
+
/*
|
477
|
+
* call-seq:
|
478
|
+
* reader.output_width -> number
|
479
|
+
*
|
480
|
+
* The width of the of the image that will be output by the decompressor.
|
481
|
+
*/
|
482
|
+
|
483
|
+
static VALUE output_width(VALUE self)
|
484
|
+
{
|
485
|
+
struct jpeg_decompress_struct * dinfo;
|
486
|
+
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
487
|
+
return INT2FIX(dinfo->output_width);
|
488
|
+
}
|
489
|
+
|
490
|
+
/*
|
491
|
+
* call-seq:
|
492
|
+
* reader.image_height -> number
|
493
|
+
*
|
494
|
+
* The height of the image that will be output by the decompressor.
|
495
|
+
*/
|
496
|
+
|
497
|
+
static VALUE output_height(VALUE self)
|
498
|
+
{
|
499
|
+
struct jpeg_decompress_struct * dinfo;
|
500
|
+
Data_Get_Struct(self, struct jpeg_decompress_struct, dinfo);
|
501
|
+
return INT2FIX(dinfo->output_height);
|
502
|
+
}
|
503
|
+
|
425
504
|
/*
|
426
505
|
* call-seq:
|
427
506
|
* reader.markers -> hash
|
@@ -710,7 +789,12 @@ static VALUE each2(struct write_jpeg_args *args)
|
|
710
789
|
if (!NIL_P(quality)) {
|
711
790
|
jpeg_set_quality(cinfo, FIX2INT(quality), FALSE);
|
712
791
|
}
|
792
|
+
}
|
713
793
|
|
794
|
+
jpeg_start_compress(cinfo, TRUE);
|
795
|
+
jpeg_start_decompress(dinfo);
|
796
|
+
|
797
|
+
if (!NIL_P(args->opts)) {
|
714
798
|
markers = rb_hash_aref(args->opts, sym_markers);
|
715
799
|
if (!NIL_P(markers)) {
|
716
800
|
Check_Type(markers, T_HASH);
|
@@ -718,9 +802,6 @@ static VALUE each2(struct write_jpeg_args *args)
|
|
718
802
|
}
|
719
803
|
}
|
720
804
|
|
721
|
-
jpeg_start_compress(cinfo, TRUE);
|
722
|
-
jpeg_start_decompress(dinfo);
|
723
|
-
|
724
805
|
for(i=0; i<scaley; i++) {
|
725
806
|
while ((yinbuf = yscaler_next(ys))) {
|
726
807
|
jpeg_read_scanlines(dinfo, (JSAMPARRAY)&inwidthbuf, 1);
|
@@ -816,12 +897,16 @@ void Init_jpeg()
|
|
816
897
|
rb_define_alloc_func(cJPEGReader, allocate);
|
817
898
|
rb_define_method(cJPEGReader, "initialize", initialize, -1);
|
818
899
|
rb_define_method(cJPEGReader, "markers", markers, 0);
|
819
|
-
rb_define_method(cJPEGReader, "
|
900
|
+
rb_define_method(cJPEGReader, "jpeg_color_space", jpeg_color_space, 0);
|
820
901
|
rb_define_method(cJPEGReader, "out_color_space", out_color_space, 0);
|
821
|
-
rb_define_method(cJPEGReader, "
|
822
|
-
rb_define_method(cJPEGReader, "
|
823
|
-
rb_define_method(cJPEGReader, "
|
824
|
-
rb_define_method(cJPEGReader, "
|
902
|
+
rb_define_method(cJPEGReader, "out_color_space=", set_out_color_space, 1);
|
903
|
+
rb_define_method(cJPEGReader, "num_components", num_components, 0);
|
904
|
+
rb_define_method(cJPEGReader, "output_components", output_components, 0);
|
905
|
+
rb_define_method(cJPEGReader, "out_color_components", out_color_components, 0);
|
906
|
+
rb_define_method(cJPEGReader, "image_width", image_width, 0);
|
907
|
+
rb_define_method(cJPEGReader, "image_height", image_height, 0);
|
908
|
+
rb_define_method(cJPEGReader, "output_width", output_width, 0);
|
909
|
+
rb_define_method(cJPEGReader, "output_height", output_height, 0);
|
825
910
|
rb_define_method(cJPEGReader, "each", each, -1);
|
826
911
|
rb_define_method(cJPEGReader, "scale_num", scale_num, 0);
|
827
912
|
rb_define_method(cJPEGReader, "scale_num=", set_scale_num, 1);
|
@@ -837,6 +922,7 @@ void Init_jpeg()
|
|
837
922
|
id_YCbCr = rb_intern("YCbCr");
|
838
923
|
id_CMYK = rb_intern("CMYK");
|
839
924
|
id_YCCK = rb_intern("YCCK");
|
925
|
+
id_RGBX = rb_intern("RGBX");
|
840
926
|
id_UNKNOWN = rb_intern("UNKNOWN");
|
841
927
|
id_APP0 = rb_intern("APP0");
|
842
928
|
id_APP1 = rb_intern("APP1");
|
data/ext/oil/png.c
CHANGED
@@ -54,6 +54,7 @@ static void write_data_fn(png_structp png_ptr, png_bytep data, png_size_t length
|
|
54
54
|
static void deallocate(struct readerdata *reader)
|
55
55
|
{
|
56
56
|
png_destroy_read_struct(&reader->png, &reader->info, NULL);
|
57
|
+
free(reader);
|
57
58
|
}
|
58
59
|
|
59
60
|
static void mark(struct readerdata *reader)
|
@@ -63,13 +64,19 @@ static void mark(struct readerdata *reader)
|
|
63
64
|
}
|
64
65
|
}
|
65
66
|
|
67
|
+
static void allocate2(struct readerdata *reader)
|
68
|
+
{
|
69
|
+
reader->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)error, (png_error_ptr)warning);
|
70
|
+
reader->info = png_create_info_struct(reader->png);
|
71
|
+
}
|
72
|
+
|
66
73
|
static VALUE allocate(VALUE klass)
|
67
74
|
{
|
68
75
|
struct readerdata *reader;
|
69
76
|
VALUE self;
|
70
77
|
|
71
78
|
self = Data_Make_Struct(klass, struct readerdata, mark, deallocate, reader);
|
72
|
-
reader
|
79
|
+
allocate2(reader);
|
73
80
|
return self;
|
74
81
|
}
|
75
82
|
|
@@ -88,16 +95,23 @@ static VALUE initialize(VALUE self, VALUE io)
|
|
88
95
|
|
89
96
|
Data_Get_Struct(self, struct readerdata, reader);
|
90
97
|
|
91
|
-
if (reader->
|
98
|
+
if (reader->info) {
|
92
99
|
png_destroy_read_struct(&reader->png, &reader->info, NULL);
|
93
|
-
reader
|
100
|
+
allocate2(reader);
|
94
101
|
reader->locked = 0;
|
95
102
|
}
|
96
103
|
|
97
104
|
reader->source_io = io;
|
98
|
-
reader->info = png_create_info_struct(reader->png);
|
99
105
|
png_set_read_fn(reader->png, (void*)io, read_data);
|
100
106
|
png_read_info(reader->png, reader->info);
|
107
|
+
|
108
|
+
png_set_packing(reader->png);
|
109
|
+
png_set_strip_16(reader->png);
|
110
|
+
png_set_expand(reader->png);
|
111
|
+
png_read_update_info(reader->png, reader->info);
|
112
|
+
|
113
|
+
reader->scale_width = png_get_image_width(reader->png, reader->info);
|
114
|
+
reader->scale_height = png_get_image_height(reader->png, reader->info);
|
101
115
|
return self;
|
102
116
|
}
|
103
117
|
|
@@ -193,54 +207,75 @@ static VALUE set_scale_height(VALUE self, VALUE scale_height)
|
|
193
207
|
return scale_height;
|
194
208
|
}
|
195
209
|
|
196
|
-
struct
|
197
|
-
VALUE opts;
|
210
|
+
struct each_args {
|
198
211
|
struct readerdata *reader;
|
212
|
+
png_structp wpng;
|
213
|
+
png_infop winfo;
|
199
214
|
unsigned char *inwidthbuf;
|
200
215
|
unsigned char *outwidthbuf;
|
201
|
-
|
202
|
-
|
203
|
-
png_infop info;
|
216
|
+
unsigned char **scanlines;
|
217
|
+
struct yscaler ys;
|
204
218
|
};
|
205
219
|
|
206
|
-
static VALUE
|
220
|
+
static VALUE each_interlace(struct each_args *args)
|
221
|
+
{
|
222
|
+
struct readerdata *reader;
|
223
|
+
unsigned char *inwidthbuf, *outwidthbuf;
|
224
|
+
uint32_t i, width, height, scalex, scaley;
|
225
|
+
int cmp;
|
226
|
+
|
227
|
+
reader = args->reader;
|
228
|
+
inwidthbuf = args->inwidthbuf;
|
229
|
+
outwidthbuf = args->outwidthbuf;
|
230
|
+
scalex = reader->scale_width;
|
231
|
+
scaley = reader->scale_height;
|
232
|
+
cmp = png_get_channels(reader->png, reader->info);
|
233
|
+
width = png_get_image_width(reader->png, reader->info);
|
234
|
+
height = png_get_image_height(reader->png, reader->info);
|
235
|
+
|
236
|
+
png_write_info(args->wpng, args->winfo);
|
237
|
+
png_read_image(args->reader->png, (png_bytepp)args->scanlines);
|
238
|
+
|
239
|
+
for (i=0; i<scaley; i++) {
|
240
|
+
yscaler_prealloc_scale(height, scaley,
|
241
|
+
(uint8_t **)args->scanlines, (uint8_t *)inwidthbuf,
|
242
|
+
i, width, cmp, 0);
|
243
|
+
xscale(inwidthbuf, width, outwidthbuf, scalex, cmp, 0);
|
244
|
+
png_write_row(args->wpng, outwidthbuf);
|
245
|
+
}
|
246
|
+
png_write_end(args->wpng, args->winfo);
|
247
|
+
return Qnil;
|
248
|
+
}
|
249
|
+
|
250
|
+
static VALUE each_interlace_none(struct each_args *args)
|
207
251
|
{
|
208
|
-
png_structp png;
|
209
|
-
png_infop info;
|
210
|
-
png_byte ctype;
|
211
252
|
struct readerdata *reader;
|
212
253
|
unsigned char *inwidthbuf, *outwidthbuf, *yinbuf;
|
213
254
|
struct yscaler *ys;
|
214
|
-
uint32_t i, scalex, scaley;
|
255
|
+
uint32_t i, width, scalex, scaley;
|
215
256
|
int cmp;
|
216
257
|
|
217
258
|
reader = args->reader;
|
218
|
-
png = args->png;
|
219
|
-
info = args->info;
|
220
259
|
inwidthbuf = args->inwidthbuf;
|
221
260
|
outwidthbuf = args->outwidthbuf;
|
222
|
-
ys = args->ys;
|
223
|
-
scalex =
|
224
|
-
scaley =
|
225
|
-
|
261
|
+
ys = &args->ys;
|
262
|
+
scalex = reader->scale_width;
|
263
|
+
scaley = reader->scale_height;
|
226
264
|
cmp = png_get_channels(reader->png, reader->info);
|
227
|
-
|
228
|
-
ctype = png_get_color_type(reader->png, reader->info);
|
265
|
+
width = png_get_image_width(reader->png, reader->info);
|
229
266
|
|
230
|
-
|
231
|
-
png_write_info(png, info);
|
267
|
+
png_write_info(args->wpng, args->winfo);
|
232
268
|
|
233
269
|
for(i=0; i<scaley; i++) {
|
234
270
|
while ((yinbuf = yscaler_next(ys))) {
|
235
271
|
png_read_row(reader->png, inwidthbuf, NULL);
|
236
|
-
xscale(inwidthbuf,
|
272
|
+
xscale(inwidthbuf, width, yinbuf, scalex, cmp, 0);
|
237
273
|
}
|
238
274
|
yscaler_scale(ys, outwidthbuf, scalex, cmp, 0);
|
239
|
-
png_write_row(
|
275
|
+
png_write_row(args->wpng, outwidthbuf);
|
240
276
|
}
|
241
277
|
|
242
|
-
png_write_end(
|
243
|
-
|
278
|
+
png_write_end(args->wpng, args->winfo);
|
244
279
|
return Qnil;
|
245
280
|
}
|
246
281
|
|
@@ -261,13 +296,15 @@ static VALUE each2(struct write_png_args *args)
|
|
261
296
|
static VALUE each(int argc, VALUE *argv, VALUE self)
|
262
297
|
{
|
263
298
|
struct readerdata *reader;
|
264
|
-
|
265
|
-
|
266
|
-
unsigned char *inwidthbuf, *outwidthbuf;
|
267
|
-
struct yscaler ys;
|
299
|
+
png_infop winfo;
|
300
|
+
png_structp wpng;
|
268
301
|
VALUE opts;
|
269
|
-
|
270
|
-
|
302
|
+
int cmp, state;
|
303
|
+
struct each_args args;
|
304
|
+
uint32_t i, height;
|
305
|
+
png_byte ctype;
|
306
|
+
unsigned char **scanlines;
|
307
|
+
size_t row_bytes;
|
271
308
|
|
272
309
|
rb_scan_args(argc, argv, "01", &opts);
|
273
310
|
|
@@ -276,41 +313,50 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
|
|
276
313
|
raise_if_locked(reader);
|
277
314
|
reader->locked = 1;
|
278
315
|
|
279
|
-
|
280
|
-
png_set_strip_16(reader->png);
|
281
|
-
png_set_expand(reader->png);
|
282
|
-
png_read_update_info(reader->png, reader->info);
|
283
|
-
|
284
|
-
if (!reader->scale_width) {
|
285
|
-
reader->scale_width = png_get_image_width(reader->png, reader->info);
|
286
|
-
}
|
287
|
-
if (!reader->scale_height) {
|
288
|
-
reader->scale_height = png_get_image_height(reader->png, reader->info);
|
289
|
-
}
|
290
|
-
|
291
|
-
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
|
316
|
+
wpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
|
292
317
|
(png_error_ptr)error, (png_error_ptr)warning);
|
293
|
-
|
318
|
+
winfo = png_create_info_struct(wpng);
|
319
|
+
png_set_write_fn(wpng, 0, write_data_fn, flush_data_fn);
|
294
320
|
|
295
|
-
inwidthbuf = malloc(png_get_rowbytes(reader->png, reader->info));
|
296
321
|
cmp = png_get_channels(reader->png, reader->info);
|
297
|
-
|
298
|
-
|
299
|
-
|
322
|
+
ctype = png_get_color_type(reader->png, reader->info);
|
323
|
+
|
324
|
+
png_set_IHDR(wpng, winfo, reader->scale_width, reader->scale_height, 8,
|
325
|
+
ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
326
|
+
PNG_FILTER_TYPE_DEFAULT);
|
327
|
+
|
328
|
+
height = png_get_image_height(reader->png, reader->info);
|
329
|
+
row_bytes = png_get_rowbytes(reader->png, reader->info);
|
300
330
|
|
301
331
|
args.reader = reader;
|
302
|
-
args.
|
303
|
-
args.
|
304
|
-
args.
|
305
|
-
args.
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
332
|
+
args.wpng = wpng;
|
333
|
+
args.winfo = winfo;
|
334
|
+
args.inwidthbuf = malloc(row_bytes);
|
335
|
+
args.outwidthbuf = malloc(reader->scale_width * cmp);
|
336
|
+
|
337
|
+
if (png_get_interlace_type(reader->png, reader->info) == PNG_INTERLACE_NONE) {
|
338
|
+
yscaler_init(&args.ys, height, reader->scale_height,
|
339
|
+
reader->scale_width * cmp);
|
340
|
+
rb_protect((VALUE(*)(VALUE))each_interlace_none, (VALUE)&args, &state);
|
341
|
+
yscaler_free(&args.ys);
|
342
|
+
} else {
|
343
|
+
scanlines = malloc(height * sizeof(unsigned char *));
|
344
|
+
for (i=0; i<height; i++) {
|
345
|
+
scanlines[i] = malloc(row_bytes);
|
346
|
+
}
|
347
|
+
|
348
|
+
args.scanlines = scanlines;
|
349
|
+
rb_protect((VALUE(*)(VALUE))each_interlace, (VALUE)&args, &state);
|
350
|
+
|
351
|
+
for (i=0; i<height; i++) {
|
352
|
+
free(scanlines[i]);
|
353
|
+
}
|
354
|
+
free(scanlines);
|
355
|
+
}
|
356
|
+
|
357
|
+
free(args.inwidthbuf);
|
358
|
+
free(args.outwidthbuf);
|
359
|
+
png_destroy_write_struct(&wpng, &winfo);
|
314
360
|
|
315
361
|
if (state) {
|
316
362
|
rb_jump_tag(state);
|
data/ext/oil/yscaler.c
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#include "yscaler.h"
|
2
|
+
#include "resample.h"
|
2
3
|
#include <stdlib.h>
|
3
4
|
#include <stdint.h>
|
4
5
|
|
@@ -136,3 +137,31 @@ void yscaler_scale(struct yscaler *ys, uint8_t *out, uint32_t width,
|
|
136
137
|
ys->out_pos++;
|
137
138
|
yscaler_map_pos(ys);
|
138
139
|
}
|
140
|
+
|
141
|
+
void yscaler_prealloc_scale(uint32_t in_height, uint32_t out_height,
|
142
|
+
uint8_t **in, uint8_t *out, uint32_t pos, uint32_t width, uint8_t cmp,
|
143
|
+
uint8_t opts)
|
144
|
+
{
|
145
|
+
uint32_t i, taps;
|
146
|
+
int32_t smp_i, strip_pos;
|
147
|
+
uint8_t **virt;
|
148
|
+
float ty;
|
149
|
+
|
150
|
+
taps = calc_taps(in_height, out_height);
|
151
|
+
virt = malloc(taps * sizeof(uint8_t *));
|
152
|
+
smp_i = split_map(in_height, out_height, pos, &ty);
|
153
|
+
strip_pos = smp_i + 1 - taps / 2;
|
154
|
+
|
155
|
+
for (i=0; i<taps; i++) {
|
156
|
+
if (strip_pos < 0) {
|
157
|
+
virt[i] = in[0];
|
158
|
+
} else if ((uint32_t)strip_pos > in_height - 1) {
|
159
|
+
virt[i] = in[in_height - 1];
|
160
|
+
} else {
|
161
|
+
virt[i] = in[strip_pos];
|
162
|
+
}
|
163
|
+
strip_pos++;
|
164
|
+
}
|
165
|
+
|
166
|
+
strip_scale((void **)virt, taps, width, (void *)out, ty, cmp, opts);
|
167
|
+
}
|
data/ext/oil/yscaler.h
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#ifndef YSCALER_H
|
2
2
|
#define YSCALER_H
|
3
3
|
|
4
|
-
#include "resample.h"
|
5
4
|
#include <stdint.h>
|
6
5
|
|
7
6
|
struct strip {
|
@@ -27,5 +26,8 @@ void yscaler_free(struct yscaler *ys);
|
|
27
26
|
unsigned char *yscaler_next(struct yscaler *ys);
|
28
27
|
void yscaler_scale(struct yscaler *ys, uint8_t *out, uint32_t width,
|
29
28
|
uint8_t cmp, uint8_t opts);
|
29
|
+
void yscaler_prealloc_scale(uint32_t in_height, uint32_t out_height,
|
30
|
+
uint8_t **in, uint8_t *out, uint32_t pos, uint32_t width, uint8_t cmp,
|
31
|
+
uint8_t opts);
|
30
32
|
|
31
33
|
#endif
|
data/lib/oil.rb
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
module Oil
|
2
|
-
VERSION = "0.1.
|
2
|
+
VERSION = "0.1.2"
|
3
|
+
|
4
|
+
def self.sniff_signature(io)
|
5
|
+
a = io.getc
|
6
|
+
b = io.getc
|
7
|
+
io.ungetc(b)
|
8
|
+
io.ungetc(a)
|
9
|
+
|
10
|
+
if (a == "\xFF".b && b == "\xD8".b)
|
11
|
+
return :JPEG
|
12
|
+
elsif (a == "\x89".b && b == "P".b)
|
13
|
+
return :PNG
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.new(io, box_width, box_height)
|
18
|
+
case sniff_signature(io)
|
19
|
+
when :JPEG
|
20
|
+
return new_jpeg_reader(io, box_width, box_height)
|
21
|
+
when :PNG
|
22
|
+
return new_png_reader(io, box_width, box_height)
|
23
|
+
else
|
24
|
+
raise "Unknown image file format."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
3
29
|
|
4
30
|
def self.fix_ratio(sw, sh, boxw, boxh)
|
5
31
|
x = boxw / sw.to_f
|
@@ -25,52 +51,52 @@ module Oil
|
|
25
51
|
return destw, desth
|
26
52
|
end
|
27
53
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
54
|
+
def self.new_jpeg_reader(io, box_width, box_height)
|
55
|
+
o = JPEGReader.new(io, [:COM, :APP1, :APP2])
|
56
|
+
|
57
|
+
# bump RGB images to RGBX
|
58
|
+
if (o.out_color_space == :RGB)
|
59
|
+
o.out_color_space = :RGBX
|
60
|
+
end
|
61
|
+
|
62
|
+
# JPEG Pre-scaling is equivalent to a box filter at an integer scale factor.
|
63
|
+
# We don't use this to scale down past 4x the target image size in order to
|
64
|
+
# get proper bicubic scaling in the final image.
|
65
|
+
inv_scale = o.image_width / box_width
|
33
66
|
inv_scale /= 4
|
34
67
|
|
35
68
|
if inv_scale >= 8
|
36
|
-
|
69
|
+
o.scale_denom = 8
|
37
70
|
elsif inv_scale >= 4
|
38
|
-
|
71
|
+
o.scale_denom = 4
|
39
72
|
elsif inv_scale >= 2
|
40
|
-
|
41
|
-
else
|
42
|
-
return 0
|
73
|
+
o.scale_denom = 2
|
43
74
|
end
|
44
|
-
end
|
45
75
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
io.ungetc(b)
|
50
|
-
io.ungetc(a)
|
76
|
+
destw, desth = self.fix_ratio(o.output_width, o.output_height, box_width, box_height)
|
77
|
+
o.scale_width = destw
|
78
|
+
o.scale_height = desth
|
51
79
|
|
52
|
-
|
53
|
-
|
54
|
-
if (o.color_space == :RGB)
|
55
|
-
o.out_color_space = :RGBX
|
56
|
-
end
|
57
|
-
elsif (a == "\x89".b && b == "P".b)
|
58
|
-
o = PNGReader.new(io)
|
59
|
-
else
|
60
|
-
raise "Unknown image file format."
|
61
|
-
end
|
80
|
+
return JPEGReaderWrapper.new(o, { markers: o.markers, quality: 95 })
|
81
|
+
end
|
62
82
|
|
83
|
+
def self.new_png_reader(io, box_width, box_height)
|
84
|
+
o = PNGReader.new(io)
|
63
85
|
destw, desth = self.fix_ratio(o.width, o.height, box_width, box_height)
|
64
|
-
pre = self.pre_scale(o.width, o.height, box_width, box_height)
|
65
|
-
|
66
86
|
o.scale_width = destw
|
67
87
|
o.scale_height = desth
|
88
|
+
return o
|
89
|
+
end
|
90
|
+
end
|
68
91
|
|
69
|
-
|
70
|
-
|
71
|
-
|
92
|
+
class JPEGReaderWrapper
|
93
|
+
def initialize(reader, opts)
|
94
|
+
@reader = reader
|
95
|
+
@opts = opts
|
96
|
+
end
|
72
97
|
|
73
|
-
|
98
|
+
def each(&block)
|
99
|
+
@reader.each(@opts, &block)
|
74
100
|
end
|
75
101
|
end
|
76
102
|
|
data/test/helper.rb
CHANGED
@@ -72,19 +72,3 @@ class NotStringIO < CustomIO
|
|
72
72
|
return 78887
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
76
|
-
def resize_string(str, width=nil, height=nil)
|
77
|
-
io = StringIO.new(str)
|
78
|
-
width ||= 100
|
79
|
-
height ||= 200
|
80
|
-
out = binary_stringio
|
81
|
-
o = Oil.new(io, width, height).each{ |d| out << d }
|
82
|
-
out.string
|
83
|
-
end
|
84
|
-
|
85
|
-
def binary_stringio
|
86
|
-
io = StringIO.new
|
87
|
-
io.set_encoding 'ASCII-8BIT' if RUBY_VERSION >= '1.9'
|
88
|
-
io
|
89
|
-
end
|
90
|
-
|
data/test/test_jpeg.rb
CHANGED
@@ -16,32 +16,46 @@ class TestJPEG < MiniTest::Test
|
|
16
16
|
\x01\x01\x00\x00\x3f\x00\xd2\xcf\x20\xff\xd9".b
|
17
17
|
|
18
18
|
BIG_JPEG = begin
|
19
|
-
|
19
|
+
s = ""
|
20
|
+
r = Oil::JPEGReader.new(StringIO.new(JPEG_DATA))
|
21
|
+
r.scale_width = 2000
|
22
|
+
r.scale_height = 2000
|
23
|
+
r.each{ |a| s << a }
|
24
|
+
s
|
20
25
|
end
|
21
26
|
|
22
27
|
def test_valid
|
23
28
|
o = Oil::JPEGReader.new(jpeg_io)
|
24
|
-
assert_equal 1, o.
|
25
|
-
assert_equal 1, o.
|
29
|
+
assert_equal 1, o.image_width
|
30
|
+
assert_equal 1, o.image_height
|
26
31
|
end
|
27
32
|
|
28
33
|
def test_missing_eof
|
29
34
|
io = StringIO.new(JPEG_DATA[0..-2])
|
30
35
|
o = Oil::JPEGReader.new(io)
|
31
|
-
assert_equal 1, o.
|
32
|
-
assert_equal 1, o.
|
36
|
+
assert_equal 1, o.image_width
|
37
|
+
assert_equal 1, o.image_height
|
33
38
|
end
|
34
39
|
|
35
40
|
def test_bogus_header_marker
|
36
41
|
str = JPEG_DATA.dup
|
37
42
|
str[3] = "\x10"
|
38
|
-
assert_raises(RuntimeError) {
|
43
|
+
assert_raises(RuntimeError) { drain_string(str) }
|
39
44
|
end
|
40
45
|
|
41
46
|
def test_bogus_body_marker
|
42
47
|
str = JPEG_DATA.dup
|
43
48
|
str[-22] = "\x10"
|
44
|
-
assert_raises(RuntimeError) {
|
49
|
+
assert_raises(RuntimeError) { drain_string(str) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_color_space
|
53
|
+
o = Oil::JPEGReader.new(jpeg_io)
|
54
|
+
assert_equal :GRAYSCALE, o.jpeg_color_space
|
55
|
+
assert_equal :GRAYSCALE, o.out_color_space
|
56
|
+
assert_equal 1, o.num_components
|
57
|
+
assert_equal 1, o.output_components
|
58
|
+
assert_equal 1, o.out_color_components
|
45
59
|
end
|
46
60
|
|
47
61
|
# Allocation tests
|
@@ -67,7 +81,10 @@ class TestJPEG < MiniTest::Test
|
|
67
81
|
end
|
68
82
|
|
69
83
|
def resize(io)
|
70
|
-
o = Oil.new(io
|
84
|
+
o = Oil::JPEGReader.new(io)
|
85
|
+
o.scale_width = 10
|
86
|
+
o.scale_height = 20
|
87
|
+
o.each{ |d| }
|
71
88
|
end
|
72
89
|
|
73
90
|
def test_io_too_much_data
|
@@ -112,18 +129,18 @@ class TestJPEG < MiniTest::Test
|
|
112
129
|
|
113
130
|
def test_raise_in_each
|
114
131
|
assert_raises(CustomError) do
|
115
|
-
Oil.new(jpeg_io
|
132
|
+
Oil::JPEGReader.new(jpeg_io).each{ raise CustomError }
|
116
133
|
end
|
117
134
|
end
|
118
135
|
|
119
136
|
def test_throw_in_each
|
120
137
|
catch(:foo) do
|
121
|
-
Oil.new(jpeg_io
|
138
|
+
Oil::JPEGReader.new(jpeg_io).each{ throw :foo }
|
122
139
|
end
|
123
140
|
end
|
124
141
|
|
125
142
|
def test_each_in_each
|
126
|
-
o = Oil.new(jpeg_io
|
143
|
+
o = Oil::JPEGReader.new(jpeg_io)
|
127
144
|
o.each do |d|
|
128
145
|
assert_raises(RuntimeError) do
|
129
146
|
o.each { |e| }
|
@@ -132,15 +149,78 @@ class TestJPEG < MiniTest::Test
|
|
132
149
|
end
|
133
150
|
|
134
151
|
def test_each_shrinks_buffer
|
135
|
-
|
136
|
-
io_out = binary_stringio
|
137
|
-
Oil.new(io, 200, 200).each{ |d| io_out << d; d.slice!(0, 4) }
|
152
|
+
Oil::JPEGReader.new(jpeg_io).each{ |d| d.slice!(0, 4) }
|
138
153
|
end
|
139
154
|
|
140
155
|
def test_each_enlarges_buffer
|
141
|
-
|
142
|
-
|
143
|
-
|
156
|
+
Oil::JPEGReader.new(jpeg_io).each{ |d| d << "foobar" }
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_marker_roundtrip
|
160
|
+
str = ""
|
161
|
+
opts = { markers: { COM: ["hello world", "foobar123"]}}
|
162
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){ |s| str << s }
|
163
|
+
|
164
|
+
r = Oil::JPEGReader.new(StringIO.new(str), [:COM])
|
165
|
+
|
166
|
+
assert_equal(r.markers, opts[:markers])
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_marker_code_unrecognized
|
170
|
+
assert_raises(RuntimeError) do
|
171
|
+
Oil::JPEGReader.new(jpeg_io, [:FOOBAR])
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_marker_codes_not_array
|
176
|
+
assert_raises(TypeError) do
|
177
|
+
Oil::JPEGReader.new(jpeg_io, 1234)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_marker_code_not_symbol
|
182
|
+
assert_raises(TypeError) do
|
183
|
+
Oil::JPEGReader.new(jpeg_io, [1234])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def test_marker_too_big
|
188
|
+
opts = { markers: { COM: ["hello world"*10000]}}
|
189
|
+
|
190
|
+
assert_raises(RuntimeError) do
|
191
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){ |s| str << s }
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_markers_not_hash
|
196
|
+
opts = { markers: 1234 }
|
197
|
+
|
198
|
+
assert_raises(TypeError) do
|
199
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){}
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def test_marker_value_not_array
|
204
|
+
opts = { markers: { COM: 1234}}
|
205
|
+
|
206
|
+
assert_raises(TypeError) do
|
207
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_marker_value_entry_not_string
|
212
|
+
opts = { markers: { COM: [1234]}}
|
213
|
+
|
214
|
+
assert_raises(TypeError) do
|
215
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){}
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_quality_not_a_number
|
220
|
+
opts = { quality: "foobar" }
|
221
|
+
assert_raises(TypeError) do
|
222
|
+
Oil::JPEGReader.new(jpeg_io).each(opts){}
|
223
|
+
end
|
144
224
|
end
|
145
225
|
|
146
226
|
private
|
@@ -148,4 +228,8 @@ class TestJPEG < MiniTest::Test
|
|
148
228
|
def jpeg_io
|
149
229
|
StringIO.new(JPEG_DATA)
|
150
230
|
end
|
231
|
+
|
232
|
+
def drain_string(str)
|
233
|
+
Oil::JPEGReader.new(StringIO.new(str)).each{ |s| }
|
234
|
+
end
|
151
235
|
end
|
data/test/test_png.rb
CHANGED
@@ -13,11 +13,16 @@ class TestPNG < MiniTest::Test
|
|
13
13
|
\x57\xBF\xAB\xD4\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82".b
|
14
14
|
|
15
15
|
BIG_PNG = begin
|
16
|
-
|
16
|
+
s = ""
|
17
|
+
r = Oil::PNGReader.new(StringIO.new(PNG_DATA))
|
18
|
+
r.scale_width = 500
|
19
|
+
r.scale_height = 1000
|
20
|
+
r.each{ |a| s << a }
|
21
|
+
s
|
17
22
|
end
|
18
23
|
|
19
24
|
def test_valid
|
20
|
-
o = Oil.new(png_io
|
25
|
+
o = Oil::PNGReader.new(png_io)
|
21
26
|
assert_equal 1, o.width
|
22
27
|
assert_equal 1, o.height
|
23
28
|
end
|
@@ -25,20 +30,20 @@ class TestPNG < MiniTest::Test
|
|
25
30
|
def test_bogus_header_chunk
|
26
31
|
str = PNG_DATA.dup
|
27
32
|
str[15] = "\x10"
|
28
|
-
assert_raises(RuntimeError) {
|
33
|
+
assert_raises(RuntimeError) { drain_string(str) }
|
29
34
|
end
|
30
35
|
|
31
36
|
def test_bogus_body_chunk
|
32
37
|
str = PNG_DATA.dup
|
33
38
|
str[37] = "\x10"
|
34
|
-
assert_raises(RuntimeError) {
|
39
|
+
assert_raises(RuntimeError) { drain_string(str) }
|
35
40
|
end
|
36
41
|
|
37
42
|
def test_bogus_end_chunk
|
38
43
|
str = PNG_DATA.dup
|
39
44
|
str[-6] = "\x10"
|
40
45
|
io = StringIO.new(str)
|
41
|
-
o = Oil.new(png_io
|
46
|
+
o = Oil::PNGReader.new(png_io)
|
42
47
|
assert_equal 1, o.width
|
43
48
|
assert_equal 1, o.height
|
44
49
|
end
|
@@ -66,7 +71,7 @@ class TestPNG < MiniTest::Test
|
|
66
71
|
end
|
67
72
|
|
68
73
|
def resize(io)
|
69
|
-
Oil.new(io
|
74
|
+
Oil::PNGReader.new(io).each{ |d| }
|
70
75
|
end
|
71
76
|
|
72
77
|
def test_io_too_much_data
|
@@ -109,33 +114,29 @@ class TestPNG < MiniTest::Test
|
|
109
114
|
|
110
115
|
def test_raise_in_each
|
111
116
|
assert_raises(CustomError) do
|
112
|
-
Oil.new(png_io
|
117
|
+
Oil::PNGReader.new(png_io).each { raise CustomError }
|
113
118
|
end
|
114
119
|
end
|
115
120
|
|
116
121
|
def test_throw_in_each
|
117
122
|
catch(:foo) do
|
118
|
-
Oil.new(png_io
|
123
|
+
Oil::PNGReader.new(png_io).each { throw :foo }
|
119
124
|
end
|
120
125
|
end
|
121
126
|
|
122
127
|
def test_each_in_each
|
123
|
-
o = Oil.new(png_io
|
128
|
+
o = Oil::PNGReader.new(png_io)
|
124
129
|
o.each do |d|
|
125
130
|
assert_raises(RuntimeError){ o.each { |e| } }
|
126
131
|
end
|
127
132
|
end
|
128
133
|
|
129
134
|
def test_each_shrinks_buffer
|
130
|
-
|
131
|
-
io_out = binary_stringio
|
132
|
-
Oil.new(io, 200, 200).each { |d| io_out << d; d.slice!(0, 4) }
|
135
|
+
Oil::PNGReader.new(png_io).each { |d| d.slice!(0, 4) }
|
133
136
|
end
|
134
137
|
|
135
138
|
def test_each_enlarges_buffer
|
136
|
-
|
137
|
-
io_out = binary_stringio
|
138
|
-
Oil.new(io, 200, 200).each { |d| io_out << d; d << "foobar" }
|
139
|
+
Oil::PNGReader.new(png_io).each { |d| d << "foobar" }
|
139
140
|
end
|
140
141
|
|
141
142
|
private
|
@@ -143,4 +144,8 @@ class TestPNG < MiniTest::Test
|
|
143
144
|
def png_io
|
144
145
|
StringIO.new(PNG_DATA)
|
145
146
|
end
|
147
|
+
|
148
|
+
def drain_string(str)
|
149
|
+
Oil::PNGReader.new(StringIO.new(str)).each{|s|}
|
150
|
+
end
|
146
151
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oil
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Timothy Elliott
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Resize JPEG and PNG images, aiming for fast performance and low memory
|
14
14
|
use.
|
@@ -54,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
54
|
version: '0'
|
55
55
|
requirements: []
|
56
56
|
rubyforge_project:
|
57
|
-
rubygems_version: 2.4.
|
57
|
+
rubygems_version: 2.4.4
|
58
58
|
signing_key:
|
59
59
|
specification_version: 4
|
60
60
|
summary: Resize JPEG and PNG images.
|