libjpeg-ruby 0.7.0 → 0.7.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/ext/jpeg/jpeg.c +399 -65
- data/lib/jpeg/version.rb +1 -1
- data/libjpeg-ruby.gemspec +1 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 919842f0b928f7b288efd9f9787401923b75afc65be46060553079ba987d7f7f
|
4
|
+
data.tar.gz: a6ea75d0773e2b4d58debcee6b76c03b944d845716409016cd9fbb471ef6fd26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fcb35ccfd0931f01408a511a66b40bc17999b6da5be6a7b3479674209fb1c529de94ec7bcfccfc5956504dd4a5b18aa8b95d6eac0735975c5d5edf2fca4549a9
|
7
|
+
data.tar.gz: e8963a8e0c94abae93314898d500fd207e5e2c98d8c31315d5863a0740ae898521786e9dca1ce37c9180883fdfff667bf56dee58f7f7a2f116387972185dcc54
|
data/.gitignore
ADDED
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>
|
@@ -33,6 +23,18 @@
|
|
33
23
|
#define DEFAULT_QUALITY 75
|
34
24
|
#define DEFAULT_INPUT_COLOR_SPACE JCS_YCbCr
|
35
25
|
#define DEFAULT_INPUT_COMPONENTS 2
|
26
|
+
#define DEFAULT_FLAGS (F_NEED_META)
|
27
|
+
|
28
|
+
#define F_NEED_META 0x00000001
|
29
|
+
#define F_EXPAND_COLORMAP 0x00000002
|
30
|
+
#define F_PARSE_EXIF 0x00000004
|
31
|
+
#define F_APPLY_ORIENTATION 0x00000008
|
32
|
+
#define F_DITHER 0x00000010
|
33
|
+
|
34
|
+
#define SET_FLAG(ptr, msk) ((ptr)->flags |= (msk))
|
35
|
+
#define CLR_FLAG(ptr, msk) ((ptr)->flags &= ~(msk))
|
36
|
+
#define TEST_FLAG(ptr, msk) ((ptr)->flags & (msk))
|
37
|
+
#define TEST_FLAG_ALL(ptr, msk) (((ptr)->flags & (msk)) == msk)
|
36
38
|
|
37
39
|
#define FMT_YUV422 1
|
38
40
|
#define FMT_RGB565 2
|
@@ -51,6 +53,9 @@
|
|
51
53
|
|
52
54
|
#define RUNTIME_ERROR(msg) rb_raise(rb_eRuntimeError, (msg))
|
53
55
|
#define ARGUMENT_ERROR(msg) rb_raise(rb_eArgError, (msg))
|
56
|
+
#define TYPE_ERROR(msg) rb_raise(rb_eTypeError, (msg))
|
57
|
+
#define RANGE_ERROR(msg) rb_raise(rb_eRangeError, (msg))
|
58
|
+
#define NOT_IMPLEMENTED_ERROR(msg) rb_raise(rb_eNotImpError, (msg))
|
54
59
|
|
55
60
|
#define IS_COLORMAPPED(ci) (((ci)->actual_number_of_colors > 0) &&\
|
56
61
|
((ci)->colormap != NULL) && \
|
@@ -76,11 +81,13 @@ static VALUE decerr_klass;
|
|
76
81
|
|
77
82
|
static ID id_meta;
|
78
83
|
static ID id_width;
|
84
|
+
static ID id_stride;
|
79
85
|
static ID id_height;
|
80
86
|
static ID id_orig_cs;
|
81
87
|
static ID id_out_cs;
|
82
88
|
static ID id_ncompo;
|
83
|
-
static ID
|
89
|
+
static ID id_exif_tags;
|
90
|
+
static ID id_colormap;
|
84
91
|
|
85
92
|
typedef struct {
|
86
93
|
int tag;
|
@@ -273,14 +280,18 @@ static const char* decoder_opts_keys[] = {
|
|
273
280
|
"do_fancy_upsampling", // {bool}
|
274
281
|
"do_smoothing", // {bool}
|
275
282
|
"dither", // [{str}MODE, {bool}2PASS, {int}NUM_COLORS]
|
283
|
+
#if 0
|
276
284
|
"use_1pass_quantizer", // {bool}
|
277
285
|
"use_external_colormap", // {bool}
|
278
286
|
"use_2pass_quantizer", // {bool}
|
287
|
+
#endif
|
279
288
|
"without_meta", // {bool}
|
280
289
|
"expand_colormap", // {bool}
|
281
290
|
"scale", // {rational} or {float}
|
282
291
|
"dct_method", // {str}
|
283
|
-
"with_exif"
|
292
|
+
"with_exif", // {bool}
|
293
|
+
"with_exif_tags", // {bool}
|
294
|
+
"orientation" // {bool}
|
284
295
|
};
|
285
296
|
|
286
297
|
static ID decoder_opts_ids[N(decoder_opts_keys)];
|
@@ -293,10 +304,9 @@ typedef struct {
|
|
293
304
|
} ext_error_t;
|
294
305
|
|
295
306
|
typedef struct {
|
307
|
+
int flags;
|
296
308
|
int format;
|
297
|
-
int
|
298
|
-
int expand_colormap;
|
299
|
-
int parse_exif;
|
309
|
+
int orientation;
|
300
310
|
|
301
311
|
J_COLOR_SPACE out_color_space;
|
302
312
|
int scale_num;
|
@@ -517,8 +527,8 @@ set_encoder_context(jpeg_encode_t* ptr, int wd, int ht, VALUE opt)
|
|
517
527
|
break;
|
518
528
|
|
519
529
|
case T_FLOAT:
|
520
|
-
scale_num = 1000;
|
521
|
-
scale_denom =
|
530
|
+
scale_num = (int)(NUM2DBL(opts[2]) * 1000.0);
|
531
|
+
scale_denom = 1000;
|
522
532
|
break;
|
523
533
|
|
524
534
|
case T_RATIONAL:
|
@@ -585,6 +595,28 @@ set_encoder_context(jpeg_encode_t* ptr, int wd, int ht, VALUE opt)
|
|
585
595
|
jpeg_suppress_tables(&ptr->cinfo, TRUE);
|
586
596
|
}
|
587
597
|
|
598
|
+
/**
|
599
|
+
* initialize encoder object
|
600
|
+
*
|
601
|
+
* @overload initialize(width, height, opts)
|
602
|
+
*
|
603
|
+
* @param width [Integer] width of input image (px)
|
604
|
+
* @param height [Integer] height of input image (px)
|
605
|
+
* @param opts [Hash] options to initialize object
|
606
|
+
*
|
607
|
+
* @option opts [Symbol] :pixel_format
|
608
|
+
* specifies the format of the input image. possible values are:
|
609
|
+
* YUV422 YUYV RGB565 RGB RGB24 BGR BGR24 YUV444 YCbCr
|
610
|
+
* RGBX RGB32 BGRX BGR32 GRAYSCALE
|
611
|
+
*
|
612
|
+
* @option opts [Integer] :quality
|
613
|
+
* specifies the quality of the compressed image.
|
614
|
+
* You can specify from 0 (lowest) to 100 (best).
|
615
|
+
*
|
616
|
+
* @option opts [Symbol] :dct_method
|
617
|
+
* specifies how encoding is handled. possible values are:
|
618
|
+
* FASTEST ISLOW IFAST FLOAT
|
619
|
+
*/
|
588
620
|
static VALUE
|
589
621
|
rb_encoder_initialize(int argc, VALUE *argv, VALUE self)
|
590
622
|
{
|
@@ -771,6 +803,15 @@ do_encode(jpeg_encode_t* ptr, uint8_t* data)
|
|
771
803
|
return ret;
|
772
804
|
}
|
773
805
|
|
806
|
+
/**
|
807
|
+
* encode data
|
808
|
+
*
|
809
|
+
* @overload encode(raw)
|
810
|
+
*
|
811
|
+
* @param raw [String] raw image data to encode.
|
812
|
+
*
|
813
|
+
* @return [String] encoded JPEG data.
|
814
|
+
*/
|
774
815
|
static VALUE
|
775
816
|
rb_encoder_encode(VALUE self, VALUE data)
|
776
817
|
{
|
@@ -861,10 +902,9 @@ rb_decoder_alloc(VALUE self)
|
|
861
902
|
ptr = ALLOC(jpeg_decode_t);
|
862
903
|
memset(ptr, 0, sizeof(*ptr));
|
863
904
|
|
905
|
+
ptr->flags = DEFAULT_FLAGS;
|
864
906
|
ptr->format = FMT_RGB;
|
865
|
-
ptr->
|
866
|
-
ptr->expand_colormap = 0;
|
867
|
-
ptr->parse_exif = 0;
|
907
|
+
ptr->orientation = 0;
|
868
908
|
|
869
909
|
ptr->out_color_space = JCS_RGB;
|
870
910
|
|
@@ -905,11 +945,15 @@ eval_decoder_opt_pixel_format(jpeg_decode_t* ptr, VALUE opt)
|
|
905
945
|
color_space = JCS_YCbCr;
|
906
946
|
components = 3;
|
907
947
|
|
948
|
+
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
949
|
+
|
908
950
|
} else if (EQ_STR(opt, "RGB565")) {
|
909
951
|
format = FMT_RGB565;
|
910
952
|
color_space = JCS_RGB;
|
911
953
|
components = 3;
|
912
954
|
|
955
|
+
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
956
|
+
|
913
957
|
} else if (EQ_STR(opt, "GRAYSCALE")) {
|
914
958
|
format = FMT_GRAYSCALE;
|
915
959
|
color_space = JCS_GRAYSCALE;
|
@@ -958,12 +1002,13 @@ eval_decoder_opt_output_gamma(jpeg_decode_t* ptr, VALUE opt)
|
|
958
1002
|
// Nothing
|
959
1003
|
break;
|
960
1004
|
|
1005
|
+
case T_FIXNUM:
|
961
1006
|
case T_FLOAT:
|
962
1007
|
ptr->output_gamma = NUM2DBL(opt);
|
963
1008
|
break;
|
964
1009
|
|
965
1010
|
default:
|
966
|
-
|
1011
|
+
TYPE_ERROR("Unsupportd :output_gamma option value.");
|
967
1012
|
break;
|
968
1013
|
}
|
969
1014
|
}
|
@@ -993,7 +1038,7 @@ eval_decoder_opt_dither( jpeg_decode_t* ptr, VALUE opt)
|
|
993
1038
|
|
994
1039
|
if (opt != Qundef) {
|
995
1040
|
if (TYPE(opt) != T_ARRAY) {
|
996
|
-
|
1041
|
+
TYPE_ERROR("Unsupportd :dither option value.");
|
997
1042
|
}
|
998
1043
|
|
999
1044
|
if (RARRAY_LEN(opt) != 3) {
|
@@ -1024,12 +1069,21 @@ eval_decoder_opt_dither( jpeg_decode_t* ptr, VALUE opt)
|
|
1024
1069
|
|
1025
1070
|
if (TYPE(n_col) == T_FIXNUM) {
|
1026
1071
|
ptr->desired_number_of_colors = FIX2INT(n_col);
|
1072
|
+
|
1073
|
+
if (ptr->desired_number_of_colors < 8 ||
|
1074
|
+
ptr->desired_number_of_colors > 256) {
|
1075
|
+
RANGE_ERROR("number of dithered colors shall be from 8 to 256.");
|
1076
|
+
}
|
1077
|
+
|
1027
1078
|
} else {
|
1028
|
-
|
1079
|
+
TYPE_ERROR("number of dithered colors is illeagal value.");
|
1029
1080
|
}
|
1081
|
+
|
1082
|
+
SET_FLAG(ptr, F_DITHER);
|
1030
1083
|
}
|
1031
1084
|
}
|
1032
1085
|
|
1086
|
+
#if 0
|
1033
1087
|
static void
|
1034
1088
|
eval_decoder_opt_use_1pass_quantizer(jpeg_decode_t* ptr, VALUE opt)
|
1035
1089
|
{
|
@@ -1068,12 +1122,17 @@ eval_decoder_opt_use_2pass_quantizer(jpeg_decode_t* ptr, VALUE opt)
|
|
1068
1122
|
}
|
1069
1123
|
}
|
1070
1124
|
}
|
1125
|
+
#endif
|
1071
1126
|
|
1072
1127
|
static void
|
1073
1128
|
eval_decoder_opt_without_meta(jpeg_decode_t* ptr, VALUE opt)
|
1074
1129
|
{
|
1075
1130
|
if (opt != Qundef) {
|
1076
|
-
|
1131
|
+
if (RTEST(opt)) {
|
1132
|
+
CLR_FLAG(ptr, F_NEED_META);
|
1133
|
+
} else {
|
1134
|
+
SET_FLAG(ptr, F_NEED_META);
|
1135
|
+
}
|
1077
1136
|
}
|
1078
1137
|
}
|
1079
1138
|
|
@@ -1081,7 +1140,11 @@ static void
|
|
1081
1140
|
eval_decoder_opt_expand_colormap(jpeg_decode_t* ptr, VALUE opt)
|
1082
1141
|
{
|
1083
1142
|
if (opt != Qundef) {
|
1084
|
-
|
1143
|
+
if (RTEST(opt)) {
|
1144
|
+
SET_FLAG(ptr, F_EXPAND_COLORMAP);
|
1145
|
+
} else {
|
1146
|
+
CLR_FLAG(ptr, F_EXPAND_COLORMAP);
|
1147
|
+
}
|
1085
1148
|
}
|
1086
1149
|
}
|
1087
1150
|
|
@@ -1094,8 +1157,8 @@ eval_decoder_opt_scale(jpeg_decode_t* ptr, VALUE opt)
|
|
1094
1157
|
break;
|
1095
1158
|
|
1096
1159
|
case T_FLOAT:
|
1097
|
-
ptr->scale_num = 1000;
|
1098
|
-
ptr->scale_denom =
|
1160
|
+
ptr->scale_num = (int)(NUM2DBL(opt) * 1000.0);
|
1161
|
+
ptr->scale_denom = 1000;
|
1099
1162
|
break;
|
1100
1163
|
|
1101
1164
|
case T_RATIONAL:
|
@@ -1103,8 +1166,16 @@ eval_decoder_opt_scale(jpeg_decode_t* ptr, VALUE opt)
|
|
1103
1166
|
ptr->scale_denom = FIX2INT(rb_rational_den(opt));
|
1104
1167
|
break;
|
1105
1168
|
|
1169
|
+
case T_ARRAY:
|
1170
|
+
if (RARRAY_LEN(opt) != 2) {
|
1171
|
+
ARGUMENT_ERROR("invalid length");
|
1172
|
+
}
|
1173
|
+
ptr->scale_num = FIX2INT(RARRAY_AREF(opt, 0));
|
1174
|
+
ptr->scale_denom = FIX2INT(RARRAY_AREF(opt, 1));
|
1175
|
+
break;
|
1176
|
+
|
1106
1177
|
default:
|
1107
|
-
|
1178
|
+
TYPE_ERROR("Unsupportd :exapnd_colormap option value.");
|
1108
1179
|
break;
|
1109
1180
|
}
|
1110
1181
|
}
|
@@ -1132,10 +1203,26 @@ eval_decoder_opt_dct_method(jpeg_decode_t* ptr, VALUE opt)
|
|
1132
1203
|
}
|
1133
1204
|
|
1134
1205
|
static void
|
1135
|
-
|
1206
|
+
eval_decoder_opt_with_exif_tags(jpeg_decode_t* ptr, VALUE opt)
|
1207
|
+
{
|
1208
|
+
if (opt != Qundef) {
|
1209
|
+
if (RTEST(opt)) {
|
1210
|
+
SET_FLAG(ptr, F_PARSE_EXIF);
|
1211
|
+
} else {
|
1212
|
+
CLR_FLAG(ptr, F_PARSE_EXIF);
|
1213
|
+
}
|
1214
|
+
}
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
static void
|
1218
|
+
eval_decoder_opt_orientation(jpeg_decode_t* ptr, VALUE opt)
|
1136
1219
|
{
|
1137
1220
|
if (opt != Qundef) {
|
1138
|
-
|
1221
|
+
if (RTEST(opt)) {
|
1222
|
+
SET_FLAG(ptr, F_APPLY_ORIENTATION);
|
1223
|
+
} else {
|
1224
|
+
CLR_FLAG(ptr, F_APPLY_ORIENTATION);
|
1225
|
+
}
|
1139
1226
|
}
|
1140
1227
|
}
|
1141
1228
|
|
@@ -1157,16 +1244,68 @@ set_decoder_context( jpeg_decode_t* ptr, VALUE opt)
|
|
1157
1244
|
eval_decoder_opt_do_fancy_upsampling(ptr, opts[2]);
|
1158
1245
|
eval_decoder_opt_do_smoothing(ptr, opts[3]);
|
1159
1246
|
eval_decoder_opt_dither(ptr, opts[4]);
|
1247
|
+
#if 0
|
1160
1248
|
eval_decoder_opt_use_1pass_quantizer(ptr, opts[5]);
|
1161
1249
|
eval_decoder_opt_use_external_colormap(ptr, opts[6]);
|
1162
1250
|
eval_decoder_opt_use_2pass_quantizer(ptr, opts[7]);
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1251
|
+
#endif
|
1252
|
+
eval_decoder_opt_without_meta(ptr, opts[5]);
|
1253
|
+
eval_decoder_opt_expand_colormap(ptr, opts[6]);
|
1254
|
+
eval_decoder_opt_scale(ptr, opts[7]);
|
1255
|
+
eval_decoder_opt_dct_method(ptr, opts[8]);
|
1256
|
+
eval_decoder_opt_with_exif_tags(ptr, opts[9]);
|
1257
|
+
eval_decoder_opt_with_exif_tags(ptr, opts[10]);
|
1258
|
+
eval_decoder_opt_orientation(ptr, opts[11]);
|
1259
|
+
}
|
1260
|
+
|
1261
|
+
/**
|
1262
|
+
* initialize decoder object
|
1263
|
+
*
|
1264
|
+
* @overload initialize(opts)
|
1265
|
+
*
|
1266
|
+
* @param opts [Hash] options to initialize object
|
1267
|
+
*
|
1268
|
+
* @option opts [Symbol] :pixel_format
|
1269
|
+
* specifies the format of the output image. possible values are:
|
1270
|
+
* YUV422 YUYV RGB565 RGB RGB24 BGR BGR24 YUV444 YCbCr
|
1271
|
+
* RGBX RGB32 BGRX BGR32 GRAYSCALE
|
1272
|
+
*
|
1273
|
+
* @option opts [Float] :output_gamma
|
1274
|
+
*
|
1275
|
+
* @option opts [Boolean] :fancy_upsampling
|
1276
|
+
*
|
1277
|
+
* @option opts [Boolean] :do_smoothing
|
1278
|
+
*
|
1279
|
+
* @option opts [Array] :dither
|
1280
|
+
* specifies dithering parameters. A 3-elements array.
|
1281
|
+
* specify the dither type as a string for the 1st element,
|
1282
|
+
* whether to use 2-pass quantize for the 2nd element as a boolean,
|
1283
|
+
* and the number of colors used for the 3rd element as an integer
|
1284
|
+
* from 16 to 256.
|
1285
|
+
*
|
1286
|
+
* @option opts [Boolean] :without_meta
|
1287
|
+
* specifies whether or not to include meta information in the
|
1288
|
+
* output data. If true, no meta-information is output.
|
1289
|
+
*
|
1290
|
+
* @option opts [Boolean] :expand_colormap
|
1291
|
+
* specifies whether to expand the color map. If dither is specified,
|
1292
|
+
* the output will be a color number of 1 byte per pixel, but if this
|
1293
|
+
* option is set to true, the output will be expanded to color information.
|
1294
|
+
*
|
1295
|
+
* @option opts [Ratioanl] :scale
|
1296
|
+
*
|
1297
|
+
* @option opts [Symbol] :dct_method
|
1298
|
+
* specifies how decoding is handled. possible values are:
|
1299
|
+
* FASTEST ISLOW IFAST FLOAT
|
1300
|
+
*
|
1301
|
+
* @option opts [Boolean] :with_exif_tags
|
1302
|
+
* specifies whether to include Exif tag information in the output data.
|
1303
|
+
* set this option to true to parse the Exif tag information and include
|
1304
|
+
* it in the meta information output.
|
1305
|
+
*
|
1306
|
+
* @option opts [Boolean] :with_exif
|
1307
|
+
* alias to :with_exif_tags option.
|
1308
|
+
*/
|
1170
1309
|
static VALUE
|
1171
1310
|
rb_decoder_initialize( int argc, VALUE *argv, VALUE self)
|
1172
1311
|
{
|
@@ -1216,8 +1355,6 @@ rb_decoder_set(VALUE self, VALUE opt)
|
|
1216
1355
|
return Qtrue;
|
1217
1356
|
}
|
1218
1357
|
|
1219
|
-
|
1220
|
-
|
1221
1358
|
static VALUE
|
1222
1359
|
get_colorspace_str( J_COLOR_SPACE cs)
|
1223
1360
|
{
|
@@ -1396,7 +1533,7 @@ exif_init(exif_t* ptr, uint8_t* src, size_t size)
|
|
1396
1533
|
uint32_t off;
|
1397
1534
|
|
1398
1535
|
/*
|
1399
|
-
* Check Exif
|
1536
|
+
* Check Exif identifier
|
1400
1537
|
*/
|
1401
1538
|
if (memcmp(src, "Exif\0\0", 6)) {
|
1402
1539
|
rb_raise(decerr_klass, "invalid exif identifier");
|
@@ -1847,7 +1984,7 @@ exif_read(exif_t* ptr, VALUE dst)
|
|
1847
1984
|
#define THUMBNAIL_SIZE ID2SYM(rb_intern("jpeg_interchange_format_length"))
|
1848
1985
|
|
1849
1986
|
static VALUE
|
1850
|
-
|
1987
|
+
create_exif_tags_hash(jpeg_decode_t* ptr)
|
1851
1988
|
{
|
1852
1989
|
VALUE ret;
|
1853
1990
|
jpeg_saved_marker_ptr marker;
|
@@ -1895,18 +2032,157 @@ create_exif_hash(jpeg_decode_t* ptr)
|
|
1895
2032
|
return ret;
|
1896
2033
|
}
|
1897
2034
|
|
2035
|
+
static void
|
2036
|
+
pick_exif_orientation(jpeg_decode_t* ptr)
|
2037
|
+
{
|
2038
|
+
jpeg_saved_marker_ptr marker;
|
2039
|
+
int o9n;
|
2040
|
+
uint8_t* p;
|
2041
|
+
int be;
|
2042
|
+
uint32_t off;
|
2043
|
+
int i;
|
2044
|
+
int n;
|
2045
|
+
|
2046
|
+
o9n = 0;
|
2047
|
+
|
2048
|
+
for (marker = ptr->cinfo.marker_list;
|
2049
|
+
marker != NULL; marker = marker->next) {
|
2050
|
+
|
2051
|
+
if (marker->data_length < 14) continue;
|
2052
|
+
|
2053
|
+
p = marker->data;
|
2054
|
+
|
2055
|
+
/*
|
2056
|
+
* check Exif identifier
|
2057
|
+
*/
|
2058
|
+
if (memcmp(p, "Exif\0\0", 6)) continue;
|
2059
|
+
|
2060
|
+
/*
|
2061
|
+
* check endian marker
|
2062
|
+
*/
|
2063
|
+
if (!memcmp(p + 6, "MM", 2)) {
|
2064
|
+
be = !0;
|
2065
|
+
|
2066
|
+
} else if (!memcmp(p + 6, "II", 2)) {
|
2067
|
+
be = 0;
|
2068
|
+
|
2069
|
+
} else {
|
2070
|
+
continue;
|
2071
|
+
}
|
2072
|
+
|
2073
|
+
/*
|
2074
|
+
* check TIFF identifier
|
2075
|
+
*/
|
2076
|
+
if (get_u16(p + 8, be) != 0x002a) continue;
|
2077
|
+
|
2078
|
+
/*
|
2079
|
+
* set 0th IFD address
|
2080
|
+
*/
|
2081
|
+
off = get_u32(p + 10, be);
|
2082
|
+
if (off < 8 || off >= marker->data_length - 6) continue;
|
2083
|
+
|
2084
|
+
p += (6 + off);
|
2085
|
+
|
2086
|
+
/* ここまでくればAPP1がExifタグなので
|
2087
|
+
* 0th IFDをなめてOrientationタグを探す */
|
2088
|
+
|
2089
|
+
n = get_u16(p, be);
|
2090
|
+
p += 2;
|
2091
|
+
|
2092
|
+
for (i = 0; i < n; i++) {
|
2093
|
+
int tag;
|
2094
|
+
int type;
|
2095
|
+
int num;
|
2096
|
+
|
2097
|
+
tag = get_u16(p + 0, be);
|
2098
|
+
type = get_u16(p + 2, be);
|
2099
|
+
num = get_u32(p + 4, be);
|
2100
|
+
|
2101
|
+
if (tag == 0x0112) {
|
2102
|
+
if (type == 3 && num == 1) {
|
2103
|
+
o9n = get_u16(p + 8, be);
|
2104
|
+
goto loop_out;
|
2105
|
+
|
2106
|
+
} else {
|
2107
|
+
fprintf(stderr,
|
2108
|
+
"Illeagal orientation tag found [type:%d, num:%d]\n",
|
2109
|
+
type,
|
2110
|
+
num);
|
2111
|
+
}
|
2112
|
+
}
|
2113
|
+
|
2114
|
+
p += 12;
|
2115
|
+
}
|
2116
|
+
}
|
2117
|
+
loop_out:
|
2118
|
+
|
2119
|
+
if (o9n > 0) {
|
2120
|
+
ptr->orientation = o9n;
|
2121
|
+
}
|
2122
|
+
}
|
2123
|
+
|
2124
|
+
static VALUE
|
2125
|
+
create_colormap(jpeg_decode_t* ptr)
|
2126
|
+
{
|
2127
|
+
VALUE ret;
|
2128
|
+
struct jpeg_decompress_struct* cinfo;
|
2129
|
+
JSAMPARRAY map;
|
2130
|
+
int i; // volatileを外すとaarch64のgcc6でクラッシュする場合がある
|
2131
|
+
uint32_t c;
|
2132
|
+
|
2133
|
+
cinfo = &ptr->cinfo;
|
2134
|
+
ret = rb_ary_new_capa(cinfo->actual_number_of_colors);
|
2135
|
+
map = cinfo->colormap;
|
2136
|
+
|
2137
|
+
switch (cinfo->out_color_components) {
|
2138
|
+
case 1:
|
2139
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2140
|
+
c = map[0][i];
|
2141
|
+
rb_ary_push(ret, INT2FIX(c));
|
2142
|
+
}
|
2143
|
+
break;
|
2144
|
+
|
2145
|
+
case 2:
|
2146
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2147
|
+
c = (map[0][i] << 8) | (map[1][i] << 0);
|
2148
|
+
rb_ary_push(ret, INT2FIX(c));
|
2149
|
+
}
|
2150
|
+
break;
|
2151
|
+
|
2152
|
+
case 3:
|
2153
|
+
for (i = 0; i < cinfo->actual_number_of_colors; i++) {
|
2154
|
+
c = (map[0][i] << 16) | (map[1][i] << 8) | (map[2][i] << 0);
|
2155
|
+
|
2156
|
+
rb_ary_push(ret, INT2FIX(c));
|
2157
|
+
}
|
2158
|
+
break;
|
2159
|
+
|
2160
|
+
default:
|
2161
|
+
RUNTIME_ERROR("this number of components is not implemented yet");
|
2162
|
+
}
|
2163
|
+
|
2164
|
+
return ret;
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
static VALUE
|
2168
|
+
rb_meta_exif_tags(VALUE self)
|
2169
|
+
{
|
2170
|
+
return rb_ivar_get(self, id_exif_tags);
|
2171
|
+
}
|
2172
|
+
|
1898
2173
|
static VALUE
|
1899
2174
|
create_meta(jpeg_decode_t* ptr)
|
1900
2175
|
{
|
1901
2176
|
VALUE ret;
|
1902
2177
|
struct jpeg_decompress_struct* cinfo;
|
2178
|
+
int stride;
|
1903
2179
|
|
1904
|
-
|
1905
|
-
|
1906
|
-
|
1907
|
-
cinfo = &ptr->cinfo;
|
2180
|
+
ret = rb_obj_alloc(meta_klass);
|
2181
|
+
cinfo = &ptr->cinfo;
|
2182
|
+
stride = cinfo->output_width * cinfo->output_components;
|
1908
2183
|
|
1909
2184
|
rb_ivar_set(ret, id_width, INT2FIX(cinfo->output_width));
|
2185
|
+
rb_ivar_set(ret, id_stride, INT2FIX(stride));
|
1910
2186
|
rb_ivar_set(ret, id_height, INT2FIX(cinfo->output_height));
|
1911
2187
|
rb_ivar_set(ret, id_orig_cs, get_colorspace_str(cinfo->jpeg_color_space));
|
1912
2188
|
|
@@ -1916,12 +2192,26 @@ create_meta(jpeg_decode_t* ptr)
|
|
1916
2192
|
rb_ivar_set(ret, id_out_cs, get_colorspace_str(cinfo->out_color_space));
|
1917
2193
|
}
|
1918
2194
|
|
1919
|
-
|
2195
|
+
if (TEST_FLAG_ALL(ptr, F_DITHER | F_EXPAND_COLORMAP)) {
|
2196
|
+
rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->out_color_components));
|
2197
|
+
} else {
|
2198
|
+
rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->output_components));
|
2199
|
+
}
|
1920
2200
|
|
1921
|
-
if (ptr
|
1922
|
-
|
2201
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION)) {
|
2202
|
+
pick_exif_orientation(ptr);
|
1923
2203
|
}
|
1924
2204
|
|
2205
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF)) {
|
2206
|
+
rb_ivar_set(ret, id_exif_tags, create_exif_tags_hash(ptr));
|
2207
|
+
rb_define_singleton_method(ret, "exif_tags", rb_meta_exif_tags, 0);
|
2208
|
+
rb_define_singleton_method(ret, "exif", rb_meta_exif_tags, 0);
|
2209
|
+
}
|
2210
|
+
|
2211
|
+
if (TEST_FLAG(ptr, F_DITHER)) {
|
2212
|
+
rb_ivar_set(ret, id_colormap, create_colormap(ptr));
|
2213
|
+
}
|
2214
|
+
|
1925
2215
|
return ret;
|
1926
2216
|
}
|
1927
2217
|
|
@@ -1933,7 +2223,7 @@ do_read_header(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
1933
2223
|
switch (ptr->format) {
|
1934
2224
|
case FMT_YUV422:
|
1935
2225
|
case FMT_RGB565:
|
1936
|
-
|
2226
|
+
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
1937
2227
|
break;
|
1938
2228
|
}
|
1939
2229
|
|
@@ -1953,7 +2243,7 @@ do_read_header(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
1953
2243
|
} else {
|
1954
2244
|
jpeg_mem_src(&ptr->cinfo, jpg, jpg_sz);
|
1955
2245
|
|
1956
|
-
if (ptr
|
2246
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
1957
2247
|
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
1958
2248
|
}
|
1959
2249
|
|
@@ -1968,6 +2258,15 @@ do_read_header(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
1968
2258
|
return ret;
|
1969
2259
|
}
|
1970
2260
|
|
2261
|
+
/**
|
2262
|
+
* read meta data
|
2263
|
+
*
|
2264
|
+
* @overload read_header(jpeg)
|
2265
|
+
*
|
2266
|
+
* @param jpeg [String] input data.
|
2267
|
+
*
|
2268
|
+
* @return [JPEG::Meta] metadata.
|
2269
|
+
*/
|
1971
2270
|
static VALUE
|
1972
2271
|
rb_decoder_read_header(VALUE self, VALUE data)
|
1973
2272
|
{
|
@@ -2018,7 +2317,7 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2018
2317
|
*/
|
2019
2318
|
|
2020
2319
|
VALUE ret;
|
2021
|
-
int i;
|
2320
|
+
volatile int i; // volatileを外すとaarch64のgcc6でクラッシュする場合がある
|
2022
2321
|
int n;
|
2023
2322
|
uint8_t* dst;
|
2024
2323
|
JSAMPARRAY map;
|
@@ -2035,6 +2334,15 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2035
2334
|
}
|
2036
2335
|
break;
|
2037
2336
|
|
2337
|
+
case 2:
|
2338
|
+
for (i = 0; i < n; i++) {
|
2339
|
+
dst[0] = map[0][src[i]];
|
2340
|
+
dst[1] = map[1][src[i]];
|
2341
|
+
|
2342
|
+
dst += 2;
|
2343
|
+
}
|
2344
|
+
break;
|
2345
|
+
|
2038
2346
|
case 3:
|
2039
2347
|
for (i = 0; i < n; i++) {
|
2040
2348
|
dst[0] = map[0][src[i]];
|
@@ -2046,7 +2354,7 @@ expand_colormap(struct jpeg_decompress_struct* cinfo, uint8_t* src)
|
|
2046
2354
|
break;
|
2047
2355
|
|
2048
2356
|
default:
|
2049
|
-
RUNTIME_ERROR("
|
2357
|
+
RUNTIME_ERROR("this number of components is not implemented yet");
|
2050
2358
|
}
|
2051
2359
|
|
2052
2360
|
rb_str_set_len(ret, n * cinfo->out_color_components);
|
@@ -2067,6 +2375,11 @@ swap_cbcr(uint8_t* p, size_t size)
|
|
2067
2375
|
}
|
2068
2376
|
}
|
2069
2377
|
|
2378
|
+
static VALUE
|
2379
|
+
apply_orientation(jpeg_decode_t* ptr, VALUE img)
|
2380
|
+
{
|
2381
|
+
}
|
2382
|
+
|
2070
2383
|
static VALUE
|
2071
2384
|
do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
2072
2385
|
{
|
@@ -2087,7 +2400,7 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2087
2400
|
switch (ptr->format) {
|
2088
2401
|
case FMT_YUV422:
|
2089
2402
|
case FMT_RGB565:
|
2090
|
-
|
2403
|
+
NOT_IMPLEMENTED_ERROR( "not implemented colorspace");
|
2091
2404
|
break;
|
2092
2405
|
|
2093
2406
|
case FMT_GRAYSCALE:
|
@@ -2113,6 +2426,11 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2113
2426
|
|
2114
2427
|
} else {
|
2115
2428
|
jpeg_mem_src(cinfo, jpg, jpg_sz);
|
2429
|
+
|
2430
|
+
if (TEST_FLAG(ptr, F_PARSE_EXIF | F_APPLY_ORIENTATION)) {
|
2431
|
+
jpeg_save_markers(&ptr->cinfo, JPEG_APP1, 0xFFFF);
|
2432
|
+
}
|
2433
|
+
|
2116
2434
|
jpeg_read_header(cinfo, TRUE);
|
2117
2435
|
|
2118
2436
|
cinfo->raw_data_out = FALSE;
|
@@ -2141,7 +2459,6 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2141
2459
|
ret = rb_str_buf_new(raw_sz);
|
2142
2460
|
raw = (uint8_t*)RSTRING_PTR(ret);
|
2143
2461
|
|
2144
|
-
|
2145
2462
|
while (cinfo->output_scanline < cinfo->output_height) {
|
2146
2463
|
for (i = 0, j = cinfo->output_scanline; i < UNIT_LINES; i++, j++) {
|
2147
2464
|
array[i] = raw + (j * stride);
|
@@ -2150,15 +2467,20 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2150
2467
|
jpeg_read_scanlines(cinfo, array, UNIT_LINES);
|
2151
2468
|
}
|
2152
2469
|
|
2153
|
-
if (ptr
|
2470
|
+
if (TEST_FLAG(ptr, F_EXPAND_COLORMAP) && IS_COLORMAPPED(cinfo)) {
|
2154
2471
|
ret = expand_colormap(cinfo, raw);
|
2155
2472
|
} else {
|
2156
|
-
rb_str_set_len(
|
2473
|
+
rb_str_set_len(ret, raw_sz);
|
2157
2474
|
}
|
2158
2475
|
|
2159
|
-
if (ptr->need_meta) add_meta(ret, ptr);
|
2160
2476
|
if (ptr->format == FMT_YVU) swap_cbcr(raw, raw_sz);
|
2161
2477
|
|
2478
|
+
if (TEST_FLAG(ptr, F_NEED_META)) add_meta(ret, ptr);
|
2479
|
+
|
2480
|
+
if (TEST_FLAG(ptr, F_APPLY_ORIENTATION)) {
|
2481
|
+
ret = apply_orientation(ptr, ret);
|
2482
|
+
}
|
2483
|
+
|
2162
2484
|
jpeg_finish_decompress(cinfo);
|
2163
2485
|
jpeg_destroy_decompress(&ptr->cinfo);
|
2164
2486
|
}
|
@@ -2170,6 +2492,15 @@ do_decode(jpeg_decode_t* ptr, uint8_t* jpg, size_t jpg_sz)
|
|
2170
2492
|
return ret;
|
2171
2493
|
}
|
2172
2494
|
|
2495
|
+
/**
|
2496
|
+
* decode JPEG data
|
2497
|
+
*
|
2498
|
+
* @overload decode(jpeg)
|
2499
|
+
*
|
2500
|
+
* @param jpeg [String] JPEG data to decode.
|
2501
|
+
*
|
2502
|
+
* @return [String] decoded raw image data.
|
2503
|
+
*/
|
2173
2504
|
static VALUE
|
2174
2505
|
rb_decoder_decode(VALUE self, VALUE data)
|
2175
2506
|
{
|
@@ -2256,11 +2587,12 @@ Init_jpeg()
|
|
2256
2587
|
|
2257
2588
|
meta_klass = rb_define_class_under(module, "Meta", rb_cObject);
|
2258
2589
|
rb_define_attr(meta_klass, "width", 1, 0);
|
2590
|
+
rb_define_attr(meta_klass, "stride", 1, 0);
|
2259
2591
|
rb_define_attr(meta_klass, "height", 1, 0);
|
2260
2592
|
rb_define_attr(meta_klass, "original_colorspace", 1, 0);
|
2261
2593
|
rb_define_attr(meta_klass, "output_colorspace", 1, 0);
|
2262
2594
|
rb_define_attr(meta_klass, "num_components", 1, 0);
|
2263
|
-
rb_define_attr(meta_klass, "
|
2595
|
+
rb_define_attr(meta_klass, "colormap", 1, 0);
|
2264
2596
|
|
2265
2597
|
decerr_klass = rb_define_class_under(module,
|
2266
2598
|
"DecodeError", rb_eRuntimeError);
|
@@ -2278,11 +2610,13 @@ Init_jpeg()
|
|
2278
2610
|
decoder_opts_ids[i] = rb_intern_const(decoder_opts_keys[i]);
|
2279
2611
|
}
|
2280
2612
|
|
2281
|
-
id_meta
|
2282
|
-
id_width
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2613
|
+
id_meta = rb_intern_const("@meta");
|
2614
|
+
id_width = rb_intern_const("@width");
|
2615
|
+
id_stride = rb_intern_const("@stride");
|
2616
|
+
id_height = rb_intern_const("@height");
|
2617
|
+
id_orig_cs = rb_intern_const("@original_colorspace");
|
2618
|
+
id_out_cs = rb_intern_const("@output_colorspace");
|
2619
|
+
id_ncompo = rb_intern_const("@num_components");
|
2620
|
+
id_exif_tags = rb_intern_const("@exif_tags");
|
2621
|
+
id_colormap = rb_intern_const("@colormap");
|
2288
2622
|
}
|
data/lib/jpeg/version.rb
CHANGED
data/libjpeg-ruby.gemspec
CHANGED
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = %q{libjpeg interface for ruby}
|
13
13
|
spec.description = %q{libjpeg interface for ruby}
|
14
14
|
spec.homepage = "https://github.com/kwgt/libjpeg-ruby"
|
15
|
+
spec.license = "MIT"
|
15
16
|
|
16
17
|
if spec.respond_to?(:metadata)
|
17
18
|
spec.metadata["homepage_uri"] = spec.homepage
|
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.7.
|
4
|
+
version: 0.7.1
|
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-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -60,6 +60,7 @@ extensions:
|
|
60
60
|
- ext/jpeg/extconf.rb
|
61
61
|
extra_rdoc_files: []
|
62
62
|
files:
|
63
|
+
- ".gitignore"
|
63
64
|
- Gemfile
|
64
65
|
- LICENSE
|
65
66
|
- README.md
|
@@ -70,7 +71,8 @@ files:
|
|
70
71
|
- lib/jpeg/version.rb
|
71
72
|
- libjpeg-ruby.gemspec
|
72
73
|
homepage: https://github.com/kwgt/libjpeg-ruby
|
73
|
-
licenses:
|
74
|
+
licenses:
|
75
|
+
- MIT
|
74
76
|
metadata:
|
75
77
|
homepage_uri: https://github.com/kwgt/libjpeg-ruby
|
76
78
|
post_install_message:
|