libjpeg-ruby 0.7.0 → 0.9.1
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/.gitignore +8 -0
- data/README.md +3 -1
- data/ext/jpeg/extconf.rb +11 -0
- data/ext/jpeg/jpeg.c +2084 -612
- data/lib/jpeg/version.rb +1 -1
- data/libjpeg-ruby.gemspec +4 -3
- metadata +18 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3523da7ee57f41d57b81fe97558564e0b0459c5977321ba88a298a450cd9273a
|
4
|
+
data.tar.gz: 103f379375f273f0f9a77109cc3dff8018779ce94837d2182e1e0ce50bb78213
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd38c818582812ce2ef404ade310846a5af944e2b05c2b16df4df66bf62dd3404c9c68c6508e65e8a603041ab6f0d21484d911680e967f7e11aa9ad94a7d2782
|
7
|
+
data.tar.gz: a05940b338d1660f90345c7eebdeea897629ac37c33949720cde9d4c4d5794eb73dcb0f1be568d078110185ffe223425e4f5cb61da10f3075dd63a6c1a1fe185
|
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -50,7 +50,8 @@ 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
|
+
| :orientation | Boolean | Specify whether to parse Exif orientation. When set to true, apply orientation for decode result. |
|
54
55
|
|
55
56
|
#### supported output format
|
56
57
|
RGB RGB24 YUV422 YUYV RGB565 YUV444 YCbCr BGR BGR24 RGBX RGB32 BGRX BGR32
|
@@ -75,4 +76,5 @@ IO.binwrite("test.jpg", enc << IO.binread("test.raw"))
|
|
75
76
|
| :quality | Integer | encode quality (0-100) |
|
76
77
|
| :scale | Rational or Float | |
|
77
78
|
| :dct_method | String or Symbol | T.B.D |
|
79
|
+
| :orientation | Integer | Specify Exif orientation value (1-8). |
|
78
80
|
|
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
@@ -4,16 +4,6 @@
|
|
4
4
|
* Copyright (C) 2015 Hiroshi Kuwagata <kgt9221@gmail.com>
|
5
5
|
*/
|
6
6
|
|
7
|
-
/*
|
8
|
-
* $Id: jpeg.c 159 2017-12-17 18:40:28Z pi $
|
9
|
-
*/
|
10
|
-
|
11
|
-
/*
|
12
|
-
* TODO
|
13
|
-
* libjpegのエラーハンドリングを全くやっていないので
|
14
|
-
* いずれ修正する事
|
15
|
-
*/
|
16
|
-
|
17
7
|
#include <stdio.h>
|
18
8
|
#include <stdint.h>
|
19
9
|
#include <strings.h>
|
@@ -22,6 +12,7 @@
|
|
22
12
|
#include <jpeglib.h>
|
23
13
|
|
24
14
|
#include "ruby.h"
|
15
|
+
#include "ruby/version.h"
|
25
16
|
#include "ruby/encoding.h"
|
26
17
|
|
27
18
|
#define UNIT_LINES 10
|
@@ -33,6 +24,23 @@
|
|
33
24
|
#define DEFAULT_QUALITY 75
|
34
25
|
#define DEFAULT_INPUT_COLOR_SPACE JCS_YCbCr
|
35
26
|
#define DEFAULT_INPUT_COMPONENTS 2
|
27
|
+
#define DEFAULT_ENCODE_FLAGS (0)
|
28
|
+
#define DEFAULT_DECODE_FLAGS (F_NEED_META)
|
29
|
+
|
30
|
+
#define F_NEED_META 0x00000001
|
31
|
+
#define F_EXPAND_COLORMAP 0x00000002
|
32
|
+
#define F_PARSE_EXIF 0x00000004
|
33
|
+
#define F_APPLY_ORIENTATION 0x00000008
|
34
|
+
#define F_DITHER 0x00000010
|
35
|
+
#define F_CREAT 0x00010000
|
36
|
+
|
37
|
+
#define SET_FLAG(ptr, msk) ((ptr)->flags |= (msk))
|
38
|
+
#define CLR_FLAG(ptr, msk) ((ptr)->flags &= ~(msk))
|
39
|
+
#define TEST_FLAG(ptr, msk) ((ptr)->flags & (msk))
|
40
|
+
#define TEST_FLAG_ALL(ptr, msk) (((ptr)->flags & (msk)) == (msk))
|
41
|
+
|
42
|
+
#define SET_DATA(ptr, dat) ((ptr)->data = (dat))
|
43
|
+
#define CLR_DATA(ptr) ((ptr)->data = Qnil)
|
36
44
|
|
37
45
|
#define FMT_YUV422 1
|
38
46
|
#define FMT_RGB565 2
|
@@ -48,20 +56,25 @@
|
|
48
56
|
#define JPEG_APP1 0xe1 /* Exif marker */
|
49
57
|
|
50
58
|
#define N(x) (sizeof(x)/sizeof(*x))
|
59
|
+
#define SWAP(a,b,t) \
|
60
|
+
do {t c; c = (a); (a) = (b); (b) = c;} while (0)
|
51
61
|
|
52
62
|
#define RUNTIME_ERROR(msg) rb_raise(rb_eRuntimeError, (msg))
|
53
63
|
#define ARGUMENT_ERROR(msg) rb_raise(rb_eArgError, (msg))
|
64
|
+
#define TYPE_ERROR(msg) rb_raise(rb_eTypeError, (msg))
|
65
|
+
#define RANGE_ERROR(msg) rb_raise(rb_eRangeError, (msg))
|
66
|
+
#define NOT_IMPLEMENTED_ERROR(msg) rb_raise(rb_eNotImpError, (msg))
|
54
67
|
|
55
68
|
#define IS_COLORMAPPED(ci) (((ci)->actual_number_of_colors > 0) &&\
|
56
69
|
((ci)->colormap != NULL) && \
|
57
70
|
((ci)->output_components == 1) && \
|
58
|
-
|
59
|
-
|
71
|
+
(((ci)->out_color_components == 1) || \
|
72
|
+
((ci)->out_color_components == 3)))
|
60
73
|
|
61
74
|
#define ALLOC_ARRAY() \
|
62
|
-
((JSAMPARRAY)
|
75
|
+
((JSAMPARRAY)malloc(sizeof(JSAMPROW) * UNIT_LINES))
|
63
76
|
#define ALLOC_ROWS(w,c) \
|
64
|
-
((JSAMPROW)
|
77
|
+
((JSAMPROW)malloc(sizeof(JSAMPLE) * (w) * (c) * UNIT_LINES))
|
65
78
|
|
66
79
|
#define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
|
67
80
|
#define EQ_INT(val,n) (FIX2INT(val) == n)
|
@@ -76,11 +89,13 @@ static VALUE decerr_klass;
|
|
76
89
|
|
77
90
|
static ID id_meta;
|
78
91
|
static ID id_width;
|
92
|
+
static ID id_stride;
|
79
93
|
static ID id_height;
|
80
94
|
static ID id_orig_cs;
|
81
95
|
static ID id_out_cs;
|
82
96
|
static ID id_ncompo;
|
83
|
-
static ID
|
97
|
+
static ID id_exif_tags;
|
98
|
+
static ID id_colormap;
|
84
99
|
|
85
100
|
typedef struct {
|
86
101
|
int tag;
|
@@ -246,25 +261,47 @@ tag_entry_t tag_i14y[] = {
|
|
246
261
|
static const char* encoder_opts_keys[] = {
|
247
262
|
"pixel_format", // {str}
|
248
263
|
"quality", // {integer}
|
249
|
-
"
|
250
|
-
"
|
264
|
+
"dct_method", // {str}
|
265
|
+
"orientation", // {integer}
|
266
|
+
"stride", // {integer}
|
251
267
|
};
|
252
268
|
|
253
269
|
static ID encoder_opts_ids[N(encoder_opts_keys)];
|
254
270
|
|
255
271
|
typedef struct {
|
256
|
-
|
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;
|
257
280
|
int width;
|
281
|
+
int stride;
|
258
282
|
int height;
|
259
|
-
|
260
283
|
int data_size;
|
284
|
+
|
285
|
+
int format;
|
286
|
+
int color_space;
|
287
|
+
int components;
|
288
|
+
int quality;
|
261
289
|
J_DCT_METHOD dct_method;
|
262
290
|
|
263
291
|
struct jpeg_compress_struct cinfo;
|
264
|
-
|
292
|
+
ext_error_t err_mgr;
|
265
293
|
|
266
294
|
JSAMPARRAY array;
|
267
295
|
JSAMPROW rows;
|
296
|
+
|
297
|
+
VALUE data;
|
298
|
+
|
299
|
+
struct {
|
300
|
+
unsigned char* mem;
|
301
|
+
unsigned long size;
|
302
|
+
} buf;
|
303
|
+
|
304
|
+
int orientation;
|
268
305
|
} jpeg_encode_t;
|
269
306
|
|
270
307
|
static const char* decoder_opts_keys[] = {
|
@@ -273,30 +310,24 @@ static const char* decoder_opts_keys[] = {
|
|
273
310
|
"do_fancy_upsampling", // {bool}
|
274
311
|
"do_smoothing", // {bool}
|
275
312
|
"dither", // [{str}MODE, {bool}2PASS, {int}NUM_COLORS]
|
313
|
+
#if 0
|
276
314
|
"use_1pass_quantizer", // {bool}
|
277
315
|
"use_external_colormap", // {bool}
|
278
316
|
"use_2pass_quantizer", // {bool}
|
317
|
+
#endif
|
279
318
|
"without_meta", // {bool}
|
280
319
|
"expand_colormap", // {bool}
|
281
320
|
"scale", // {rational} or {float}
|
282
321
|
"dct_method", // {str}
|
283
|
-
"
|
322
|
+
"with_exif_tags", // {bool}
|
323
|
+
"orientation" // {bool}
|
284
324
|
};
|
285
325
|
|
286
326
|
static ID decoder_opts_ids[N(decoder_opts_keys)];
|
287
327
|
|
288
328
|
typedef struct {
|
289
|
-
|
290
|
-
|
291
|
-
char msg[JMSG_LENGTH_MAX+10];
|
292
|
-
jmp_buf jmpbuf;
|
293
|
-
} ext_error_t;
|
294
|
-
|
295
|
-
typedef struct {
|
329
|
+
int flags;
|
296
330
|
int format;
|
297
|
-
int need_meta;
|
298
|
-
int expand_colormap;
|
299
|
-
int parse_exif;
|
300
331
|
|
301
332
|
J_COLOR_SPACE out_color_space;
|
302
333
|
int scale_num;
|
@@ -317,8 +348,131 @@ typedef struct {
|
|
317
348
|
|
318
349
|
struct jpeg_decompress_struct cinfo;
|
319
350
|
ext_error_t err_mgr;
|
351
|
+
|
352
|
+
JSAMPARRAY array;
|
353
|
+
|
354
|
+
VALUE data;
|
355
|
+
|
356
|
+
struct {
|
357
|
+
int value;
|
358
|
+
VALUE buf;
|
359
|
+
} orientation;
|
320
360
|
} jpeg_decode_t;
|
321
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
|
+
}
|
322
476
|
|
323
477
|
static VALUE
|
324
478
|
lookup_tag_symbol(tag_entry_t* tbl, size_t n, int tag)
|
@@ -361,40 +515,87 @@ lookup_tag_symbol(tag_entry_t* tbl, size_t n, int tag)
|
|
361
515
|
}
|
362
516
|
|
363
517
|
static void
|
364
|
-
|
518
|
+
rb_encoder_mark(void* _ptr)
|
365
519
|
{
|
366
|
-
|
520
|
+
jpeg_encode_t* ptr;
|
521
|
+
|
522
|
+
ptr = (jpeg_encode_t*)_ptr;
|
367
523
|
|
368
|
-
(
|
524
|
+
if (ptr->data != Qnil) {
|
525
|
+
rb_gc_mark(ptr->data);
|
526
|
+
}
|
369
527
|
}
|
370
528
|
|
371
529
|
static void
|
372
|
-
|
530
|
+
rb_encoder_free(void* _ptr)
|
373
531
|
{
|
374
|
-
|
532
|
+
jpeg_encode_t* ptr;
|
375
533
|
|
376
|
-
(*
|
534
|
+
ptr = (jpeg_encode_t*)_ptr;
|
377
535
|
|
378
|
-
|
379
|
-
|
380
|
-
}
|
536
|
+
if (ptr->array != NULL) {
|
537
|
+
free(ptr->array);
|
538
|
+
}
|
381
539
|
|
540
|
+
if (ptr->rows != NULL) {
|
541
|
+
free(ptr->rows);
|
542
|
+
}
|
382
543
|
|
383
|
-
|
384
|
-
|
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)
|
385
557
|
{
|
558
|
+
size_t ret;
|
386
559
|
jpeg_encode_t* ptr;
|
387
560
|
|
388
|
-
ptr
|
389
|
-
|
390
|
-
if (ptr->array != NULL) xfree(ptr->array);
|
391
|
-
if (ptr->rows != NULL) xfree(ptr->rows);
|
561
|
+
ptr = (jpeg_encode_t*)_ptr;
|
392
562
|
|
393
|
-
|
563
|
+
ret = sizeof(jpeg_encode_t);
|
564
|
+
ret += sizeof(JSAMPROW) * UNIT_LINES;
|
565
|
+
ret += sizeof(JSAMPLE) * ptr->stride * UNIT_LINES;
|
394
566
|
|
395
|
-
|
567
|
+
return ret;
|
396
568
|
}
|
397
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
|
+
|
398
599
|
static VALUE
|
399
600
|
rb_encoder_alloc(VALUE self)
|
400
601
|
{
|
@@ -403,192 +604,396 @@ rb_encoder_alloc(VALUE self)
|
|
403
604
|
ptr = ALLOC(jpeg_encode_t);
|
404
605
|
memset(ptr, 0, sizeof(*ptr));
|
405
606
|
|
406
|
-
ptr->
|
607
|
+
ptr->flags = DEFAULT_ENCODE_FLAGS;
|
407
608
|
|
408
|
-
return
|
609
|
+
return TypedData_Wrap_Struct(encoder_klass, &jpeg_encoder_data_type, ptr);
|
409
610
|
}
|
410
611
|
|
411
|
-
static
|
412
|
-
|
612
|
+
static VALUE
|
613
|
+
eval_encoder_pixel_format_opt(jpeg_encode_t* ptr, VALUE opt)
|
413
614
|
{
|
414
|
-
VALUE
|
615
|
+
VALUE ret;
|
415
616
|
int format;
|
416
617
|
int color_space;
|
417
618
|
int components;
|
418
|
-
int data_size;
|
419
|
-
int quality;
|
420
|
-
int scale_num;
|
421
|
-
int scale_denom;
|
422
|
-
int i;
|
423
619
|
|
424
|
-
|
425
|
-
* parse options
|
426
|
-
*/
|
427
|
-
rb_get_kwargs(opt, encoder_opts_ids, 0, N(encoder_opts_ids), opts);
|
620
|
+
ret = Qnil;
|
428
621
|
|
429
|
-
|
430
|
-
|
431
|
-
*/
|
432
|
-
if (opts[0] == Qundef||EQ_STR(opts[0], "YUV422")||EQ_STR(opts[0], "YUYV")) {
|
622
|
+
switch (TYPE(opt)) {
|
623
|
+
case T_UNDEF:
|
433
624
|
format = FMT_YUV422;
|
434
625
|
color_space = JCS_YCbCr;
|
435
626
|
components = 3;
|
436
|
-
|
627
|
+
break;
|
437
628
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
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;
|
443
635
|
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
data_size = (wd * ht * 3);
|
636
|
+
} else if (EQ_STR(opt, "RGB565")) {
|
637
|
+
format = FMT_RGB565;
|
638
|
+
color_space = JCS_RGB;
|
639
|
+
components = 3;
|
449
640
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
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;
|
455
645
|
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
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;
|
461
650
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
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;
|
467
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;
|
468
660
|
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
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;
|
474
665
|
|
666
|
+
} else if (EQ_STR(opt, "GRAYSCALE")) {
|
667
|
+
format = FMT_GRAYSCALE;
|
668
|
+
color_space = JCS_GRAYSCALE;
|
669
|
+
components = 1;
|
475
670
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
data_size = (wd * ht);
|
671
|
+
} else {
|
672
|
+
ret = create_argument_error("unsupportd :pixel_format option value");
|
673
|
+
}
|
674
|
+
break;
|
481
675
|
|
482
|
-
|
483
|
-
|
676
|
+
default:
|
677
|
+
ret = create_type_error("unsupportd :pixel_format option type");
|
678
|
+
break;
|
484
679
|
}
|
485
680
|
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
} else {
|
493
|
-
if (TYPE(opts[1]) != T_FIXNUM) {
|
494
|
-
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
|
+
}
|
495
686
|
|
496
|
-
|
497
|
-
|
498
|
-
}
|
687
|
+
return ret;
|
688
|
+
}
|
499
689
|
|
500
|
-
|
501
|
-
|
690
|
+
static VALUE
|
691
|
+
eval_encoder_quality_opt(jpeg_encode_t* ptr, VALUE opt)
|
692
|
+
{
|
693
|
+
VALUE ret;
|
694
|
+
long quality;
|
502
695
|
|
503
|
-
|
504
|
-
ARGUMENT_ERROR(":quality value is to big.");
|
505
|
-
}
|
506
|
-
}
|
507
|
-
|
508
|
-
/*
|
509
|
-
* eval scale option
|
510
|
-
*/
|
511
|
-
(void)scale_num;
|
512
|
-
(void)scale_denom;
|
696
|
+
ret = Qnil;
|
513
697
|
|
514
|
-
switch (TYPE(
|
698
|
+
switch (TYPE(opt)) {
|
515
699
|
case T_UNDEF:
|
516
|
-
|
700
|
+
quality = DEFAULT_QUALITY;
|
517
701
|
break;
|
518
702
|
|
519
703
|
case T_FLOAT:
|
520
|
-
|
521
|
-
|
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
|
+
}
|
522
716
|
break;
|
523
717
|
|
524
|
-
case
|
525
|
-
|
526
|
-
|
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
|
+
}
|
527
728
|
break;
|
528
729
|
|
529
730
|
default:
|
530
|
-
|
731
|
+
ret = create_type_error("unsupportd :quality option type");
|
531
732
|
break;
|
532
733
|
}
|
533
734
|
|
534
|
-
|
535
|
-
* eval dct_method option
|
536
|
-
*/
|
537
|
-
if (opts[3] == Qundef || EQ_STR(opts[3], "FASTEST")) {
|
538
|
-
ptr->dct_method = JDCT_FASTEST;
|
735
|
+
if (!RTEST(ret)) ptr->quality = quality;
|
539
736
|
|
540
|
-
|
541
|
-
|
737
|
+
return ret;
|
738
|
+
}
|
542
739
|
|
543
|
-
|
544
|
-
|
740
|
+
static VALUE
|
741
|
+
eval_encoder_dct_method_opt(jpeg_encode_t* ptr, VALUE opt)
|
742
|
+
{
|
743
|
+
VALUE ret;
|
744
|
+
int dct_method;
|
545
745
|
|
546
|
-
|
547
|
-
ptr->dct_method = JDCT_FLOAT;
|
746
|
+
ret = Qnil;
|
548
747
|
|
549
|
-
|
550
|
-
|
551
|
-
|
748
|
+
switch (TYPE(opt)) {
|
749
|
+
case T_UNDEF:
|
750
|
+
dct_method = JDCT_FASTEST;
|
751
|
+
break;
|
552
752
|
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
ptr->width = wd;
|
558
|
-
ptr->height = ht;
|
559
|
-
ptr->data_size = data_size;
|
560
|
-
ptr->array = ALLOC_ARRAY();
|
561
|
-
ptr->rows = ALLOC_ROWS(wd, components);
|
753
|
+
case T_STRING:
|
754
|
+
case T_SYMBOL:
|
755
|
+
if (EQ_STR(opt, "FASTEST")) {
|
756
|
+
dct_method = JDCT_FASTEST;
|
562
757
|
|
563
|
-
|
564
|
-
|
565
|
-
}
|
758
|
+
} else if (EQ_STR(opt, "ISLOW")) {
|
759
|
+
dct_method = JDCT_ISLOW;
|
566
760
|
|
567
|
-
|
761
|
+
} else if (EQ_STR(opt, "IFAST")) {
|
762
|
+
dct_method = JDCT_IFAST;
|
763
|
+
|
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;
|
775
|
+
}
|
776
|
+
|
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;
|
789
|
+
|
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;
|
831
|
+
|
832
|
+
default:
|
833
|
+
ret = create_type_error("unsupportd :stride option type");
|
834
|
+
}
|
835
|
+
|
836
|
+
if (!RTEST(ret)) ptr->stride = stride;
|
837
|
+
|
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);
|
568
915
|
|
569
|
-
|
570
|
-
|
571
|
-
|
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
|
+
}
|
572
935
|
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
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
|
+
}
|
577
958
|
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
959
|
+
/*
|
960
|
+
* post process
|
961
|
+
*/
|
962
|
+
if (RTEST(ret)) {
|
963
|
+
if (ary != NULL) free(ary);
|
964
|
+
if (rows != NULL) free(rows);
|
965
|
+
}
|
582
966
|
|
583
|
-
|
584
|
-
jpeg_set_quality(&ptr->cinfo, quality, TRUE);
|
585
|
-
jpeg_suppress_tables(&ptr->cinfo, TRUE);
|
967
|
+
return ret;
|
586
968
|
}
|
587
969
|
|
970
|
+
/**
|
971
|
+
* initialize encoder object
|
972
|
+
*
|
973
|
+
* @overload initialize(width, height, opts)
|
974
|
+
*
|
975
|
+
* @param width [Integer] width of input image (px)
|
976
|
+
* @param height [Integer] height of input image (px)
|
977
|
+
* @param opts [Hash] options to initialize object
|
978
|
+
*
|
979
|
+
* @option opts [Symbol] :pixel_format
|
980
|
+
* specifies the format of the input image. possible values are:
|
981
|
+
* YUV422 YUYV RGB565 RGB RGB24 BGR BGR24 YUV444 YCbCr
|
982
|
+
* RGBX RGB32 BGRX BGR32 GRAYSCALE
|
983
|
+
*
|
984
|
+
* @option opts [Integer] :quality
|
985
|
+
* specifies the quality of the compressed image.
|
986
|
+
* You can specify from 0 (lowest) to 100 (best).
|
987
|
+
*
|
988
|
+
* @option opts [Symbol] :dct_method
|
989
|
+
* specifies how encoding is handled. possible values are:
|
990
|
+
* FASTEST ISLOW IFAST FLOAT
|
991
|
+
*/
|
588
992
|
static VALUE
|
589
993
|
rb_encoder_initialize(int argc, VALUE *argv, VALUE self)
|
590
994
|
{
|
591
995
|
jpeg_encode_t* ptr;
|
996
|
+
VALUE exc;
|
592
997
|
VALUE wd;
|
593
998
|
VALUE ht;
|
594
999
|
VALUE opt;
|
@@ -596,191 +1001,281 @@ rb_encoder_initialize(int argc, VALUE *argv, VALUE self)
|
|
596
1001
|
/*
|
597
1002
|
* initialize
|
598
1003
|
*/
|
599
|
-
|
1004
|
+
exc = Qnil;
|
1005
|
+
|
1006
|
+
TypedData_Get_Struct(self, jpeg_encode_t, &jpeg_encoder_data_type, ptr);
|
600
1007
|
|
601
1008
|
/*
|
602
1009
|
* parse arguments
|
603
1010
|
*/
|
604
|
-
rb_scan_args(argc, argv, "
|
1011
|
+
rb_scan_args(argc, argv, "2:", &wd, &ht, &opt);
|
1012
|
+
|
1013
|
+
/*
|
1014
|
+
* argument check
|
1015
|
+
*/
|
1016
|
+
do {
|
1017
|
+
if (TYPE(wd) != T_FIXNUM) {
|
1018
|
+
exc = create_argument_error("invalid width");
|
1019
|
+
break;
|
1020
|
+
}
|
605
1021
|
|
606
|
-
|
607
|
-
|
608
|
-
|
1022
|
+
if (TYPE(ht) != T_FIXNUM) {
|
1023
|
+
exc = create_argument_error("invalid height");
|
1024
|
+
break;
|
1025
|
+
}
|
1026
|
+
} while (0);
|
609
1027
|
|
610
1028
|
/*
|
611
1029
|
* set context
|
612
1030
|
*/
|
613
|
-
|
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);
|
614
1039
|
|
615
1040
|
return Qtrue;
|
616
1041
|
}
|
617
1042
|
|
618
|
-
static
|
619
|
-
push_rows_yuv422(JSAMPROW
|
1043
|
+
static void
|
1044
|
+
push_rows_yuv422(JSAMPROW dst, int wd, int st, uint8_t* data, int nrow)
|
620
1045
|
{
|
621
|
-
|
1046
|
+
uint8_t* src;
|
622
1047
|
int i;
|
1048
|
+
int j;
|
623
1049
|
|
624
|
-
|
1050
|
+
for (i = 0; i < nrow; i++) {
|
1051
|
+
src = data;
|
625
1052
|
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
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];
|
633
1060
|
|
634
|
-
|
635
|
-
|
636
|
-
|
1061
|
+
dst += 6;
|
1062
|
+
src += 4;
|
1063
|
+
}
|
637
1064
|
|
638
|
-
|
1065
|
+
data += st;
|
1066
|
+
}
|
639
1067
|
}
|
640
1068
|
|
641
|
-
static
|
642
|
-
push_rows_rgb565(JSAMPROW
|
1069
|
+
static void
|
1070
|
+
push_rows_rgb565(JSAMPROW dst, int wd, int st, uint8_t* data, int nrow)
|
643
1071
|
{
|
644
|
-
|
1072
|
+
uint8_t* src;
|
645
1073
|
int i;
|
1074
|
+
int j;
|
646
1075
|
|
647
|
-
|
1076
|
+
for (i = 0; i < nrow; i++) {
|
1077
|
+
src = data;
|
648
1078
|
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
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;
|
653
1083
|
|
654
|
-
|
655
|
-
|
656
|
-
|
1084
|
+
dst += 3;
|
1085
|
+
src += 2;
|
1086
|
+
}
|
657
1087
|
|
658
|
-
|
1088
|
+
data += st;
|
1089
|
+
}
|
659
1090
|
}
|
660
1091
|
|
661
|
-
static
|
662
|
-
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)
|
663
1094
|
{
|
664
1095
|
int size;
|
1096
|
+
int i;
|
1097
|
+
|
1098
|
+
size = wd * 3;
|
665
1099
|
|
666
|
-
|
667
|
-
|
1100
|
+
for (i = 0; i < nrow; i++) {
|
1101
|
+
memcpy(rows, data, size);
|
668
1102
|
|
669
|
-
|
1103
|
+
rows += size;
|
1104
|
+
data += st;
|
1105
|
+
}
|
670
1106
|
}
|
671
1107
|
|
672
|
-
static
|
673
|
-
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)
|
674
1110
|
{
|
675
1111
|
int size;
|
1112
|
+
int i;
|
676
1113
|
|
677
|
-
size = wd *
|
678
|
-
memcpy(rows, data, size);
|
679
|
-
|
680
|
-
return size;
|
681
|
-
}
|
1114
|
+
size = wd * 4;
|
682
1115
|
|
1116
|
+
for (i = 0; i < nrow; i++) {
|
1117
|
+
memcpy(rows, data, size);
|
683
1118
|
|
1119
|
+
rows += size;
|
1120
|
+
data += st;
|
1121
|
+
}
|
1122
|
+
}
|
684
1123
|
|
685
|
-
static
|
686
|
-
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)
|
687
1126
|
{
|
688
|
-
int
|
1127
|
+
int i;
|
689
1128
|
|
690
|
-
|
691
|
-
|
1129
|
+
for (i = 0; i < nrow; i++) {
|
1130
|
+
memcpy(rows, data, wd);
|
692
1131
|
|
693
|
-
|
1132
|
+
rows += wd;
|
1133
|
+
data += st;
|
1134
|
+
}
|
694
1135
|
}
|
695
1136
|
|
696
|
-
static
|
1137
|
+
static void
|
697
1138
|
push_rows(jpeg_encode_t* ptr, uint8_t* data, int nrow)
|
698
1139
|
{
|
699
|
-
int ret;
|
700
|
-
|
701
1140
|
switch (ptr->format) {
|
702
1141
|
case FMT_YUV422:
|
703
|
-
|
1142
|
+
push_rows_yuv422(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
704
1143
|
break;
|
705
1144
|
|
706
1145
|
case FMT_RGB565:
|
707
|
-
|
1146
|
+
push_rows_rgb565(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
708
1147
|
break;
|
709
1148
|
|
710
1149
|
case FMT_YUV:
|
711
1150
|
case FMT_RGB:
|
712
1151
|
case FMT_BGR:
|
713
|
-
|
1152
|
+
push_rows_comp3(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
714
1153
|
break;
|
715
1154
|
|
716
1155
|
case FMT_RGB32:
|
717
1156
|
case FMT_BGR32:
|
718
|
-
|
1157
|
+
push_rows_comp4(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
719
1158
|
break;
|
720
1159
|
|
721
1160
|
case FMT_GRAYSCALE:
|
722
|
-
|
1161
|
+
push_rows_grayscale(ptr->rows, ptr->width, ptr->stride, data, nrow);
|
723
1162
|
break;
|
724
1163
|
|
725
1164
|
default:
|
726
1165
|
RUNTIME_ERROR("Really?");
|
727
1166
|
}
|
1167
|
+
}
|
728
1168
|
|
729
|
-
|
1169
|
+
static void
|
1170
|
+
put_exif_tags(jpeg_encode_t* ptr)
|
1171
|
+
{
|
1172
|
+
uint8_t data[] = {
|
1173
|
+
/* Exif header */
|
1174
|
+
'E', 'x', 'i', 'f', 0x00, 0x00,
|
1175
|
+
'M', 'M',
|
1176
|
+
0x00, 0x2a,
|
1177
|
+
0x00, 0x00, 0x00, 0x08,
|
1178
|
+
0x00, 0x01,
|
1179
|
+
|
1180
|
+
/* orieatation */
|
1181
|
+
0x01, 0x12,
|
1182
|
+
0x00, 0x03,
|
1183
|
+
0x00, 0x00, 0x00, 0x01,
|
1184
|
+
0x00, 0x00,
|
1185
|
+
0x00, 0x00,
|
1186
|
+
|
1187
|
+
/* end mark */
|
1188
|
+
0x00, 0x00, 0x00, 0x00,
|
1189
|
+
};
|
1190
|
+
|
1191
|
+
data[24] = (ptr->orientation >> 8) & 0xff;
|
1192
|
+
data[25] = (ptr->orientation >> 0) & 0xff;
|
1193
|
+
|
1194
|
+
jpeg_write_marker(&ptr->cinfo, JPEG_APP1, data, sizeof(data));
|
730
1195
|
}
|
731
1196
|
|
732
1197
|
static VALUE
|
733
|
-
do_encode(
|
1198
|
+
do_encode(VALUE _ptr)
|
734
1199
|
{
|
735
1200
|
VALUE ret;
|
736
|
-
|
737
|
-
|
738
|
-
unsigned long buf_size;
|
1201
|
+
jpeg_encode_t* ptr;
|
1202
|
+
uint8_t* data;
|
739
1203
|
int nrow;
|
740
1204
|
|
741
|
-
|
1205
|
+
/*
|
1206
|
+
* initialize
|
1207
|
+
*/
|
1208
|
+
ret = Qnil;
|
1209
|
+
ptr = (jpeg_encode_t*)_ptr;
|
1210
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
742
1211
|
|
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);
|
743
1221
|
|
744
|
-
|
1222
|
+
} else {
|
1223
|
+
/*
|
1224
|
+
* normal path
|
1225
|
+
*/
|
1226
|
+
jpeg_start_compress(&ptr->cinfo, TRUE);
|
745
1227
|
|
746
|
-
|
1228
|
+
if (ptr->orientation != 0) {
|
1229
|
+
put_exif_tags(ptr);
|
1230
|
+
}
|
747
1231
|
|
748
|
-
|
749
|
-
|
750
|
-
|
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;
|
751
1235
|
|
752
|
-
|
753
|
-
jpeg_write_scanlines(&ptr->cinfo, ptr->array, nrow);
|
754
|
-
}
|
1236
|
+
push_rows(ptr, data, nrow);
|
755
1237
|
|
756
|
-
|
1238
|
+
jpeg_write_scanlines(&ptr->cinfo, ptr->array, nrow);
|
1239
|
+
data += (ptr->stride * nrow);
|
1240
|
+
}
|
757
1241
|
|
758
|
-
|
759
|
-
* create return data
|
760
|
-
*/
|
761
|
-
ret = rb_str_buf_new(buf_size);
|
762
|
-
rb_str_set_len(ret, buf_size);
|
1242
|
+
jpeg_finish_compress(&ptr->cinfo);
|
763
1243
|
|
764
|
-
|
1244
|
+
/*
|
1245
|
+
* build return data
|
1246
|
+
*/
|
1247
|
+
ret = rb_str_buf_new(ptr->buf.size);
|
1248
|
+
rb_str_set_len(ret, ptr->buf.size);
|
765
1249
|
|
766
|
-
|
767
|
-
|
768
|
-
*/
|
769
|
-
free(buf);
|
1250
|
+
memcpy(RSTRING_PTR(ret), ptr->buf.mem, ptr->buf.size);
|
1251
|
+
}
|
770
1252
|
|
771
1253
|
return ret;
|
772
1254
|
}
|
773
1255
|
|
1256
|
+
/**
|
1257
|
+
* encode data
|
1258
|
+
*
|
1259
|
+
* @overload encode(raw)
|
1260
|
+
*
|
1261
|
+
* @param raw [String] raw image data to encode.
|
1262
|
+
*
|
1263
|
+
* @return [String] encoded JPEG data.
|
1264
|
+
*/
|
774
1265
|
static VALUE
|
775
1266
|
rb_encoder_encode(VALUE self, VALUE data)
|
776
1267
|
{
|
777
1268
|
VALUE ret;
|
1269
|
+
int state;
|
778
1270
|
jpeg_encode_t* ptr;
|
779
1271
|
|
780
1272
|
/*
|
781
1273
|
* initialize
|
782
1274
|
*/
|
783
|
-
|
1275
|
+
ret = Qnil;
|
1276
|
+
state = 0;
|
1277
|
+
|
1278
|
+
TypedData_Get_Struct(self, jpeg_encode_t, &jpeg_encoder_data_type, ptr);
|
784
1279
|
|
785
1280
|
/*
|
786
1281
|
* argument check
|
@@ -788,70 +1283,123 @@ rb_encoder_encode(VALUE self, VALUE data)
|
|
788
1283
|
Check_Type(data, T_STRING);
|
789
1284
|
|
790
1285
|
if (RSTRING_LEN(data) < ptr->data_size) {
|
791
|
-
ARGUMENT_ERROR("
|
1286
|
+
ARGUMENT_ERROR("image data is too short");
|
792
1287
|
}
|
793
1288
|
|
794
1289
|
if (RSTRING_LEN(data) > ptr->data_size) {
|
795
|
-
ARGUMENT_ERROR("
|
1290
|
+
ARGUMENT_ERROR("image data is too large");
|
1291
|
+
}
|
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");
|
796
1299
|
}
|
797
1300
|
|
1301
|
+
/*
|
1302
|
+
* prepare
|
1303
|
+
*/
|
1304
|
+
SET_DATA(ptr, data);
|
1305
|
+
|
798
1306
|
/*
|
799
1307
|
* do encode
|
800
1308
|
*/
|
801
|
-
ret = do_encode(ptr,
|
1309
|
+
ret = rb_protect(do_encode, (VALUE)ptr, &state);
|
1310
|
+
|
1311
|
+
/*
|
1312
|
+
* post process
|
1313
|
+
*/
|
1314
|
+
CLR_DATA(ptr);
|
1315
|
+
|
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);
|
802
1324
|
|
803
1325
|
return ret;
|
804
1326
|
}
|
805
1327
|
|
806
1328
|
static void
|
807
|
-
|
1329
|
+
rb_decoder_mark(void* _ptr)
|
808
1330
|
{
|
809
|
-
|
1331
|
+
jpeg_decode_t* ptr;
|
810
1332
|
|
811
|
-
|
1333
|
+
ptr = (jpeg_decode_t*)_ptr;
|
1334
|
+
|
1335
|
+
if (ptr->orientation.buf != Qnil) {
|
1336
|
+
rb_gc_mark(ptr->orientation.buf);
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
if (ptr->data != Qnil) {
|
1340
|
+
rb_gc_mark(ptr->data);
|
1341
|
+
}
|
812
1342
|
}
|
813
1343
|
|
814
1344
|
static void
|
815
|
-
|
1345
|
+
rb_decoder_free(void* _ptr)
|
816
1346
|
{
|
817
|
-
|
1347
|
+
jpeg_decode_t* ptr;
|
818
1348
|
|
819
|
-
|
1349
|
+
ptr = (jpeg_decode_t*)_ptr;
|
820
1350
|
|
821
|
-
(
|
822
|
-
|
1351
|
+
if (ptr->array != NULL) {
|
1352
|
+
free(ptr->array);
|
1353
|
+
}
|
823
1354
|
|
824
|
-
|
825
|
-
|
826
|
-
{
|
827
|
-
ext_error_t* err;
|
1355
|
+
ptr->orientation.buf = Qnil;
|
1356
|
+
ptr->data = Qnil;
|
828
1357
|
|
829
|
-
if (
|
830
|
-
|
831
|
-
(*err->jerr.format_message)(cinfo, err->msg);
|
832
|
-
/*
|
833
|
-
* 以前はemit_messageが呼ばれるとエラー扱いしていたが、
|
834
|
-
* Logicoolの一部のモデルなどで問題が出るので無視する
|
835
|
-
* ようにした。
|
836
|
-
* また本来であれば、警告表示を行うべきでもあるが一部
|
837
|
-
* のモデルで大量にemitされる場合があるので表示しない
|
838
|
-
* ようにしている。
|
839
|
-
* 問題が発生した際は、最後のメッセージをオブジェクト
|
840
|
-
* のインスタンスとして持たすべき。
|
841
|
-
*/
|
842
|
-
// longjmp(err->jmpbuf, 1);
|
1358
|
+
if (TEST_FLAG(ptr, F_CREAT)) {
|
1359
|
+
jpeg_destroy_decompress(&ptr->cinfo);
|
843
1360
|
}
|
1361
|
+
|
1362
|
+
free(ptr);
|
844
1363
|
}
|
845
1364
|
|
846
|
-
static
|
847
|
-
|
1365
|
+
static size_t
|
1366
|
+
rb_decoder_size(const void* ptr)
|
848
1367
|
{
|
849
|
-
|
1368
|
+
size_t ret;
|
850
1369
|
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
}
|
1370
|
+
ret = sizeof(jpeg_decode_t);
|
1371
|
+
|
1372
|
+
return ret;
|
1373
|
+
}
|
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 */
|
855
1403
|
|
856
1404
|
static VALUE
|
857
1405
|
rb_decoder_alloc(VALUE self)
|
@@ -861,54 +1409,40 @@ rb_decoder_alloc(VALUE self)
|
|
861
1409
|
ptr = ALLOC(jpeg_decode_t);
|
862
1410
|
memset(ptr, 0, sizeof(*ptr));
|
863
1411
|
|
864
|
-
ptr->
|
865
|
-
ptr->need_meta = !0;
|
866
|
-
ptr->expand_colormap = 0;
|
867
|
-
ptr->parse_exif = 0;
|
868
|
-
|
869
|
-
ptr->out_color_space = JCS_RGB;
|
870
|
-
|
871
|
-
ptr->scale_num = 1;
|
872
|
-
ptr->scale_denom = 1;
|
1412
|
+
ptr->flags = DEFAULT_DECODE_FLAGS;
|
873
1413
|
|
874
|
-
ptr
|
875
|
-
ptr->output_gamma = 0.0;
|
876
|
-
ptr->buffered_image = FALSE;
|
877
|
-
ptr->do_fancy_upsampling = FALSE;
|
878
|
-
ptr->do_block_smoothing = FALSE;
|
879
|
-
ptr->quantize_colors = FALSE;
|
880
|
-
ptr->dither_mode = JDITHER_NONE;
|
881
|
-
ptr->dct_method = JDCT_FASTEST;
|
882
|
-
ptr->desired_number_of_colors = 0;
|
883
|
-
ptr->enable_1pass_quant = FALSE;
|
884
|
-
ptr->enable_external_quant = FALSE;
|
885
|
-
ptr->enable_2pass_quant = FALSE;
|
886
|
-
|
887
|
-
return Data_Wrap_Struct(decoder_klass, 0, rb_decoder_free, ptr);
|
1414
|
+
return TypedData_Wrap_Struct(decoder_klass, &jpeg_decoder_data_type, ptr);
|
888
1415
|
}
|
889
1416
|
|
890
|
-
static
|
891
|
-
|
1417
|
+
static VALUE
|
1418
|
+
eval_decoder_pixel_format_opt(jpeg_decode_t* ptr, VALUE opt)
|
892
1419
|
{
|
1420
|
+
VALUE ret;
|
893
1421
|
int format;
|
894
1422
|
int color_space;
|
895
1423
|
int components;
|
896
1424
|
|
897
|
-
|
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:
|
898
1436
|
if(EQ_STR(opt, "RGB") || EQ_STR(opt, "RGB24")) {
|
899
1437
|
format = FMT_RGB;
|
900
1438
|
color_space = JCS_RGB;
|
901
1439
|
components = 3;
|
902
1440
|
|
903
1441
|
} else if (EQ_STR(opt, "YUV422") || EQ_STR(opt, "YUYV")) {
|
904
|
-
|
905
|
-
color_space = JCS_YCbCr;
|
906
|
-
components = 3;
|
1442
|
+
ret = create_not_implement_error( "not implemented colorspace");
|
907
1443
|
|
908
1444
|
} else if (EQ_STR(opt, "RGB565")) {
|
909
|
-
|
910
|
-
color_space = JCS_RGB;
|
911
|
-
components = 3;
|
1445
|
+
ret = create_not_implement_error( "not implemented colorspace");
|
912
1446
|
|
913
1447
|
} else if (EQ_STR(opt, "GRAYSCALE")) {
|
914
1448
|
format = FMT_GRAYSCALE;
|
@@ -941,254 +1475,555 @@ eval_decoder_opt_pixel_format(jpeg_decode_t* ptr, VALUE opt)
|
|
941
1475
|
components = 4;
|
942
1476
|
|
943
1477
|
} else {
|
944
|
-
|
1478
|
+
ret = create_argument_error("unsupportd :pixel_format option value");
|
945
1479
|
}
|
1480
|
+
break;
|
1481
|
+
|
1482
|
+
default:
|
1483
|
+
ret = create_type_error("unsupportd :pixel_format option type");
|
1484
|
+
break;
|
1485
|
+
}
|
946
1486
|
|
947
|
-
|
948
|
-
ptr->
|
949
|
-
ptr->
|
1487
|
+
if (!RTEST(ret)) {
|
1488
|
+
ptr->format = format;
|
1489
|
+
ptr->out_color_space = color_space;
|
1490
|
+
ptr->out_color_components = components;
|
950
1491
|
}
|
1492
|
+
|
1493
|
+
return ret;
|
951
1494
|
}
|
952
1495
|
|
953
|
-
static
|
954
|
-
|
1496
|
+
static VALUE
|
1497
|
+
eval_decoder_output_gamma_opt(jpeg_decode_t* ptr, VALUE opt)
|
955
1498
|
{
|
1499
|
+
VALUE ret;
|
1500
|
+
double gamma;
|
1501
|
+
|
1502
|
+
ret = Qnil;
|
1503
|
+
|
956
1504
|
switch (TYPE(opt)) {
|
957
1505
|
case T_UNDEF:
|
958
|
-
|
1506
|
+
gamma = 0.0;
|
959
1507
|
break;
|
960
1508
|
|
1509
|
+
case T_FIXNUM:
|
961
1510
|
case T_FLOAT:
|
962
|
-
|
1511
|
+
if (isnan(NUM2DBL(opt)) || isinf(NUM2DBL(opt))) {
|
1512
|
+
ret = create_argument_error("unsupported :output_gamma value");
|
1513
|
+
} else {
|
1514
|
+
gamma = NUM2DBL(opt);
|
1515
|
+
}
|
963
1516
|
break;
|
964
1517
|
|
965
1518
|
default:
|
966
|
-
|
1519
|
+
ret = create_type_error("unsupported :output_gamma type");
|
967
1520
|
break;
|
968
1521
|
}
|
1522
|
+
|
1523
|
+
if (!RTEST(ret)) ptr->output_gamma = gamma;
|
1524
|
+
|
1525
|
+
return ret;
|
969
1526
|
}
|
970
1527
|
|
971
|
-
static
|
972
|
-
|
1528
|
+
static VALUE
|
1529
|
+
eval_decoder_do_fancy_upsampling_opt(jpeg_decode_t* ptr, VALUE opt)
|
973
1530
|
{
|
974
|
-
if (opt != Qundef) {
|
975
|
-
ptr->do_fancy_upsampling =
|
1531
|
+
if (opt != Qundef && RTEST(opt)) {
|
1532
|
+
ptr->do_fancy_upsampling = TRUE;
|
1533
|
+
} else {
|
1534
|
+
ptr->do_fancy_upsampling = FALSE;
|
976
1535
|
}
|
1536
|
+
|
1537
|
+
return Qnil;
|
977
1538
|
}
|
978
1539
|
|
979
|
-
static
|
980
|
-
|
1540
|
+
static VALUE
|
1541
|
+
eval_decoder_do_smoothing_opt(jpeg_decode_t* ptr, VALUE opt)
|
981
1542
|
{
|
982
|
-
if (opt != Qundef) {
|
983
|
-
ptr->do_block_smoothing =
|
1543
|
+
if (opt != Qundef && RTEST(opt)) {
|
1544
|
+
ptr->do_block_smoothing = TRUE;
|
1545
|
+
} else {
|
1546
|
+
ptr->do_block_smoothing = FALSE;
|
984
1547
|
}
|
1548
|
+
|
1549
|
+
return Qnil;
|
985
1550
|
}
|
986
1551
|
|
987
|
-
static
|
988
|
-
|
1552
|
+
static VALUE
|
1553
|
+
eval_decoder_dither_opt( jpeg_decode_t* ptr, VALUE opt)
|
989
1554
|
{
|
990
|
-
VALUE
|
991
|
-
VALUE
|
992
|
-
|
1555
|
+
VALUE ret;
|
1556
|
+
VALUE tmp;
|
1557
|
+
int mode;
|
1558
|
+
int quant;
|
1559
|
+
int pass2;
|
1560
|
+
int ncol;
|
993
1561
|
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
1562
|
+
ret = Qnil;
|
1563
|
+
|
1564
|
+
switch (TYPE(opt)) {
|
1565
|
+
case T_UNDEF:
|
1566
|
+
mode = JDITHER_NONE;
|
1567
|
+
quant = FALSE;
|
1568
|
+
ncol = 0;
|
1569
|
+
pass2 = FALSE;
|
1570
|
+
break;
|
998
1571
|
|
1572
|
+
case T_ARRAY:
|
999
1573
|
if (RARRAY_LEN(opt) != 3) {
|
1000
|
-
|
1001
|
-
|
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;
|
1002
1584
|
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
if (EQ_STR(dmode, "NONE")) {
|
1008
|
-
ptr->dither_mode = JDITHER_NONE;
|
1009
|
-
ptr->quantize_colors = FALSE;
|
1585
|
+
} else if (EQ_STR(tmp, "NONE")) {
|
1586
|
+
mode = JDITHER_NONE;
|
1587
|
+
quant = FALSE;
|
1010
1588
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1589
|
+
} else if(EQ_STR(tmp, "ORDERED")) {
|
1590
|
+
mode = JDITHER_ORDERED;
|
1591
|
+
quant = TRUE;
|
1014
1592
|
|
1015
|
-
|
1016
|
-
|
1017
|
-
|
1593
|
+
} else if(EQ_STR(tmp, "FS")) {
|
1594
|
+
mode = JDITHER_FS;
|
1595
|
+
quant = TRUE;
|
1018
1596
|
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1597
|
+
} else {
|
1598
|
+
ret = create_argument_error("dither mode is illeagal value.");
|
1599
|
+
break;
|
1600
|
+
}
|
1022
1601
|
|
1023
|
-
|
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;
|
1024
1614
|
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1615
|
+
} else if (FIX2LONG(tmp) < 8) {
|
1616
|
+
ret = create_range_error("number of colors less than 0");
|
1617
|
+
break;
|
1618
|
+
|
1619
|
+
} else if (FIX2LONG(tmp) > 256) {
|
1620
|
+
ret = create_range_error("number of colors greater than 256");
|
1621
|
+
break;
|
1622
|
+
|
1623
|
+
} else {
|
1624
|
+
ncol = FIX2INT(tmp);
|
1625
|
+
}
|
1626
|
+
} while (0);
|
1627
|
+
break;
|
1628
|
+
|
1629
|
+
default:
|
1630
|
+
ret = create_type_error("unsupported :dither type");
|
1631
|
+
break;
|
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);
|
1030
1641
|
}
|
1642
|
+
|
1643
|
+
return ret;
|
1031
1644
|
}
|
1032
1645
|
|
1646
|
+
#if 0
|
1033
1647
|
static void
|
1034
|
-
|
1648
|
+
eval_decoder_use_1pass_quantizer_opt(jpeg_decode_t* ptr, VALUE opt)
|
1035
1649
|
{
|
1036
|
-
if (opt != Qundef) {
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
} else {
|
1041
|
-
ptr->enable_1pass_quant = FALSE;
|
1042
|
-
}
|
1650
|
+
if (opt != Qundef && RTEST(opt)) {
|
1651
|
+
ptr->enable_1pass_quant = TRUE;
|
1652
|
+
} else {
|
1653
|
+
ptr->enable_1pass_quant = FALSE;
|
1043
1654
|
}
|
1655
|
+
|
1656
|
+
return Qnil;
|
1044
1657
|
}
|
1045
1658
|
|
1046
|
-
static
|
1047
|
-
|
1659
|
+
static VALUE
|
1660
|
+
eval_decoder_use_external_colormap_opt(jpeg_decode_t* ptr, VALUE opt)
|
1048
1661
|
{
|
1049
|
-
if (opt != Qundef) {
|
1050
|
-
if (RTEST(opt)) {
|
1662
|
+
if (opt != Qundef && RTEST(opt)) {
|
1051
1663
|
ptr->enable_external_quant = TRUE;
|
1052
|
-
ptr->buffered_image = TRUE;
|
1053
1664
|
} else {
|
1054
1665
|
ptr->enable_external_quant = FALSE;
|
1055
1666
|
}
|
1056
1667
|
}
|
1668
|
+
|
1669
|
+
return Qnil;
|
1057
1670
|
}
|
1058
1671
|
|
1059
|
-
static
|
1060
|
-
|
1672
|
+
static VALUE
|
1673
|
+
eval_decoder_use_2pass_quantizer_opt(jpeg_decode_t* ptr, VALUE opt)
|
1061
1674
|
{
|
1062
|
-
if (opt != Qundef) {
|
1063
|
-
if (RTEST(opt)) {
|
1675
|
+
if (opt != Qundef && RTEST(opt)) {
|
1064
1676
|
ptr->enable_2pass_quant = TRUE;
|
1065
|
-
ptr->buffered_image = TRUE;
|
1066
1677
|
} else {
|
1067
1678
|
ptr->enable_2pass_quant = FALSE;
|
1068
1679
|
}
|
1069
1680
|
}
|
1681
|
+
|
1682
|
+
return Qnil;
|
1070
1683
|
}
|
1684
|
+
#endif
|
1071
1685
|
|
1072
|
-
static
|
1073
|
-
|
1686
|
+
static VALUE
|
1687
|
+
eval_decoder_without_meta_opt(jpeg_decode_t* ptr, VALUE opt)
|
1074
1688
|
{
|
1075
|
-
if (opt != Qundef) {
|
1076
|
-
ptr
|
1689
|
+
if (opt != Qundef && RTEST(opt)) {
|
1690
|
+
CLR_FLAG(ptr, F_NEED_META);
|
1691
|
+
} else {
|
1692
|
+
SET_FLAG(ptr, F_NEED_META);
|
1077
1693
|
}
|
1694
|
+
|
1695
|
+
return Qnil;
|
1078
1696
|
}
|
1079
1697
|
|
1080
|
-
static
|
1081
|
-
|
1698
|
+
static VALUE
|
1699
|
+
eval_decoder_expand_colormap_opt(jpeg_decode_t* ptr, VALUE opt)
|
1082
1700
|
{
|
1083
|
-
if (opt != Qundef) {
|
1084
|
-
ptr
|
1701
|
+
if (opt != Qundef && RTEST(opt)) {
|
1702
|
+
SET_FLAG(ptr, F_EXPAND_COLORMAP);
|
1703
|
+
} else {
|
1704
|
+
CLR_FLAG(ptr, F_EXPAND_COLORMAP);
|
1085
1705
|
}
|
1706
|
+
|
1707
|
+
return Qnil;
|
1086
1708
|
}
|
1087
1709
|
|
1088
|
-
|
1089
|
-
|
1710
|
+
|
1711
|
+
static VALUE
|
1712
|
+
eval_decoder_scale_opt(jpeg_decode_t* ptr, VALUE opt)
|
1090
1713
|
{
|
1714
|
+
VALUE ret;
|
1715
|
+
int scale_num;
|
1716
|
+
int scale_denom;
|
1717
|
+
|
1718
|
+
ret = Qnil;
|
1719
|
+
|
1091
1720
|
switch (TYPE(opt)) {
|
1092
1721
|
case T_UNDEF:
|
1093
|
-
|
1722
|
+
scale_num = 1;
|
1723
|
+
scale_denom = 1;
|
1724
|
+
break;
|
1725
|
+
|
1726
|
+
case T_FIXNUM:
|
1727
|
+
if (FIX2LONG(opt) <= 0) {
|
1728
|
+
ret = create_range_error(":scale less equal 0");
|
1729
|
+
|
1730
|
+
} else {
|
1731
|
+
scale_num = FIX2INT(opt) * 1000;
|
1732
|
+
scale_denom = 1000;
|
1733
|
+
}
|
1094
1734
|
break;
|
1095
1735
|
|
1096
1736
|
case T_FLOAT:
|
1097
|
-
|
1098
|
-
|
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;
|
1746
|
+
}
|
1099
1747
|
break;
|
1100
1748
|
|
1101
1749
|
case T_RATIONAL:
|
1102
|
-
|
1103
|
-
|
1750
|
+
scale_num = (int)FIX2LONG(rb_rational_num(opt));
|
1751
|
+
scale_denom = (int)FIX2LONG(rb_rational_den(opt));
|
1104
1752
|
break;
|
1105
1753
|
|
1106
1754
|
default:
|
1107
|
-
|
1755
|
+
ret = create_type_error("unsupportd :scale option type");
|
1108
1756
|
break;
|
1109
1757
|
}
|
1758
|
+
|
1759
|
+
if (!RTEST(ret)) {
|
1760
|
+
ptr->scale_num = scale_num;
|
1761
|
+
ptr->scale_denom = scale_denom;
|
1762
|
+
}
|
1763
|
+
|
1764
|
+
return ret;
|
1110
1765
|
}
|
1111
1766
|
|
1112
|
-
static
|
1113
|
-
|
1767
|
+
static VALUE
|
1768
|
+
eval_decoder_dct_method_opt(jpeg_decode_t* ptr, VALUE opt)
|
1114
1769
|
{
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
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;
|
1118
1787
|
|
1119
1788
|
} else if (EQ_STR(opt, "IFAST")) {
|
1120
|
-
|
1789
|
+
dct_method = JDCT_IFAST;
|
1121
1790
|
|
1122
1791
|
} else if (EQ_STR(opt, "FLOAT")) {
|
1123
|
-
|
1124
|
-
|
1125
|
-
} else if (EQ_STR(opt, "FASTEST")) {
|
1126
|
-
ptr->dct_method = JDCT_FASTEST;
|
1792
|
+
dct_method = JDCT_FLOAT;
|
1127
1793
|
|
1128
1794
|
} else {
|
1129
|
-
|
1795
|
+
ret = create_argument_error("unsupportd :dct_method option value");
|
1130
1796
|
}
|
1797
|
+
break;
|
1798
|
+
|
1799
|
+
default:
|
1800
|
+
ret = create_type_error("unsupportd :dct_method option type");
|
1801
|
+
break;
|
1131
1802
|
}
|
1803
|
+
|
1804
|
+
if (!RTEST(ret)) ptr->dct_method = dct_method;
|
1805
|
+
|
1806
|
+
return ret;
|
1132
1807
|
}
|
1133
1808
|
|
1134
|
-
static
|
1135
|
-
|
1809
|
+
static VALUE
|
1810
|
+
eval_decoder_with_exif_tags_opt(jpeg_decode_t* ptr, VALUE opt)
|
1811
|
+
{
|
1812
|
+
if (opt != Qundef && RTEST(opt)) {
|
1813
|
+
SET_FLAG(ptr, F_PARSE_EXIF);
|
1814
|
+
} else {
|
1815
|
+
CLR_FLAG(ptr, F_PARSE_EXIF);
|
1816
|
+
}
|
1817
|
+
|
1818
|
+
return Qnil;
|
1819
|
+
}
|
1820
|
+
|
1821
|
+
static VALUE
|
1822
|
+
eval_decoder_orientation_opt(jpeg_decode_t* ptr, VALUE opt)
|
1136
1823
|
{
|
1137
|
-
if (opt != Qundef) {
|
1138
|
-
ptr
|
1824
|
+
if (opt != Qundef && RTEST(opt)) {
|
1825
|
+
SET_FLAG(ptr, F_APPLY_ORIENTATION);
|
1826
|
+
} else {
|
1827
|
+
CLR_FLAG(ptr, F_APPLY_ORIENTATION);
|
1139
1828
|
}
|
1829
|
+
|
1830
|
+
return Qnil;
|
1140
1831
|
}
|
1141
1832
|
|
1142
|
-
static
|
1833
|
+
static VALUE
|
1143
1834
|
set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
1144
1835
|
{
|
1836
|
+
VALUE ret;
|
1145
1837
|
VALUE opts[N(decoder_opts_ids)];
|
1838
|
+
JSAMPARRAY ary;
|
1839
|
+
|
1840
|
+
/*
|
1841
|
+
* initialize
|
1842
|
+
*/
|
1843
|
+
ret = Qnil;
|
1844
|
+
ary = NULL;
|
1146
1845
|
|
1147
1846
|
/*
|
1148
1847
|
* parse options
|
1149
1848
|
*/
|
1150
|
-
|
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);
|
1899
|
+
|
1900
|
+
/*
|
1901
|
+
* alloc memory
|
1902
|
+
*/
|
1903
|
+
if (!RTEST(ret)) {
|
1904
|
+
ary = ALLOC_ARRAY();
|
1905
|
+
if (ary == NULL) ret = create_memory_error();
|
1906
|
+
}
|
1151
1907
|
|
1152
1908
|
/*
|
1153
|
-
* set context
|
1909
|
+
* set the rest context parameter
|
1910
|
+
*/
|
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
|
+
|
1923
|
+
#if 0
|
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
|
+
}
|
1932
|
+
#endif
|
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
|
1154
1942
|
*/
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
eval_decoder_opt_without_meta(ptr, opts[8]);
|
1164
|
-
eval_decoder_opt_expand_colormap(ptr, opts[9]);
|
1165
|
-
eval_decoder_opt_scale(ptr, opts[10]);
|
1166
|
-
eval_decoder_opt_dct_method(ptr, opts[11]);
|
1167
|
-
eval_decoder_opt_with_exif(ptr, opts[12]);
|
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;
|
1168
1951
|
}
|
1169
1952
|
|
1953
|
+
/**
|
1954
|
+
* initialize decoder object
|
1955
|
+
*
|
1956
|
+
* @overload initialize(opts)
|
1957
|
+
*
|
1958
|
+
* @param opts [Hash] options to initialize object
|
1959
|
+
*
|
1960
|
+
* @option opts [Symbol] :pixel_format
|
1961
|
+
* specifies the format of the output image. possible values are:
|
1962
|
+
* YUV422 YUYV RGB565 RGB RGB24 BGR BGR24 YUV444 YCbCr
|
1963
|
+
* RGBX RGB32 BGRX BGR32 GRAYSCALE
|
1964
|
+
*
|
1965
|
+
* @option opts [Float] :output_gamma
|
1966
|
+
*
|
1967
|
+
* @option opts [Boolean] :fancy_upsampling
|
1968
|
+
*
|
1969
|
+
* @option opts [Boolean] :do_smoothing
|
1970
|
+
*
|
1971
|
+
* @option opts [Array] :dither
|
1972
|
+
* specifies dithering parameters. A 3-elements array.
|
1973
|
+
* specify the dither type as a string for the 1st element,
|
1974
|
+
* whether to use 2-pass quantize for the 2nd element as a boolean,
|
1975
|
+
* and the number of colors used for the 3rd element as an integer
|
1976
|
+
* from 16 to 256.
|
1977
|
+
*
|
1978
|
+
* @option opts [Boolean] :without_meta
|
1979
|
+
* specifies whether or not to include meta information in the
|
1980
|
+
* output data. If true, no meta-information is output.
|
1981
|
+
*
|
1982
|
+
* @option opts [Boolean] :expand_colormap
|
1983
|
+
* specifies whether to expand the color map. If dither is specified,
|
1984
|
+
* the output will be a color number of 1 byte per pixel, but if this
|
1985
|
+
* option is set to true, the output will be expanded to color information.
|
1986
|
+
*
|
1987
|
+
* @option opts [Ratioanl] :scale
|
1988
|
+
*
|
1989
|
+
* @option opts [Symbol] :dct_method
|
1990
|
+
* specifies how decoding is handled. possible values are:
|
1991
|
+
* FASTEST ISLOW IFAST FLOAT
|
1992
|
+
*
|
1993
|
+
* @option opts [Boolean] :with_exif_tags
|
1994
|
+
* specifies whether to include Exif tag information in the output data.
|
1995
|
+
* set this option to true to parse the Exif tag information and include
|
1996
|
+
* it in the meta information output.
|
1997
|
+
*
|
1998
|
+
* @option opts [Boolean] :with_exif
|
1999
|
+
* alias to :with_exif_tags option.
|
2000
|
+
*/
|
1170
2001
|
static VALUE
|
1171
2002
|
rb_decoder_initialize( int argc, VALUE *argv, VALUE self)
|
1172
2003
|
{
|
1173
2004
|
jpeg_decode_t* ptr;
|
2005
|
+
VALUE exc;
|
1174
2006
|
VALUE opt;
|
1175
2007
|
|
1176
2008
|
/*
|
1177
2009
|
* initialize
|
1178
2010
|
*/
|
1179
|
-
|
2011
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
1180
2012
|
|
1181
2013
|
/*
|
1182
2014
|
* parse arguments
|
1183
2015
|
*/
|
1184
|
-
rb_scan_args( argc, argv, "
|
1185
|
-
|
1186
|
-
if (opt != Qnil) Check_Type(opt, T_HASH);
|
2016
|
+
rb_scan_args( argc, argv, "0:", &opt);
|
1187
2017
|
|
1188
2018
|
/*
|
1189
2019
|
* set context
|
1190
2020
|
*/
|
1191
|
-
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);
|
1192
2027
|
|
1193
2028
|
return Qtrue;
|
1194
2029
|
}
|
@@ -1197,11 +2032,12 @@ static VALUE
|
|
1197
2032
|
rb_decoder_set(VALUE self, VALUE opt)
|
1198
2033
|
{
|
1199
2034
|
jpeg_decode_t* ptr;
|
2035
|
+
VALUE exc;
|
1200
2036
|
|
1201
2037
|
/*
|
1202
2038
|
* initialize
|
1203
2039
|
*/
|
1204
|
-
|
2040
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
1205
2041
|
|
1206
2042
|
/*
|
1207
2043
|
* check argument
|
@@ -1211,13 +2047,16 @@ rb_decoder_set(VALUE self, VALUE opt)
|
|
1211
2047
|
/*
|
1212
2048
|
* set context
|
1213
2049
|
*/
|
1214
|
-
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);
|
1215
2056
|
|
1216
2057
|
return Qtrue;
|
1217
2058
|
}
|
1218
2059
|
|
1219
|
-
|
1220
|
-
|
1221
2060
|
static VALUE
|
1222
2061
|
get_colorspace_str( J_COLOR_SPACE cs)
|
1223
2062
|
{
|
@@ -1396,7 +2235,7 @@ exif_init(exif_t* ptr, uint8_t* src, size_t size)
|
|
1396
2235
|
uint32_t off;
|
1397
2236
|
|
1398
2237
|
/*
|
1399
|
-
* Check Exif
|
2238
|
+
* Check Exif identifier
|
1400
2239
|
*/
|
1401
2240
|
if (memcmp(src, "Exif\0\0", 6)) {
|
1402
2241
|
rb_raise(decerr_klass, "invalid exif identifier");
|
@@ -1847,7 +2686,7 @@ exif_read(exif_t* ptr, VALUE dst)
|
|
1847
2686
|
#define THUMBNAIL_SIZE ID2SYM(rb_intern("jpeg_interchange_format_length"))
|
1848
2687
|
|
1849
2688
|
static VALUE
|
1850
|
-
|
2689
|
+
create_exif_tags_hash(jpeg_decode_t* ptr)
|
1851
2690
|
{
|
1852
2691
|
VALUE ret;
|
1853
2692
|
jpeg_saved_marker_ptr marker;
|
@@ -1895,99 +2734,291 @@ create_exif_hash(jpeg_decode_t* ptr)
|
|
1895
2734
|
return ret;
|
1896
2735
|
}
|
1897
2736
|
|
1898
|
-
static
|
1899
|
-
|
2737
|
+
static void
|
2738
|
+
pick_exif_orientation(jpeg_decode_t* ptr)
|
1900
2739
|
{
|
1901
|
-
|
1902
|
-
|
2740
|
+
jpeg_saved_marker_ptr marker;
|
2741
|
+
int o9n;
|
2742
|
+
uint8_t* p;
|
2743
|
+
int be;
|
2744
|
+
uint32_t off;
|
2745
|
+
int i;
|
2746
|
+
int n;
|
1903
2747
|
|
1904
|
-
|
2748
|
+
o9n = 0;
|
1905
2749
|
|
1906
|
-
|
1907
|
-
|
2750
|
+
for (marker = ptr->cinfo.marker_list;
|
2751
|
+
marker != NULL; marker = marker->next) {
|
1908
2752
|
|
1909
|
-
|
1910
|
-
rb_ivar_set(ret, id_height, INT2FIX(cinfo->output_height));
|
1911
|
-
rb_ivar_set(ret, id_orig_cs, get_colorspace_str(cinfo->jpeg_color_space));
|
2753
|
+
if (marker->data_length < 14) continue;
|
1912
2754
|
|
1913
|
-
|
1914
|
-
rb_ivar_set(ret, id_out_cs, rb_str_new_cstr("YCrCb"));
|
1915
|
-
} else {
|
1916
|
-
rb_ivar_set(ret, id_out_cs, get_colorspace_str(cinfo->out_color_space));
|
1917
|
-
}
|
2755
|
+
p = marker->data;
|
1918
2756
|
|
1919
|
-
|
2757
|
+
/*
|
2758
|
+
* check Exif identifier
|
2759
|
+
*/
|
2760
|
+
if (memcmp(p, "Exif\0\0", 6)) continue;
|
1920
2761
|
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
2762
|
+
/*
|
2763
|
+
* check endian marker
|
2764
|
+
*/
|
2765
|
+
if (!memcmp(p + 6, "MM", 2)) {
|
2766
|
+
be = !0;
|
1924
2767
|
|
1925
|
-
|
1926
|
-
|
2768
|
+
} else if (!memcmp(p + 6, "II", 2)) {
|
2769
|
+
be = 0;
|
1927
2770
|
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
VALUE ret;
|
2771
|
+
} else {
|
2772
|
+
continue;
|
2773
|
+
}
|
1932
2774
|
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
2775
|
+
/*
|
2776
|
+
* check TIFF identifier
|
2777
|
+
*/
|
2778
|
+
if (get_u16(p + 8, be) != 0x002a) continue;
|
2779
|
+
|
2780
|
+
/*
|
2781
|
+
* set 0th IFD address
|
2782
|
+
*/
|
2783
|
+
off = get_u32(p + 10, be);
|
2784
|
+
if (off < 8 || off >= marker->data_length - 6) continue;
|
2785
|
+
|
2786
|
+
p += (6 + off);
|
2787
|
+
|
2788
|
+
/* ここまでくればAPP1がExifタグなので
|
2789
|
+
* 0th IFDをなめてOrientationタグを探す */
|
2790
|
+
|
2791
|
+
n = get_u16(p, be);
|
2792
|
+
p += 2;
|
2793
|
+
|
2794
|
+
for (i = 0; i < n; i++) {
|
2795
|
+
int tag;
|
2796
|
+
int type;
|
2797
|
+
int num;
|
2798
|
+
|
2799
|
+
tag = get_u16(p + 0, be);
|
2800
|
+
type = get_u16(p + 2, be);
|
2801
|
+
num = get_u32(p + 4, be);
|
2802
|
+
|
2803
|
+
if (tag == 0x0112) {
|
2804
|
+
if (type == 3 && num == 1) {
|
2805
|
+
o9n = get_u16(p + 8, be);
|
2806
|
+
goto loop_out;
|
2807
|
+
|
2808
|
+
} else {
|
2809
|
+
fprintf(stderr,
|
2810
|
+
"Illeagal orientation tag found [type:%d, num:%d]\n",
|
2811
|
+
type,
|
2812
|
+
num);
|
2813
|
+
}
|
2814
|
+
}
|
2815
|
+
|
2816
|
+
p += 12;
|
2817
|
+
}
|
2818
|
+
}
|
2819
|
+
loop_out:
|
2820
|
+
|
2821
|
+
ptr->orientation.value = (o9n >= 1 && o9n <= 8)? (o9n - 1): 0;
|
2822
|
+
}
|
2823
|
+
|
2824
|
+
static VALUE
|
2825
|
+
create_colormap(jpeg_decode_t* ptr)
|
2826
|
+
{
|
2827
|
+
VALUE ret;
|
2828
|
+
struct jpeg_decompress_struct* cinfo;
|
2829
|
+
JSAMPARRAY map;
|
2830
|
+
int i; // volatileを外すとaarch64のgcc6でクラッシュする場合がある
|
2831
|
+
uint32_t c;
|
2832
|
+
|
2833
|
+
cinfo = &ptr->cinfo;
|
2834
|
+
ret = rb_ary_new_capa(cinfo->actual_number_of_colors);
|
2835
|
+
map = cinfo->colormap;
|
2836
|
+
|
2837
|
+
switch (cinfo->out_color_components) {
|
2838
|
+
case 1:
|
2839
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2840
|
+
c = map[0][i];
|
2841
|
+
rb_ary_push(ret, INT2FIX(c));
|
2842
|
+
}
|
2843
|
+
break;
|
2844
|
+
|
2845
|
+
case 2:
|
2846
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2847
|
+
c = (map[0][i] << 8) | (map[1][i] << 0);
|
2848
|
+
rb_ary_push(ret, INT2FIX(c));
|
2849
|
+
}
|
2850
|
+
break;
|
2851
|
+
|
2852
|
+
case 3:
|
2853
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2854
|
+
c = (map[0][i] << 16) | (map[1][i] << 8) | (map[2][i] << 0);
|
2855
|
+
|
2856
|
+
rb_ary_push(ret, INT2FIX(c));
|
2857
|
+
}
|
1937
2858
|
break;
|
2859
|
+
|
2860
|
+
default:
|
2861
|
+
RUNTIME_ERROR("this number of components is not implemented yet");
|
1938
2862
|
}
|
1939
2863
|
|
1940
|
-
|
2864
|
+
return ret;
|
2865
|
+
}
|
1941
2866
|
|
1942
|
-
|
1943
|
-
|
1944
|
-
|
1945
|
-
|
2867
|
+
static VALUE
|
2868
|
+
rb_meta_exif_tags(VALUE self)
|
2869
|
+
{
|
2870
|
+
return rb_ivar_get(self, id_exif_tags);
|
2871
|
+
}
|
1946
2872
|
|
1947
|
-
|
1948
|
-
|
2873
|
+
static VALUE
|
2874
|
+
create_meta(jpeg_decode_t* ptr)
|
2875
|
+
{
|
2876
|
+
VALUE ret;
|
2877
|
+
struct jpeg_decompress_struct* cinfo;
|
2878
|
+
int width;
|
2879
|
+
int height;
|
2880
|
+
int stride;
|
2881
|
+
|
2882
|
+
ret = rb_obj_alloc(meta_klass);
|
2883
|
+
cinfo = &ptr->cinfo;
|
2884
|
+
|
2885
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION) && (ptr->orientation.value & 4)) {
|
2886
|
+
width = cinfo->output_height;
|
2887
|
+
height = cinfo->output_width;
|
2888
|
+
} else {
|
2889
|
+
width = cinfo->output_width;
|
2890
|
+
height = cinfo->output_height;
|
2891
|
+
}
|
2892
|
+
|
2893
|
+
stride = cinfo->output_width * cinfo->output_components;
|
2894
|
+
|
2895
|
+
rb_ivar_set(ret, id_width, INT2FIX(width));
|
2896
|
+
rb_ivar_set(ret, id_stride, INT2FIX(stride));
|
2897
|
+
rb_ivar_set(ret, id_height, INT2FIX(height));
|
2898
|
+
|
2899
|
+
rb_ivar_set(ret, id_orig_cs, get_colorspace_str(cinfo->jpeg_color_space));
|
2900
|
+
|
2901
|
+
if (ptr->format == FMT_YVU) {
|
2902
|
+
rb_ivar_set(ret, id_out_cs, rb_str_new_cstr("YCrCb"));
|
2903
|
+
} else {
|
2904
|
+
rb_ivar_set(ret, id_out_cs, get_colorspace_str(cinfo->out_color_space));
|
2905
|
+
}
|
2906
|
+
|
2907
|
+
if (TEST_FLAG_ALL(ptr, F_DITHER | F_EXPAND_COLORMAP)) {
|
2908
|
+
rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->out_color_components));
|
2909
|
+
} else {
|
2910
|
+
rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->output_components));
|
2911
|
+
}
|
2912
|
+
|
2913
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF)) {
|
2914
|
+
rb_ivar_set(ret, id_exif_tags, create_exif_tags_hash(ptr));
|
2915
|
+
rb_define_singleton_method(ret, "exif_tags", rb_meta_exif_tags, 0);
|
2916
|
+
rb_define_singleton_method(ret, "exif", rb_meta_exif_tags, 0);
|
2917
|
+
}
|
2918
|
+
|
2919
|
+
if (TEST_FLAG(ptr, F_DITHER)) {
|
2920
|
+
rb_ivar_set(ret, id_colormap, create_colormap(ptr));
|
2921
|
+
}
|
2922
|
+
|
2923
|
+
return ret;
|
2924
|
+
}
|
2925
|
+
|
2926
|
+
static VALUE
|
2927
|
+
do_read_header(VALUE _ptr)
|
2928
|
+
{
|
2929
|
+
VALUE ret;
|
2930
|
+
jpeg_decode_t* ptr;
|
2931
|
+
uint8_t* data;
|
2932
|
+
size_t size;
|
2933
|
+
|
2934
|
+
/*
|
2935
|
+
* initialize
|
2936
|
+
*/
|
2937
|
+
ret = Qnil;
|
2938
|
+
ptr = (jpeg_decode_t*)_ptr;
|
2939
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
2940
|
+
size = RSTRING_LEN(ptr->data);
|
2941
|
+
|
2942
|
+
/*
|
2943
|
+
* process body
|
2944
|
+
*/
|
2945
|
+
ptr->cinfo.raw_data_out = FALSE;
|
2946
|
+
ptr->cinfo.dct_method = JDCT_FLOAT;
|
1949
2947
|
|
1950
2948
|
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
1951
|
-
|
2949
|
+
/*
|
2950
|
+
* when error occurred
|
2951
|
+
*/
|
1952
2952
|
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
2953
|
+
|
1953
2954
|
} else {
|
1954
|
-
|
2955
|
+
/*
|
2956
|
+
* normal path
|
2957
|
+
*/
|
2958
|
+
jpeg_mem_src(&ptr->cinfo, data, size);
|
1955
2959
|
|
1956
|
-
if (ptr
|
2960
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
1957
2961
|
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
1958
2962
|
}
|
1959
2963
|
|
1960
2964
|
jpeg_read_header(&ptr->cinfo, TRUE);
|
1961
2965
|
jpeg_calc_output_dimensions(&ptr->cinfo);
|
1962
2966
|
|
1963
|
-
|
2967
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION)) {
|
2968
|
+
pick_exif_orientation(ptr);
|
2969
|
+
}
|
1964
2970
|
|
1965
|
-
|
2971
|
+
ret = create_meta(ptr);
|
1966
2972
|
}
|
1967
2973
|
|
1968
2974
|
return ret;
|
1969
2975
|
}
|
1970
2976
|
|
2977
|
+
/**
|
2978
|
+
* read meta data
|
2979
|
+
*
|
2980
|
+
* @overload read_header(jpeg)
|
2981
|
+
*
|
2982
|
+
* @param jpeg [String] input data.
|
2983
|
+
*
|
2984
|
+
* @return [JPEG::Meta] metadata.
|
2985
|
+
*/
|
1971
2986
|
static VALUE
|
1972
2987
|
rb_decoder_read_header(VALUE self, VALUE data)
|
1973
2988
|
{
|
1974
2989
|
VALUE ret;
|
1975
2990
|
jpeg_decode_t* ptr;
|
2991
|
+
int state;
|
1976
2992
|
|
1977
2993
|
/*
|
1978
2994
|
* initialize
|
1979
2995
|
*/
|
1980
|
-
|
2996
|
+
ret = Qnil;
|
2997
|
+
state = 0;
|
2998
|
+
|
2999
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
1981
3000
|
|
1982
3001
|
/*
|
1983
3002
|
* argument check
|
1984
3003
|
*/
|
1985
3004
|
Check_Type(data, T_STRING);
|
1986
3005
|
|
3006
|
+
/*
|
3007
|
+
* prepare
|
3008
|
+
*/
|
3009
|
+
SET_DATA(ptr, data);
|
3010
|
+
|
1987
3011
|
/*
|
1988
3012
|
* do encode
|
1989
3013
|
*/
|
1990
|
-
ret = do_read_header
|
3014
|
+
ret = rb_protect(do_read_header, (VALUE)ptr, &state);
|
3015
|
+
|
3016
|
+
/*
|
3017
|
+
* post process
|
3018
|
+
*/
|
3019
|
+
CLR_DATA(ptr);
|
3020
|
+
|
3021
|
+
if (state != 0) rb_jump_tag(state);
|
1991
3022
|
|
1992
3023
|
return ret;
|
1993
3024
|
}
|
@@ -2018,7 +3049,7 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2018
3049
|
*/
|
2019
3050
|
|
2020
3051
|
VALUE ret;
|
2021
|
-
int i;
|
3052
|
+
volatile int i; // volatileを外すとaarch64のgcc6でクラッシュする場合がある
|
2022
3053
|
int n;
|
2023
3054
|
uint8_t* dst;
|
2024
3055
|
JSAMPARRAY map;
|
@@ -2035,6 +3066,15 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2035
3066
|
}
|
2036
3067
|
break;
|
2037
3068
|
|
3069
|
+
case 2:
|
3070
|
+
for (i = 0; i < n; i++) {
|
3071
|
+
dst[0] = map[0][src[i]];
|
3072
|
+
dst[1] = map[1][src[i]];
|
3073
|
+
|
3074
|
+
dst += 2;
|
3075
|
+
}
|
3076
|
+
break;
|
3077
|
+
|
2038
3078
|
case 3:
|
2039
3079
|
for (i = 0; i < n; i++) {
|
2040
3080
|
dst[0] = map[0][src[i]];
|
@@ -2046,7 +3086,7 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2046
3086
|
break;
|
2047
3087
|
|
2048
3088
|
default:
|
2049
|
-
RUNTIME_ERROR("
|
3089
|
+
RUNTIME_ERROR("this number of components is not implemented yet");
|
2050
3090
|
}
|
2051
3091
|
|
2052
3092
|
rb_str_set_len(ret, n * cinfo->out_color_components);
|
@@ -2067,10 +3107,417 @@ swap_cbcr(uint8_t* p, size_t size)
|
|
2067
3107
|
}
|
2068
3108
|
}
|
2069
3109
|
|
3110
|
+
static void
|
3111
|
+
do_transpose8(uint8_t* img, int wd, int ht, void* dst)
|
3112
|
+
{
|
3113
|
+
int x;
|
3114
|
+
int y;
|
3115
|
+
|
3116
|
+
uint8_t* sp;
|
3117
|
+
uint8_t* dp;
|
3118
|
+
|
3119
|
+
sp = (uint8_t*)img;
|
3120
|
+
|
3121
|
+
for (y = 0; y < ht; y++) {
|
3122
|
+
dp = (uint8_t*)dst + y;
|
3123
|
+
|
3124
|
+
for (x = 0; x < wd; x++) {
|
3125
|
+
*dp = *sp;
|
3126
|
+
|
3127
|
+
sp++;
|
3128
|
+
dp += ht;
|
3129
|
+
}
|
3130
|
+
}
|
3131
|
+
}
|
3132
|
+
|
3133
|
+
static void
|
3134
|
+
do_transpose16(void* img, int wd, int ht, void* dst)
|
3135
|
+
{
|
3136
|
+
int x;
|
3137
|
+
int y;
|
3138
|
+
|
3139
|
+
uint16_t* sp;
|
3140
|
+
uint16_t* dp;
|
3141
|
+
|
3142
|
+
sp = (uint16_t*)img;
|
3143
|
+
|
3144
|
+
for (y = 0; y < ht; y++) {
|
3145
|
+
dp = (uint16_t*)dst + y;
|
3146
|
+
|
3147
|
+
for (x = 0; x < wd; x++) {
|
3148
|
+
*dp = *sp;
|
3149
|
+
|
3150
|
+
sp++;
|
3151
|
+
dp += ht;
|
3152
|
+
}
|
3153
|
+
}
|
3154
|
+
}
|
3155
|
+
|
3156
|
+
static void
|
3157
|
+
do_transpose24(void* img, int wd, int ht, void* dst)
|
3158
|
+
{
|
3159
|
+
int x;
|
3160
|
+
int y;
|
3161
|
+
int st;
|
3162
|
+
|
3163
|
+
uint8_t* sp;
|
3164
|
+
uint8_t* dp;
|
3165
|
+
|
3166
|
+
sp = (uint8_t*)img;
|
3167
|
+
st = ht * 3;
|
3168
|
+
|
3169
|
+
for (y = 0; y < ht; y++) {
|
3170
|
+
dp = (uint8_t*)dst + (y * 3);
|
3171
|
+
|
3172
|
+
for (x = 0; x < wd; x++) {
|
3173
|
+
dp[0] = sp[0];
|
3174
|
+
dp[1] = sp[1];
|
3175
|
+
dp[2] = sp[2];
|
3176
|
+
|
3177
|
+
sp += 3;
|
3178
|
+
dp += st;
|
3179
|
+
}
|
3180
|
+
}
|
3181
|
+
}
|
3182
|
+
|
3183
|
+
static void
|
3184
|
+
do_transpose32(void* img, int wd, int ht, void* dst)
|
3185
|
+
{
|
3186
|
+
int x;
|
3187
|
+
int y;
|
3188
|
+
|
3189
|
+
uint32_t* sp;
|
3190
|
+
uint32_t* dp;
|
3191
|
+
|
3192
|
+
sp = (uint32_t*)img;
|
3193
|
+
|
3194
|
+
for (y = 0; y < ht; y++) {
|
3195
|
+
dp = (uint32_t*)dst + y;
|
3196
|
+
|
3197
|
+
for (x = 0; x < wd; x++) {
|
3198
|
+
*dp = *sp;
|
3199
|
+
|
3200
|
+
sp++;
|
3201
|
+
dp += ht;
|
3202
|
+
}
|
3203
|
+
}
|
3204
|
+
}
|
3205
|
+
|
3206
|
+
static void
|
3207
|
+
do_transpose(void* img, int wd, int ht, int nc, void* dst)
|
3208
|
+
{
|
3209
|
+
switch (nc) {
|
3210
|
+
case 1:
|
3211
|
+
do_transpose8(img, wd, ht, dst);
|
3212
|
+
break;
|
3213
|
+
|
3214
|
+
case 2:
|
3215
|
+
do_transpose16(img, wd, ht, dst);
|
3216
|
+
break;
|
3217
|
+
|
3218
|
+
case 3:
|
3219
|
+
do_transpose24(img, wd, ht, dst);
|
3220
|
+
break;
|
3221
|
+
|
3222
|
+
case 4:
|
3223
|
+
do_transpose32(img, wd, ht, dst);
|
3224
|
+
break;
|
3225
|
+
}
|
3226
|
+
}
|
3227
|
+
|
3228
|
+
static void
|
3229
|
+
do_upside_down8(void* img, int wd, int ht)
|
3230
|
+
{
|
3231
|
+
uint8_t* sp;
|
3232
|
+
uint8_t* dp;
|
3233
|
+
|
3234
|
+
sp = (uint8_t*)img;
|
3235
|
+
dp = (uint8_t*)img + ((wd * ht) - 1);
|
3236
|
+
|
3237
|
+
while (sp < dp) {
|
3238
|
+
SWAP(*sp, *dp, uint8_t);
|
3239
|
+
|
3240
|
+
sp++;
|
3241
|
+
dp--;
|
3242
|
+
}
|
3243
|
+
}
|
3244
|
+
|
3245
|
+
static void
|
3246
|
+
do_upside_down16(void* img, int wd, int ht)
|
3247
|
+
{
|
3248
|
+
uint16_t* sp;
|
3249
|
+
uint16_t* dp;
|
3250
|
+
|
3251
|
+
sp = (uint16_t*)img;
|
3252
|
+
dp = (uint16_t*)img + ((wd * ht) - 1);
|
3253
|
+
|
3254
|
+
while (sp < dp) {
|
3255
|
+
SWAP(*sp, *dp, uint8_t);
|
3256
|
+
|
3257
|
+
sp++;
|
3258
|
+
dp--;
|
3259
|
+
}
|
3260
|
+
}
|
3261
|
+
|
3262
|
+
static void
|
3263
|
+
do_upside_down24(void* img, int wd, int ht)
|
3264
|
+
{
|
3265
|
+
uint8_t* sp;
|
3266
|
+
uint8_t* dp;
|
3267
|
+
|
3268
|
+
sp = (uint8_t*)img;
|
3269
|
+
dp = (uint8_t*)img + ((wd * ht * 3) - 3);
|
3270
|
+
|
3271
|
+
while (sp < dp) {
|
3272
|
+
SWAP(sp[0], dp[0], uint8_t);
|
3273
|
+
SWAP(sp[1], dp[1], uint8_t);
|
3274
|
+
SWAP(sp[2], dp[2], uint8_t);
|
3275
|
+
|
3276
|
+
sp += 3;
|
3277
|
+
dp -= 3;
|
3278
|
+
}
|
3279
|
+
}
|
3280
|
+
|
3281
|
+
static void
|
3282
|
+
do_upside_down32(void* img, int wd, int ht)
|
3283
|
+
{
|
3284
|
+
uint32_t* sp;
|
3285
|
+
uint32_t* dp;
|
3286
|
+
|
3287
|
+
sp = (uint32_t*)img;
|
3288
|
+
dp = (uint32_t*)img + ((wd * ht) - 1);
|
3289
|
+
|
3290
|
+
ht /= 2;
|
3291
|
+
|
3292
|
+
while (sp < dp) {
|
3293
|
+
SWAP(*sp, *dp, uint32_t);
|
3294
|
+
|
3295
|
+
sp++;
|
3296
|
+
dp--;
|
3297
|
+
}
|
3298
|
+
}
|
3299
|
+
|
3300
|
+
static void
|
3301
|
+
do_upside_down(void* img, int wd, int ht, int nc)
|
3302
|
+
{
|
3303
|
+
switch (nc) {
|
3304
|
+
case 1:
|
3305
|
+
do_upside_down8(img, wd, ht);
|
3306
|
+
break;
|
3307
|
+
|
3308
|
+
case 2:
|
3309
|
+
do_upside_down16(img, wd, ht);
|
3310
|
+
break;
|
3311
|
+
|
3312
|
+
case 3:
|
3313
|
+
do_upside_down24(img, wd, ht);
|
3314
|
+
break;
|
3315
|
+
|
3316
|
+
case 4:
|
3317
|
+
do_upside_down32(img, wd, ht);
|
3318
|
+
break;
|
3319
|
+
}
|
3320
|
+
}
|
3321
|
+
|
3322
|
+
static void
|
3323
|
+
do_flip_horizon8(void* img, int wd, int ht)
|
3324
|
+
{
|
3325
|
+
int y;
|
3326
|
+
int st;
|
3327
|
+
|
3328
|
+
uint8_t* sp;
|
3329
|
+
uint8_t* dp;
|
3330
|
+
|
3331
|
+
st = wd;
|
3332
|
+
wd /= 2;
|
3333
|
+
|
3334
|
+
sp = (uint8_t*)img;
|
3335
|
+
dp = (uint8_t*)img + (st - 1);
|
3336
|
+
|
3337
|
+
for (y = 0; y < ht; y++) {
|
3338
|
+
while (sp < dp) {
|
3339
|
+
SWAP(*sp, *dp, uint8_t);
|
3340
|
+
|
3341
|
+
sp++;
|
3342
|
+
dp--;
|
3343
|
+
}
|
3344
|
+
|
3345
|
+
sp = sp - wd + st;
|
3346
|
+
dp = sp + (st - 1);
|
3347
|
+
}
|
3348
|
+
}
|
3349
|
+
|
3350
|
+
static void
|
3351
|
+
do_flip_horizon16(void* img, int wd, int ht)
|
3352
|
+
{
|
3353
|
+
int y;
|
3354
|
+
int st;
|
3355
|
+
|
3356
|
+
uint16_t* sp;
|
3357
|
+
uint16_t* dp;
|
3358
|
+
|
3359
|
+
st = wd;
|
3360
|
+
wd /= 2;
|
3361
|
+
|
3362
|
+
sp = (uint16_t*)img;
|
3363
|
+
dp = (uint16_t*)img + (st - 1);
|
3364
|
+
|
3365
|
+
for (y = 0; y < ht; y++) {
|
3366
|
+
while (sp < dp) {
|
3367
|
+
SWAP(*sp, *dp, uint16_t);
|
3368
|
+
|
3369
|
+
sp++;
|
3370
|
+
dp--;
|
3371
|
+
}
|
3372
|
+
|
3373
|
+
sp = sp - wd + st;
|
3374
|
+
dp = sp + (st - 1);
|
3375
|
+
}
|
3376
|
+
}
|
3377
|
+
|
3378
|
+
static void
|
3379
|
+
do_flip_horizon24(void* img, int wd, int ht)
|
3380
|
+
{
|
3381
|
+
int y;
|
3382
|
+
int st;
|
3383
|
+
|
3384
|
+
uint8_t* sp;
|
3385
|
+
uint8_t* dp;
|
3386
|
+
|
3387
|
+
st = wd * 3;
|
3388
|
+
wd /= 2;
|
3389
|
+
|
3390
|
+
sp = (uint8_t*)img;
|
3391
|
+
dp = (uint8_t*)img + (st - 3);
|
3392
|
+
|
3393
|
+
for (y = 0; y < ht; y++) {
|
3394
|
+
while (sp < dp) {
|
3395
|
+
SWAP(sp[0], dp[0], uint8_t);
|
3396
|
+
SWAP(sp[1], dp[1], uint8_t);
|
3397
|
+
SWAP(sp[2], dp[2], uint8_t);
|
3398
|
+
|
3399
|
+
sp += 3;
|
3400
|
+
dp -= 3;
|
3401
|
+
}
|
3402
|
+
|
3403
|
+
sp = (sp - (wd * 3)) + st;
|
3404
|
+
dp = sp + (st - 3);
|
3405
|
+
}
|
3406
|
+
}
|
3407
|
+
|
3408
|
+
static void
|
3409
|
+
do_flip_horizon32(void* img, int wd, int ht)
|
3410
|
+
{
|
3411
|
+
int y;
|
3412
|
+
int st;
|
3413
|
+
|
3414
|
+
uint32_t* sp;
|
3415
|
+
uint32_t* dp;
|
3416
|
+
|
3417
|
+
st = wd;
|
3418
|
+
wd /= 2;
|
3419
|
+
|
3420
|
+
sp = (uint32_t*)img;
|
3421
|
+
dp = (uint32_t*)img + (st - 1);
|
3422
|
+
|
3423
|
+
for (y = 0; y < ht; y++) {
|
3424
|
+
while (sp < dp) {
|
3425
|
+
SWAP(*sp, *dp, uint32_t);
|
3426
|
+
|
3427
|
+
sp++;
|
3428
|
+
dp--;
|
3429
|
+
}
|
3430
|
+
|
3431
|
+
sp = sp - wd + st;
|
3432
|
+
dp = sp + (st - 1);
|
3433
|
+
}
|
3434
|
+
}
|
3435
|
+
|
3436
|
+
static void
|
3437
|
+
do_flip_horizon(void* img, int wd, int ht, int nc)
|
3438
|
+
{
|
3439
|
+
switch (nc) {
|
3440
|
+
case 1:
|
3441
|
+
do_flip_horizon8(img, wd, ht);
|
3442
|
+
break;
|
3443
|
+
|
3444
|
+
case 2:
|
3445
|
+
do_flip_horizon16(img, wd, ht);
|
3446
|
+
break;
|
3447
|
+
|
3448
|
+
case 3:
|
3449
|
+
do_flip_horizon24(img, wd, ht);
|
3450
|
+
break;
|
3451
|
+
|
3452
|
+
case 4:
|
3453
|
+
do_flip_horizon32(img, wd, ht);
|
3454
|
+
break;
|
3455
|
+
}
|
3456
|
+
}
|
3457
|
+
|
3458
|
+
static VALUE
|
3459
|
+
shift_orientation_buffer(jpeg_decode_t* ptr, VALUE img)
|
3460
|
+
{
|
3461
|
+
VALUE ret;
|
3462
|
+
int len;
|
3463
|
+
|
3464
|
+
ret = ptr->orientation.buf;
|
3465
|
+
len = RSTRING_LEN(img);
|
3466
|
+
|
3467
|
+
if (ret == Qnil || RSTRING_LEN(ret) != len) {
|
3468
|
+
ret = rb_str_buf_new(len);
|
3469
|
+
rb_str_set_len(ret, len);
|
3470
|
+
}
|
3471
|
+
|
3472
|
+
ptr->orientation.buf = img;
|
3473
|
+
|
3474
|
+
return ret;
|
3475
|
+
}
|
3476
|
+
|
3477
|
+
static VALUE
|
3478
|
+
apply_orientation(jpeg_decode_t* ptr, VALUE img)
|
3479
|
+
{
|
3480
|
+
struct jpeg_decompress_struct* cinfo;
|
3481
|
+
int wd;
|
3482
|
+
int ht;
|
3483
|
+
int nc;
|
3484
|
+
VALUE tmp;
|
3485
|
+
|
3486
|
+
cinfo = &ptr->cinfo;
|
3487
|
+
wd = cinfo->output_width;
|
3488
|
+
ht = cinfo->output_height;
|
3489
|
+
nc = cinfo->output_components;
|
3490
|
+
|
3491
|
+
if (ptr->orientation.value & 4) {
|
3492
|
+
/* 転置は交換アルゴリズムでは実装できないので新規バッファを
|
3493
|
+
用意する */
|
3494
|
+
tmp = img;
|
3495
|
+
img = shift_orientation_buffer(ptr, tmp);
|
3496
|
+
SWAP(wd, ht, int);
|
3497
|
+
|
3498
|
+
do_transpose(RSTRING_PTR(tmp), ht, wd, nc, RSTRING_PTR(img));
|
3499
|
+
}
|
3500
|
+
|
3501
|
+
if (ptr->orientation.value & 2) {
|
3502
|
+
do_upside_down(RSTRING_PTR(img), wd, ht, nc);
|
3503
|
+
}
|
3504
|
+
|
3505
|
+
if (ptr->orientation.value & 1) {
|
3506
|
+
do_flip_horizon(RSTRING_PTR(img), wd, ht, nc);
|
3507
|
+
}
|
3508
|
+
|
3509
|
+
return img;
|
3510
|
+
}
|
3511
|
+
|
2070
3512
|
static VALUE
|
2071
|
-
do_decode(
|
3513
|
+
do_decode(VALUE _ptr)
|
2072
3514
|
{
|
2073
3515
|
VALUE ret;
|
3516
|
+
|
3517
|
+
jpeg_decode_t* ptr;
|
3518
|
+
uint8_t* data;
|
3519
|
+
size_t size;
|
3520
|
+
|
2074
3521
|
struct jpeg_decompress_struct* cinfo;
|
2075
3522
|
JSAMPARRAY array;
|
2076
3523
|
|
@@ -2080,118 +3527,149 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2080
3527
|
int i;
|
2081
3528
|
int j;
|
2082
3529
|
|
2083
|
-
|
3530
|
+
/*
|
3531
|
+
* initialize
|
3532
|
+
*/
|
3533
|
+
ret = Qnil; // warning対策
|
3534
|
+
ptr = (jpeg_decode_t*)_ptr;
|
3535
|
+
data = (uint8_t*)RSTRING_PTR(ptr->data);
|
3536
|
+
size = RSTRING_LEN(ptr->data);
|
2084
3537
|
cinfo = &ptr->cinfo;
|
2085
|
-
array =
|
2086
|
-
|
2087
|
-
switch (ptr->format) {
|
2088
|
-
case FMT_YUV422:
|
2089
|
-
case FMT_RGB565:
|
2090
|
-
RUNTIME_ERROR( "Not implement");
|
2091
|
-
break;
|
3538
|
+
array = ptr->array;
|
2092
3539
|
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
3540
|
+
/*
|
3541
|
+
* do decode
|
3542
|
+
*/
|
3543
|
+
if (setjmp(ptr->err_mgr.jmpbuf)) {
|
3544
|
+
/*
|
3545
|
+
* when error occurred
|
3546
|
+
*/
|
3547
|
+
jpeg_abort_decompress(&ptr->cinfo);
|
3548
|
+
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
2101
3549
|
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
3550
|
+
} else {
|
3551
|
+
/*
|
3552
|
+
* initialize
|
3553
|
+
*/
|
3554
|
+
jpeg_mem_src(cinfo, data, size);
|
2106
3555
|
|
2107
|
-
if (
|
2108
|
-
|
2109
|
-
|
3556
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
3557
|
+
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
3558
|
+
}
|
2110
3559
|
|
2111
|
-
|
2112
|
-
|
3560
|
+
jpeg_read_header(cinfo, TRUE);
|
3561
|
+
jpeg_calc_output_dimensions(cinfo);
|
2113
3562
|
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
cinfo->enable_2pass_quant = ptr->enable_2pass_quant;
|
2135
|
-
|
2136
|
-
jpeg_calc_output_dimensions(cinfo);
|
2137
|
-
jpeg_start_decompress(cinfo);
|
2138
|
-
|
2139
|
-
stride = cinfo->output_components * cinfo->output_width;
|
2140
|
-
raw_sz = stride * cinfo->output_height;
|
2141
|
-
ret = rb_str_buf_new(raw_sz);
|
2142
|
-
raw = (uint8_t*)RSTRING_PTR(ret);
|
2143
|
-
|
2144
|
-
|
2145
|
-
while (cinfo->output_scanline < cinfo->output_height) {
|
2146
|
-
for (i = 0, j = cinfo->output_scanline; i < UNIT_LINES; i++, j++) {
|
2147
|
-
array[i] = raw + (j * stride);
|
2148
|
-
}
|
3563
|
+
/*
|
3564
|
+
* configuration
|
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;
|
2149
3583
|
|
2150
|
-
|
2151
|
-
|
3584
|
+
/*
|
3585
|
+
* decode process
|
3586
|
+
*/
|
3587
|
+
jpeg_start_decompress(cinfo);
|
2152
3588
|
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
3589
|
+
stride = cinfo->output_components * cinfo->output_width;
|
3590
|
+
raw_sz = stride * cinfo->output_height;
|
3591
|
+
ret = rb_str_buf_new(raw_sz);
|
3592
|
+
raw = (uint8_t*)RSTRING_PTR(ret);
|
3593
|
+
|
3594
|
+
while (cinfo->output_scanline < cinfo->output_height) {
|
3595
|
+
for (i = 0, j = cinfo->output_scanline; i < UNIT_LINES; i++, j++) {
|
3596
|
+
array[i] = raw + (j * stride);
|
2157
3597
|
}
|
2158
3598
|
|
2159
|
-
|
2160
|
-
|
3599
|
+
jpeg_read_scanlines(cinfo, array, UNIT_LINES);
|
3600
|
+
}
|
3601
|
+
|
3602
|
+
jpeg_finish_decompress(&ptr->cinfo);
|
2161
3603
|
|
2162
|
-
|
2163
|
-
|
3604
|
+
/*
|
3605
|
+
* build return data
|
3606
|
+
*/
|
3607
|
+
if (TEST_FLAG(ptr, F_EXPAND_COLORMAP) && IS_COLORMAPPED(cinfo)) {
|
3608
|
+
ret = expand_colormap(cinfo, raw);
|
3609
|
+
} else {
|
3610
|
+
rb_str_set_len(ret, raw_sz);
|
2164
3611
|
}
|
2165
|
-
break;
|
2166
|
-
}
|
2167
3612
|
|
2168
|
-
|
3613
|
+
if (ptr->format == FMT_YVU) swap_cbcr(raw, raw_sz);
|
3614
|
+
|
3615
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION)) {
|
3616
|
+
pick_exif_orientation(ptr);
|
3617
|
+
ret = apply_orientation(ptr, ret);
|
3618
|
+
}
|
3619
|
+
|
3620
|
+
if (TEST_FLAG(ptr, F_NEED_META)) add_meta(ret, ptr);
|
3621
|
+
}
|
2169
3622
|
|
2170
3623
|
return ret;
|
2171
3624
|
}
|
2172
3625
|
|
3626
|
+
/**
|
3627
|
+
* decode JPEG data
|
3628
|
+
*
|
3629
|
+
* @overload decode(jpeg)
|
3630
|
+
*
|
3631
|
+
* @param jpeg [String] JPEG data to decode.
|
3632
|
+
*
|
3633
|
+
* @return [String] decoded raw image data.
|
3634
|
+
*/
|
2173
3635
|
static VALUE
|
2174
3636
|
rb_decoder_decode(VALUE self, VALUE data)
|
2175
3637
|
{
|
2176
|
-
|
2177
|
-
|
3638
|
+
VALUE ret;
|
3639
|
+
jpeg_decode_t* ptr;
|
3640
|
+
int state;
|
2178
3641
|
|
2179
|
-
|
2180
|
-
|
2181
|
-
|
2182
|
-
|
3642
|
+
/*
|
3643
|
+
* initialize
|
3644
|
+
*/
|
3645
|
+
ret = Qnil;
|
3646
|
+
state = 0;
|
2183
3647
|
|
2184
|
-
|
2185
|
-
* argument check
|
2186
|
-
*/
|
2187
|
-
Check_Type(data, T_STRING);
|
3648
|
+
TypedData_Get_Struct(self, jpeg_decode_t, &jpeg_decoder_data_type, ptr);
|
2188
3649
|
|
2189
|
-
|
2190
|
-
|
2191
|
-
|
2192
|
-
|
3650
|
+
/*
|
3651
|
+
* argument check
|
3652
|
+
*/
|
3653
|
+
Check_Type(data, T_STRING);
|
3654
|
+
|
3655
|
+
/*
|
3656
|
+
* prepare
|
3657
|
+
*/
|
3658
|
+
SET_DATA(ptr, data);
|
2193
3659
|
|
2194
|
-
|
3660
|
+
/*
|
3661
|
+
* do decode
|
3662
|
+
*/
|
3663
|
+
ret = rb_protect(do_decode, (VALUE)ptr, &state);
|
3664
|
+
|
3665
|
+
/*
|
3666
|
+
* post process
|
3667
|
+
*/
|
3668
|
+
CLR_DATA(ptr);
|
3669
|
+
|
3670
|
+
if (state != 0) rb_jump_tag(state);
|
3671
|
+
|
3672
|
+
return ret;
|
2195
3673
|
}
|
2196
3674
|
|
2197
3675
|
static VALUE
|
@@ -2201,28 +3679,19 @@ rb_test_image(VALUE self, VALUE data)
|
|
2201
3679
|
struct jpeg_decompress_struct cinfo;
|
2202
3680
|
ext_error_t err_mgr;
|
2203
3681
|
|
2204
|
-
|
2205
|
-
|
2206
|
-
cinfo.err = jpeg_std_error(&err_mgr.jerr);
|
2207
|
-
|
2208
|
-
err_mgr.jerr.output_message = decode_output_message;
|
2209
|
-
err_mgr.jerr.emit_message = decode_emit_message;
|
2210
|
-
err_mgr.jerr.error_exit = decode_error_exit;
|
2211
|
-
|
2212
|
-
cinfo.raw_data_out = FALSE;
|
2213
|
-
cinfo.dct_method = JDCT_FLOAT;
|
3682
|
+
cinfo.raw_data_out = FALSE;
|
3683
|
+
cinfo.dct_method = JDCT_FLOAT;
|
2214
3684
|
|
2215
3685
|
if (setjmp(err_mgr.jmpbuf)) {
|
2216
|
-
ret = Qtrue;
|
2217
|
-
} else {
|
2218
3686
|
ret = Qfalse;
|
2219
3687
|
|
3688
|
+
} else {
|
2220
3689
|
jpeg_mem_src(&cinfo, (uint8_t*)RSTRING_PTR(data), RSTRING_LEN(data));
|
2221
3690
|
jpeg_read_header(&cinfo, TRUE);
|
2222
3691
|
jpeg_calc_output_dimensions(&cinfo);
|
2223
|
-
}
|
2224
3692
|
|
2225
|
-
|
3693
|
+
ret = Qtrue;
|
3694
|
+
}
|
2226
3695
|
|
2227
3696
|
return ret;
|
2228
3697
|
}
|
@@ -2256,11 +3725,12 @@ Init_jpeg()
|
|
2256
3725
|
|
2257
3726
|
meta_klass = rb_define_class_under(module, "Meta", rb_cObject);
|
2258
3727
|
rb_define_attr(meta_klass, "width", 1, 0);
|
3728
|
+
rb_define_attr(meta_klass, "stride", 1, 0);
|
2259
3729
|
rb_define_attr(meta_klass, "height", 1, 0);
|
2260
3730
|
rb_define_attr(meta_klass, "original_colorspace", 1, 0);
|
2261
3731
|
rb_define_attr(meta_klass, "output_colorspace", 1, 0);
|
2262
3732
|
rb_define_attr(meta_klass, "num_components", 1, 0);
|
2263
|
-
rb_define_attr(meta_klass, "
|
3733
|
+
rb_define_attr(meta_klass, "colormap", 1, 0);
|
2264
3734
|
|
2265
3735
|
decerr_klass = rb_define_class_under(module,
|
2266
3736
|
"DecodeError", rb_eRuntimeError);
|
@@ -2278,11 +3748,13 @@ Init_jpeg()
|
|
2278
3748
|
decoder_opts_ids[i] = rb_intern_const(decoder_opts_keys[i]);
|
2279
3749
|
}
|
2280
3750
|
|
2281
|
-
id_meta
|
2282
|
-
id_width
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
3751
|
+
id_meta = rb_intern_const("@meta");
|
3752
|
+
id_width = rb_intern_const("@width");
|
3753
|
+
id_stride = rb_intern_const("@stride");
|
3754
|
+
id_height = rb_intern_const("@height");
|
3755
|
+
id_orig_cs = rb_intern_const("@original_colorspace");
|
3756
|
+
id_out_cs = rb_intern_const("@output_colorspace");
|
3757
|
+
id_ncompo = rb_intern_const("@num_components");
|
3758
|
+
id_exif_tags = rb_intern_const("@exif_tags");
|
3759
|
+
id_colormap = rb_intern_const("@colormap");
|
2288
3760
|
}
|