libjpeg-ruby 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7117f5dece9f78e847213078d1cba56591a30c01ea4b9de58cb4886647d5c530
4
- data.tar.gz: 7bb5c400d519e4958fb9522c8a3af313931dc033a45c404a288d0d5020f02b7c
3
+ metadata.gz: 919842f0b928f7b288efd9f9787401923b75afc65be46060553079ba987d7f7f
4
+ data.tar.gz: a6ea75d0773e2b4d58debcee6b76c03b944d845716409016cd9fbb471ef6fd26
5
5
  SHA512:
6
- metadata.gz: 457f1b3f55ba6c164a40e66303a9c34df6e9ec590137d161c98cee69bbac1385aa4b309c60feb853637c0c392afabdb356996b6809adefd0ed5827051eb318f6
7
- data.tar.gz: 9427246e376ff7a9464b0e4c8cf22b0dff47e9036649f13a49a213b769f7ceab7d3e76dbbd258d65c6c65e5c03bda362cf06acc1b921c83bde74bd49d0c8c85f
6
+ metadata.gz: fcb35ccfd0931f01408a511a66b40bc17999b6da5be6a7b3479674209fb1c529de94ec7bcfccfc5956504dd4a5b18aa8b95d6eac0735975c5d5edf2fca4549a9
7
+ data.tar.gz: e8963a8e0c94abae93314898d500fd207e5e2c98d8c31315d5863a0740ae898521786e9dca1ce37c9180883fdfff667bf56dee58f7f7a2f116387972185dcc54
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .rbenv-gemsets
3
+ .ruby-version
4
+ /.config
5
+ /pkg/
6
+ /doc/
7
+ /tmp/
8
+ /.yardoc/
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 id_exif;
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" // {bool}
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 need_meta;
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 = (int)(NUM2DBL(opts[2]) * 1000.0);
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->need_meta = !0;
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
- ARGUMENT_ERROR("Unsupportd :output_gamma option value.");
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
- ARGUMENT_ERROR("Unsupportd :dither option value.");
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
- ARGUMENT_ERROR( "number of dithered colors is illeagal value.");
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
- ptr->need_meta = RTEST(opt);
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
- ptr->expand_colormap = RTEST(opt);
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 = (int)(NUM2DBL(opt) * 1000.0);
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
- ARGUMENT_ERROR("Unsupportd :exapnd_colormap option value.");
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
- eval_decoder_opt_with_exif(jpeg_decode_t* ptr, VALUE opt)
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
- ptr->parse_exif = RTEST(opt);
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
- 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]);
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 idntifier
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
- create_exif_hash(jpeg_decode_t* ptr)
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
- /* TODO: そのうちディザをかけた場合のカラーマップをメタで返すようにする */
1905
-
1906
- ret = rb_obj_alloc(meta_klass);
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
- rb_ivar_set(ret, id_ncompo, INT2FIX(cinfo->output_components));
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->parse_exif) {
1922
- rb_ivar_set(ret, id_exif, create_exif_hash(ptr));
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
- RUNTIME_ERROR( "Not implement");
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->parse_exif) {
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("Really?");
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
- RUNTIME_ERROR( "Not implement");
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->expand_colormap && IS_COLORMAPPED( cinfo)) {
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( ret, raw_sz);
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, "exif", 1, 0);
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 = 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");
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
@@ -1,3 +1,3 @@
1
1
  module JPEG
2
- VERSION = "0.7.0"
2
+ VERSION = "0.7.1"
3
3
  end
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.0
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-06-23 00:00:00.000000000 Z
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: