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