libjpeg-ruby 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/ext/jpeg/jpeg.c +899 -163
- data/lib/jpeg/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7117f5dece9f78e847213078d1cba56591a30c01ea4b9de58cb4886647d5c530
|
4
|
+
data.tar.gz: 7bb5c400d519e4958fb9522c8a3af313931dc033a45c404a288d0d5020f02b7c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 457f1b3f55ba6c164a40e66303a9c34df6e9ec590137d161c98cee69bbac1385aa4b309c60feb853637c0c392afabdb356996b6809adefd0ed5827051eb318f6
|
7
|
+
data.tar.gz: 9427246e376ff7a9464b0e4c8cf22b0dff47e9036649f13a49a213b769f7ceab7d3e76dbbd258d65c6c65e5c03bda362cf06acc1b921c83bde74bd49d0c8c85f
|
data/README.md
CHANGED
@@ -50,6 +50,7 @@ IO.binwrite("test.bgr", raw)
|
|
50
50
|
| :expand_colormap | Booblean | T.B.D |
|
51
51
|
| :scale | Rational or Float | T.B.D |
|
52
52
|
| :dct_method | String or Symbol | T.B.D |
|
53
|
+
| :with_exif | Boolean | Specify whether to read Exif tag. When set to true, the content of Exif tag will included in the meta information. |
|
53
54
|
|
54
55
|
#### supported output format
|
55
56
|
RGB RGB24 YUV422 YUYV RGB565 YUV444 YCbCr BGR BGR24 RGBX RGB32 BGRX BGR32
|
data/ext/jpeg/jpeg.c
CHANGED
@@ -22,46 +22,49 @@
|
|
22
22
|
#include <jpeglib.h>
|
23
23
|
|
24
24
|
#include "ruby.h"
|
25
|
+
#include "ruby/encoding.h"
|
25
26
|
|
26
|
-
#define UNIT_LINES
|
27
|
+
#define UNIT_LINES 10
|
27
28
|
|
28
29
|
#ifdef DEFAULT_QUALITY
|
29
30
|
#undef DEFAULT_QUALITY
|
30
31
|
#endif /* defined(DEFAULT_QUALITY) */
|
31
32
|
|
32
|
-
#define DEFAULT_QUALITY
|
33
|
-
#define DEFAULT_INPUT_COLOR_SPACE
|
34
|
-
#define DEFAULT_INPUT_COMPONENTS
|
33
|
+
#define DEFAULT_QUALITY 75
|
34
|
+
#define DEFAULT_INPUT_COLOR_SPACE JCS_YCbCr
|
35
|
+
#define DEFAULT_INPUT_COMPONENTS 2
|
35
36
|
|
36
|
-
#define FMT_YUV422
|
37
|
-
#define FMT_RGB565
|
38
|
-
#define FMT_GRAYSCALE
|
39
|
-
#define FMT_YUV
|
40
|
-
#define FMT_RGB
|
41
|
-
#define FMT_BGR
|
42
|
-
#define FMT_RGB32
|
43
|
-
#define FMT_BGR32
|
37
|
+
#define FMT_YUV422 1
|
38
|
+
#define FMT_RGB565 2
|
39
|
+
#define FMT_GRAYSCALE 3
|
40
|
+
#define FMT_YUV 4
|
41
|
+
#define FMT_RGB 5
|
42
|
+
#define FMT_BGR 6
|
43
|
+
#define FMT_RGB32 7
|
44
|
+
#define FMT_BGR32 8
|
44
45
|
|
45
|
-
#define FMT_YVU 20
|
46
|
+
#define FMT_YVU 20 /* original extend */
|
46
47
|
|
47
|
-
#define
|
48
|
+
#define JPEG_APP1 0xe1 /* Exif marker */
|
48
49
|
|
49
|
-
#define
|
50
|
-
#define ARGUMENT_ERROR(msg) rb_raise(rb_eArgError, (msg))
|
50
|
+
#define N(x) (sizeof(x)/sizeof(*x))
|
51
51
|
|
52
|
-
#define
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
#define RUNTIME_ERROR(msg) rb_raise(rb_eRuntimeError, (msg))
|
53
|
+
#define ARGUMENT_ERROR(msg) rb_raise(rb_eArgError, (msg))
|
54
|
+
|
55
|
+
#define IS_COLORMAPPED(ci) (((ci)->actual_number_of_colors > 0) &&\
|
56
|
+
((ci)->colormap != NULL) && \
|
57
|
+
((ci)->output_components == 1) && \
|
58
|
+
(((ci)->out_color_components == 1) || \
|
59
|
+
((ci)->out_color_components == 3)))
|
57
60
|
|
58
61
|
#define ALLOC_ARRAY() \
|
59
62
|
((JSAMPARRAY)xmalloc(sizeof(JSAMPROW) * UNIT_LINES))
|
60
63
|
#define ALLOC_ROWS(w,c) \
|
61
64
|
((JSAMPROW)xmalloc(sizeof(JSAMPLE) * (w) * (c) * UNIT_LINES))
|
62
65
|
|
63
|
-
#define EQ_STR(val,str)
|
64
|
-
#define EQ_INT(val,n)
|
66
|
+
#define EQ_STR(val,str) (rb_to_id(val) == rb_intern(str))
|
67
|
+
#define EQ_INT(val,n) (FIX2INT(val) == n)
|
65
68
|
|
66
69
|
static VALUE module;
|
67
70
|
static VALUE encoder_klass;
|
@@ -77,6 +80,168 @@ static ID id_height;
|
|
77
80
|
static ID id_orig_cs;
|
78
81
|
static ID id_out_cs;
|
79
82
|
static ID id_ncompo;
|
83
|
+
static ID id_exif;
|
84
|
+
|
85
|
+
typedef struct {
|
86
|
+
int tag;
|
87
|
+
const char* name;
|
88
|
+
} tag_entry_t;
|
89
|
+
|
90
|
+
tag_entry_t tag_tiff[] = {
|
91
|
+
/* 0th IFD */
|
92
|
+
{0x0100, "image_width", },
|
93
|
+
{0x0101, "image_length", },
|
94
|
+
{0x0102, "bits_per_sample", },
|
95
|
+
{0x0103, "compression", },
|
96
|
+
{0x0106, "photometric_interpretation", },
|
97
|
+
{0x010e, "image_description", },
|
98
|
+
{0x010f, "maker", },
|
99
|
+
{0x0110, "model", },
|
100
|
+
{0x0111, "strip_offsets", },
|
101
|
+
{0x0112, "orientation", },
|
102
|
+
{0x0115, "sample_per_pixel", },
|
103
|
+
{0x0116, "rows_per_strip", },
|
104
|
+
{0x0117, "strip_byte_counts", },
|
105
|
+
{0x011a, "x_resolution", },
|
106
|
+
{0x011b, "y_resolution", },
|
107
|
+
{0x011c, "planer_configuration", },
|
108
|
+
{0x0128, "resolution_unit", },
|
109
|
+
{0x012d, "transfer_function", },
|
110
|
+
{0x0131, "software", },
|
111
|
+
{0x0132, "date_time", },
|
112
|
+
{0x013b, "artist", },
|
113
|
+
{0x013e, "white_point", },
|
114
|
+
{0x013f, "primary_chromaticities", },
|
115
|
+
{0x0201, "jpeg_interchange_format", },
|
116
|
+
{0x0202, "jpeg_interchange_format_length"},
|
117
|
+
{0x0211, "ycbcr_coefficients", },
|
118
|
+
{0x0212, "ycbcr_sub_sampling", },
|
119
|
+
{0x0213, "ycbcr_positioning", },
|
120
|
+
{0x0214, "reference_black_white", },
|
121
|
+
{0x0d68, "copyright", },
|
122
|
+
{0x8298, "copyright", },
|
123
|
+
{0x8769, NULL, }, /* ExifIFDPointer */
|
124
|
+
{0x8825, NULL, }, /* GPSInfoIFDPointer */
|
125
|
+
{0xc4a5, "print_im", },
|
126
|
+
};
|
127
|
+
|
128
|
+
tag_entry_t tag_exif[] = {
|
129
|
+
/* Exif IFD */
|
130
|
+
{0x829a, "exposure_time", },
|
131
|
+
{0x829d, "f_number", },
|
132
|
+
{0x8822, "exposure_program", },
|
133
|
+
{0x8824, "spectral_sensitivity", },
|
134
|
+
{0x8827, "iso_speed_ratings", },
|
135
|
+
{0x8828, "oecf", },
|
136
|
+
{0x882a, "time_zone_offset", },
|
137
|
+
{0x882b, "self_timer_mode", },
|
138
|
+
{0x8830, "sensitivity_type", },
|
139
|
+
{0x8831, "standard_output_sensitivity", },
|
140
|
+
{0x8832, "recommended_exposure_index", },
|
141
|
+
{0x9000, "exif_version", },
|
142
|
+
{0x9003, "data_time_original", },
|
143
|
+
{0x9004, "data_time_digitized", },
|
144
|
+
{0x9010, "offset_time", },
|
145
|
+
{0x9011, "offset_time_original", },
|
146
|
+
{0x9012, "offset_time_digitized", },
|
147
|
+
{0x9101, "color_space", },
|
148
|
+
{0x9102, "components_configuration", },
|
149
|
+
{0x9201, "shutter_speed_value", },
|
150
|
+
{0x9202, "apertutre_value", },
|
151
|
+
{0x9203, "brightness_value", },
|
152
|
+
{0x9204, "exposure_bias_value", },
|
153
|
+
{0x9205, "max_aperture_value", },
|
154
|
+
{0x9206, "subject_distance", },
|
155
|
+
{0x9207, "metering_mode", },
|
156
|
+
{0x9208, "light_source", },
|
157
|
+
{0x9209, "flash", },
|
158
|
+
{0x920a, "focal_length", },
|
159
|
+
{0x927c, "marker_note", },
|
160
|
+
{0x9286, "user_comment", },
|
161
|
+
{0x9290, "sub_sec_time", },
|
162
|
+
{0x9291, "sub_sec_time_original", },
|
163
|
+
{0x9292, "sub_sec_time_digitized", },
|
164
|
+
{0xa000, "flash_pix_version", },
|
165
|
+
{0xa001, "color_space", },
|
166
|
+
{0xa002, "pixel_x_dimension", },
|
167
|
+
{0xa003, "pixel_y_dimension", },
|
168
|
+
{0xa004, "related_sound_file", },
|
169
|
+
{0xa005, NULL, }, /* InteroperabilityIFDPointer */
|
170
|
+
{0xa20b, "flash_energy", },
|
171
|
+
{0xa20b, "flash_energy", },
|
172
|
+
{0xa20c, "spatial_frequency_response", },
|
173
|
+
{0xa20e, "focal_panel_x_resolution", },
|
174
|
+
{0xa20f, "focal_panel_y_resolution", },
|
175
|
+
{0xa210, "focal_panel_resolution_unit", },
|
176
|
+
{0xa214, "subject_location", },
|
177
|
+
{0xa215, "exposure_index", },
|
178
|
+
{0xa217, "sensing_method", },
|
179
|
+
{0xa300, "file_source", },
|
180
|
+
{0xa301, "scene_type", },
|
181
|
+
{0xa302, "cfa_pattern", },
|
182
|
+
{0xa401, "custom_rendered", },
|
183
|
+
{0xa402, "exposure_mode", },
|
184
|
+
{0xa403, "white_balance", },
|
185
|
+
{0xa404, "digital_zoom_ratio", },
|
186
|
+
{0xa405, "focal_length_in_35mm_film", },
|
187
|
+
{0xa406, "scene_capture_type", },
|
188
|
+
{0xa407, "gain_control", },
|
189
|
+
{0xa408, "contrast", },
|
190
|
+
{0xa409, "sturation", },
|
191
|
+
{0xa40a, "sharpness", },
|
192
|
+
{0xa40b, "device_setting_description", },
|
193
|
+
{0xa40c, "subject_distance_range", },
|
194
|
+
{0xa420, "image_unique_id", },
|
195
|
+
{0xa430, "owner_name", },
|
196
|
+
{0xa431, "serial_number", },
|
197
|
+
{0xa432, "lens_info", },
|
198
|
+
{0xa433, "lens_make", },
|
199
|
+
{0xa434, "lens_model", },
|
200
|
+
{0xa435, "lens_serial_number", },
|
201
|
+
};
|
202
|
+
|
203
|
+
tag_entry_t tag_gps[] = {
|
204
|
+
/* GPS IFD */
|
205
|
+
{0x0000, "version_id", },
|
206
|
+
{0x0001, "latitude_ref", },
|
207
|
+
{0x0002, "latitude", },
|
208
|
+
{0x0003, "longitude_ref", },
|
209
|
+
{0x0004, "longitude", },
|
210
|
+
{0x0005, "altitude_ref", },
|
211
|
+
{0x0006, "altitude", },
|
212
|
+
{0x0007, "timestamp", },
|
213
|
+
{0x0008, "satellites", },
|
214
|
+
{0x0009, "status", },
|
215
|
+
{0x000a, "measure_mode", },
|
216
|
+
{0x000b, "dop", },
|
217
|
+
{0x000c, "speed_ref", },
|
218
|
+
{0x000d, "speed", },
|
219
|
+
{0x000e, "track_ref", },
|
220
|
+
{0x000f, "track", },
|
221
|
+
{0x0010, "img_direction_ref", },
|
222
|
+
{0x0011, "img_direction", },
|
223
|
+
{0x0012, "map_datum", },
|
224
|
+
{0x0013, "dest_latitude_ref", },
|
225
|
+
{0x0014, "dest_latitude", },
|
226
|
+
{0x0015, "dest_longitude_ref", },
|
227
|
+
{0x0016, "dest_longitude", },
|
228
|
+
{0x0017, "bearing_ref", },
|
229
|
+
{0x0018, "bearing", },
|
230
|
+
{0x0019, "dest_distance_ref", },
|
231
|
+
{0x001a, "dest_distance", },
|
232
|
+
{0x001b, "processing_method", },
|
233
|
+
{0x001c, "area_infotmation", },
|
234
|
+
{0x001d, "date_stamp", },
|
235
|
+
{0x001e, "differential", },
|
236
|
+
};
|
237
|
+
|
238
|
+
tag_entry_t tag_i14y[] = {
|
239
|
+
/* Interoperability IFD */
|
240
|
+
{0x0001, "interoperability_index", },
|
241
|
+
{0x0002, "interoperability_version", },
|
242
|
+
{0x1000, "related_image_file_format", },
|
243
|
+
{0x1001, "related_image_width", },
|
244
|
+
};
|
80
245
|
|
81
246
|
static const char* encoder_opts_keys[] = {
|
82
247
|
"pixel_format", // {str}
|
@@ -114,7 +279,8 @@ static const char* decoder_opts_keys[] = {
|
|
114
279
|
"without_meta", // {bool}
|
115
280
|
"expand_colormap", // {bool}
|
116
281
|
"scale", // {rational} or {float}
|
117
|
-
"dct_method"
|
282
|
+
"dct_method", // {str}
|
283
|
+
"with_exif" // {bool}
|
118
284
|
};
|
119
285
|
|
120
286
|
static ID decoder_opts_ids[N(decoder_opts_keys)];
|
@@ -130,6 +296,7 @@ typedef struct {
|
|
130
296
|
int format;
|
131
297
|
int need_meta;
|
132
298
|
int expand_colormap;
|
299
|
+
int parse_exif;
|
133
300
|
|
134
301
|
J_COLOR_SPACE out_color_space;
|
135
302
|
int scale_num;
|
@@ -152,6 +319,47 @@ typedef struct {
|
|
152
319
|
ext_error_t err_mgr;
|
153
320
|
} jpeg_decode_t;
|
154
321
|
|
322
|
+
|
323
|
+
static VALUE
|
324
|
+
lookup_tag_symbol(tag_entry_t* tbl, size_t n, int tag)
|
325
|
+
{
|
326
|
+
VALUE ret;
|
327
|
+
int l;
|
328
|
+
int r;
|
329
|
+
int i;
|
330
|
+
tag_entry_t* p;
|
331
|
+
char buf[16];
|
332
|
+
|
333
|
+
ret = Qundef;
|
334
|
+
l = 0;
|
335
|
+
r = n - 1;
|
336
|
+
|
337
|
+
while (r >= l) {
|
338
|
+
i = (l + r) / 2;
|
339
|
+
p = tbl + i;
|
340
|
+
|
341
|
+
if (p->tag < tag) {
|
342
|
+
l = i + 1;
|
343
|
+
continue;
|
344
|
+
}
|
345
|
+
|
346
|
+
if (p->tag > tag) {
|
347
|
+
r = i - 1;
|
348
|
+
continue;
|
349
|
+
}
|
350
|
+
|
351
|
+
ret = (p->name)? ID2SYM(rb_intern(p->name)): Qnil;
|
352
|
+
break;
|
353
|
+
}
|
354
|
+
|
355
|
+
if (ret == Qundef) {
|
356
|
+
sprintf(buf, "tag_%04x", tag);
|
357
|
+
ret = ID2SYM(rb_intern(buf));
|
358
|
+
}
|
359
|
+
|
360
|
+
return ret;
|
361
|
+
}
|
362
|
+
|
155
363
|
static void
|
156
364
|
encode_output_message(j_common_ptr cinfo)
|
157
365
|
{
|
@@ -300,6 +508,9 @@ set_encoder_context(jpeg_encode_t* ptr, int wd, int ht, VALUE opt)
|
|
300
508
|
/*
|
301
509
|
* eval scale option
|
302
510
|
*/
|
511
|
+
(void)scale_num;
|
512
|
+
(void)scale_denom;
|
513
|
+
|
303
514
|
switch (TYPE(opts[2])) {
|
304
515
|
case T_UNDEF:
|
305
516
|
// Nothing
|
@@ -653,6 +864,7 @@ rb_decoder_alloc(VALUE self)
|
|
653
864
|
ptr->format = FMT_RGB;
|
654
865
|
ptr->need_meta = !0;
|
655
866
|
ptr->expand_colormap = 0;
|
867
|
+
ptr->parse_exif = 0;
|
656
868
|
|
657
869
|
ptr->out_color_space = JCS_RGB;
|
658
870
|
|
@@ -759,44 +971,16 @@ eval_decoder_opt_output_gamma(jpeg_decode_t* ptr, VALUE opt)
|
|
759
971
|
static void
|
760
972
|
eval_decoder_opt_do_fancy_upsampling(jpeg_decode_t* ptr, VALUE opt)
|
761
973
|
{
|
762
|
-
|
763
|
-
|
764
|
-
// Nothing
|
765
|
-
break;
|
766
|
-
|
767
|
-
case T_TRUE:
|
768
|
-
ptr->do_fancy_upsampling = TRUE;
|
769
|
-
break;
|
770
|
-
|
771
|
-
case T_FALSE:
|
772
|
-
ptr->do_fancy_upsampling = FALSE;
|
773
|
-
break;
|
774
|
-
|
775
|
-
default:
|
776
|
-
ARGUMENT_ERROR("Unsupportd :do_fancy_up_sampling option value.");
|
777
|
-
break;
|
974
|
+
if (opt != Qundef) {
|
975
|
+
ptr->do_fancy_upsampling = (RTEST(opt))? TRUE: FALSE;
|
778
976
|
}
|
779
977
|
}
|
780
978
|
|
781
979
|
static void
|
782
980
|
eval_decoder_opt_do_smoothing(jpeg_decode_t* ptr, VALUE opt)
|
783
981
|
{
|
784
|
-
|
785
|
-
|
786
|
-
// Nothing
|
787
|
-
break;
|
788
|
-
|
789
|
-
case T_TRUE:
|
790
|
-
ptr->do_block_smoothing = TRUE;
|
791
|
-
break;
|
792
|
-
|
793
|
-
case T_FALSE:
|
794
|
-
ptr->do_block_smoothing = FALSE;
|
795
|
-
break;
|
796
|
-
|
797
|
-
default:
|
798
|
-
ARGUMENT_ERROR("Unsupportd :do_smoothing option value.");
|
799
|
-
break;
|
982
|
+
if (opt != Qundef) {
|
983
|
+
ptr->do_block_smoothing = (RTEST(opt))? TRUE: FALSE;
|
800
984
|
}
|
801
985
|
}
|
802
986
|
|
@@ -836,18 +1020,7 @@ eval_decoder_opt_dither( jpeg_decode_t* ptr, VALUE opt)
|
|
836
1020
|
ARGUMENT_ERROR("dither mode is illeagal value.");
|
837
1021
|
}
|
838
1022
|
|
839
|
-
|
840
|
-
case T_TRUE:
|
841
|
-
ptr->two_pass_quantize = TRUE;
|
842
|
-
break;
|
843
|
-
|
844
|
-
case T_FALSE:
|
845
|
-
ptr->two_pass_quantize = FALSE;
|
846
|
-
break;
|
847
|
-
|
848
|
-
default:
|
849
|
-
ARGUMENT_ERROR( "2pass quantize flag is illeagal value.");
|
850
|
-
}
|
1023
|
+
ptr->two_pass_quantize = (RTEST(pass2))? TRUE: FALSE;
|
851
1024
|
|
852
1025
|
if (TYPE(n_col) == T_FIXNUM) {
|
853
1026
|
ptr->desired_number_of_colors = FIX2INT(n_col);
|
@@ -860,113 +1033,55 @@ eval_decoder_opt_dither( jpeg_decode_t* ptr, VALUE opt)
|
|
860
1033
|
static void
|
861
1034
|
eval_decoder_opt_use_1pass_quantizer(jpeg_decode_t* ptr, VALUE opt)
|
862
1035
|
{
|
863
|
-
|
864
|
-
|
865
|
-
|
866
|
-
|
867
|
-
|
868
|
-
|
869
|
-
|
870
|
-
ptr->buffered_image = TRUE;
|
871
|
-
break;
|
872
|
-
|
873
|
-
case T_FALSE:
|
874
|
-
ptr->enable_1pass_quant = FALSE;
|
875
|
-
break;
|
876
|
-
|
877
|
-
default:
|
878
|
-
ARGUMENT_ERROR("Unsupportd :use_1pass_quantizer option value.");
|
879
|
-
break;
|
1036
|
+
if (opt != Qundef) {
|
1037
|
+
if (RTEST(opt)) {
|
1038
|
+
ptr->enable_1pass_quant = TRUE;
|
1039
|
+
ptr->buffered_image = TRUE;
|
1040
|
+
} else {
|
1041
|
+
ptr->enable_1pass_quant = FALSE;
|
1042
|
+
}
|
880
1043
|
}
|
881
1044
|
}
|
882
1045
|
|
883
1046
|
static void
|
884
1047
|
eval_decoder_opt_use_external_colormap(jpeg_decode_t* ptr, VALUE opt)
|
885
1048
|
{
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
ptr->buffered_image = TRUE;
|
894
|
-
break;
|
895
|
-
|
896
|
-
case T_FALSE:
|
897
|
-
ptr->enable_external_quant = FALSE;
|
898
|
-
break;
|
899
|
-
|
900
|
-
default:
|
901
|
-
ARGUMENT_ERROR("Unsupportd :use_external_colormap option value.");
|
902
|
-
break;
|
1049
|
+
if (opt != Qundef) {
|
1050
|
+
if (RTEST(opt)) {
|
1051
|
+
ptr->enable_external_quant = TRUE;
|
1052
|
+
ptr->buffered_image = TRUE;
|
1053
|
+
} else {
|
1054
|
+
ptr->enable_external_quant = FALSE;
|
1055
|
+
}
|
903
1056
|
}
|
904
1057
|
}
|
905
1058
|
|
906
1059
|
static void
|
907
1060
|
eval_decoder_opt_use_2pass_quantizer(jpeg_decode_t* ptr, VALUE opt)
|
908
1061
|
{
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
ptr->buffered_image = TRUE;
|
917
|
-
break;
|
918
|
-
|
919
|
-
case T_FALSE:
|
920
|
-
ptr->enable_2pass_quant = FALSE;
|
921
|
-
break;
|
922
|
-
|
923
|
-
default:
|
924
|
-
ARGUMENT_ERROR("Unsupportd :use_2pass_quantizer option value.");
|
925
|
-
break;
|
1062
|
+
if (opt != Qundef) {
|
1063
|
+
if (RTEST(opt)) {
|
1064
|
+
ptr->enable_2pass_quant = TRUE;
|
1065
|
+
ptr->buffered_image = TRUE;
|
1066
|
+
} else {
|
1067
|
+
ptr->enable_2pass_quant = FALSE;
|
1068
|
+
}
|
926
1069
|
}
|
927
1070
|
}
|
928
1071
|
|
929
1072
|
static void
|
930
1073
|
eval_decoder_opt_without_meta(jpeg_decode_t* ptr, VALUE opt)
|
931
1074
|
{
|
932
|
-
|
933
|
-
|
934
|
-
// Nothing
|
935
|
-
break;
|
936
|
-
|
937
|
-
case T_TRUE:
|
938
|
-
ptr->need_meta = 0;
|
939
|
-
break;
|
940
|
-
|
941
|
-
case T_FALSE:
|
942
|
-
ptr->need_meta = !0;
|
943
|
-
break;
|
944
|
-
|
945
|
-
default:
|
946
|
-
ARGUMENT_ERROR("Unsupportd :without_meta option value.");
|
947
|
-
break;
|
1075
|
+
if (opt != Qundef) {
|
1076
|
+
ptr->need_meta = RTEST(opt);
|
948
1077
|
}
|
949
1078
|
}
|
950
1079
|
|
951
1080
|
static void
|
952
1081
|
eval_decoder_opt_expand_colormap(jpeg_decode_t* ptr, VALUE opt)
|
953
1082
|
{
|
954
|
-
|
955
|
-
|
956
|
-
// Nothing
|
957
|
-
break;
|
958
|
-
|
959
|
-
case T_TRUE:
|
960
|
-
ptr->expand_colormap = !0;
|
961
|
-
break;
|
962
|
-
|
963
|
-
case T_FALSE:
|
964
|
-
ptr->expand_colormap = 0;
|
965
|
-
break;
|
966
|
-
|
967
|
-
default:
|
968
|
-
ARGUMENT_ERROR("Unsupportd :exapnd_colormap option value.");
|
969
|
-
break;
|
1083
|
+
if (opt != Qundef) {
|
1084
|
+
ptr->expand_colormap = RTEST(opt);
|
970
1085
|
}
|
971
1086
|
}
|
972
1087
|
|
@@ -1016,6 +1131,14 @@ eval_decoder_opt_dct_method(jpeg_decode_t* ptr, VALUE opt)
|
|
1016
1131
|
}
|
1017
1132
|
}
|
1018
1133
|
|
1134
|
+
static void
|
1135
|
+
eval_decoder_opt_with_exif(jpeg_decode_t* ptr, VALUE opt)
|
1136
|
+
{
|
1137
|
+
if (opt != Qundef) {
|
1138
|
+
ptr->parse_exif = RTEST(opt);
|
1139
|
+
}
|
1140
|
+
}
|
1141
|
+
|
1019
1142
|
static void
|
1020
1143
|
set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
1021
1144
|
{
|
@@ -1024,7 +1147,7 @@ set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
|
1024
1147
|
/*
|
1025
1148
|
* parse options
|
1026
1149
|
*/
|
1027
|
-
rb_get_kwargs(
|
1150
|
+
rb_get_kwargs(opt, decoder_opts_ids, 0, N(decoder_opts_ids), opts);
|
1028
1151
|
|
1029
1152
|
/*
|
1030
1153
|
* set context
|
@@ -1041,6 +1164,7 @@ set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
|
1041
1164
|
eval_decoder_opt_expand_colormap(ptr, opts[9]);
|
1042
1165
|
eval_decoder_opt_scale(ptr, opts[10]);
|
1043
1166
|
eval_decoder_opt_dct_method(ptr, opts[11]);
|
1167
|
+
eval_decoder_opt_with_exif(ptr, opts[12]);
|
1044
1168
|
}
|
1045
1169
|
|
1046
1170
|
static VALUE
|
@@ -1072,7 +1196,6 @@ rb_decoder_initialize( int argc, VALUE *argv, VALUE self)
|
|
1072
1196
|
static VALUE
|
1073
1197
|
rb_decoder_set(VALUE self, VALUE opt)
|
1074
1198
|
{
|
1075
|
-
VALUE ret;
|
1076
1199
|
jpeg_decode_t* ptr;
|
1077
1200
|
|
1078
1201
|
/*
|
@@ -1083,7 +1206,7 @@ rb_decoder_set(VALUE self, VALUE opt)
|
|
1083
1206
|
/*
|
1084
1207
|
* check argument
|
1085
1208
|
*/
|
1086
|
-
Check_Type(
|
1209
|
+
Check_Type(opt, T_HASH);
|
1087
1210
|
|
1088
1211
|
/*
|
1089
1212
|
* set context
|
@@ -1170,6 +1293,608 @@ get_colorspace_str( J_COLOR_SPACE cs)
|
|
1170
1293
|
return rb_str_new_cstr(cstr);
|
1171
1294
|
}
|
1172
1295
|
|
1296
|
+
typedef struct {
|
1297
|
+
int be;
|
1298
|
+
uint8_t* head;
|
1299
|
+
uint8_t* cur;
|
1300
|
+
size_t size;
|
1301
|
+
|
1302
|
+
struct {
|
1303
|
+
tag_entry_t* tbl;
|
1304
|
+
size_t n;
|
1305
|
+
} tags;
|
1306
|
+
|
1307
|
+
int next;
|
1308
|
+
} exif_t;
|
1309
|
+
|
1310
|
+
static uint16_t
|
1311
|
+
get_u16(uint8_t* src, int be)
|
1312
|
+
{
|
1313
|
+
uint16_t ret;
|
1314
|
+
|
1315
|
+
if (be) {
|
1316
|
+
ret = (((src[0] << 8) & 0xff00)|
|
1317
|
+
((src[1] << 0) & 0x00ff));
|
1318
|
+
} else {
|
1319
|
+
ret = (((src[1] << 8) & 0xff00)|
|
1320
|
+
((src[0] << 0) & 0x00ff));
|
1321
|
+
}
|
1322
|
+
|
1323
|
+
return ret;
|
1324
|
+
}
|
1325
|
+
|
1326
|
+
/*
|
1327
|
+
static int16_t
|
1328
|
+
get_s16(uint8_t* src, int be)
|
1329
|
+
{
|
1330
|
+
int16_t ret;
|
1331
|
+
|
1332
|
+
if (be) {
|
1333
|
+
ret = (((src[0] << 8) & 0xff00)|
|
1334
|
+
((src[1] << 0) & 0x00ff));
|
1335
|
+
} else {
|
1336
|
+
ret = (((src[1] << 8) & 0xff00)|
|
1337
|
+
((src[0] << 0) & 0x00ff));
|
1338
|
+
}
|
1339
|
+
|
1340
|
+
return ret;
|
1341
|
+
}
|
1342
|
+
*/
|
1343
|
+
|
1344
|
+
static uint32_t
|
1345
|
+
get_u32(uint8_t* src, int be)
|
1346
|
+
{
|
1347
|
+
uint32_t ret;
|
1348
|
+
|
1349
|
+
if (be) {
|
1350
|
+
ret = (((src[0] << 24) & 0xff000000)|
|
1351
|
+
((src[1] << 16) & 0x00ff0000)|
|
1352
|
+
((src[2] << 8) & 0x0000ff00)|
|
1353
|
+
((src[3] << 0) & 0x000000ff));
|
1354
|
+
} else {
|
1355
|
+
ret = (((src[3] << 24) & 0xff000000)|
|
1356
|
+
((src[2] << 16) & 0x00ff0000)|
|
1357
|
+
((src[1] << 8) & 0x0000ff00)|
|
1358
|
+
((src[0] << 0) & 0x000000ff));
|
1359
|
+
}
|
1360
|
+
|
1361
|
+
return ret;
|
1362
|
+
}
|
1363
|
+
|
1364
|
+
static int32_t
|
1365
|
+
get_s32(uint8_t* src, int be)
|
1366
|
+
{
|
1367
|
+
int32_t ret;
|
1368
|
+
|
1369
|
+
if (be) {
|
1370
|
+
ret = (((src[0] << 24) & 0xff000000)|
|
1371
|
+
((src[1] << 16) & 0x00ff0000)|
|
1372
|
+
((src[2] << 8) & 0x0000ff00)|
|
1373
|
+
((src[3] << 0) & 0x000000ff));
|
1374
|
+
} else {
|
1375
|
+
ret = (((src[3] << 24) & 0xff000000)|
|
1376
|
+
((src[2] << 16) & 0x00ff0000)|
|
1377
|
+
((src[1] << 8) & 0x0000ff00)|
|
1378
|
+
((src[0] << 0) & 0x000000ff));
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
return ret;
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
static void
|
1385
|
+
exif_increase(exif_t* ptr, size_t size)
|
1386
|
+
{
|
1387
|
+
ptr->cur += size;
|
1388
|
+
ptr->size -= size;
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
static void
|
1392
|
+
exif_init(exif_t* ptr, uint8_t* src, size_t size)
|
1393
|
+
{
|
1394
|
+
int be;
|
1395
|
+
uint16_t ident;
|
1396
|
+
uint32_t off;
|
1397
|
+
|
1398
|
+
/*
|
1399
|
+
* Check Exif idntifier
|
1400
|
+
*/
|
1401
|
+
if (memcmp(src, "Exif\0\0", 6)) {
|
1402
|
+
rb_raise(decerr_klass, "invalid exif identifier");
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
/*
|
1406
|
+
* Check TIFF header and judge endian
|
1407
|
+
*/
|
1408
|
+
do {
|
1409
|
+
if (!memcmp(src + 6, "MM", 2)) {
|
1410
|
+
be = !0;
|
1411
|
+
break;
|
1412
|
+
}
|
1413
|
+
|
1414
|
+
if (!memcmp(src + 6, "II", 2)) {
|
1415
|
+
be = 0;
|
1416
|
+
break;
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
rb_raise(decerr_klass, "invalid tiff header");
|
1420
|
+
} while (0);
|
1421
|
+
|
1422
|
+
/*
|
1423
|
+
* Check TIFF identifier
|
1424
|
+
*/
|
1425
|
+
ident = get_u16(src + 8, be);
|
1426
|
+
if (ident != 0x002a) {
|
1427
|
+
rb_raise(decerr_klass, "invalid tiff identifier");
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
/*
|
1431
|
+
* get offset for 0th IFD
|
1432
|
+
*/
|
1433
|
+
off = get_u32(src + 10, be);
|
1434
|
+
if (off < 8 || off >= size - 6) {
|
1435
|
+
rb_raise(decerr_klass, "invalid offset dentifier");
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
/*
|
1439
|
+
* initialize Exif context
|
1440
|
+
*/
|
1441
|
+
ptr->be = be;
|
1442
|
+
ptr->head = src + 6;
|
1443
|
+
ptr->cur = ptr->head + off;
|
1444
|
+
ptr->size = size - (6 + off);
|
1445
|
+
ptr->tags.tbl = tag_tiff;
|
1446
|
+
ptr->tags.n = N(tag_tiff);
|
1447
|
+
ptr->next = 0;
|
1448
|
+
}
|
1449
|
+
|
1450
|
+
static void
|
1451
|
+
exif_fetch_tag_header(exif_t* ptr, uint16_t* tag, uint16_t* type)
|
1452
|
+
{
|
1453
|
+
*tag = get_u16(ptr->cur + 0, ptr->be);
|
1454
|
+
*type = get_u16(ptr->cur + 2, ptr->be);
|
1455
|
+
}
|
1456
|
+
|
1457
|
+
|
1458
|
+
static void
|
1459
|
+
exif_fetch_byte_data(exif_t* ptr, VALUE* dst)
|
1460
|
+
{
|
1461
|
+
VALUE obj;
|
1462
|
+
|
1463
|
+
int i;
|
1464
|
+
uint32_t n;
|
1465
|
+
uint8_t* p;
|
1466
|
+
|
1467
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1468
|
+
p = ptr->cur + 8;
|
1469
|
+
|
1470
|
+
switch (n) {
|
1471
|
+
case 0:
|
1472
|
+
obj = Qnil;
|
1473
|
+
break;
|
1474
|
+
|
1475
|
+
case 1:
|
1476
|
+
obj = INT2FIX(*p);
|
1477
|
+
break;
|
1478
|
+
|
1479
|
+
default:
|
1480
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1481
|
+
|
1482
|
+
case 2:
|
1483
|
+
case 3:
|
1484
|
+
case 4:
|
1485
|
+
obj = rb_ary_new_capa(n);
|
1486
|
+
for (i = 0; i < (int)n; i++) {
|
1487
|
+
rb_ary_push(obj, INT2FIX(p[i]));
|
1488
|
+
}
|
1489
|
+
break;
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
*dst = obj;
|
1493
|
+
}
|
1494
|
+
|
1495
|
+
static void
|
1496
|
+
exif_fetch_ascii_data(exif_t* ptr, VALUE* dst)
|
1497
|
+
{
|
1498
|
+
VALUE obj;
|
1499
|
+
|
1500
|
+
uint32_t n;
|
1501
|
+
uint8_t* p;
|
1502
|
+
|
1503
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1504
|
+
p = ptr->cur + 8;
|
1505
|
+
|
1506
|
+
if (n > 4) {
|
1507
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1508
|
+
}
|
1509
|
+
|
1510
|
+
obj = rb_utf8_str_new((char*)p, n);
|
1511
|
+
rb_funcall(obj, rb_intern("strip!"), 0);
|
1512
|
+
|
1513
|
+
*dst = obj;
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
static void
|
1517
|
+
exif_fetch_short_data(exif_t* ptr, VALUE* dst)
|
1518
|
+
{
|
1519
|
+
VALUE obj;
|
1520
|
+
|
1521
|
+
int i;
|
1522
|
+
uint32_t n;
|
1523
|
+
uint8_t* p;
|
1524
|
+
|
1525
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1526
|
+
p = ptr->cur + 8;
|
1527
|
+
|
1528
|
+
switch (n) {
|
1529
|
+
case 0:
|
1530
|
+
obj = Qnil;
|
1531
|
+
break;
|
1532
|
+
|
1533
|
+
case 1:
|
1534
|
+
obj = INT2FIX(get_u16(p, ptr->be));
|
1535
|
+
break;
|
1536
|
+
|
1537
|
+
default:
|
1538
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1539
|
+
|
1540
|
+
case 2:
|
1541
|
+
obj = rb_ary_new_capa(n);
|
1542
|
+
for (i = 0; i < (int)n; i++) {
|
1543
|
+
rb_ary_push(obj, INT2FIX(get_u16(p, ptr->be)));
|
1544
|
+
p += 2;
|
1545
|
+
}
|
1546
|
+
break;
|
1547
|
+
}
|
1548
|
+
|
1549
|
+
*dst = obj;
|
1550
|
+
}
|
1551
|
+
|
1552
|
+
static void
|
1553
|
+
exif_fetch_long_data(exif_t* ptr, VALUE* dst)
|
1554
|
+
{
|
1555
|
+
VALUE obj;
|
1556
|
+
|
1557
|
+
int i;
|
1558
|
+
uint32_t n;
|
1559
|
+
uint8_t* p;
|
1560
|
+
|
1561
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1562
|
+
p = ptr->cur + 8;
|
1563
|
+
|
1564
|
+
switch (n) {
|
1565
|
+
case 0:
|
1566
|
+
obj = Qnil;
|
1567
|
+
break;
|
1568
|
+
|
1569
|
+
case 1:
|
1570
|
+
obj = INT2FIX(get_u32(p, ptr->be));
|
1571
|
+
break;
|
1572
|
+
|
1573
|
+
default:
|
1574
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1575
|
+
obj = rb_ary_new_capa(n);
|
1576
|
+
for (i = 0; i < (int)n; i++) {
|
1577
|
+
rb_ary_push(obj, INT2FIX(get_u32(p, ptr->be)));
|
1578
|
+
p += 4;
|
1579
|
+
}
|
1580
|
+
break;
|
1581
|
+
}
|
1582
|
+
|
1583
|
+
*dst = obj;
|
1584
|
+
}
|
1585
|
+
|
1586
|
+
static void
|
1587
|
+
exif_fetch_rational_data(exif_t* ptr, VALUE* dst)
|
1588
|
+
{
|
1589
|
+
VALUE obj;
|
1590
|
+
|
1591
|
+
int i;
|
1592
|
+
uint32_t n;
|
1593
|
+
uint8_t* p;
|
1594
|
+
uint32_t deno;
|
1595
|
+
uint32_t num;
|
1596
|
+
|
1597
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1598
|
+
p = ptr->head + get_u32(ptr->cur + 8, ptr->be);
|
1599
|
+
|
1600
|
+
switch (n) {
|
1601
|
+
case 0:
|
1602
|
+
obj = Qnil;
|
1603
|
+
break;
|
1604
|
+
|
1605
|
+
case 1:
|
1606
|
+
num = get_u32(p + 0, ptr->be);
|
1607
|
+
deno = get_u32(p + 4, ptr->be);
|
1608
|
+
if (num == 0 && deno == 0) {
|
1609
|
+
deno = 1;
|
1610
|
+
}
|
1611
|
+
obj = rb_rational_new(INT2FIX(num), INT2FIX(deno));
|
1612
|
+
break;
|
1613
|
+
|
1614
|
+
default:
|
1615
|
+
obj = rb_ary_new_capa(n);
|
1616
|
+
for (i = 0; i < (int)n; i++) {
|
1617
|
+
num = get_u32(p + 0, ptr->be);
|
1618
|
+
deno = get_u32(p + 4, ptr->be);
|
1619
|
+
if (num == 0 && deno == 0) {
|
1620
|
+
deno = 1;
|
1621
|
+
}
|
1622
|
+
rb_ary_push(obj, rb_rational_new(INT2FIX(num), INT2FIX(deno)));
|
1623
|
+
p += 8;
|
1624
|
+
}
|
1625
|
+
break;
|
1626
|
+
}
|
1627
|
+
|
1628
|
+
*dst = obj;
|
1629
|
+
}
|
1630
|
+
|
1631
|
+
static void
|
1632
|
+
exif_fetch_undefined_data(exif_t* ptr, VALUE* dst)
|
1633
|
+
{
|
1634
|
+
VALUE obj;
|
1635
|
+
|
1636
|
+
uint32_t n;
|
1637
|
+
uint8_t* p;
|
1638
|
+
|
1639
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1640
|
+
p = ptr->cur + 8;
|
1641
|
+
|
1642
|
+
if (n > 4) {
|
1643
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1644
|
+
}
|
1645
|
+
|
1646
|
+
obj = rb_enc_str_new((char*)p, n, rb_ascii8bit_encoding());
|
1647
|
+
|
1648
|
+
*dst = obj;
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
static void
|
1652
|
+
exif_fetch_slong_data(exif_t* ptr, VALUE* dst)
|
1653
|
+
{
|
1654
|
+
VALUE obj;
|
1655
|
+
|
1656
|
+
int i;
|
1657
|
+
uint32_t n;
|
1658
|
+
uint8_t* p;
|
1659
|
+
|
1660
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1661
|
+
p = ptr->cur + 8;
|
1662
|
+
|
1663
|
+
switch (n) {
|
1664
|
+
case 0:
|
1665
|
+
obj = Qnil;
|
1666
|
+
break;
|
1667
|
+
|
1668
|
+
case 1:
|
1669
|
+
obj = INT2FIX(get_s32(p, ptr->be));
|
1670
|
+
break;
|
1671
|
+
|
1672
|
+
default:
|
1673
|
+
p = ptr->head + get_u32(p, ptr->be);
|
1674
|
+
obj = rb_ary_new_capa(n);
|
1675
|
+
for (i = 0; i < (int)n; i++) {
|
1676
|
+
rb_ary_push(obj, INT2FIX(get_s32(p, ptr->be)));
|
1677
|
+
p += 4;
|
1678
|
+
}
|
1679
|
+
break;
|
1680
|
+
}
|
1681
|
+
|
1682
|
+
*dst = obj;
|
1683
|
+
}
|
1684
|
+
|
1685
|
+
static void
|
1686
|
+
exif_fetch_srational_data(exif_t* ptr, VALUE* dst)
|
1687
|
+
{
|
1688
|
+
VALUE obj;
|
1689
|
+
|
1690
|
+
int i;
|
1691
|
+
uint32_t n;
|
1692
|
+
uint8_t* p;
|
1693
|
+
uint32_t deno;
|
1694
|
+
uint32_t num;
|
1695
|
+
|
1696
|
+
n = get_u32(ptr->cur + 4, ptr->be);
|
1697
|
+
p = ptr->head + get_u32(ptr->cur + 8, ptr->be);
|
1698
|
+
|
1699
|
+
switch (n) {
|
1700
|
+
case 0:
|
1701
|
+
obj = Qnil;
|
1702
|
+
break;
|
1703
|
+
|
1704
|
+
case 1:
|
1705
|
+
num = get_s32(p + 0, ptr->be);
|
1706
|
+
deno = get_s32(p + 4, ptr->be);
|
1707
|
+
if (num == 0 && deno == 0) {
|
1708
|
+
deno = 1;
|
1709
|
+
}
|
1710
|
+
obj = rb_rational_new(INT2FIX(num), INT2FIX(deno));
|
1711
|
+
break;
|
1712
|
+
|
1713
|
+
default:
|
1714
|
+
obj = rb_ary_new_capa(n);
|
1715
|
+
for (i = 0; i < (int)n; i++) {
|
1716
|
+
num = get_s32(p + 0, ptr->be);
|
1717
|
+
deno = get_s32(p + 4, ptr->be);
|
1718
|
+
if (num == 0 && deno == 0) {
|
1719
|
+
deno = 1;
|
1720
|
+
}
|
1721
|
+
rb_ary_push(obj, rb_rational_new(INT2FIX(num), INT2FIX(deno)));
|
1722
|
+
p += 8;
|
1723
|
+
}
|
1724
|
+
break;
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
*dst = obj;
|
1728
|
+
}
|
1729
|
+
|
1730
|
+
static void
|
1731
|
+
exif_fetch_child_ifd(exif_t* ptr, tag_entry_t* tbl, size_t n, exif_t* dst)
|
1732
|
+
{
|
1733
|
+
uint32_t off;
|
1734
|
+
|
1735
|
+
off = get_u32(ptr->cur + 8, ptr->be);
|
1736
|
+
|
1737
|
+
dst->be = ptr->be;
|
1738
|
+
dst->head = ptr->head;
|
1739
|
+
dst->cur = ptr->head + off;
|
1740
|
+
dst->size = ptr->size - off;
|
1741
|
+
dst->tags.tbl = tbl;
|
1742
|
+
dst->tags.n = n;
|
1743
|
+
dst->next = 0;
|
1744
|
+
}
|
1745
|
+
|
1746
|
+
static int
|
1747
|
+
exif_read(exif_t* ptr, VALUE dst)
|
1748
|
+
{
|
1749
|
+
int ret;
|
1750
|
+
int i;
|
1751
|
+
uint16_t ntag;
|
1752
|
+
uint16_t tag;
|
1753
|
+
uint16_t type;
|
1754
|
+
uint32_t off;
|
1755
|
+
|
1756
|
+
exif_t child;
|
1757
|
+
|
1758
|
+
VALUE key;
|
1759
|
+
VALUE val;
|
1760
|
+
|
1761
|
+
ntag = get_u16(ptr->cur, ptr->be);
|
1762
|
+
exif_increase(ptr, 2);
|
1763
|
+
|
1764
|
+
for (i = 0; i < ntag; i++) {
|
1765
|
+
exif_fetch_tag_header(ptr, &tag, &type);
|
1766
|
+
|
1767
|
+
switch (tag) {
|
1768
|
+
case 34665: // ExifIFDPointer
|
1769
|
+
key = ID2SYM(rb_intern("exif"));
|
1770
|
+
val = rb_hash_new();
|
1771
|
+
|
1772
|
+
exif_fetch_child_ifd(ptr, tag_exif, N(tag_exif), &child);
|
1773
|
+
exif_read(&child, val);
|
1774
|
+
break;
|
1775
|
+
|
1776
|
+
case 34853: // GPSInfoIFDPointer
|
1777
|
+
key = ID2SYM(rb_intern("gps"));
|
1778
|
+
val = rb_hash_new();
|
1779
|
+
|
1780
|
+
exif_fetch_child_ifd(ptr, tag_gps, N(tag_gps), &child);
|
1781
|
+
exif_read(&child, val);
|
1782
|
+
break;
|
1783
|
+
|
1784
|
+
case 40965: // InteroperabilityIFDPointer
|
1785
|
+
key = ID2SYM(rb_intern("interoperability"));
|
1786
|
+
val = rb_hash_new();
|
1787
|
+
|
1788
|
+
exif_fetch_child_ifd(ptr, tag_i14y, N(tag_i14y), &child);
|
1789
|
+
exif_read(&child, val);
|
1790
|
+
break;
|
1791
|
+
|
1792
|
+
default:
|
1793
|
+
key = lookup_tag_symbol(ptr->tags.tbl, ptr->tags.n, tag);
|
1794
|
+
|
1795
|
+
switch (type) {
|
1796
|
+
case 1: // when BYTE
|
1797
|
+
exif_fetch_byte_data(ptr, &val);
|
1798
|
+
break;
|
1799
|
+
|
1800
|
+
case 2: // when ASCII
|
1801
|
+
exif_fetch_ascii_data(ptr, &val);
|
1802
|
+
break;
|
1803
|
+
|
1804
|
+
case 3: // when SHORT
|
1805
|
+
exif_fetch_short_data(ptr, &val);
|
1806
|
+
break;
|
1807
|
+
|
1808
|
+
case 4: // when LONG
|
1809
|
+
exif_fetch_long_data(ptr, &val);
|
1810
|
+
break;
|
1811
|
+
|
1812
|
+
case 5: // when RATIONAL
|
1813
|
+
exif_fetch_rational_data(ptr, &val);
|
1814
|
+
break;
|
1815
|
+
|
1816
|
+
case 7: // when UNDEFINED
|
1817
|
+
exif_fetch_undefined_data(ptr, &val);
|
1818
|
+
break;
|
1819
|
+
|
1820
|
+
case 9: // when SLONG
|
1821
|
+
exif_fetch_slong_data(ptr, &val);
|
1822
|
+
break;
|
1823
|
+
|
1824
|
+
case 10: // when SRATIONAL
|
1825
|
+
exif_fetch_srational_data(ptr, &val);
|
1826
|
+
break;
|
1827
|
+
|
1828
|
+
default:
|
1829
|
+
rb_raise(decerr_klass, "invalid tag data type");
|
1830
|
+
}
|
1831
|
+
}
|
1832
|
+
|
1833
|
+
rb_hash_aset(dst, key, val);
|
1834
|
+
exif_increase(ptr, 12);
|
1835
|
+
}
|
1836
|
+
|
1837
|
+
off = get_u32(ptr->cur, ptr->be);
|
1838
|
+
if (off != 0) {
|
1839
|
+
ptr->cur = ptr->head + off;
|
1840
|
+
ptr->next = !0;
|
1841
|
+
}
|
1842
|
+
|
1843
|
+
return ret;
|
1844
|
+
}
|
1845
|
+
|
1846
|
+
#define THUMBNAIL_OFFSET ID2SYM(rb_intern("jpeg_interchange_format"))
|
1847
|
+
#define THUMBNAIL_SIZE ID2SYM(rb_intern("jpeg_interchange_format_length"))
|
1848
|
+
|
1849
|
+
static VALUE
|
1850
|
+
create_exif_hash(jpeg_decode_t* ptr)
|
1851
|
+
{
|
1852
|
+
VALUE ret;
|
1853
|
+
jpeg_saved_marker_ptr marker;
|
1854
|
+
exif_t exif;
|
1855
|
+
|
1856
|
+
ret = rb_hash_new();
|
1857
|
+
|
1858
|
+
for (marker = ptr->cinfo.marker_list;
|
1859
|
+
marker != NULL; marker = marker->next) {
|
1860
|
+
|
1861
|
+
if (marker->data_length < 14) continue;
|
1862
|
+
if (memcmp(marker->data, "Exif\0\0", 6)) continue;
|
1863
|
+
|
1864
|
+
/* 0th IFD */
|
1865
|
+
exif_init(&exif, marker->data, marker->data_length);
|
1866
|
+
exif_read(&exif, ret);
|
1867
|
+
|
1868
|
+
if (exif.next) {
|
1869
|
+
/* when 1th IFD (tumbnail) exist */
|
1870
|
+
VALUE info;
|
1871
|
+
VALUE off;
|
1872
|
+
VALUE size;
|
1873
|
+
VALUE data;
|
1874
|
+
|
1875
|
+
info = rb_hash_new();
|
1876
|
+
|
1877
|
+
exif_read(&exif, info);
|
1878
|
+
|
1879
|
+
off = rb_hash_lookup(info, THUMBNAIL_OFFSET);
|
1880
|
+
size = rb_hash_lookup(info, THUMBNAIL_SIZE);
|
1881
|
+
|
1882
|
+
if (TYPE(off) == T_FIXNUM && TYPE(size) == T_FIXNUM) {
|
1883
|
+
data = rb_enc_str_new((char*)exif.head + FIX2INT(off),
|
1884
|
+
FIX2INT(size), rb_ascii8bit_encoding());
|
1885
|
+
|
1886
|
+
rb_hash_lookup(info, THUMBNAIL_OFFSET);
|
1887
|
+
rb_hash_lookup(info, THUMBNAIL_SIZE);
|
1888
|
+
rb_hash_aset(info, ID2SYM(rb_intern("jpeg_interchange")), data);
|
1889
|
+
rb_hash_aset(ret, ID2SYM(rb_intern("thumbnail")), info);
|
1890
|
+
}
|
1891
|
+
}
|
1892
|
+
break;
|
1893
|
+
}
|
1894
|
+
|
1895
|
+
return ret;
|
1896
|
+
}
|
1897
|
+
|
1173
1898
|
static VALUE
|
1174
1899
|
create_meta(jpeg_decode_t* ptr)
|
1175
1900
|
{
|
@@ -1178,7 +1903,7 @@ create_meta(jpeg_decode_t* ptr)
|
|
1178
1903
|
|
1179
1904
|
/* TODO: そのうちディザをかけた場合のカラーマップをメタで返すようにする */
|
1180
1905
|
|
1181
|
-
ret = rb_obj_alloc(
|
1906
|
+
ret = rb_obj_alloc(meta_klass);
|
1182
1907
|
cinfo = &ptr->cinfo;
|
1183
1908
|
|
1184
1909
|
rb_ivar_set(ret, id_width, INT2FIX(cinfo->output_width));
|
@@ -1193,6 +1918,10 @@ create_meta(jpeg_decode_t* ptr)
|
|
1193
1918
|
|
1194
1919
|
rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->output_components));
|
1195
1920
|
|
1921
|
+
if (ptr->parse_exif) {
|
1922
|
+
rb_ivar_set(ret, id_exif, create_exif_hash(ptr));
|
1923
|
+
}
|
1924
|
+
|
1196
1925
|
return ret;
|
1197
1926
|
}
|
1198
1927
|
|
@@ -1223,6 +1952,11 @@ do_read_header(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
1223
1952
|
rb_raise(decerr_klass, "%s", ptr->err_mgr.msg);
|
1224
1953
|
} else {
|
1225
1954
|
jpeg_mem_src(&ptr->cinfo, jpg, jpg_sz);
|
1955
|
+
|
1956
|
+
if (ptr->parse_exif) {
|
1957
|
+
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
1958
|
+
}
|
1959
|
+
|
1226
1960
|
jpeg_read_header(&ptr->cinfo, TRUE);
|
1227
1961
|
jpeg_calc_output_dimensions(&ptr->cinfo);
|
1228
1962
|
|
@@ -1326,7 +2060,7 @@ swap_cbcr(uint8_t* p, size_t size)
|
|
1326
2060
|
int i;
|
1327
2061
|
uint8_t tmp;
|
1328
2062
|
|
1329
|
-
for (i = 0; i < size; i++) {
|
2063
|
+
for (i = 0; i < (int)size; i++) {
|
1330
2064
|
tmp = p[1];
|
1331
2065
|
p[1] = p[2];
|
1332
2066
|
p[2] = tmp;
|
@@ -1483,7 +2217,7 @@ rb_test_image(VALUE self, VALUE data)
|
|
1483
2217
|
} else {
|
1484
2218
|
ret = Qfalse;
|
1485
2219
|
|
1486
|
-
jpeg_mem_src(&cinfo, RSTRING_PTR(data), RSTRING_LEN(data));
|
2220
|
+
jpeg_mem_src(&cinfo, (uint8_t*)RSTRING_PTR(data), RSTRING_LEN(data));
|
1487
2221
|
jpeg_read_header(&cinfo, TRUE);
|
1488
2222
|
jpeg_calc_output_dimensions(&cinfo);
|
1489
2223
|
}
|
@@ -1526,6 +2260,7 @@ Init_jpeg()
|
|
1526
2260
|
rb_define_attr(meta_klass, "original_colorspace", 1, 0);
|
1527
2261
|
rb_define_attr(meta_klass, "output_colorspace", 1, 0);
|
1528
2262
|
rb_define_attr(meta_klass, "num_components", 1, 0);
|
2263
|
+
rb_define_attr(meta_klass, "exif", 1, 0);
|
1529
2264
|
|
1530
2265
|
decerr_klass = rb_define_class_under(module,
|
1531
2266
|
"DecodeError", rb_eRuntimeError);
|
@@ -1543,10 +2278,11 @@ Init_jpeg()
|
|
1543
2278
|
decoder_opts_ids[i] = rb_intern_const(decoder_opts_keys[i]);
|
1544
2279
|
}
|
1545
2280
|
|
1546
|
-
id_meta
|
1547
|
-
id_width
|
1548
|
-
id_height
|
1549
|
-
id_orig_cs
|
1550
|
-
id_out_cs
|
1551
|
-
id_ncompo
|
2281
|
+
id_meta = rb_intern_const("@meta");
|
2282
|
+
id_width = rb_intern_const("@width");
|
2283
|
+
id_height = rb_intern_const("@height");
|
2284
|
+
id_orig_cs = rb_intern_const("@original_colorspace");
|
2285
|
+
id_out_cs = rb_intern_const("@output_colorspace");
|
2286
|
+
id_ncompo = rb_intern_const("@num_components");
|
2287
|
+
id_exif = rb_intern_const("@exif");
|
1552
2288
|
}
|
data/lib/jpeg/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libjpeg-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hiroshi Kuwagata
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -88,7 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
requirements: []
|
91
|
-
rubygems_version: 3.0.
|
91
|
+
rubygems_version: 3.0.3
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: libjpeg interface for ruby
|