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 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: