oil 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e7ab475c778d9843d41134e7ad33cb989be6364e
4
- data.tar.gz: 91ac3a1eef0a7869e6282116b6de9fea04bb7b89
2
+ SHA256:
3
+ metadata.gz: 8667c59ce2f99a70651d4f217513aa0de0ee294b444bba1dcfa5e6123d841c18
4
+ data.tar.gz: b32ae44e0fc03708e7ea10a4f0e9b10378377fcc1ce78c6e74a15f56a543526c
5
5
  SHA512:
6
- metadata.gz: 619ef438853c052c54f9bc3063a2837d097fac003d3f251e24599532425986042b0c970eccce61ecb268ffb891d89f5efe2d0571d3009477b14f455a94daad08
7
- data.tar.gz: 933ed077f03c19a12d72bf8eed8eb79c0cbd0ff21905b9269fa17e49c9a859c0c606b1ee35a8f725ecd144cfddecac641857621bc7bbc05a62080d2f9310ea6c
6
+ metadata.gz: 33d09f09e4f4f897e98e50496415485d5ed5861b0ee260fd6eee7cb491c93d1844ec4567957d3dfeb4491be23f9fdd10e3ec9ba544e0d7b0c88d23d785146aca
7
+ data.tar.gz: ec308eb4710bc46faffbe24d802539d6fabf33d0a37e2edf2fd6c2706508fac486efb12e8bbc41960e7b4f018f1bda286054fc1526564210441875fcb83a1eaf
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Timothy Elliott
3
+ Copyright (c) 2018 Timothy Elliott
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -11,6 +11,9 @@ performance and low memory use.
11
11
 
12
12
  $ gem install oil
13
13
 
14
+ # when using homebrew w/ jpeg-turbo
15
+ $ gem install oil --with-ldflags=-L/usr/local/opt/jpeg-turbo/lib --with-cflags=-I/usr/local/opt/jpeg-turbo/include
16
+
14
17
  == SYNOPSIS:
15
18
 
16
19
  require 'oil'
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.3') do |s|
9
+ s = Gem::Specification.new('oil', '0.2.0') 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.'
@@ -19,8 +19,6 @@ s = Gem::Specification.new('oil', '0.1.3') do |s|
19
19
  lib/oil.rb
20
20
  ext/oil/resample.c
21
21
  ext/oil/resample.h
22
- ext/oil/yscaler.c
23
- ext/oil/yscaler.h
24
22
  ext/oil/jpeg.c
25
23
  ext/oil/png.c
26
24
  ext/oil/oil.c
@@ -1,6 +1,6 @@
1
1
  require 'mkmf'
2
2
 
3
- $CFLAGS += " -O3 -ffast-math -march=native"
3
+ $CFLAGS += " -O3 -march=native"
4
4
 
5
5
  unless have_header('jpeglib.h')
6
6
  abort "libjpeg headers were not found."
@@ -2,7 +2,6 @@
2
2
  #include <ruby/st.h>
3
3
  #include <jpeglib.h>
4
4
  #include "resample.h"
5
- #include "yscaler.h"
6
5
 
7
6
  #define READ_SIZE 1024
8
7
  #define WRITE_SIZE 1024
@@ -30,6 +29,10 @@ static ID j_color_space_to_id(J_COLOR_SPACE cs)
30
29
  return id_CMYK;
31
30
  case JCS_YCCK:
32
31
  return id_YCCK;
32
+ #ifdef JCS_EXTENSIONS
33
+ case JCS_EXT_RGBX:
34
+ return id_RGBX;
35
+ #endif
33
36
  default:
34
37
  return id_UNKNOWN;
35
38
  }
@@ -50,7 +53,11 @@ static J_COLOR_SPACE sym_to_j_color_space(VALUE sym)
50
53
  } else if (rb == id_YCCK) {
51
54
  return JCS_YCCK;
52
55
  } else if (rb == id_RGBX) {
56
+ #ifdef JCS_EXTENSIONS
53
57
  return JCS_EXT_RGBX;
58
+ #else
59
+ return JCS_RGB;
60
+ #endif
54
61
  }
55
62
  rb_raise(rb_eRuntimeError, "Color space not recognized.");
56
63
  }
@@ -103,37 +110,37 @@ static VALUE marker_code_to_sym(int marker_code)
103
110
  case JPEG_COM:
104
111
  return ID2SYM(id_COM);
105
112
  case JPEG_APP0:
106
- return ID2SYM(id_APP0);
113
+ return ID2SYM(id_APP0);
107
114
  case JPEG_APP0 + 1:
108
- return ID2SYM(id_APP1);
115
+ return ID2SYM(id_APP1);
109
116
  case JPEG_APP0 + 2:
110
- return ID2SYM(id_APP2);
117
+ return ID2SYM(id_APP2);
111
118
  case JPEG_APP0 + 3:
112
- return ID2SYM(id_APP3);
119
+ return ID2SYM(id_APP3);
113
120
  case JPEG_APP0 + 4:
114
- return ID2SYM(id_APP4);
121
+ return ID2SYM(id_APP4);
115
122
  case JPEG_APP0 + 5:
116
- return ID2SYM(id_APP5);
123
+ return ID2SYM(id_APP5);
117
124
  case JPEG_APP0 + 6:
118
- return ID2SYM(id_APP6);
125
+ return ID2SYM(id_APP6);
119
126
  case JPEG_APP0 + 7:
120
- return ID2SYM(id_APP7);
127
+ return ID2SYM(id_APP7);
121
128
  case JPEG_APP0 + 8:
122
- return ID2SYM(id_APP8);
129
+ return ID2SYM(id_APP8);
123
130
  case JPEG_APP0 + 9:
124
- return ID2SYM(id_APP9);
131
+ return ID2SYM(id_APP9);
125
132
  case JPEG_APP0 + 10:
126
- return ID2SYM(id_APP10);
133
+ return ID2SYM(id_APP10);
127
134
  case JPEG_APP0 + 11:
128
- return ID2SYM(id_APP11);
135
+ return ID2SYM(id_APP11);
129
136
  case JPEG_APP0 + 12:
130
- return ID2SYM(id_APP12);
137
+ return ID2SYM(id_APP12);
131
138
  case JPEG_APP0 + 13:
132
- return ID2SYM(id_APP13);
139
+ return ID2SYM(id_APP13);
133
140
  case JPEG_APP0 + 14:
134
- return ID2SYM(id_APP14);
141
+ return ID2SYM(id_APP14);
135
142
  case JPEG_APP0 + 15:
136
- return ID2SYM(id_APP15);
143
+ return ID2SYM(id_APP15);
137
144
  }
138
145
  rb_raise(rb_eRuntimeError, "Marker code not recognized.");
139
146
  }
@@ -274,7 +281,7 @@ static void raise_if_locked(struct readerdata *reader)
274
281
  *
275
282
  * io = File.open("image.jpg", "r")
276
283
  * reader = Oil::JPEGReader.new(io)
277
- *
284
+ *
278
285
  * io = File.open("image.jpg", "r")
279
286
  * reader = Oil::JPEGReader.new(io, [:APP1, :APP2])
280
287
  */
@@ -747,7 +754,8 @@ struct write_jpeg_args {
747
754
  struct writerdata *writer;
748
755
  unsigned char *inwidthbuf;
749
756
  unsigned char *outwidthbuf;
750
- struct yscaler *ys;
757
+ struct yscaler ys;
758
+ struct preprocess_xscaler xs;
751
759
  };
752
760
 
753
761
  static VALUE each2(struct write_jpeg_args *args)
@@ -755,24 +763,18 @@ static VALUE each2(struct write_jpeg_args *args)
755
763
  struct writerdata *writer;
756
764
  struct jpeg_decompress_struct *dinfo;
757
765
  struct jpeg_compress_struct *cinfo;
758
- unsigned char *inwidthbuf, *outwidthbuf, *yinbuf;
759
- struct yscaler *ys;
766
+ unsigned char *outwidthbuf, *xinbuf;
767
+ uint16_t *yinbuf;
760
768
  uint32_t i, scalex, scaley;
761
769
  VALUE quality, markers;
762
- int cmp, opts;
763
770
 
764
771
  writer = args->writer;
765
- inwidthbuf = args->inwidthbuf;
766
772
  outwidthbuf = args->outwidthbuf;
767
- ys = args->ys;
768
773
  dinfo = &args->reader->dinfo;
769
774
  cinfo = &writer->cinfo;
770
775
  scalex = args->reader->scale_width;
771
776
  scaley = args->reader->scale_height;
772
777
 
773
- cmp = dinfo->output_components;
774
- opts = dinfo->out_color_space == JCS_EXT_RGBX ? OIL_FILLER : 0;
775
-
776
778
  writer->mgr.init_destination = init_destination;
777
779
  writer->mgr.empty_output_buffer = empty_output_buffer;
778
780
  writer->mgr.term_destination = term_destination;
@@ -780,7 +782,9 @@ static VALUE each2(struct write_jpeg_args *args)
780
782
  writer->cinfo.image_width = scalex;
781
783
  writer->cinfo.image_height = scaley;
782
784
  writer->cinfo.in_color_space = dinfo->out_color_space;
783
- writer->cinfo.input_components = cmp;
785
+ writer->cinfo.input_components = dinfo->output_components;
786
+
787
+ xinbuf = args->inwidthbuf;
784
788
 
785
789
  jpeg_set_defaults(cinfo);
786
790
 
@@ -803,11 +807,11 @@ static VALUE each2(struct write_jpeg_args *args)
803
807
  }
804
808
 
805
809
  for(i=0; i<scaley; i++) {
806
- while ((yinbuf = yscaler_next(ys))) {
807
- jpeg_read_scanlines(dinfo, (JSAMPARRAY)&inwidthbuf, 1);
808
- xscale(inwidthbuf, dinfo->output_width, yinbuf, scalex, cmp, opts);
810
+ while ((yinbuf = yscaler_next(&args->ys))) {
811
+ jpeg_read_scanlines(dinfo, (JSAMPARRAY)&xinbuf, 1);
812
+ preprocess_xscaler_scale(&args->xs, xinbuf, yinbuf);
809
813
  }
810
- yscaler_scale(ys, outwidthbuf, scalex, cmp, opts);
814
+ yscaler_scale(&args->ys, outwidthbuf, i);
811
815
  jpeg_write_scanlines(cinfo, (JSAMPARRAY)&outwidthbuf, 1);
812
816
  }
813
817
 
@@ -816,6 +820,24 @@ static VALUE each2(struct write_jpeg_args *args)
816
820
  return Qnil;
817
821
  }
818
822
 
823
+ static enum oil_colorspace jpeg_cs_to_oil(J_COLOR_SPACE cs)
824
+ {
825
+ switch(cs) {
826
+ case JCS_GRAYSCALE:
827
+ return OIL_CS_G;
828
+ case JCS_RGB:
829
+ return OIL_CS_RGB;
830
+ case JCS_CMYK:
831
+ return OIL_CS_CMYK;
832
+ #ifdef JCS_EXTENSIONS
833
+ case JCS_EXT_RGBX:
834
+ return OIL_CS_RGBX;
835
+ #endif
836
+ default:
837
+ rb_raise(rb_eRuntimeError, "Color space not recognized.");
838
+ }
839
+ }
840
+
819
841
  /*
820
842
  * call-seq:
821
843
  * reader.each(opts, &block) -> self
@@ -834,11 +856,12 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
834
856
  {
835
857
  struct readerdata *reader;
836
858
  struct writerdata writer;
837
- int cmp, state;
859
+ int state;
838
860
  struct write_jpeg_args args;
839
861
  unsigned char *inwidthbuf, *outwidthbuf;
840
- struct yscaler ys;
862
+ uint32_t width_in, width_out;
841
863
  VALUE opts;
864
+ enum oil_colorspace cs;
842
865
 
843
866
  rb_scan_args(argc, argv, "01", &opts);
844
867
 
@@ -854,24 +877,27 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
854
877
  writer.cinfo.err = &reader->jerr;
855
878
  jpeg_create_compress(&writer.cinfo);
856
879
 
857
- cmp = reader->dinfo.output_components;
858
- inwidthbuf = malloc(reader->dinfo.output_width * cmp);
859
- outwidthbuf = malloc(reader->scale_width * cmp);
860
- yscaler_init(&ys, reader->dinfo.output_height, reader->scale_height,
861
- reader->scale_width * cmp);
880
+ cs = jpeg_cs_to_oil(reader->dinfo.out_color_space);
881
+ width_in = reader->dinfo.output_width;
882
+ width_out = reader->scale_width;
883
+ inwidthbuf = malloc(width_in * CS_TO_CMP(cs));
884
+ outwidthbuf = malloc(width_out * CS_TO_CMP(cs));
885
+ preprocess_xscaler_init(&args.xs, width_in, width_out, cs);
886
+ yscaler_init(&args.ys, reader->dinfo.output_height, reader->scale_height,
887
+ width_out, cs);
862
888
 
863
889
  args.reader = reader;
864
890
  args.opts = opts;
865
891
  args.writer = &writer;
866
892
  args.inwidthbuf = inwidthbuf;
867
893
  args.outwidthbuf = outwidthbuf;
868
- args.ys = &ys;
869
894
  reader->locked = 1;
870
895
  rb_protect((VALUE(*)(VALUE))each2, (VALUE)&args, &state);
871
896
 
872
- yscaler_free(&ys);
873
- free(inwidthbuf);
897
+ yscaler_free(&args.ys);
898
+ preprocess_xscaler_free(&args.xs);
874
899
  free(outwidthbuf);
900
+ free(inwidthbuf);
875
901
  jpeg_destroy_compress(&writer.cinfo);
876
902
 
877
903
  if (state) {
@@ -1,10 +1,27 @@
1
1
  #include <ruby.h>
2
+ #include "resample.h"
3
+
4
+ static VALUE rb_fix_ratio(VALUE self, VALUE src_w, VALUE src_h, VALUE out_w, VALUE out_h)
5
+ {
6
+ uint32_t out_width, out_height;
7
+ VALUE ret;
8
+ out_width = NUM2INT(out_w);
9
+ out_height = NUM2INT(out_h);
10
+ fix_ratio(NUM2INT(src_w), NUM2INT(src_h), &out_width, &out_height);
11
+ ret = rb_ary_new2(2);
12
+ rb_ary_push(ret, INT2FIX(out_width));
13
+ rb_ary_push(ret, INT2FIX(out_height));
14
+ return ret;
15
+ }
2
16
 
3
17
  void Init_jpeg();
4
18
  void Init_png();
5
19
 
6
20
  void Init_oil()
7
21
  {
8
- Init_jpeg();
9
- Init_png();
22
+ VALUE mOil;
23
+ mOil = rb_const_get(rb_cObject, rb_intern("Oil"));
24
+ rb_define_singleton_method(mOil, "fix_ratio", rb_fix_ratio, 4);
25
+ Init_jpeg();
26
+ Init_png();
10
27
  }
@@ -1,7 +1,6 @@
1
1
  #include <ruby.h>
2
2
  #include <png.h>
3
3
  #include "resample.h"
4
- #include "yscaler.h"
5
4
 
6
5
  static ID id_read;
7
6
 
@@ -215,34 +214,37 @@ struct each_args {
215
214
  unsigned char *outwidthbuf;
216
215
  unsigned char **scanlines;
217
216
  struct yscaler ys;
217
+ struct preprocess_xscaler xs;
218
218
  };
219
219
 
220
220
  static VALUE each_interlace(struct each_args *args)
221
221
  {
222
222
  struct readerdata *reader;
223
- unsigned char *inwidthbuf, *outwidthbuf;
224
- uint32_t i, width, height, scalex, scaley;
225
- int cmp;
223
+ unsigned char **scanlines, *outwidthbuf;
224
+ uint32_t i, n, scaley;
225
+ uint16_t *yinbuf;
226
+ struct yscaler *ys;
227
+ struct preprocess_xscaler *xs;
226
228
 
227
229
  reader = args->reader;
228
- inwidthbuf = args->inwidthbuf;
230
+ xs = &args->xs;
231
+ ys = &args->ys;
232
+ scanlines = args->scanlines;
229
233
  outwidthbuf = args->outwidthbuf;
230
- scalex = reader->scale_width;
231
234
  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
235
 
236
236
  png_write_info(args->wpng, args->winfo);
237
237
  png_read_image(args->reader->png, (png_bytepp)args->scanlines);
238
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);
239
+ n = 0;
240
+ for(i=0; i<scaley; i++) {
241
+ while ((yinbuf = yscaler_next(ys))) {
242
+ preprocess_xscaler_scale(xs, scanlines[n++], yinbuf);
243
+ }
244
+ yscaler_scale(ys, outwidthbuf, i);
244
245
  png_write_row(args->wpng, outwidthbuf);
245
246
  }
247
+
246
248
  png_write_end(args->wpng, args->winfo);
247
249
  return Qnil;
248
250
  }
@@ -250,28 +252,27 @@ static VALUE each_interlace(struct each_args *args)
250
252
  static VALUE each_interlace_none(struct each_args *args)
251
253
  {
252
254
  struct readerdata *reader;
253
- unsigned char *inwidthbuf, *outwidthbuf, *yinbuf;
255
+ unsigned char *inwidthbuf, *outwidthbuf;
256
+ uint16_t *yinbuf;
257
+ struct preprocess_xscaler *xs;
254
258
  struct yscaler *ys;
255
- uint32_t i, width, scalex, scaley;
256
- int cmp;
259
+ uint32_t i, scaley;
257
260
 
258
261
  reader = args->reader;
262
+ xs = &args->xs;
259
263
  inwidthbuf = args->inwidthbuf;
260
264
  outwidthbuf = args->outwidthbuf;
261
265
  ys = &args->ys;
262
- scalex = reader->scale_width;
263
266
  scaley = reader->scale_height;
264
- cmp = png_get_channels(reader->png, reader->info);
265
- width = png_get_image_width(reader->png, reader->info);
266
267
 
267
268
  png_write_info(args->wpng, args->winfo);
268
269
 
269
270
  for(i=0; i<scaley; i++) {
270
271
  while ((yinbuf = yscaler_next(ys))) {
271
272
  png_read_row(reader->png, inwidthbuf, NULL);
272
- xscale(inwidthbuf, width, yinbuf, scalex, cmp, 0);
273
+ preprocess_xscaler_scale(xs, inwidthbuf, yinbuf);
273
274
  }
274
- yscaler_scale(ys, outwidthbuf, scalex, cmp, 0);
275
+ yscaler_scale(ys, outwidthbuf, i);
275
276
  png_write_row(args->wpng, outwidthbuf);
276
277
  }
277
278
 
@@ -279,6 +280,21 @@ static VALUE each_interlace_none(struct each_args *args)
279
280
  return Qnil;
280
281
  }
281
282
 
283
+ static enum oil_colorspace png_cs_to_oil(png_byte cs)
284
+ {
285
+ switch(cs) {
286
+ case PNG_COLOR_TYPE_GRAY:
287
+ return OIL_CS_G;
288
+ case PNG_COLOR_TYPE_GA:
289
+ return OIL_CS_GA;
290
+ case PNG_COLOR_TYPE_RGB:
291
+ return OIL_CS_RGB;
292
+ case PNG_COLOR_TYPE_RGBA:
293
+ return OIL_CS_RGBA;
294
+ }
295
+ rb_raise(rb_eRuntimeError, "Color space not recognized.");
296
+ }
297
+
282
298
  /*
283
299
  * call-seq:
284
300
  * reader.each(opts, &block) -> self
@@ -301,10 +317,11 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
301
317
  VALUE opts;
302
318
  int cmp, state;
303
319
  struct each_args args;
304
- uint32_t i, height;
320
+ uint32_t i, height, width;
305
321
  png_byte ctype;
306
322
  unsigned char **scanlines;
307
323
  size_t row_bytes;
324
+ enum oil_colorspace cs;
308
325
 
309
326
  rb_scan_args(argc, argv, "01", &opts);
310
327
 
@@ -313,32 +330,35 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
313
330
  raise_if_locked(reader);
314
331
  reader->locked = 1;
315
332
 
333
+ cmp = png_get_channels(reader->png, reader->info);
334
+ ctype = png_get_color_type(reader->png, reader->info);
335
+ cs = png_cs_to_oil(ctype);
336
+
316
337
  wpng = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,
317
338
  (png_error_ptr)error, (png_error_ptr)warning);
318
339
  winfo = png_create_info_struct(wpng);
319
340
  png_set_write_fn(wpng, 0, write_data_fn, flush_data_fn);
320
341
 
321
- cmp = png_get_channels(reader->png, reader->info);
322
- ctype = png_get_color_type(reader->png, reader->info);
323
-
324
342
  png_set_IHDR(wpng, winfo, reader->scale_width, reader->scale_height, 8,
325
343
  ctype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
326
344
  PNG_FILTER_TYPE_DEFAULT);
327
345
 
346
+ width = png_get_image_width(reader->png, reader->info);
328
347
  height = png_get_image_height(reader->png, reader->info);
329
348
  row_bytes = png_get_rowbytes(reader->png, reader->info);
330
349
 
331
350
  args.reader = reader;
332
351
  args.wpng = wpng;
333
352
  args.winfo = winfo;
334
- args.inwidthbuf = malloc(row_bytes);
335
353
  args.outwidthbuf = malloc(reader->scale_width * cmp);
336
354
 
355
+ preprocess_xscaler_init(&args.xs, width, reader->scale_width, cs);
356
+ yscaler_init(&args.ys, height, reader->scale_height, reader->scale_width, cs);
357
+
337
358
  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);
359
+ args.inwidthbuf = malloc(width * cmp);
340
360
  rb_protect((VALUE(*)(VALUE))each_interlace_none, (VALUE)&args, &state);
341
- yscaler_free(&args.ys);
361
+ free(args.inwidthbuf);
342
362
  } else {
343
363
  scanlines = malloc(height * sizeof(unsigned char *));
344
364
  for (i=0; i<height; i++) {
@@ -354,7 +374,8 @@ static VALUE each(int argc, VALUE *argv, VALUE self)
354
374
  free(scanlines);
355
375
  }
356
376
 
357
- free(args.inwidthbuf);
377
+ yscaler_free(&args.ys);
378
+ preprocess_xscaler_free(&args.xs);
358
379
  free(args.outwidthbuf);
359
380
  png_destroy_write_struct(&wpng, &winfo);
360
381