libjpeg-ruby 0.8.0 → 0.9.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 +1 -1
- data/ext/jpeg/extconf.rb +11 -0
- data/ext/jpeg/jpeg.c +1297 -634
- data/lib/jpeg/version.rb +1 -1
- data/libjpeg-ruby.gemspec +3 -3
- metadata +15 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8bd107f31f10ef4251f056cfc06e2c16082b1d5e42b98a6b810385a171f92991
|
4
|
+
data.tar.gz: eef3261d6619e567a5b063ccd5c72468ab975b4fc80d693ebe49bc3531c76139
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8d4ce1bd5e96f70f26cc167282f1761c5085c0eb901df9c5b948d2ce6bd9aac8cb3006e4d17a28bbed1a7d6ef597dcbbb028529075839aca992ce2e5dd5e55a
|
7
|
+
data.tar.gz: 4e4f0fc6e9a9ec579e50ad00f6f5558caf1753f689e1a5aea8fe7fe11bb188863cbd77f1706591a14532d77be92316b2eb16b912a835ac80bf18ae74952deb57
|
data/README.md
CHANGED
@@ -50,7 +50,7 @@ IO.binwrite("test.bgr", raw)
|
|
50
50
|
| :expand_colormap | Booblean | T.B.D |
|
51
51
|
| :scale | Rational or Float | T.B.D |
|
52
52
|
| :dct_method | String or Symbol | T.B.D |
|
53
|
-
| :
|
53
|
+
| :with_exif_tags | Boolean | Specify whether to read Exif tag. When set to true, the content of Exif tag will included in the meta information. |
|
54
54
|
| :orientation | Boolean | Specify whether to parse Exif orientation. When set to true, apply orientation for decode result. |
|
55
55
|
|
56
56
|
#### supported output format
|
data/ext/jpeg/extconf.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'mkmf'
|
2
2
|
require 'optparse'
|
3
|
+
require 'rbconfig'
|
3
4
|
|
4
5
|
OptionParser.new { |opt|
|
5
6
|
opt.on('--with-jpeg-include=PATH', String) { |path|
|
@@ -16,4 +17,14 @@ OptionParser.new { |opt|
|
|
16
17
|
have_library( "jpeg")
|
17
18
|
have_header( "jpeglib.h")
|
18
19
|
|
20
|
+
RbConfig::CONFIG.instance_eval {
|
21
|
+
flag = false
|
22
|
+
|
23
|
+
if /gcc/ =~ self['CC']
|
24
|
+
flag = ['CFLAGS', 'CPPFLAGS'].any? {|s| /-D_FORTIFY_SOURCE/ =~ self[s]}
|
25
|
+
end
|
26
|
+
|
27
|
+
have_library( "ssp") if flag
|
28
|
+
}
|
29
|
+
|
19
30
|
create_makefile( "jpeg/jpeg")
|
data/ext/jpeg/jpeg.c
CHANGED
@@ -12,6 +12,7 @@
|
|
12
12
|
#include <jpeglib.h>
|
13
13
|
|
14
14
|
#include "ruby.h"
|
15
|
+
#include "ruby/version.h"
|
15
16
|
#include "ruby/encoding.h"
|
16
17
|
|
17
18
|
#define UNIT_LINES 10
|
@@ -23,19 +24,25 @@
|
|
23
24
|
#define DEFAULT_QUALITY 75
|
24
25
|
#define DEFAULT_INPUT_COLOR_SPACE JCS_YCbCr
|
25
26
|
#define DEFAULT_INPUT_COMPONENTS 2
|
26
|
-
#define
|
27
|
+
#define DEFAULT_ENCODE_FLAGS (0)
|
28
|
+
#define DEFAULT_DECODE_FLAGS (F_NEED_META)
|
27
29
|
|
28
30
|
#define F_NEED_META 0x00000001
|
29
31
|
#define F_EXPAND_COLORMAP 0x00000002
|
30
32
|
#define F_PARSE_EXIF 0x00000004
|
31
33
|
#define F_APPLY_ORIENTATION 0x00000008
|
32
34
|
#define F_DITHER 0x00000010
|
35
|
+
#define F_CREAT 0x00010000
|
36
|
+
#define F_START 0x00020000
|
33
37
|
|
34
38
|
#define SET_FLAG(ptr, msk) ((ptr)->flags |= (msk))
|
35
39
|
#define CLR_FLAG(ptr, msk) ((ptr)->flags &= ~(msk))
|
36
40
|
#define TEST_FLAG(ptr, msk) ((ptr)->flags & (msk))
|
37
41
|
#define TEST_FLAG_ALL(ptr, msk) (((ptr)->flags & (msk)) == (msk))
|
38
42
|
|
43
|
+
#define SET_DATA(ptr, dat) ((ptr)->data = (dat))
|
44
|
+
#define CLR_DATA(ptr) ((ptr)->data = Qnil)
|
45
|
+
|
39
46
|
#define FMT_YUV422 1
|
40
47
|
#define FMT_RGB565 2
|
41
48
|
#define FMT_GRAYSCALE 3
|
@@ -66,9 +73,9 @@
|
|
66
73
|
((ci)->out_color_components == 3)))
|
67
74
|
|
68
75
|
#define ALLOC_ARRAY() \
|
69
|
-
((JSAMPARRAY)
|
76
|
+
((JSAMPARRAY)malloc(sizeof(JSAMPROW) * UNIT_LINES))
|
70
77
|
#define ALLOC_ROWS(w,c) \
|
71
|
-
((JSAMPROW)
|
78
|
+
((JSAMPROW)malloc(sizeof(JSAMPLE) * (w) * (c) * UNIT_LINES))
|
72
79
|
|
73
80
|
#define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
|
74
81
|
#define EQ_INT(val,n) (FIX2INT(val) == n)
|
@@ -255,27 +262,46 @@ tag_entry_t tag_i14y[] = {
|
|
255
262
|
static const char* encoder_opts_keys[] = {
|
256
263
|
"pixel_format", // {str}
|
257
264
|
"quality", // {integer}
|
258
|
-
"scale", // {rational} or {float}
|
259
265
|
"dct_method", // {str}
|
260
|
-
"orientation"
|
266
|
+
"orientation", // {integer}
|
267
|
+
"stride", // {integer}
|
261
268
|
};
|
262
269
|
|
263
270
|
static ID encoder_opts_ids[N(encoder_opts_keys)];
|
264
271
|
|
265
272
|
typedef struct {
|
266
|
-
|
273
|
+
struct jpeg_error_mgr jerr;
|
274
|
+
|
275
|
+
char msg[JMSG_LENGTH_MAX+10];
|
276
|
+
jmp_buf jmpbuf;
|
277
|
+
} ext_error_t;
|
278
|
+
|
279
|
+
typedef struct {
|
280
|
+
int flags;
|
267
281
|
int width;
|
282
|
+
int stride;
|
268
283
|
int height;
|
269
|
-
|
270
284
|
int data_size;
|
285
|
+
|
286
|
+
int format;
|
287
|
+
int color_space;
|
288
|
+
int components;
|
289
|
+
int quality;
|
271
290
|
J_DCT_METHOD dct_method;
|
272
291
|
|
273
292
|
struct jpeg_compress_struct cinfo;
|
274
|
-
|
293
|
+
ext_error_t err_mgr;
|
275
294
|
|
276
295
|
JSAMPARRAY array;
|
277
296
|
JSAMPROW rows;
|
278
297
|
|
298
|
+
VALUE data;
|
299
|
+
|
300
|
+
struct {
|
301
|
+
unsigned char* mem;
|
302
|
+
unsigned long size;
|
303
|
+
} buf;
|
304
|
+
|
279
305
|
int orientation;
|
280
306
|
} jpeg_encode_t;
|
281
307
|
|
@@ -294,20 +320,12 @@ static const char* decoder_opts_keys[] = {
|
|
294
320
|
"expand_colormap", // {bool}
|
295
321
|
"scale", // {rational} or {float}
|
296
322
|
"dct_method", // {str}
|
297
|
-
"with_exif", // {bool}
|
298
323
|
"with_exif_tags", // {bool}
|
299
324
|
"orientation" // {bool}
|
300
325
|
};
|
301
326
|
|
302
327
|
static ID decoder_opts_ids[N(decoder_opts_keys)];
|
303
328
|
|
304
|
-
typedef struct {
|
305
|
-
struct jpeg_error_mgr jerr;
|
306
|
-
|
307
|
-
char msg[JMSG_LENGTH_MAX+10];
|
308
|
-
jmp_buf jmpbuf;
|
309
|
-
} ext_error_t;
|
310
|
-
|
311
329
|
typedef struct {
|
312
330
|
int flags;
|
313
331
|
int format;
|
@@ -332,12 +350,130 @@ typedef struct {
|
|
332
350
|
struct jpeg_decompress_struct cinfo;
|
333
351
|
ext_error_t err_mgr;
|
334
352
|
|
353
|
+
JSAMPARRAY array;
|
354
|
+
|
355
|
+
VALUE data;
|
356
|
+
|
335
357
|
struct {
|
336
358
|
int value;
|
337
359
|
VALUE buf;
|
338
360
|
} orientation;
|
339
361
|
} jpeg_decode_t;
|
340
362
|
|
363
|
+
#if 0
|
364
|
+
static VALUE
|
365
|
+
create_runtime_error(const char* fmt, ...)
|
366
|
+
{
|
367
|
+
VALUE ret;
|
368
|
+
va_list ap;
|
369
|
+
|
370
|
+
va_start(ap, fmt);
|
371
|
+
ret = rb_exc_new_str(rb_eRuntimeError, rb_vsprintf(fmt, ap));
|
372
|
+
va_end(ap);
|
373
|
+
|
374
|
+
return ret;
|
375
|
+
}
|
376
|
+
#endif
|
377
|
+
|
378
|
+
static VALUE
|
379
|
+
create_argument_error(const char* fmt, ...)
|
380
|
+
{
|
381
|
+
VALUE ret;
|
382
|
+
va_list ap;
|
383
|
+
|
384
|
+
va_start(ap, fmt);
|
385
|
+
ret = rb_exc_new_str(rb_eArgError, rb_vsprintf(fmt, ap));
|
386
|
+
va_end(ap);
|
387
|
+
|
388
|
+
return ret;
|
389
|
+
}
|
390
|
+
|
391
|
+
static VALUE
|
392
|
+
create_type_error(const char* fmt, ...)
|
393
|
+
{
|
394
|
+
VALUE ret;
|
395
|
+
va_list ap;
|
396
|
+
|
397
|
+
va_start(ap, fmt);
|
398
|
+
ret = rb_exc_new_str(rb_eTypeError, rb_vsprintf(fmt, ap));
|
399
|
+
va_end(ap);
|
400
|
+
|
401
|
+
return ret;
|
402
|
+
}
|
403
|
+
|
404
|
+
static VALUE
|
405
|
+
create_range_error(const char* fmt, ...)
|
406
|
+
{
|
407
|
+
VALUE ret;
|
408
|
+
va_list ap;
|
409
|
+
|
410
|
+
va_start(ap, fmt);
|
411
|
+
ret = rb_exc_new_str(rb_eRangeError, rb_vsprintf(fmt, ap));
|
412
|
+
va_end(ap);
|
413
|
+
|
414
|
+
return ret;
|
415
|
+
}
|
416
|
+
|
417
|
+
static VALUE
|
418
|
+
create_not_implement_error(const char* fmt, ...)
|
419
|
+
{
|
420
|
+
VALUE ret;
|
421
|
+
va_list ap;
|
422
|
+
|
423
|
+
va_start(ap, fmt);
|
424
|
+
ret = rb_exc_new_str(rb_eNotImpError, rb_vsprintf(fmt, ap));
|
425
|
+
va_end(ap);
|
426
|
+
|
427
|
+
return ret;
|
428
|
+
}
|
429
|
+
|
430
|
+
static VALUE
|
431
|
+
create_memory_error()
|
432
|
+
{
|
433
|
+
return rb_exc_new_str(rb_eRangeError, rb_str_new_cstr("no memory"));
|
434
|
+
}
|
435
|
+
|
436
|
+
static void
|
437
|
+
output_message(j_common_ptr cinfo)
|
438
|
+
{
|
439
|
+
ext_error_t* err;
|
440
|
+
|
441
|
+
err = (ext_error_t*)cinfo->err;
|
442
|
+
|
443
|
+
(*err->jerr.format_message)(cinfo, err->msg);
|
444
|
+
}
|
445
|
+
|
446
|
+
static void
|
447
|
+
emit_message(j_common_ptr cinfo, int msg_level)
|
448
|
+
{
|
449
|
+
ext_error_t* err;
|
450
|
+
|
451
|
+
if (msg_level < 0) {
|
452
|
+
err = (ext_error_t*)cinfo->err;
|
453
|
+
(*err->jerr.format_message)(cinfo, err->msg);
|
454
|
+
/*
|
455
|
+
* 以前はemit_messageが呼ばれるとエラー扱いしていたが、
|
456
|
+
* Logicoolの一部のモデルなどで問題が出るので無視する
|
457
|
+
* ようにした。
|
458
|
+
* また本来であれば、警告表示を行うべきでもあるが一部
|
459
|
+
* のモデルで大量にemitされる場合があるので表示しない
|
460
|
+
* ようにしている。
|
461
|
+
* 問題が発生した際は、最後のメッセージをオブジェクト
|
462
|
+
* のインスタンスとして持たすべき。
|
463
|
+
*/
|
464
|
+
// longjmp(err->jmpbuf, 1);
|
465
|
+
}
|
466
|
+
}
|
467
|
+
|
468
|
+
static void
|
469
|
+
error_exit(j_common_ptr cinfo)
|
470
|
+
{
|
471
|
+
ext_error_t* err;
|
472
|
+
|
473
|
+
err = (ext_error_t*)cinfo->err;
|
474
|
+
(*err->jerr.format_message)(cinfo, err->msg);
|
475
|
+
longjmp(err->jmpbuf, 1);
|
476
|
+
}
|
341
477
|
|
342
478
|
static VALUE
|
343
479
|
lookup_tag_symbol(tag_entry_t* tbl, size_t n, int tag)
|
@@ -380,40 +516,87 @@ lookup_tag_symbol(tag_entry_t* tbl, size_t n, int tag)
|
|
380
516
|
}
|
381
517
|
|
382
518
|
static void
|
383
|
-
|
519
|
+
rb_encoder_mark(void* _ptr)
|
384
520
|
{
|
385
|
-
|
521
|
+
jpeg_encode_t* ptr;
|
522
|
+
|
523
|
+
ptr = (jpeg_encode_t*)_ptr;
|
386
524
|
|
387
|
-
(
|
525
|
+
if (ptr->data != Qnil) {
|
526
|
+
rb_gc_mark(ptr->data);
|
527
|
+
}
|
388
528
|
}
|
389
529
|
|
390
530
|
static void
|
391
|
-
|
531
|
+
rb_encoder_free(void* _ptr)
|
392
532
|
{
|
393
|
-
|
533
|
+
jpeg_encode_t* ptr;
|
394
534
|
|
395
|
-
(*
|
535
|
+
ptr = (jpeg_encode_t*)_ptr;
|
396
536
|
|
397
|
-
|
398
|
-
|
399
|
-
}
|
537
|
+
if (ptr->array != NULL) {
|
538
|
+
free(ptr->array);
|
539
|
+
}
|
400
540
|
|
541
|
+
if (ptr->rows != NULL) {
|
542
|
+
free(ptr->rows);
|
543
|
+
}
|
401
544
|
|
402
|
-
|
403
|
-
|
545
|
+
if (ptr->buf.mem != NULL) {
|
546
|
+
free(ptr->buf.mem);
|
547
|
+
}
|
548
|
+
|
549
|
+
if (TEST_FLAG(ptr, F_CREAT)) {
|
550
|
+
jpeg_destroy_compress(&ptr->cinfo);
|
551
|
+
}
|
552
|
+
|
553
|
+
free(ptr);
|
554
|
+
}
|
555
|
+
|
556
|
+
static size_t
|
557
|
+
rb_encoder_size(const void* _ptr)
|
404
558
|
{
|
559
|
+
size_t ret;
|
405
560
|
jpeg_encode_t* ptr;
|
406
561
|
|
407
|
-
ptr
|
408
|
-
|
409
|
-
if (ptr->array != NULL) xfree(ptr->array);
|
410
|
-
if (ptr->rows != NULL) xfree(ptr->rows);
|
562
|
+
ptr = (jpeg_encode_t*)_ptr;
|
411
563
|
|
412
|
-
|
564
|
+
ret = sizeof(jpeg_encode_t);
|
565
|
+
ret += sizeof(JSAMPROW) * UNIT_LINES;
|
566
|
+
ret += sizeof(JSAMPLE) * ptr->stride * UNIT_LINES;
|
413
567
|
|
414
|
-
|
568
|
+
return ret;
|
415
569
|
}
|
416
570
|
|
571
|
+
#if RUBY_API_VERSION_CODE > 20600
|
572
|
+
static const rb_data_type_t jpeg_encoder_data_type = {
|
573
|
+
"libjpeg-ruby encoder object", // wrap_struct_name
|
574
|
+
{
|
575
|
+
rb_encoder_mark, // function.dmark
|
576
|
+
rb_encoder_free, // function.dfree
|
577
|
+
rb_encoder_size, // function.dsize
|
578
|
+
NULL, // function.dcompact
|
579
|
+
{NULL}, // function.reserved
|
580
|
+
},
|
581
|
+
NULL, // parent
|
582
|
+
NULL, // data
|
583
|
+
(VALUE)RUBY_TYPED_FREE_IMMEDIATELY // flags
|
584
|
+
};
|
585
|
+
#else /* RUBY_API_VERSION_CODE > 20600 */
|
586
|
+
static const rb_data_type_t jpeg_encoder_data_type = {
|
587
|
+
"libjpeg-ruby encoder object", // wrap_struct_name
|
588
|
+
{
|
589
|
+
rb_encoder_mark, // function.dmark
|
590
|
+
rb_encoder_free, // function.dfree
|
591
|
+
rb_encoder_size, // function.dsize
|
592
|
+
{NULL, NULL}, // function.reserved
|
593
|
+
},
|
594
|
+
NULL, // parent
|
595
|
+
NULL, // data
|
596
|
+
(VALUE)RUBY_TYPED_FREE_IMMEDIATELY // flags
|
597
|
+
};
|
598
|
+
#endif /* RUBY_API_VERSION_CODE > 20600 */
|
599
|
+
|
417
600
|
static VALUE
|
418
601
|
rb_encoder_alloc(VALUE self)
|
419
602
|
{
|
@@ -422,203 +605,367 @@ rb_encoder_alloc(VALUE self)
|
|
422
605
|
ptr = ALLOC(jpeg_encode_t);
|
423
606
|
memset(ptr, 0, sizeof(*ptr));
|
424
607
|
|
425
|
-
|
608
|
+
ptr->flags = DEFAULT_ENCODE_FLAGS;
|
609
|
+
|
610
|
+
return TypedData_Wrap_Struct(encoder_klass, &jpeg_encoder_data_type, ptr);
|
426
611
|
}
|
427
612
|
|
428
|
-
static
|
429
|
-
|
613
|
+
static VALUE
|
614
|
+
eval_encoder_pixel_format_opt(jpeg_encode_t* ptr, VALUE opt)
|
430
615
|
{
|
431
|
-
VALUE
|
616
|
+
VALUE ret;
|
432
617
|
int format;
|
433
618
|
int color_space;
|
434
619
|
int components;
|
435
|
-
int data_size;
|
436
|
-
int quality;
|
437
|
-
int scale_num;
|
438
|
-
int scale_denom;
|
439
|
-
int i;
|
440
620
|
|
441
|
-
|
442
|
-
* parse options
|
443
|
-
*/
|
444
|
-
rb_get_kwargs(opt, encoder_opts_ids, 0, N(encoder_opts_ids), opts);
|
621
|
+
ret = Qnil;
|
445
622
|
|
446
|
-
|
447
|
-
|
448
|
-
*/
|
449
|
-
if (opts[0] == Qundef||EQ_STR(opts[0], "YUV422")||EQ_STR(opts[0], "YUYV")) {
|
623
|
+
switch (TYPE(opt)) {
|
624
|
+
case T_UNDEF:
|
450
625
|
format = FMT_YUV422;
|
451
626
|
color_space = JCS_YCbCr;
|
452
627
|
components = 3;
|
453
|
-
|
628
|
+
break;
|
454
629
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
630
|
+
case T_STRING:
|
631
|
+
case T_SYMBOL:
|
632
|
+
if (EQ_STR(opt, "YUV422") || EQ_STR(opt, "YUYV")) {
|
633
|
+
format = FMT_YUV422;
|
634
|
+
color_space = JCS_YCbCr;
|
635
|
+
components = 3;
|
460
636
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
data_size = (wd * ht * 3);
|
637
|
+
} else if (EQ_STR(opt, "RGB565")) {
|
638
|
+
format = FMT_RGB565;
|
639
|
+
color_space = JCS_RGB;
|
640
|
+
components = 3;
|
466
641
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
data_size = (wd * ht * 3);
|
642
|
+
} else if (EQ_STR(opt, "RGB") || EQ_STR(opt, "RGB24")) {
|
643
|
+
format = FMT_RGB;
|
644
|
+
color_space = JCS_RGB;
|
645
|
+
components = 3;
|
472
646
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
data_size = (wd * ht * 3);
|
647
|
+
} else if (EQ_STR(opt, "BGR") || EQ_STR(opt, "BGR24")) {
|
648
|
+
format = FMT_BGR;
|
649
|
+
color_space = JCS_EXT_BGR;
|
650
|
+
components = 3;
|
478
651
|
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
data_size = (wd * ht * 4);
|
652
|
+
} else if (EQ_STR(opt, "YUV444") || EQ_STR(opt, "YCbCr")) {
|
653
|
+
format = FMT_YUV;
|
654
|
+
color_space = JCS_YCbCr;
|
655
|
+
components = 3;
|
484
656
|
|
657
|
+
} else if (EQ_STR(opt, "RGBX") || EQ_STR(opt, "RGB32")) {
|
658
|
+
format = FMT_RGB32;
|
659
|
+
color_space = JCS_EXT_RGBX;
|
660
|
+
components = 4;
|
485
661
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
data_size = (wd * ht * 4);
|
662
|
+
} else if (EQ_STR(opt, "BGRX") || EQ_STR(opt, "BGR32")) {
|
663
|
+
format = FMT_BGR32;
|
664
|
+
color_space = JCS_EXT_BGRX;
|
665
|
+
components = 4;
|
491
666
|
|
667
|
+
} else if (EQ_STR(opt, "GRAYSCALE")) {
|
668
|
+
format = FMT_GRAYSCALE;
|
669
|
+
color_space = JCS_GRAYSCALE;
|
670
|
+
components = 1;
|
492
671
|
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
data_size = (wd * ht);
|
672
|
+
} else {
|
673
|
+
ret = create_argument_error("unsupportd :pixel_format option value");
|
674
|
+
}
|
675
|
+
break;
|
498
676
|
|
499
|
-
|
500
|
-
|
677
|
+
default:
|
678
|
+
ret = create_type_error("unsupportd :pixel_format option type");
|
679
|
+
break;
|
501
680
|
}
|
502
681
|
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
} else {
|
510
|
-
if (TYPE(opts[1]) != T_FIXNUM) {
|
511
|
-
ARGUMENT_ERROR("Unsupportd :quality option value.");
|
682
|
+
if (!RTEST(ret)) {
|
683
|
+
ptr->format = format;
|
684
|
+
ptr->color_space = color_space;
|
685
|
+
ptr->components = components;
|
686
|
+
}
|
512
687
|
|
513
|
-
|
514
|
-
|
515
|
-
}
|
688
|
+
return ret;
|
689
|
+
}
|
516
690
|
|
517
|
-
|
518
|
-
|
691
|
+
static VALUE
|
692
|
+
eval_encoder_quality_opt(jpeg_encode_t* ptr, VALUE opt)
|
693
|
+
{
|
694
|
+
VALUE ret;
|
695
|
+
long quality;
|
519
696
|
|
520
|
-
|
521
|
-
ARGUMENT_ERROR(":quality value is to big.");
|
522
|
-
}
|
523
|
-
}
|
524
|
-
|
525
|
-
/*
|
526
|
-
* eval scale option
|
527
|
-
*/
|
528
|
-
(void)scale_num;
|
529
|
-
(void)scale_denom;
|
697
|
+
ret = Qnil;
|
530
698
|
|
531
|
-
switch (TYPE(
|
699
|
+
switch (TYPE(opt)) {
|
532
700
|
case T_UNDEF:
|
533
|
-
|
701
|
+
quality = DEFAULT_QUALITY;
|
534
702
|
break;
|
535
703
|
|
536
704
|
case T_FLOAT:
|
537
|
-
|
538
|
-
|
705
|
+
if (isnan(NUM2DBL(opt)) || isinf(NUM2DBL(opt))) {
|
706
|
+
ret = create_argument_error("unsupportd :quality option value");
|
707
|
+
|
708
|
+
} else if (NUM2DBL(opt) < 0.0) {
|
709
|
+
ret = create_range_error(":quality less than 0");
|
710
|
+
|
711
|
+
} else if (NUM2DBL(opt) > 100.0) {
|
712
|
+
ret = create_range_error(":quality greater than 100");
|
713
|
+
|
714
|
+
} else {
|
715
|
+
quality = NUM2INT(opt);
|
716
|
+
}
|
539
717
|
break;
|
540
718
|
|
541
|
-
case
|
542
|
-
|
543
|
-
|
719
|
+
case T_FIXNUM:
|
720
|
+
if (FIX2LONG(opt) < 0) {
|
721
|
+
ret = create_range_error(":quality less than 0");
|
722
|
+
|
723
|
+
} if (FIX2LONG(opt) > 100) {
|
724
|
+
ret = create_range_error(":quality greater than 100");
|
725
|
+
|
726
|
+
} else {
|
727
|
+
quality = FIX2INT(opt);
|
728
|
+
}
|
544
729
|
break;
|
545
730
|
|
546
731
|
default:
|
547
|
-
|
732
|
+
ret = create_type_error("unsupportd :quality option type");
|
548
733
|
break;
|
549
734
|
}
|
550
735
|
|
551
|
-
|
552
|
-
* eval dct_method option
|
553
|
-
*/
|
554
|
-
if (opts[3] == Qundef || EQ_STR(opts[3], "FASTEST")) {
|
555
|
-
ptr->dct_method = JDCT_FASTEST;
|
556
|
-
|
557
|
-
} else if (EQ_STR(opts[3], "ISLOW")) {
|
558
|
-
ptr->dct_method = JDCT_ISLOW;
|
736
|
+
if (!RTEST(ret)) ptr->quality = quality;
|
559
737
|
|
560
|
-
|
561
|
-
|
738
|
+
return ret;
|
739
|
+
}
|
562
740
|
|
563
|
-
|
564
|
-
|
741
|
+
static VALUE
|
742
|
+
eval_encoder_dct_method_opt(jpeg_encode_t* ptr, VALUE opt)
|
743
|
+
{
|
744
|
+
VALUE ret;
|
745
|
+
int dct_method;
|
565
746
|
|
566
|
-
|
567
|
-
ARGUMENT_ERROR("Unsupportd :dct_method option value.");
|
568
|
-
}
|
747
|
+
ret = Qnil;
|
569
748
|
|
570
|
-
|
571
|
-
* eval orientation option
|
572
|
-
*/
|
573
|
-
switch (TYPE(opts[4])) {
|
749
|
+
switch (TYPE(opt)) {
|
574
750
|
case T_UNDEF:
|
575
|
-
|
751
|
+
dct_method = JDCT_FASTEST;
|
576
752
|
break;
|
577
753
|
|
578
|
-
case
|
579
|
-
|
580
|
-
if (
|
581
|
-
|
582
|
-
}
|
583
|
-
break;
|
754
|
+
case T_STRING:
|
755
|
+
case T_SYMBOL:
|
756
|
+
if (EQ_STR(opt, "FASTEST")) {
|
757
|
+
dct_method = JDCT_FASTEST;
|
584
758
|
|
585
|
-
|
586
|
-
|
587
|
-
}
|
759
|
+
} else if (EQ_STR(opt, "ISLOW")) {
|
760
|
+
dct_method = JDCT_ISLOW;
|
588
761
|
|
589
|
-
|
590
|
-
|
591
|
-
*/
|
592
|
-
ptr->format = format;
|
593
|
-
ptr->width = wd;
|
594
|
-
ptr->height = ht;
|
595
|
-
ptr->data_size = data_size;
|
596
|
-
ptr->array = ALLOC_ARRAY();
|
597
|
-
ptr->rows = ALLOC_ROWS(wd, components);
|
762
|
+
} else if (EQ_STR(opt, "IFAST")) {
|
763
|
+
dct_method = JDCT_IFAST;
|
598
764
|
|
599
|
-
|
600
|
-
|
765
|
+
} else if (EQ_STR(opt, "FLOAT")) {
|
766
|
+
dct_method = JDCT_FLOAT;
|
767
|
+
|
768
|
+
} else {
|
769
|
+
ret = create_argument_error("unsupportd :dct_method option value");
|
770
|
+
}
|
771
|
+
break;
|
772
|
+
|
773
|
+
default:
|
774
|
+
ret = create_type_error("unsupportd :dct_method option type");
|
775
|
+
break;
|
601
776
|
}
|
602
777
|
|
603
|
-
|
778
|
+
if (!RTEST(ret)) ptr->dct_method = dct_method;
|
604
779
|
|
605
|
-
|
606
|
-
|
607
|
-
|
780
|
+
return ret;
|
781
|
+
}
|
782
|
+
|
783
|
+
static VALUE
|
784
|
+
eval_encoder_orientation_opt(jpeg_encode_t* ptr, VALUE opt)
|
785
|
+
{
|
786
|
+
VALUE ret;
|
787
|
+
int orientation;
|
788
|
+
|
789
|
+
ret = Qnil;
|
790
|
+
|
791
|
+
switch (TYPE(opt)) {
|
792
|
+
case T_UNDEF:
|
793
|
+
orientation = 0;
|
794
|
+
break;
|
795
|
+
|
796
|
+
case T_FIXNUM:
|
797
|
+
orientation = FIX2INT(opt);
|
798
|
+
if (orientation < 1 || orientation > 8) {
|
799
|
+
ret = create_range_error(":orientation option ouf range");
|
800
|
+
}
|
801
|
+
break;
|
608
802
|
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
803
|
+
default:
|
804
|
+
ret = create_type_error("Unsupportd :orientation option type.");
|
805
|
+
break;
|
806
|
+
}
|
613
807
|
|
614
|
-
ptr->
|
615
|
-
ptr->cinfo.arith_code = TRUE;
|
616
|
-
ptr->cinfo.raw_data_in = FALSE;
|
617
|
-
ptr->cinfo.dct_method = ptr->dct_method;
|
808
|
+
if (!RTEST(ret)) ptr->orientation = orientation;
|
618
809
|
|
619
|
-
|
620
|
-
|
621
|
-
|
810
|
+
return ret;
|
811
|
+
}
|
812
|
+
|
813
|
+
static VALUE
|
814
|
+
eval_encoder_stride_opt(jpeg_encode_t* ptr, VALUE opt)
|
815
|
+
{
|
816
|
+
VALUE ret;
|
817
|
+
int stride;
|
818
|
+
|
819
|
+
ret = Qnil;
|
820
|
+
|
821
|
+
switch (TYPE(opt)) {
|
822
|
+
case T_UNDEF:
|
823
|
+
stride = ptr->width * ptr->components;
|
824
|
+
break;
|
825
|
+
|
826
|
+
case T_FIXNUM:
|
827
|
+
stride = FIX2INT(opt);
|
828
|
+
if (stride < (ptr->width * ptr->components)) {
|
829
|
+
ret = create_range_error(":stride too little");
|
830
|
+
}
|
831
|
+
break;
|
832
|
+
|
833
|
+
default:
|
834
|
+
ret = create_type_error("unsupportd :stride option type");
|
835
|
+
}
|
836
|
+
|
837
|
+
if (!RTEST(ret)) ptr->stride = stride;
|
838
|
+
|
839
|
+
return ret;
|
840
|
+
}
|
841
|
+
|
842
|
+
static VALUE
|
843
|
+
set_encoder_context(jpeg_encode_t* ptr, int wd, int ht, VALUE opt)
|
844
|
+
{
|
845
|
+
VALUE ret;
|
846
|
+
VALUE opts[N(encoder_opts_ids)];
|
847
|
+
JSAMPARRAY ary;
|
848
|
+
JSAMPROW rows;
|
849
|
+
|
850
|
+
int i;
|
851
|
+
|
852
|
+
/*
|
853
|
+
* initialize
|
854
|
+
*/
|
855
|
+
ret = Qnil;
|
856
|
+
ary = NULL;
|
857
|
+
rows = NULL;
|
858
|
+
|
859
|
+
/*
|
860
|
+
* argument check
|
861
|
+
*/
|
862
|
+
do {
|
863
|
+
if (wd <= 0) {
|
864
|
+
ret = create_range_error("image width less equal zero");
|
865
|
+
break;
|
866
|
+
}
|
867
|
+
|
868
|
+
if (ht <= 0) {
|
869
|
+
ret = create_range_error("image height less equal zero");
|
870
|
+
break;
|
871
|
+
}
|
872
|
+
} while (0);
|
873
|
+
|
874
|
+
/*
|
875
|
+
* parse options
|
876
|
+
*/
|
877
|
+
if (!RTEST(ret)) do {
|
878
|
+
rb_get_kwargs(opt, encoder_opts_ids, 0, N(encoder_opts_ids), opts);
|
879
|
+
|
880
|
+
// オプション評価で使用するので前もって設定しておく
|
881
|
+
ptr->width = wd;
|
882
|
+
ptr->height = ht;
|
883
|
+
|
884
|
+
ret = eval_encoder_pixel_format_opt(ptr, opts[0]);
|
885
|
+
if (RTEST(ret)) break;
|
886
|
+
|
887
|
+
ret = eval_encoder_quality_opt(ptr, opts[1]);
|
888
|
+
if (RTEST(ret)) break;
|
889
|
+
|
890
|
+
ret = eval_encoder_dct_method_opt(ptr, opts[2]);
|
891
|
+
if (RTEST(ret)) break;
|
892
|
+
|
893
|
+
ret = eval_encoder_orientation_opt(ptr, opts[3]);
|
894
|
+
if (RTEST(ret)) break;
|
895
|
+
|
896
|
+
ret = eval_encoder_stride_opt(ptr, opts[4]);
|
897
|
+
if (RTEST(ret)) break;
|
898
|
+
} while (0);
|
899
|
+
|
900
|
+
/*
|
901
|
+
* alloc memory
|
902
|
+
*/
|
903
|
+
if (!RTEST(ret)) do {
|
904
|
+
ary = ALLOC_ARRAY();
|
905
|
+
if (ary == NULL) {
|
906
|
+
ret = create_memory_error();
|
907
|
+
break;
|
908
|
+
}
|
909
|
+
|
910
|
+
rows = ALLOC_ROWS(ptr->width, ptr->components);
|
911
|
+
if (rows == NULL) {
|
912
|
+
ret = create_memory_error();
|
913
|
+
break;
|
914
|
+
}
|
915
|
+
} while (0);
|
916
|
+
|
917
|
+
/*
|
918
|
+
* set the rest context parameter
|
919
|
+
*/
|
920
|
+
if (!RTEST(ret)) {
|
921
|
+
ptr->err_mgr.jerr.output_message = output_message;
|
922
|
+
ptr->err_mgr.jerr.emit_message = emit_message;
|
923
|
+
ptr->err_mgr.jerr.error_exit = error_exit;
|
924
|
+
|
925
|
+
ptr->data_size = ptr->stride * ptr->height;
|
926
|
+
ptr->buf.mem = NULL;
|
927
|
+
ptr->buf.size = 0;
|
928
|
+
ptr->array = ary;
|
929
|
+
ptr->rows = rows;
|
930
|
+
ptr->data = Qnil;
|
931
|
+
|
932
|
+
for (i = 0; i < UNIT_LINES; i++) {
|
933
|
+
ptr->array[i] = ptr->rows + (i * ptr->width * ptr->components);
|
934
|
+
}
|
935
|
+
}
|
936
|
+
|
937
|
+
/*
|
938
|
+
* setup libjpeg
|
939
|
+
*/
|
940
|
+
if (!RTEST(ret)) {
|
941
|
+
jpeg_create_compress(&ptr->cinfo);
|
942
|
+
SET_FLAG(ptr, F_CREAT);
|
943
|
+
|
944
|
+
ptr->cinfo.err = jpeg_std_error(&ptr->err_mgr.jerr);
|
945
|
+
ptr->cinfo.image_width = ptr->width;
|
946
|
+
ptr->cinfo.image_height = ptr->height;
|
947
|
+
ptr->cinfo.in_color_space = ptr->color_space;
|
948
|
+
ptr->cinfo.input_components = ptr->components;
|
949
|
+
|
950
|
+
ptr->cinfo.optimize_coding = TRUE;
|
951
|
+
ptr->cinfo.arith_code = TRUE;
|
952
|
+
ptr->cinfo.raw_data_in = FALSE;
|
953
|
+
ptr->cinfo.dct_method = ptr->dct_method;
|
954
|
+
|
955
|
+
jpeg_set_defaults(&ptr->cinfo);
|
956
|
+
jpeg_set_quality(&ptr->cinfo, ptr->quality, TRUE);
|
957
|
+
jpeg_suppress_tables(&ptr->cinfo, TRUE);
|
958
|
+
}
|
959
|
+
|
960
|
+
/*
|
961
|
+
* post process
|
962
|
+
*/
|
963
|
+
if (RTEST(ret)) {
|
964
|
+
if (ary != NULL) free(ary);
|
965
|
+
if (rows != NULL) free(rows);
|
966
|
+
}
|
967
|
+
|
968
|
+
return ret;
|
622
969
|
}
|
623
970
|
|
624
971
|
/**
|
@@ -647,6 +994,7 @@ static VALUE
|
|
647
994
|
rb_encoder_initialize(int argc, VALUE *argv, VALUE self)
|
648
995
|
{
|
649
996
|
jpeg_encode_t* ptr;
|
997
|
+
VALUE exc;
|
650
998
|
VALUE wd;
|
651
999
|
VALUE ht;
|
652
1000
|
VALUE opt;
|
@@ -654,137 +1002,169 @@ rb_encoder_initialize(int argc, VALUE *argv, VALUE self)
|
|
654
1002
|
/*
|
655
1003
|
* initialize
|
656
1004
|
*/
|
657
|
-
|
1005
|
+
exc = Qnil;
|
1006
|
+
|
1007
|
+
TypedData_Get_Struct(self, jpeg_encode_t, &jpeg_encoder_data_type, ptr);
|
658
1008
|
|
659
1009
|
/*
|
660
1010
|
* parse arguments
|
661
1011
|
*/
|
662
|
-
rb_scan_args(argc, argv, "
|
1012
|
+
rb_scan_args(argc, argv, "2:", &wd, &ht, &opt);
|
1013
|
+
|
1014
|
+
/*
|
1015
|
+
* argument check
|
1016
|
+
*/
|
1017
|
+
do {
|
1018
|
+
if (TYPE(wd) != T_FIXNUM) {
|
1019
|
+
exc = create_argument_error("invalid width");
|
1020
|
+
break;
|
1021
|
+
}
|
663
1022
|
|
664
|
-
|
665
|
-
|
666
|
-
|
1023
|
+
if (TYPE(ht) != T_FIXNUM) {
|
1024
|
+
exc = create_argument_error("invalid height");
|
1025
|
+
break;
|
1026
|
+
}
|
1027
|
+
} while (0);
|
667
1028
|
|
668
1029
|
/*
|
669
1030
|
* set context
|
670
1031
|
*/
|
671
|
-
|
1032
|
+
if (!RTEST(exc)) {
|
1033
|
+
exc = set_encoder_context(ptr, FIX2INT(wd), FIX2INT(ht), opt);
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
/*
|
1037
|
+
* post process
|
1038
|
+
*/
|
1039
|
+
if (RTEST(exc)) rb_exc_raise(exc);
|
672
1040
|
|
673
1041
|
return Qtrue;
|
674
1042
|
}
|
675
1043
|
|
676
|
-
static
|
677
|
-
push_rows_yuv422(JSAMPROW
|
1044
|
+
static void
|
1045
|
+
push_rows_yuv422(JSAMPROW dst, int wd, int st, uint8_t* data, int nrow)
|
678
1046
|
{
|
679
|
-
|
1047
|
+
uint8_t* src;
|
680
1048
|
int i;
|
1049
|
+
int j;
|
681
1050
|
|
682
|
-
|
1051
|
+
for (i = 0; i < nrow; i++) {
|
1052
|
+
src = data;
|
683
1053
|
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
1054
|
+
for (j = 0; j < wd; j += 2) {
|
1055
|
+
dst[0] = src[0];
|
1056
|
+
dst[1] = src[1];
|
1057
|
+
dst[2] = src[3];
|
1058
|
+
dst[3] = src[2];
|
1059
|
+
dst[4] = src[1];
|
1060
|
+
dst[5] = src[3];
|
691
1061
|
|
692
|
-
|
693
|
-
|
694
|
-
|
1062
|
+
dst += 6;
|
1063
|
+
src += 4;
|
1064
|
+
}
|
695
1065
|
|
696
|
-
|
1066
|
+
data += st;
|
1067
|
+
}
|
697
1068
|
}
|
698
1069
|
|
699
|
-
static
|
700
|
-
push_rows_rgb565(JSAMPROW
|
1070
|
+
static void
|
1071
|
+
push_rows_rgb565(JSAMPROW dst, int wd, int st, uint8_t* data, int nrow)
|
701
1072
|
{
|
702
|
-
|
1073
|
+
uint8_t* src;
|
703
1074
|
int i;
|
1075
|
+
int j;
|
704
1076
|
|
705
|
-
|
1077
|
+
for (i = 0; i < nrow; i++) {
|
1078
|
+
src = data;
|
706
1079
|
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
1080
|
+
for (j = 0; j < wd; j++) {
|
1081
|
+
dst[0] = src[1] & 0xf8;
|
1082
|
+
dst[1] = ((src[1] << 5) & 0xe0) | ((src[0] >> 3) & 0x1c);
|
1083
|
+
dst[2] = (src[0] << 3) & 0xf8;
|
711
1084
|
|
712
|
-
|
713
|
-
|
714
|
-
|
1085
|
+
dst += 3;
|
1086
|
+
src += 2;
|
1087
|
+
}
|
715
1088
|
|
716
|
-
|
1089
|
+
data += st;
|
1090
|
+
}
|
717
1091
|
}
|
718
1092
|
|
719
|
-
static
|
720
|
-
push_rows_comp3(JSAMPROW rows, int wd, uint8_t* data, int nrow)
|
1093
|
+
static void
|
1094
|
+
push_rows_comp3(JSAMPROW rows, int wd, int st, uint8_t* data, int nrow)
|
721
1095
|
{
|
722
1096
|
int size;
|
1097
|
+
int i;
|
1098
|
+
|
1099
|
+
size = wd * 3;
|
723
1100
|
|
724
|
-
|
725
|
-
|
1101
|
+
for (i = 0; i < nrow; i++) {
|
1102
|
+
memcpy(rows, data, size);
|
726
1103
|
|
727
|
-
|
1104
|
+
rows += size;
|
1105
|
+
data += st;
|
1106
|
+
}
|
728
1107
|
}
|
729
1108
|
|
730
|
-
static
|
731
|
-
push_rows_comp4(JSAMPROW rows, int wd, uint8_t* data, int nrow)
|
1109
|
+
static void
|
1110
|
+
push_rows_comp4(JSAMPROW rows, int wd, int st, uint8_t* data, int nrow)
|
732
1111
|
{
|
733
1112
|
int size;
|
1113
|
+
int i;
|
734
1114
|
|
735
|
-
size = wd *
|
736
|
-
memcpy(rows, data, size);
|
737
|
-
|
738
|
-
return size;
|
739
|
-
}
|
1115
|
+
size = wd * 4;
|
740
1116
|
|
1117
|
+
for (i = 0; i < nrow; i++) {
|
1118
|
+
memcpy(rows, data, size);
|
741
1119
|
|
1120
|
+
rows += size;
|
1121
|
+
data += st;
|
1122
|
+
}
|
1123
|
+
}
|
742
1124
|
|
743
|
-
static
|
744
|
-
push_rows_grayscale(JSAMPROW rows, int wd, uint8_t* data, int nrow)
|
1125
|
+
static void
|
1126
|
+
push_rows_grayscale(JSAMPROW rows, int wd, int st, uint8_t* data, int nrow)
|
745
1127
|
{
|
746
|
-
int
|
1128
|
+
int i;
|
747
1129
|
|
748
|
-
|
749
|
-
|
1130
|
+
for (i = 0; i < nrow; i++) {
|
1131
|
+
memcpy(rows, data, wd);
|
750
1132
|
|
751
|
-
|
1133
|
+
rows += wd;
|
1134
|
+
data += st;
|
1135
|
+
}
|
752
1136
|
}
|
753
1137
|
|
754
|
-
static
|
1138
|
+
static void
|
755
1139
|
push_rows(jpeg_encode_t* ptr, uint8_t* data, int nrow)
|
756
1140
|
{
|
757
|
-
int ret;
|
758
|
-
|
759
1141
|
switch (ptr->format) {
|
760
1142
|
case FMT_YUV422:
|
761
|
-
|
1143
|
+
push_rows_yuv422(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
762
1144
|
break;
|
763
1145
|
|
764
1146
|
case FMT_RGB565:
|
765
|
-
|
1147
|
+
push_rows_rgb565(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
766
1148
|
break;
|
767
1149
|
|
768
1150
|
case FMT_YUV:
|
769
1151
|
case FMT_RGB:
|
770
1152
|
case FMT_BGR:
|
771
|
-
|
1153
|
+
push_rows_comp3(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
772
1154
|
break;
|
773
1155
|
|
774
1156
|
case FMT_RGB32:
|
775
1157
|
case FMT_BGR32:
|
776
|
-
|
1158
|
+
push_rows_comp4(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
777
1159
|
break;
|
778
1160
|
|
779
1161
|
case FMT_GRAYSCALE:
|
780
|
-
|
1162
|
+
push_rows_grayscale(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
781
1163
|
break;
|
782
1164
|
|
783
1165
|
default:
|
784
1166
|
RUNTIME_ERROR("Really?");
|
785
1167
|
}
|
786
|
-
|
787
|
-
return ret;
|
788
1168
|
}
|
789
1169
|
|
790
1170
|
static void
|
@@ -816,46 +1196,58 @@ put_exif_tags(jpeg_encode_t* ptr)
|
|
816
1196
|
}
|
817
1197
|
|
818
1198
|
static VALUE
|
819
|
-
do_encode(
|
1199
|
+
do_encode(VALUE _ptr)
|
820
1200
|
{
|
821
1201
|
VALUE ret;
|
822
|
-
|
823
|
-
|
824
|
-
unsigned long buf_size;
|
1202
|
+
jpeg_encode_t* ptr;
|
1203
|
+
uint8_t* data;
|
825
1204
|
int nrow;
|
826
1205
|
|
827
|
-
|
828
|
-
|
829
|
-
|
1206
|
+
/*
|
1207
|
+
* initialize
|
1208
|
+
*/
|
1209
|
+
ret = Qnil;
|
1210
|
+
ptr = (jpeg_encode_t*)_ptr;
|
1211
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
830
1212
|
|
831
|
-
|
1213
|
+
/*
|
1214
|
+
* do encode
|
1215
|
+
*/
|
1216
|
+
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
1217
|
+
/*
|
1218
|
+
* when error occurred
|
1219
|
+
*/
|
1220
|
+
rb_raise(encerr_klass, "%s", ptr->err_mgr.msg);
|
832
1221
|
|
833
|
-
|
834
|
-
|
835
|
-
|
1222
|
+
} else {
|
1223
|
+
/*
|
1224
|
+
* normal path
|
1225
|
+
*/
|
1226
|
+
jpeg_start_compress(&ptr->cinfo, TRUE);
|
1227
|
+
SET_FLAG(ptr, F_START);
|
836
1228
|
|
837
|
-
|
838
|
-
|
839
|
-
|
1229
|
+
if (ptr->orientation != 0) {
|
1230
|
+
put_exif_tags(ptr);
|
1231
|
+
}
|
840
1232
|
|
841
|
-
|
842
|
-
|
843
|
-
|
1233
|
+
while (ptr->cinfo.next_scanline < ptr->cinfo.image_height) {
|
1234
|
+
nrow = ptr->cinfo.image_height - ptr->cinfo.next_scanline;
|
1235
|
+
if (nrow > UNIT_LINES) nrow = UNIT_LINES;
|
844
1236
|
|
845
|
-
|
1237
|
+
push_rows(ptr, data, nrow);
|
846
1238
|
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
ret = rb_str_buf_new(buf_size);
|
851
|
-
rb_str_set_len(ret, buf_size);
|
1239
|
+
jpeg_write_scanlines(&ptr->cinfo, ptr->array, nrow);
|
1240
|
+
data += (ptr->stride * nrow);
|
1241
|
+
}
|
852
1242
|
|
853
|
-
|
1243
|
+
/*
|
1244
|
+
* build return data
|
1245
|
+
*/
|
1246
|
+
ret = rb_str_buf_new(ptr->buf.size);
|
1247
|
+
rb_str_set_len(ret, ptr->buf.size);
|
854
1248
|
|
855
|
-
|
856
|
-
|
857
|
-
*/
|
858
|
-
free(buf);
|
1249
|
+
memcpy(RSTRING_PTR(ret), ptr->buf.mem, ptr->buf.size);
|
1250
|
+
}
|
859
1251
|
|
860
1252
|
return ret;
|
861
1253
|
}
|
@@ -873,12 +1265,16 @@ static VALUE
|
|
873
1265
|
rb_encoder_encode(VALUE self, VALUE data)
|
874
1266
|
{
|
875
1267
|
VALUE ret;
|
1268
|
+
int state;
|
876
1269
|
jpeg_encode_t* ptr;
|
877
1270
|
|
878
1271
|
/*
|
879
1272
|
* initialize
|
880
1273
|
*/
|
881
|
-
|
1274
|
+
ret = Qnil;
|
1275
|
+
state = 0;
|
1276
|
+
|
1277
|
+
TypedData_Get_Struct(self, jpeg_encode_t, &jpeg_encoder_data_type, ptr);
|
882
1278
|
|
883
1279
|
/*
|
884
1280
|
* argument check
|
@@ -886,26 +1282,51 @@ rb_encoder_encode(VALUE self, VALUE data)
|
|
886
1282
|
Check_Type(data, T_STRING);
|
887
1283
|
|
888
1284
|
if (RSTRING_LEN(data) < ptr->data_size) {
|
889
|
-
ARGUMENT_ERROR("
|
1285
|
+
ARGUMENT_ERROR("image data is too short");
|
890
1286
|
}
|
891
1287
|
|
892
1288
|
if (RSTRING_LEN(data) > ptr->data_size) {
|
893
|
-
ARGUMENT_ERROR("
|
1289
|
+
ARGUMENT_ERROR("image data is too large");
|
1290
|
+
}
|
1291
|
+
|
1292
|
+
/*
|
1293
|
+
* alloc memory
|
1294
|
+
*/
|
1295
|
+
jpeg_mem_dest(&ptr->cinfo, &ptr->buf.mem, &ptr->buf.size);
|
1296
|
+
if (ptr->buf.mem == NULL) {
|
1297
|
+
RUNTIME_ERROR("jpeg_mem_dest() failed");
|
894
1298
|
}
|
895
1299
|
|
1300
|
+
/*
|
1301
|
+
* prepare
|
1302
|
+
*/
|
1303
|
+
SET_DATA(ptr, data);
|
1304
|
+
|
896
1305
|
/*
|
897
1306
|
* do encode
|
898
1307
|
*/
|
899
|
-
ret = do_encode(ptr,
|
1308
|
+
ret = rb_protect(do_encode, (VALUE)ptr, &state);
|
900
1309
|
|
901
|
-
|
902
|
-
|
1310
|
+
/*
|
1311
|
+
* post process
|
1312
|
+
*/
|
1313
|
+
if (TEST_FLAG(ptr, F_START)) {
|
1314
|
+
jpeg_finish_compress(&ptr->cinfo);
|
1315
|
+
CLR_FLAG(ptr, F_START);
|
1316
|
+
}
|
903
1317
|
|
904
|
-
|
905
|
-
|
906
|
-
{
|
907
|
-
|
908
|
-
|
1318
|
+
CLR_DATA(ptr);
|
1319
|
+
|
1320
|
+
if (ptr->buf.mem != NULL) {
|
1321
|
+
free(ptr->buf.mem);
|
1322
|
+
|
1323
|
+
ptr->buf.mem = NULL;
|
1324
|
+
ptr->buf.size = 0;
|
1325
|
+
}
|
1326
|
+
|
1327
|
+
if (state != 0) rb_jump_tag(state);
|
1328
|
+
|
1329
|
+
return ret;
|
909
1330
|
}
|
910
1331
|
|
911
1332
|
static void
|
@@ -918,50 +1339,72 @@ rb_decoder_mark(void* _ptr)
|
|
918
1339
|
if (ptr->orientation.buf != Qnil) {
|
919
1340
|
rb_gc_mark(ptr->orientation.buf);
|
920
1341
|
}
|
1342
|
+
|
1343
|
+
if (ptr->data != Qnil) {
|
1344
|
+
rb_gc_mark(ptr->data);
|
1345
|
+
}
|
921
1346
|
}
|
922
1347
|
|
923
1348
|
static void
|
924
|
-
|
1349
|
+
rb_decoder_free(void* _ptr)
|
925
1350
|
{
|
926
|
-
|
1351
|
+
jpeg_decode_t* ptr;
|
927
1352
|
|
928
|
-
|
1353
|
+
ptr = (jpeg_decode_t*)_ptr;
|
929
1354
|
|
930
|
-
(
|
931
|
-
|
1355
|
+
if (ptr->array != NULL) {
|
1356
|
+
free(ptr->array);
|
1357
|
+
}
|
932
1358
|
|
933
|
-
|
934
|
-
|
935
|
-
{
|
936
|
-
ext_error_t* err;
|
1359
|
+
ptr->orientation.buf = Qnil;
|
1360
|
+
ptr->data = Qnil;
|
937
1361
|
|
938
|
-
if (
|
939
|
-
|
940
|
-
(*err->jerr.format_message)(cinfo, err->msg);
|
941
|
-
/*
|
942
|
-
* 以前はemit_messageが呼ばれるとエラー扱いしていたが、
|
943
|
-
* Logicoolの一部のモデルなどで問題が出るので無視する
|
944
|
-
* ようにした。
|
945
|
-
* また本来であれば、警告表示を行うべきでもあるが一部
|
946
|
-
* のモデルで大量にemitされる場合があるので表示しない
|
947
|
-
* ようにしている。
|
948
|
-
* 問題が発生した際は、最後のメッセージをオブジェクト
|
949
|
-
* のインスタンスとして持たすべき。
|
950
|
-
*/
|
951
|
-
// longjmp(err->jmpbuf, 1);
|
1362
|
+
if (TEST_FLAG(ptr, F_CREAT)) {
|
1363
|
+
jpeg_destroy_decompress(&ptr->cinfo);
|
952
1364
|
}
|
1365
|
+
|
1366
|
+
free(ptr);
|
953
1367
|
}
|
954
1368
|
|
955
|
-
static
|
956
|
-
|
1369
|
+
static size_t
|
1370
|
+
rb_decoder_size(const void* ptr)
|
957
1371
|
{
|
958
|
-
|
1372
|
+
size_t ret;
|
959
1373
|
|
960
|
-
|
961
|
-
|
962
|
-
|
1374
|
+
ret = sizeof(jpeg_decode_t);
|
1375
|
+
|
1376
|
+
return ret;
|
963
1377
|
}
|
964
1378
|
|
1379
|
+
#if RUBY_API_VERSION_CODE > 20600
|
1380
|
+
static const rb_data_type_t jpeg_decoder_data_type = {
|
1381
|
+
"libjpeg-ruby decoder object", // wrap_struct_name
|
1382
|
+
{
|
1383
|
+
rb_decoder_mark, // function.dmark
|
1384
|
+
rb_decoder_free, // function.dfree
|
1385
|
+
rb_decoder_size, // function.dsize
|
1386
|
+
NULL, // function.dcompact
|
1387
|
+
{NULL}, // function.reserved
|
1388
|
+
},
|
1389
|
+
NULL, // parent
|
1390
|
+
NULL, // data
|
1391
|
+
(VALUE)RUBY_TYPED_FREE_IMMEDIATELY // flags
|
1392
|
+
};
|
1393
|
+
#else /* RUBY_API_VERSION_CODE > 20600 */
|
1394
|
+
static const rb_data_type_t jpeg_decoder_data_type = {
|
1395
|
+
"libjpeg-ruby decoder object", // wrap_struct_name
|
1396
|
+
{
|
1397
|
+
rb_decoder_mark, // function.dmark
|
1398
|
+
rb_decoder_free, // function.dfree
|
1399
|
+
rb_decoder_size, // function.dsize
|
1400
|
+
{NULL, NULL}, // function.reserved
|
1401
|
+
},
|
1402
|
+
NULL, // parent
|
1403
|
+
NULL, // data
|
1404
|
+
(VALUE)RUBY_TYPED_FREE_IMMEDIATELY // flags
|
1405
|
+
};
|
1406
|
+
#endif /* RUBY_API_VERSION_CODE > 20600 */
|
1407
|
+
|
965
1408
|
static VALUE
|
966
1409
|
rb_decoder_alloc(VALUE self)
|
967
1410
|
{
|
@@ -970,59 +1413,40 @@ rb_decoder_alloc(VALUE self)
|
|
970
1413
|
ptr = ALLOC(jpeg_decode_t);
|
971
1414
|
memset(ptr, 0, sizeof(*ptr));
|
972
1415
|
|
973
|
-
ptr->flags
|
974
|
-
ptr->format = FMT_RGB;
|
975
|
-
|
976
|
-
ptr->out_color_space = JCS_RGB;
|
977
|
-
|
978
|
-
ptr->scale_num = 1;
|
979
|
-
ptr->scale_denom = 1;
|
980
|
-
|
981
|
-
ptr->out_color_components = 3;
|
982
|
-
ptr->output_gamma = 0.0;
|
983
|
-
ptr->buffered_image = FALSE;
|
984
|
-
ptr->do_fancy_upsampling = FALSE;
|
985
|
-
ptr->do_block_smoothing = FALSE;
|
986
|
-
ptr->quantize_colors = FALSE;
|
987
|
-
ptr->dither_mode = JDITHER_NONE;
|
988
|
-
ptr->dct_method = JDCT_FASTEST;
|
989
|
-
ptr->desired_number_of_colors = 0;
|
990
|
-
ptr->enable_1pass_quant = FALSE;
|
991
|
-
ptr->enable_external_quant = FALSE;
|
992
|
-
ptr->enable_2pass_quant = FALSE;
|
993
|
-
|
994
|
-
ptr->orientation.value = 0;
|
995
|
-
ptr->orientation.buf = Qnil;
|
1416
|
+
ptr->flags = DEFAULT_DECODE_FLAGS;
|
996
1417
|
|
997
|
-
return
|
1418
|
+
return TypedData_Wrap_Struct(decoder_klass, &jpeg_decoder_data_type, ptr);
|
998
1419
|
}
|
999
1420
|
|
1000
|
-
static
|
1001
|
-
|
1421
|
+
static VALUE
|
1422
|
+
eval_decoder_pixel_format_opt(jpeg_decode_t* ptr, VALUE opt)
|
1002
1423
|
{
|
1424
|
+
VALUE ret;
|
1003
1425
|
int format;
|
1004
1426
|
int color_space;
|
1005
1427
|
int components;
|
1006
1428
|
|
1007
|
-
|
1429
|
+
ret = Qnil;
|
1430
|
+
|
1431
|
+
switch (TYPE(opt)) {
|
1432
|
+
case T_UNDEF:
|
1433
|
+
format = FMT_RGB;
|
1434
|
+
color_space = JCS_RGB;
|
1435
|
+
components = 3;
|
1436
|
+
break;
|
1437
|
+
|
1438
|
+
case T_STRING:
|
1439
|
+
case T_SYMBOL:
|
1008
1440
|
if(EQ_STR(opt, "RGB") || EQ_STR(opt, "RGB24")) {
|
1009
1441
|
format = FMT_RGB;
|
1010
1442
|
color_space = JCS_RGB;
|
1011
1443
|
components = 3;
|
1012
1444
|
|
1013
1445
|
} else if (EQ_STR(opt, "YUV422") || EQ_STR(opt, "YUYV")) {
|
1014
|
-
|
1015
|
-
color_space = JCS_YCbCr;
|
1016
|
-
components = 3;
|
1017
|
-
|
1018
|
-
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
1446
|
+
ret = create_not_implement_error( "not implemented colorspace");
|
1019
1447
|
|
1020
1448
|
} else if (EQ_STR(opt, "RGB565")) {
|
1021
|
-
|
1022
|
-
color_space = JCS_RGB;
|
1023
|
-
components = 3;
|
1024
|
-
|
1025
|
-
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
1449
|
+
ret = create_not_implement_error( "not implemented colorspace");
|
1026
1450
|
|
1027
1451
|
} else if (EQ_STR(opt, "GRAYSCALE")) {
|
1028
1452
|
format = FMT_GRAYSCALE;
|
@@ -1055,277 +1479,479 @@ eval_decoder_opt_pixel_format(jpeg_decode_t* ptr, VALUE opt)
|
|
1055
1479
|
components = 4;
|
1056
1480
|
|
1057
1481
|
} else {
|
1058
|
-
|
1482
|
+
ret = create_argument_error("unsupportd :pixel_format option value");
|
1059
1483
|
}
|
1484
|
+
break;
|
1060
1485
|
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1486
|
+
default:
|
1487
|
+
ret = create_type_error("unsupportd :pixel_format option type");
|
1488
|
+
break;
|
1064
1489
|
}
|
1490
|
+
|
1491
|
+
if (!RTEST(ret)) {
|
1492
|
+
ptr->format = format;
|
1493
|
+
ptr->out_color_space = color_space;
|
1494
|
+
ptr->out_color_components = components;
|
1495
|
+
}
|
1496
|
+
|
1497
|
+
return ret;
|
1065
1498
|
}
|
1066
1499
|
|
1067
|
-
static
|
1068
|
-
|
1500
|
+
static VALUE
|
1501
|
+
eval_decoder_output_gamma_opt(jpeg_decode_t* ptr, VALUE opt)
|
1069
1502
|
{
|
1503
|
+
VALUE ret;
|
1504
|
+
double gamma;
|
1505
|
+
|
1506
|
+
ret = Qnil;
|
1507
|
+
|
1070
1508
|
switch (TYPE(opt)) {
|
1071
1509
|
case T_UNDEF:
|
1072
|
-
|
1510
|
+
gamma = 0.0;
|
1073
1511
|
break;
|
1074
1512
|
|
1075
1513
|
case T_FIXNUM:
|
1076
1514
|
case T_FLOAT:
|
1077
|
-
|
1515
|
+
if (isnan(NUM2DBL(opt)) || isinf(NUM2DBL(opt))) {
|
1516
|
+
ret = create_argument_error("unsupported :output_gamma value");
|
1517
|
+
} else {
|
1518
|
+
gamma = NUM2DBL(opt);
|
1519
|
+
}
|
1078
1520
|
break;
|
1079
1521
|
|
1080
1522
|
default:
|
1081
|
-
|
1523
|
+
ret = create_type_error("unsupported :output_gamma type");
|
1082
1524
|
break;
|
1083
1525
|
}
|
1526
|
+
|
1527
|
+
if (!RTEST(ret)) ptr->output_gamma = gamma;
|
1528
|
+
|
1529
|
+
return ret;
|
1084
1530
|
}
|
1085
1531
|
|
1086
|
-
static
|
1087
|
-
|
1532
|
+
static VALUE
|
1533
|
+
eval_decoder_do_fancy_upsampling_opt(jpeg_decode_t* ptr, VALUE opt)
|
1088
1534
|
{
|
1089
|
-
if (opt != Qundef) {
|
1090
|
-
ptr->do_fancy_upsampling =
|
1535
|
+
if (opt != Qundef && RTEST(opt)) {
|
1536
|
+
ptr->do_fancy_upsampling = TRUE;
|
1537
|
+
} else {
|
1538
|
+
ptr->do_fancy_upsampling = FALSE;
|
1091
1539
|
}
|
1540
|
+
|
1541
|
+
return Qnil;
|
1092
1542
|
}
|
1093
1543
|
|
1094
|
-
static
|
1095
|
-
|
1544
|
+
static VALUE
|
1545
|
+
eval_decoder_do_smoothing_opt(jpeg_decode_t* ptr, VALUE opt)
|
1096
1546
|
{
|
1097
|
-
if (opt != Qundef) {
|
1098
|
-
ptr->do_block_smoothing =
|
1547
|
+
if (opt != Qundef && RTEST(opt)) {
|
1548
|
+
ptr->do_block_smoothing = TRUE;
|
1549
|
+
} else {
|
1550
|
+
ptr->do_block_smoothing = FALSE;
|
1099
1551
|
}
|
1552
|
+
|
1553
|
+
return Qnil;
|
1100
1554
|
}
|
1101
1555
|
|
1102
|
-
static
|
1103
|
-
|
1556
|
+
static VALUE
|
1557
|
+
eval_decoder_dither_opt( jpeg_decode_t* ptr, VALUE opt)
|
1104
1558
|
{
|
1105
|
-
VALUE
|
1106
|
-
VALUE
|
1107
|
-
|
1559
|
+
VALUE ret;
|
1560
|
+
VALUE tmp;
|
1561
|
+
int mode;
|
1562
|
+
int quant;
|
1563
|
+
int pass2;
|
1564
|
+
int ncol;
|
1108
1565
|
|
1109
|
-
|
1110
|
-
if (TYPE(opt) != T_ARRAY) {
|
1111
|
-
TYPE_ERROR("Unsupportd :dither option value.");
|
1112
|
-
}
|
1566
|
+
ret = Qnil;
|
1113
1567
|
|
1568
|
+
switch (TYPE(opt)) {
|
1569
|
+
case T_UNDEF:
|
1570
|
+
mode = JDITHER_NONE;
|
1571
|
+
quant = FALSE;
|
1572
|
+
ncol = 0;
|
1573
|
+
pass2 = FALSE;
|
1574
|
+
break;
|
1575
|
+
|
1576
|
+
case T_ARRAY:
|
1114
1577
|
if (RARRAY_LEN(opt) != 3) {
|
1115
|
-
|
1116
|
-
|
1578
|
+
ret = create_argument_error(":dither invalid size");
|
1579
|
+
|
1580
|
+
} else do {
|
1581
|
+
/*
|
1582
|
+
* dither mode
|
1583
|
+
*/
|
1584
|
+
tmp = rb_ary_entry(opt, 0);
|
1585
|
+
if (TYPE(tmp) != T_STRING && TYPE(tmp) != T_SYMBOL) {
|
1586
|
+
ret = create_type_error("unsupported dither mode type");
|
1587
|
+
break;
|
1117
1588
|
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
if (EQ_STR(dmode, "NONE")) {
|
1123
|
-
ptr->dither_mode = JDITHER_NONE;
|
1124
|
-
ptr->quantize_colors = FALSE;
|
1589
|
+
} else if (EQ_STR(tmp, "NONE")) {
|
1590
|
+
mode = JDITHER_NONE;
|
1591
|
+
quant = FALSE;
|
1125
1592
|
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1593
|
+
} else if(EQ_STR(tmp, "ORDERED")) {
|
1594
|
+
mode = JDITHER_ORDERED;
|
1595
|
+
quant = TRUE;
|
1129
1596
|
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1597
|
+
} else if(EQ_STR(tmp, "FS")) {
|
1598
|
+
mode = JDITHER_FS;
|
1599
|
+
quant = TRUE;
|
1133
1600
|
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1601
|
+
} else {
|
1602
|
+
ret = create_argument_error("dither mode is illeagal value.");
|
1603
|
+
break;
|
1604
|
+
}
|
1137
1605
|
|
1138
|
-
|
1606
|
+
/*
|
1607
|
+
* 2 pass flag
|
1608
|
+
*/
|
1609
|
+
pass2 = (RTEST(rb_ary_entry(opt, 1)))? TRUE: FALSE;
|
1610
|
+
|
1611
|
+
/*
|
1612
|
+
* number of color
|
1613
|
+
*/
|
1614
|
+
tmp = rb_ary_entry(opt, 2);
|
1615
|
+
if (TYPE(tmp) != T_FIXNUM) {
|
1616
|
+
ret = create_type_error("unsupported number of colors type");
|
1617
|
+
break;
|
1618
|
+
|
1619
|
+
} else if (FIX2LONG(tmp) < 8) {
|
1620
|
+
ret = create_range_error("number of colors less than 0");
|
1621
|
+
break;
|
1622
|
+
|
1623
|
+
} else if (FIX2LONG(tmp) > 256) {
|
1624
|
+
ret = create_range_error("number of colors greater than 256");
|
1625
|
+
break;
|
1139
1626
|
|
1140
|
-
|
1141
|
-
|
1627
|
+
} else {
|
1628
|
+
ncol = FIX2INT(tmp);
|
1629
|
+
}
|
1630
|
+
} while (0);
|
1631
|
+
break;
|
1142
1632
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1633
|
+
default:
|
1634
|
+
ret = create_type_error("unsupported :dither type");
|
1635
|
+
break;
|
1636
|
+
}
|
1147
1637
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1638
|
+
if (!RTEST(ret)) {
|
1639
|
+
ptr->dither_mode = mode;
|
1640
|
+
ptr->quantize_colors = quant;
|
1641
|
+
ptr->two_pass_quantize = pass2;
|
1642
|
+
ptr->desired_number_of_colors = ncol;
|
1151
1643
|
|
1152
|
-
SET_FLAG(ptr, F_DITHER);
|
1644
|
+
if (mode != JDITHER_NONE) SET_FLAG(ptr, F_DITHER);
|
1153
1645
|
}
|
1646
|
+
|
1647
|
+
return ret;
|
1154
1648
|
}
|
1155
1649
|
|
1156
1650
|
#if 0
|
1157
1651
|
static void
|
1158
|
-
|
1652
|
+
eval_decoder_use_1pass_quantizer_opt(jpeg_decode_t* ptr, VALUE opt)
|
1159
1653
|
{
|
1160
|
-
if (opt != Qundef) {
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
} else {
|
1165
|
-
ptr->enable_1pass_quant = FALSE;
|
1166
|
-
}
|
1654
|
+
if (opt != Qundef && RTEST(opt)) {
|
1655
|
+
ptr->enable_1pass_quant = TRUE;
|
1656
|
+
} else {
|
1657
|
+
ptr->enable_1pass_quant = FALSE;
|
1167
1658
|
}
|
1659
|
+
|
1660
|
+
return Qnil;
|
1168
1661
|
}
|
1169
1662
|
|
1170
|
-
static
|
1171
|
-
|
1663
|
+
static VALUE
|
1664
|
+
eval_decoder_use_external_colormap_opt(jpeg_decode_t* ptr, VALUE opt)
|
1172
1665
|
{
|
1173
|
-
if (opt != Qundef) {
|
1174
|
-
if (RTEST(opt)) {
|
1666
|
+
if (opt != Qundef && RTEST(opt)) {
|
1175
1667
|
ptr->enable_external_quant = TRUE;
|
1176
|
-
ptr->buffered_image = TRUE;
|
1177
1668
|
} else {
|
1178
1669
|
ptr->enable_external_quant = FALSE;
|
1179
1670
|
}
|
1180
1671
|
}
|
1672
|
+
|
1673
|
+
return Qnil;
|
1181
1674
|
}
|
1182
1675
|
|
1183
|
-
static
|
1184
|
-
|
1676
|
+
static VALUE
|
1677
|
+
eval_decoder_use_2pass_quantizer_opt(jpeg_decode_t* ptr, VALUE opt)
|
1185
1678
|
{
|
1186
|
-
if (opt != Qundef) {
|
1187
|
-
if (RTEST(opt)) {
|
1679
|
+
if (opt != Qundef && RTEST(opt)) {
|
1188
1680
|
ptr->enable_2pass_quant = TRUE;
|
1189
|
-
ptr->buffered_image = TRUE;
|
1190
1681
|
} else {
|
1191
1682
|
ptr->enable_2pass_quant = FALSE;
|
1192
1683
|
}
|
1193
1684
|
}
|
1685
|
+
|
1686
|
+
return Qnil;
|
1194
1687
|
}
|
1195
1688
|
#endif
|
1196
1689
|
|
1197
|
-
static
|
1198
|
-
|
1690
|
+
static VALUE
|
1691
|
+
eval_decoder_without_meta_opt(jpeg_decode_t* ptr, VALUE opt)
|
1199
1692
|
{
|
1200
|
-
if (opt != Qundef) {
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
SET_FLAG(ptr, F_NEED_META);
|
1205
|
-
}
|
1693
|
+
if (opt != Qundef && RTEST(opt)) {
|
1694
|
+
CLR_FLAG(ptr, F_NEED_META);
|
1695
|
+
} else {
|
1696
|
+
SET_FLAG(ptr, F_NEED_META);
|
1206
1697
|
}
|
1698
|
+
|
1699
|
+
return Qnil;
|
1207
1700
|
}
|
1208
1701
|
|
1209
|
-
static
|
1210
|
-
|
1702
|
+
static VALUE
|
1703
|
+
eval_decoder_expand_colormap_opt(jpeg_decode_t* ptr, VALUE opt)
|
1211
1704
|
{
|
1212
|
-
if (opt != Qundef) {
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
CLR_FLAG(ptr, F_EXPAND_COLORMAP);
|
1217
|
-
}
|
1705
|
+
if (opt != Qundef && RTEST(opt)) {
|
1706
|
+
SET_FLAG(ptr, F_EXPAND_COLORMAP);
|
1707
|
+
} else {
|
1708
|
+
CLR_FLAG(ptr, F_EXPAND_COLORMAP);
|
1218
1709
|
}
|
1710
|
+
|
1711
|
+
return Qnil;
|
1219
1712
|
}
|
1220
1713
|
|
1221
|
-
|
1222
|
-
|
1714
|
+
|
1715
|
+
static VALUE
|
1716
|
+
eval_decoder_scale_opt(jpeg_decode_t* ptr, VALUE opt)
|
1223
1717
|
{
|
1718
|
+
VALUE ret;
|
1719
|
+
int scale_num;
|
1720
|
+
int scale_denom;
|
1721
|
+
|
1722
|
+
ret = Qnil;
|
1723
|
+
|
1224
1724
|
switch (TYPE(opt)) {
|
1225
1725
|
case T_UNDEF:
|
1226
|
-
|
1726
|
+
scale_num = 1;
|
1727
|
+
scale_denom = 1;
|
1227
1728
|
break;
|
1228
1729
|
|
1229
|
-
case
|
1230
|
-
|
1231
|
-
|
1232
|
-
break;
|
1730
|
+
case T_FIXNUM:
|
1731
|
+
if (FIX2LONG(opt) <= 0) {
|
1732
|
+
ret = create_range_error(":scale less equal 0");
|
1233
1733
|
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1734
|
+
} else {
|
1735
|
+
scale_num = FIX2INT(opt) * 1000;
|
1736
|
+
scale_denom = 1000;
|
1737
|
+
}
|
1237
1738
|
break;
|
1238
1739
|
|
1239
|
-
case
|
1240
|
-
if (
|
1241
|
-
|
1740
|
+
case T_FLOAT:
|
1741
|
+
if (isnan(NUM2DBL(opt)) || isinf(NUM2DBL(opt))) {
|
1742
|
+
ret = create_argument_error("unsupportd :quality option value");
|
1743
|
+
|
1744
|
+
} else if (NUM2DBL(opt) <= 0.0) {
|
1745
|
+
ret = create_range_error(":scale less equal 0");
|
1746
|
+
|
1747
|
+
} else {
|
1748
|
+
scale_num = (int)(NUM2DBL(opt) * 1000.0);
|
1749
|
+
scale_denom = 1000;
|
1242
1750
|
}
|
1243
|
-
|
1244
|
-
|
1751
|
+
break;
|
1752
|
+
|
1753
|
+
case T_RATIONAL:
|
1754
|
+
scale_num = (int)FIX2LONG(rb_rational_num(opt));
|
1755
|
+
scale_denom = (int)FIX2LONG(rb_rational_den(opt));
|
1245
1756
|
break;
|
1246
1757
|
|
1247
1758
|
default:
|
1248
|
-
|
1759
|
+
ret = create_type_error("unsupportd :scale option type");
|
1249
1760
|
break;
|
1250
1761
|
}
|
1762
|
+
|
1763
|
+
if (!RTEST(ret)) {
|
1764
|
+
ptr->scale_num = scale_num;
|
1765
|
+
ptr->scale_denom = scale_denom;
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
return ret;
|
1251
1769
|
}
|
1252
1770
|
|
1253
|
-
static
|
1254
|
-
|
1771
|
+
static VALUE
|
1772
|
+
eval_decoder_dct_method_opt(jpeg_decode_t* ptr, VALUE opt)
|
1255
1773
|
{
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1774
|
+
VALUE ret;
|
1775
|
+
int dct_method;
|
1776
|
+
|
1777
|
+
ret = Qnil;
|
1778
|
+
|
1779
|
+
switch (TYPE(opt)) {
|
1780
|
+
case T_UNDEF:
|
1781
|
+
dct_method = JDCT_FASTEST;
|
1782
|
+
break;
|
1783
|
+
|
1784
|
+
case T_STRING:
|
1785
|
+
case T_SYMBOL:
|
1786
|
+
if (EQ_STR(opt, "FASTEST")) {
|
1787
|
+
dct_method = JDCT_FASTEST;
|
1788
|
+
|
1789
|
+
} else if (EQ_STR(opt, "ISLOW")) {
|
1790
|
+
dct_method = JDCT_ISLOW;
|
1259
1791
|
|
1260
1792
|
} else if (EQ_STR(opt, "IFAST")) {
|
1261
|
-
|
1793
|
+
dct_method = JDCT_IFAST;
|
1262
1794
|
|
1263
1795
|
} else if (EQ_STR(opt, "FLOAT")) {
|
1264
|
-
|
1265
|
-
|
1266
|
-
} else if (EQ_STR(opt, "FASTEST")) {
|
1267
|
-
ptr->dct_method = JDCT_FASTEST;
|
1796
|
+
dct_method = JDCT_FLOAT;
|
1268
1797
|
|
1269
1798
|
} else {
|
1270
|
-
|
1799
|
+
ret = create_argument_error("unsupportd :dct_method option value");
|
1271
1800
|
}
|
1801
|
+
break;
|
1802
|
+
|
1803
|
+
default:
|
1804
|
+
ret = create_type_error("unsupportd :dct_method option type");
|
1805
|
+
break;
|
1272
1806
|
}
|
1807
|
+
|
1808
|
+
if (!RTEST(ret)) ptr->dct_method = dct_method;
|
1809
|
+
|
1810
|
+
return ret;
|
1273
1811
|
}
|
1274
1812
|
|
1275
|
-
static
|
1276
|
-
|
1813
|
+
static VALUE
|
1814
|
+
eval_decoder_with_exif_tags_opt(jpeg_decode_t* ptr, VALUE opt)
|
1277
1815
|
{
|
1278
|
-
if (opt != Qundef) {
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
CLR_FLAG(ptr, F_PARSE_EXIF);
|
1283
|
-
}
|
1816
|
+
if (opt != Qundef && RTEST(opt)) {
|
1817
|
+
SET_FLAG(ptr, F_PARSE_EXIF);
|
1818
|
+
} else {
|
1819
|
+
CLR_FLAG(ptr, F_PARSE_EXIF);
|
1284
1820
|
}
|
1821
|
+
|
1822
|
+
return Qnil;
|
1285
1823
|
}
|
1286
1824
|
|
1287
|
-
static
|
1288
|
-
|
1825
|
+
static VALUE
|
1826
|
+
eval_decoder_orientation_opt(jpeg_decode_t* ptr, VALUE opt)
|
1289
1827
|
{
|
1290
|
-
if (opt != Qundef) {
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
CLR_FLAG(ptr, F_APPLY_ORIENTATION);
|
1295
|
-
}
|
1828
|
+
if (opt != Qundef && RTEST(opt)) {
|
1829
|
+
SET_FLAG(ptr, F_APPLY_ORIENTATION);
|
1830
|
+
} else {
|
1831
|
+
CLR_FLAG(ptr, F_APPLY_ORIENTATION);
|
1296
1832
|
}
|
1833
|
+
|
1834
|
+
return Qnil;
|
1297
1835
|
}
|
1298
1836
|
|
1299
|
-
static
|
1837
|
+
static VALUE
|
1300
1838
|
set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
1301
1839
|
{
|
1840
|
+
VALUE ret;
|
1302
1841
|
VALUE opts[N(decoder_opts_ids)];
|
1842
|
+
JSAMPARRAY ary;
|
1843
|
+
|
1844
|
+
/*
|
1845
|
+
* initialize
|
1846
|
+
*/
|
1847
|
+
ret = Qnil;
|
1848
|
+
ary = NULL;
|
1303
1849
|
|
1304
1850
|
/*
|
1305
1851
|
* parse options
|
1306
1852
|
*/
|
1307
|
-
|
1853
|
+
do {
|
1854
|
+
rb_get_kwargs(opt, decoder_opts_ids, 0, N(decoder_opts_ids), opts);
|
1855
|
+
|
1856
|
+
/*
|
1857
|
+
* set context
|
1858
|
+
*/
|
1859
|
+
ret = eval_decoder_pixel_format_opt(ptr, opts[0]);
|
1860
|
+
if (RTEST(ret)) break;
|
1861
|
+
|
1862
|
+
ret = eval_decoder_output_gamma_opt(ptr, opts[1]);
|
1863
|
+
if (RTEST(ret)) break;
|
1864
|
+
|
1865
|
+
ret = eval_decoder_do_fancy_upsampling_opt(ptr, opts[2]);
|
1866
|
+
if (RTEST(ret)) break;
|
1867
|
+
|
1868
|
+
ret = eval_decoder_do_smoothing_opt(ptr, opts[3]);
|
1869
|
+
if (RTEST(ret)) break;
|
1870
|
+
|
1871
|
+
ret = eval_decoder_dither_opt(ptr, opts[4]);
|
1872
|
+
if (RTEST(ret)) break;
|
1873
|
+
|
1874
|
+
#if 0
|
1875
|
+
ret = eval_decoder_use_1pass_quantizer_opt(ptr, opts[5]);
|
1876
|
+
if (RTEST(ret)) break;
|
1877
|
+
|
1878
|
+
ret = eval_decoder_use_external_colormap_opt(ptr, opts[6]);
|
1879
|
+
if (RTEST(ret)) break;
|
1880
|
+
|
1881
|
+
ret = eval_decoder_use_2pass_quantizer_opt(ptr, opts[7]);
|
1882
|
+
if (RTEST(ret)) break;
|
1883
|
+
#endif
|
1884
|
+
|
1885
|
+
ret = eval_decoder_without_meta_opt(ptr, opts[5]);
|
1886
|
+
if (RTEST(ret)) break;
|
1887
|
+
|
1888
|
+
ret = eval_decoder_expand_colormap_opt(ptr, opts[6]);
|
1889
|
+
if (RTEST(ret)) break;
|
1890
|
+
|
1891
|
+
ret = eval_decoder_scale_opt(ptr, opts[7]);
|
1892
|
+
if (RTEST(ret)) break;
|
1893
|
+
|
1894
|
+
ret = eval_decoder_dct_method_opt(ptr, opts[8]);
|
1895
|
+
if (RTEST(ret)) break;
|
1896
|
+
|
1897
|
+
ret = eval_decoder_with_exif_tags_opt(ptr, opts[9]);
|
1898
|
+
if (RTEST(ret)) break;
|
1899
|
+
|
1900
|
+
ret = eval_decoder_orientation_opt(ptr, opts[10]);
|
1901
|
+
if (RTEST(ret)) break;
|
1902
|
+
} while (0);
|
1903
|
+
|
1904
|
+
/*
|
1905
|
+
* alloc memory
|
1906
|
+
*/
|
1907
|
+
if (!RTEST(ret)) {
|
1908
|
+
ary = ALLOC_ARRAY();
|
1909
|
+
if (ary == NULL) ret = create_memory_error();
|
1910
|
+
}
|
1308
1911
|
|
1309
1912
|
/*
|
1310
|
-
* set context
|
1913
|
+
* set the rest context parameter
|
1311
1914
|
*/
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1915
|
+
if (!RTEST(ret)) {
|
1916
|
+
ptr->err_mgr.jerr.output_message = output_message;
|
1917
|
+
ptr->err_mgr.jerr.emit_message = emit_message;
|
1918
|
+
ptr->err_mgr.jerr.error_exit = error_exit;
|
1919
|
+
|
1920
|
+
// 現時点でオプションでの対応をおこなっていないので
|
1921
|
+
// ここで値を設定
|
1922
|
+
ptr->enable_1pass_quant = FALSE;
|
1923
|
+
ptr->enable_external_quant = FALSE;
|
1924
|
+
ptr->enable_2pass_quant = FALSE;
|
1925
|
+
ptr->buffered_image = FALSE;
|
1926
|
+
|
1317
1927
|
#if 0
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1928
|
+
if (ptr->enable_1pass_quant == TRUE ||
|
1929
|
+
ptr->enable_external_quant == TRUE ||
|
1930
|
+
ptr->enable_2pass_quant == TRUE) {
|
1931
|
+
ptr->buffered_image = TRUE;
|
1932
|
+
|
1933
|
+
} else {
|
1934
|
+
ptr->buffered_image = FALSE;
|
1935
|
+
}
|
1321
1936
|
#endif
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1937
|
+
|
1938
|
+
ptr->array = ary;
|
1939
|
+
ptr->data = Qnil;
|
1940
|
+
ptr->orientation.value = 0;
|
1941
|
+
ptr->orientation.buf = Qnil;
|
1942
|
+
}
|
1943
|
+
|
1944
|
+
/*
|
1945
|
+
* setup libjpeg
|
1946
|
+
*/
|
1947
|
+
if (!RTEST(ret)) {
|
1948
|
+
jpeg_create_decompress(&ptr->cinfo);
|
1949
|
+
SET_FLAG(ptr, F_CREAT);
|
1950
|
+
|
1951
|
+
ptr->cinfo.err = jpeg_std_error(&ptr->err_mgr.jerr);
|
1952
|
+
}
|
1953
|
+
|
1954
|
+
return ret;
|
1329
1955
|
}
|
1330
1956
|
|
1331
1957
|
/**
|
@@ -1380,24 +2006,28 @@ static VALUE
|
|
1380
2006
|
rb_decoder_initialize( int argc, VALUE *argv, VALUE self)
|
1381
2007
|
{
|
1382
2008
|
jpeg_decode_t* ptr;
|
2009
|
+
VALUE exc;
|
1383
2010
|
VALUE opt;
|
1384
2011
|
|
1385
2012
|
/*
|
1386
2013
|
* initialize
|
1387
2014
|
*/
|
1388
|
-
|
2015
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
1389
2016
|
|
1390
2017
|
/*
|
1391
2018
|
* parse arguments
|
1392
2019
|
*/
|
1393
|
-
rb_scan_args( argc, argv, "
|
1394
|
-
|
1395
|
-
if (opt != Qnil) Check_Type(opt, T_HASH);
|
2020
|
+
rb_scan_args( argc, argv, "0:", &opt);
|
1396
2021
|
|
1397
2022
|
/*
|
1398
2023
|
* set context
|
1399
2024
|
*/
|
1400
|
-
set_decoder_context(ptr, opt);
|
2025
|
+
exc = set_decoder_context(ptr, opt);
|
2026
|
+
|
2027
|
+
/*
|
2028
|
+
* post process
|
2029
|
+
*/
|
2030
|
+
if (RTEST(exc)) rb_exc_raise(exc);
|
1401
2031
|
|
1402
2032
|
return Qtrue;
|
1403
2033
|
}
|
@@ -1406,11 +2036,12 @@ static VALUE
|
|
1406
2036
|
rb_decoder_set(VALUE self, VALUE opt)
|
1407
2037
|
{
|
1408
2038
|
jpeg_decode_t* ptr;
|
2039
|
+
VALUE exc;
|
1409
2040
|
|
1410
2041
|
/*
|
1411
2042
|
* initialize
|
1412
2043
|
*/
|
1413
|
-
|
2044
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
1414
2045
|
|
1415
2046
|
/*
|
1416
2047
|
* check argument
|
@@ -1420,7 +2051,12 @@ rb_decoder_set(VALUE self, VALUE opt)
|
|
1420
2051
|
/*
|
1421
2052
|
* set context
|
1422
2053
|
*/
|
1423
|
-
set_decoder_context(ptr, opt);
|
2054
|
+
exc = set_decoder_context(ptr, opt);
|
2055
|
+
|
2056
|
+
/*
|
2057
|
+
* post process
|
2058
|
+
*/
|
2059
|
+
if (RTEST(exc)) rb_exc_raise(exc);
|
1424
2060
|
|
1425
2061
|
return Qtrue;
|
1426
2062
|
}
|
@@ -2292,32 +2928,38 @@ create_meta(jpeg_decode_t* ptr)
|
|
2292
2928
|
}
|
2293
2929
|
|
2294
2930
|
static VALUE
|
2295
|
-
do_read_header(
|
2931
|
+
do_read_header(VALUE _ptr)
|
2296
2932
|
{
|
2297
2933
|
VALUE ret;
|
2934
|
+
jpeg_decode_t* ptr;
|
2935
|
+
uint8_t* data;
|
2936
|
+
size_t size;
|
2298
2937
|
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
jpeg_create_decompress(&ptr->cinfo);
|
2307
|
-
|
2308
|
-
ptr->cinfo.err = jpeg_std_error(&ptr->err_mgr.jerr);
|
2309
|
-
ptr->err_mgr.jerr.output_message = decode_output_message;
|
2310
|
-
ptr->err_mgr.jerr.emit_message = decode_emit_message;
|
2311
|
-
ptr->err_mgr.jerr.error_exit = decode_error_exit;
|
2938
|
+
/*
|
2939
|
+
* initialize
|
2940
|
+
*/
|
2941
|
+
ret = Qnil;
|
2942
|
+
ptr = (jpeg_decode_t*)_ptr;
|
2943
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
2944
|
+
size = RSTRING_LEN(ptr->data);
|
2312
2945
|
|
2313
|
-
|
2314
|
-
|
2946
|
+
/*
|
2947
|
+
* process body
|
2948
|
+
*/
|
2949
|
+
ptr->cinfo.raw_data_out = FALSE;
|
2950
|
+
ptr->cinfo.dct_method = JDCT_FLOAT;
|
2315
2951
|
|
2316
2952
|
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
2317
|
-
|
2953
|
+
/*
|
2954
|
+
* when error occurred
|
2955
|
+
*/
|
2318
2956
|
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
2957
|
+
|
2319
2958
|
} else {
|
2320
|
-
|
2959
|
+
/*
|
2960
|
+
* normal path
|
2961
|
+
*/
|
2962
|
+
jpeg_mem_src(&ptr->cinfo, data, size);
|
2321
2963
|
|
2322
2964
|
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
2323
2965
|
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
@@ -2331,8 +2973,6 @@ do_read_header(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2331
2973
|
}
|
2332
2974
|
|
2333
2975
|
ret = create_meta(ptr);
|
2334
|
-
|
2335
|
-
jpeg_destroy_decompress(&ptr->cinfo);
|
2336
2976
|
}
|
2337
2977
|
|
2338
2978
|
return ret;
|
@@ -2352,21 +2992,37 @@ rb_decoder_read_header(VALUE self, VALUE data)
|
|
2352
2992
|
{
|
2353
2993
|
VALUE ret;
|
2354
2994
|
jpeg_decode_t* ptr;
|
2995
|
+
int state;
|
2355
2996
|
|
2356
2997
|
/*
|
2357
2998
|
* initialize
|
2358
2999
|
*/
|
2359
|
-
|
3000
|
+
ret = Qnil;
|
3001
|
+
state = 0;
|
3002
|
+
|
3003
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
2360
3004
|
|
2361
3005
|
/*
|
2362
3006
|
* argument check
|
2363
3007
|
*/
|
2364
3008
|
Check_Type(data, T_STRING);
|
2365
3009
|
|
3010
|
+
/*
|
3011
|
+
* prepare
|
3012
|
+
*/
|
3013
|
+
SET_DATA(ptr, data);
|
3014
|
+
|
2366
3015
|
/*
|
2367
3016
|
* do encode
|
2368
3017
|
*/
|
2369
|
-
ret = do_read_header
|
3018
|
+
ret = rb_protect(do_read_header, (VALUE)ptr, &state);
|
3019
|
+
|
3020
|
+
/*
|
3021
|
+
* post process
|
3022
|
+
*/
|
3023
|
+
CLR_DATA(ptr);
|
3024
|
+
|
3025
|
+
if (state != 0) rb_jump_tag(state);
|
2370
3026
|
|
2371
3027
|
return ret;
|
2372
3028
|
}
|
@@ -2858,9 +3514,14 @@ apply_orientation(jpeg_decode_t* ptr, VALUE img)
|
|
2858
3514
|
}
|
2859
3515
|
|
2860
3516
|
static VALUE
|
2861
|
-
do_decode(
|
3517
|
+
do_decode(VALUE _ptr)
|
2862
3518
|
{
|
2863
3519
|
VALUE ret;
|
3520
|
+
|
3521
|
+
jpeg_decode_t* ptr;
|
3522
|
+
uint8_t* data;
|
3523
|
+
size_t size;
|
3524
|
+
|
2864
3525
|
struct jpeg_decompress_struct* cinfo;
|
2865
3526
|
JSAMPARRAY array;
|
2866
3527
|
|
@@ -2870,102 +3531,87 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2870
3531
|
int i;
|
2871
3532
|
int j;
|
2872
3533
|
|
2873
|
-
|
3534
|
+
/*
|
3535
|
+
* initialize
|
3536
|
+
*/
|
3537
|
+
ret = Qnil; // warning対策
|
3538
|
+
ptr = (jpeg_decode_t*)_ptr;
|
3539
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
3540
|
+
size = RSTRING_LEN(ptr->data);
|
2874
3541
|
cinfo = &ptr->cinfo;
|
2875
|
-
array =
|
2876
|
-
|
2877
|
-
switch (ptr->format) {
|
2878
|
-
case FMT_YUV422:
|
2879
|
-
case FMT_RGB565:
|
2880
|
-
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
2881
|
-
break;
|
2882
|
-
|
2883
|
-
case FMT_GRAYSCALE:
|
2884
|
-
case FMT_YUV:
|
2885
|
-
case FMT_RGB:
|
2886
|
-
case FMT_BGR:
|
2887
|
-
case FMT_YVU:
|
2888
|
-
case FMT_RGB32:
|
2889
|
-
case FMT_BGR32:
|
2890
|
-
jpeg_create_decompress(cinfo);
|
2891
|
-
|
2892
|
-
cinfo->err = jpeg_std_error(&ptr->err_mgr.jerr);
|
2893
|
-
ptr->err_mgr.jerr.output_message = decode_output_message;
|
2894
|
-
ptr->err_mgr.jerr.emit_message = decode_emit_message;
|
2895
|
-
ptr->err_mgr.jerr.error_exit = decode_error_exit;
|
2896
|
-
|
2897
|
-
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
2898
|
-
jpeg_abort_decompress(cinfo);
|
2899
|
-
jpeg_destroy_decompress(&ptr->cinfo);
|
2900
|
-
|
2901
|
-
free(array);
|
2902
|
-
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
3542
|
+
array = ptr->array;
|
2903
3543
|
|
2904
|
-
|
2905
|
-
|
2906
|
-
|
2907
|
-
|
2908
|
-
|
2909
|
-
|
3544
|
+
/*
|
3545
|
+
* do decode
|
3546
|
+
*/
|
3547
|
+
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
3548
|
+
/*
|
3549
|
+
* when error occurred
|
3550
|
+
*/
|
3551
|
+
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
2910
3552
|
|
2911
|
-
|
2912
|
-
|
2913
|
-
|
2914
|
-
|
2915
|
-
|
2916
|
-
cinfo->out_color_space = ptr->out_color_space;
|
2917
|
-
cinfo->out_color_components = ptr->out_color_components;
|
2918
|
-
cinfo->scale_num = ptr->scale_num;
|
2919
|
-
cinfo->scale_denom = ptr->scale_denom;
|
2920
|
-
cinfo->output_gamma = ptr->output_gamma;
|
2921
|
-
cinfo->do_fancy_upsampling = ptr->do_fancy_upsampling;
|
2922
|
-
cinfo->do_block_smoothing = ptr->do_block_smoothing;
|
2923
|
-
cinfo->quantize_colors = ptr->quantize_colors;
|
2924
|
-
cinfo->dither_mode = ptr->dither_mode;
|
2925
|
-
cinfo->two_pass_quantize = ptr->two_pass_quantize;
|
2926
|
-
cinfo->desired_number_of_colors = ptr->desired_number_of_colors;
|
2927
|
-
cinfo->enable_1pass_quant = ptr->enable_1pass_quant;
|
2928
|
-
cinfo->enable_external_quant = ptr->enable_external_quant;
|
2929
|
-
cinfo->enable_2pass_quant = ptr->enable_2pass_quant;
|
2930
|
-
|
2931
|
-
jpeg_calc_output_dimensions(cinfo);
|
2932
|
-
jpeg_start_decompress(cinfo);
|
2933
|
-
|
2934
|
-
stride = cinfo->output_components * cinfo->output_width;
|
2935
|
-
raw_sz = stride * cinfo->output_height;
|
2936
|
-
ret = rb_str_buf_new(raw_sz);
|
2937
|
-
raw = (uint8_t*)RSTRING_PTR(ret);
|
2938
|
-
|
2939
|
-
while (cinfo->output_scanline < cinfo->output_height) {
|
2940
|
-
for (i = 0, j = cinfo->output_scanline; i < UNIT_LINES; i++, j++) {
|
2941
|
-
array[i] = raw + (j * stride);
|
2942
|
-
}
|
3553
|
+
} else {
|
3554
|
+
/*
|
3555
|
+
* normal path
|
3556
|
+
*/
|
3557
|
+
jpeg_mem_src(cinfo, data, size);
|
2943
3558
|
|
2944
|
-
|
2945
|
-
|
3559
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
3560
|
+
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
3561
|
+
}
|
2946
3562
|
|
2947
|
-
|
2948
|
-
|
2949
|
-
|
2950
|
-
|
3563
|
+
jpeg_read_header(cinfo, TRUE);
|
3564
|
+
jpeg_calc_output_dimensions(cinfo);
|
3565
|
+
|
3566
|
+
cinfo->raw_data_out = FALSE;
|
3567
|
+
cinfo->dct_method = ptr->dct_method;
|
3568
|
+
|
3569
|
+
cinfo->out_color_space = ptr->out_color_space;
|
3570
|
+
cinfo->out_color_components = ptr->out_color_components;
|
3571
|
+
cinfo->scale_num = ptr->scale_num;
|
3572
|
+
cinfo->scale_denom = ptr->scale_denom;
|
3573
|
+
cinfo->output_gamma = ptr->output_gamma;
|
3574
|
+
cinfo->do_fancy_upsampling = ptr->do_fancy_upsampling;
|
3575
|
+
cinfo->do_block_smoothing = ptr->do_block_smoothing;
|
3576
|
+
cinfo->quantize_colors = ptr->quantize_colors;
|
3577
|
+
cinfo->dither_mode = ptr->dither_mode;
|
3578
|
+
cinfo->two_pass_quantize = ptr->two_pass_quantize;
|
3579
|
+
cinfo->desired_number_of_colors = ptr->desired_number_of_colors;
|
3580
|
+
cinfo->enable_1pass_quant = ptr->enable_1pass_quant;
|
3581
|
+
cinfo->enable_external_quant = ptr->enable_external_quant;
|
3582
|
+
cinfo->enable_2pass_quant = ptr->enable_2pass_quant;
|
3583
|
+
|
3584
|
+
jpeg_start_decompress(cinfo);
|
3585
|
+
SET_FLAG(ptr, F_START);
|
3586
|
+
|
3587
|
+
stride = cinfo->output_components * cinfo->output_width;
|
3588
|
+
raw_sz = stride * cinfo->output_height;
|
3589
|
+
ret = rb_str_buf_new(raw_sz);
|
3590
|
+
raw = (uint8_t*)RSTRING_PTR(ret);
|
3591
|
+
|
3592
|
+
while (cinfo->output_scanline < cinfo->output_height) {
|
3593
|
+
for (i = 0, j = cinfo->output_scanline; i < UNIT_LINES; i++, j++) {
|
3594
|
+
array[i] = raw + (j * stride);
|
2951
3595
|
}
|
2952
3596
|
|
2953
|
-
|
3597
|
+
jpeg_read_scanlines(cinfo, array, UNIT_LINES);
|
3598
|
+
}
|
2954
3599
|
|
2955
|
-
|
2956
|
-
|
2957
|
-
|
2958
|
-
|
3600
|
+
if (TEST_FLAG(ptr, F_EXPAND_COLORMAP) && IS_COLORMAPPED(cinfo)) {
|
3601
|
+
ret = expand_colormap(cinfo, raw);
|
3602
|
+
} else {
|
3603
|
+
rb_str_set_len(ret, raw_sz);
|
3604
|
+
}
|
2959
3605
|
|
2960
|
-
|
3606
|
+
if (ptr->format == FMT_YVU) swap_cbcr(raw, raw_sz);
|
2961
3607
|
|
2962
|
-
|
2963
|
-
|
3608
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION)) {
|
3609
|
+
pick_exif_orientation(ptr);
|
3610
|
+
ret = apply_orientation(ptr, ret);
|
2964
3611
|
}
|
2965
|
-
break;
|
2966
|
-
}
|
2967
3612
|
|
2968
|
-
|
3613
|
+
if (TEST_FLAG(ptr, F_NEED_META)) add_meta(ret, ptr);
|
3614
|
+
}
|
2969
3615
|
|
2970
3616
|
return ret;
|
2971
3617
|
}
|
@@ -2982,25 +3628,51 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2982
3628
|
static VALUE
|
2983
3629
|
rb_decoder_decode(VALUE self, VALUE data)
|
2984
3630
|
{
|
2985
|
-
|
2986
|
-
|
3631
|
+
VALUE ret;
|
3632
|
+
jpeg_decode_t* ptr;
|
3633
|
+
int state;
|
2987
3634
|
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
3635
|
+
/*
|
3636
|
+
* initialize
|
3637
|
+
*/
|
3638
|
+
ret = Qnil;
|
3639
|
+
state = 0;
|
2992
3640
|
|
2993
|
-
|
2994
|
-
* argument check
|
2995
|
-
*/
|
2996
|
-
Check_Type(data, T_STRING);
|
3641
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
2997
3642
|
|
2998
|
-
|
2999
|
-
|
3000
|
-
|
3001
|
-
|
3643
|
+
/*
|
3644
|
+
* argument check
|
3645
|
+
*/
|
3646
|
+
Check_Type(data, T_STRING);
|
3647
|
+
|
3648
|
+
/*
|
3649
|
+
* prepare
|
3650
|
+
*/
|
3651
|
+
SET_DATA(ptr, data);
|
3652
|
+
|
3653
|
+
/*
|
3654
|
+
* do decode
|
3655
|
+
*/
|
3656
|
+
ret = rb_protect(do_decode, (VALUE)ptr, &state);
|
3657
|
+
|
3658
|
+
/*
|
3659
|
+
* post process
|
3660
|
+
*/
|
3661
|
+
if (TEST_FLAG(ptr, F_START)) {
|
3662
|
+
if (state == 0) {
|
3663
|
+
jpeg_finish_decompress(&ptr->cinfo);
|
3664
|
+
} else {
|
3665
|
+
jpeg_abort_decompress(&ptr->cinfo);
|
3666
|
+
}
|
3667
|
+
|
3668
|
+
CLR_FLAG(ptr, F_START);
|
3669
|
+
}
|
3002
3670
|
|
3003
|
-
|
3671
|
+
CLR_DATA(ptr);
|
3672
|
+
|
3673
|
+
if (state != 0) rb_jump_tag(state);
|
3674
|
+
|
3675
|
+
return ret;
|
3004
3676
|
}
|
3005
3677
|
|
3006
3678
|
static VALUE
|
@@ -3010,28 +3682,19 @@ rb_test_image(VALUE self, VALUE data)
|
|
3010
3682
|
struct jpeg_decompress_struct cinfo;
|
3011
3683
|
ext_error_t err_mgr;
|
3012
3684
|
|
3013
|
-
|
3014
|
-
|
3015
|
-
cinfo.err = jpeg_std_error(&err_mgr.jerr);
|
3016
|
-
|
3017
|
-
err_mgr.jerr.output_message = decode_output_message;
|
3018
|
-
err_mgr.jerr.emit_message = decode_emit_message;
|
3019
|
-
err_mgr.jerr.error_exit = decode_error_exit;
|
3020
|
-
|
3021
|
-
cinfo.raw_data_out = FALSE;
|
3022
|
-
cinfo.dct_method = JDCT_FLOAT;
|
3685
|
+
cinfo.raw_data_out = FALSE;
|
3686
|
+
cinfo.dct_method = JDCT_FLOAT;
|
3023
3687
|
|
3024
3688
|
if (setjmp(err_mgr.jmpbuf)) {
|
3025
|
-
ret = Qtrue;
|
3026
|
-
} else {
|
3027
3689
|
ret = Qfalse;
|
3028
3690
|
|
3691
|
+
} else {
|
3029
3692
|
jpeg_mem_src(&cinfo, (uint8_t*)RSTRING_PTR(data), RSTRING_LEN(data));
|
3030
3693
|
jpeg_read_header(&cinfo, TRUE);
|
3031
3694
|
jpeg_calc_output_dimensions(&cinfo);
|
3032
|
-
}
|
3033
3695
|
|
3034
|
-
|
3696
|
+
ret = Qtrue;
|
3697
|
+
}
|
3035
3698
|
|
3036
3699
|
return ret;
|
3037
3700
|
}
|