exif 1.0.1 → 2.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62ee375b5a2f547b733036b6d45e9f07f9157a7f
4
- data.tar.gz: 1777637e0b478a47d4008a0953addbbc1b24f73b
3
+ metadata.gz: cfc6778c57933986114267b125c79dcc46e21ef1
4
+ data.tar.gz: 34fb03f95acd3955bbdca79d97ddeff8ae0029ea
5
5
  SHA512:
6
- metadata.gz: 47983ae0fb7a3ad48c5b01d973da975c0d74bd1e50abb1db4ff310a4296b29c9ee435286c80a5280f45f804524f82e2f118bce0e8b0219f5674913206e09741d
7
- data.tar.gz: f026ead2e3e8c67a13cec1093bba58c7c162d7c67e347c967362ee8c19fe992eba2a077ea91ccd3130004451a1b97d72742a05bc3dcc8a73861a762d91aec272
6
+ metadata.gz: f93647cdb95d30d49575efc2117f92cd6cef714f2d02c6f3beaa385db034eb4fc93ac3e2cc60859e349c0d00aa665341101ca2a1530f185c716f2aa67532324f
7
+ data.tar.gz: 04a4b02e1f799d1c41301582d55c9d68f0d6afb0056caf08bb6427e808e55eaa1460e42f64d06ed6fbf2e0d043b4c15438a108ce53d17218927c1e661ddbf941
@@ -1,591 +1,198 @@
1
+ #include "data.h"
2
+ #include "libjpeg/jpeg-data.h"
3
+ #include "ruby.h"
4
+
1
5
  #include <libexif/exif-data.h>
6
+ #include <libexif/exif-loader.h>
2
7
  #include <time.h>
3
- #include "data.h"
8
+ #include <stdint.h>
4
9
 
5
- extern VALUE rb_mExif;
6
- VALUE rb_cData;
7
- static VALUE IFD2SYM[5];
10
+ extern VALUE rb_mExif, rb_eNotReadble, rb_eIFDNotFound;
11
+ extern const char* exif_entry_to_ivar(ExifEntry* entry);
12
+
13
+ VALUE rb_cExifData;
14
+ static const char* ifd_name_mapping[] = {"ifd0", "ifd1", "exif", "gps", "interoperability"};
15
+ static const char* attr_readers[] = {"ifds", "aperture_value", "artist", "battery_level", "bits_per_sample", "brightness_value", "cfa_pattern", "cfa_repeat_pattern_dim", "color_space", "components_configuration", "compressed_bits_per_pixel", "compression", "contrast", "copyright", "custom_rendered", "date_time", "date_time_digitized", "date_time_original", "device_setting_description", "digital_zoom_ratio", "document_name", "exif_ifd_pointer", "exif_version", "exposure_bias_value", "exposure_index", "exposure_mode", "exposure_program", "exposure_time", "file_source", "fill_order", "flash", "flash_energy", "flash_pix_version", "fnumber", "focal_length", "focal_length_in_35mm_film", "focal_plane_resolution_unit", "focal_plane_x_resolution", "focal_plane_y_resolution", "gain_control", "gamma", "gps_altitude", "gps_altitude_ref", "gps_area_information", "gps_date_stamp", "gps_dest_bearing", "gps_dest_bearing_ref", "gps_dest_distance", "gps_dest_distance_ref", "gps_dest_latitude", "gps_dest_latitude_ref", "gps_dest_longitude", "gps_dest_longitude_ref", "gps_differential", "gps_dop", "gps_img_direction", "gps_img_direction_ref", "gps_info_ifd_pointer", "gps_latitude", "gps_latitude_ref", "gps_longitude", "gps_longitude_ref", "gps_map_datum", "gps_measure_mode", "gps_processing_method", "gps_satellites", "gps_speed", "gps_speed_ref", "gps_status", "gps_time_stamp", "gps_track", "gps_track_ref", "gps_version_id", "image_description", "image_length", "image_resources", "image_unique_id", "image_width", "inter_color_profile", "interoperability_ifd_pointer", "interoperability_index", "interoperability_version", "iptc_naa", "iso_speed_ratings", "jpeg_interchange_format", "jpeg_interchange_format_length", "jpeg_proc", "light_source", "make", "maker_note", "max_aperture_value", "metering_mode", "model", "new_cfa_pattern", "new_subfile_type", "oecf", "orientation", "padding", "photometric_interpretation", "pixel_x_dimension", "pixel_y_dimension", "planar_configuration", "primary_chromaticities", "print_image_matching", "reference_black_white", "related_image_file_format", "related_image_length", "related_image_width", "related_sound_file", "resolution_unit", "rows_per_strip", "samples_per_pixel", "saturation", "scene_capture_type", "scene_type", "sensing_method", "sharpness", "shutter_speed_value", "software", "spatial_frequency_response", "spectral_sensitivity", "strip_byte_counts", "strip_offsets", "sub_ifds", "sub_sec_time", "sub_sec_time_digitized", "sub_sec_time_original", "subject_area", "subject_distance", "subject_distance_range", "subject_location", "tiff_ep_standard_id", "time_zone_offset", "transfer_function", "transfer_range", "user_comment", "white_balance", "white_point", "x_resolution", "xml_packet", "xp_author", "xp_comment", "xp_keywords", "xp_subject", "xp_title", "y_resolution", "ycbcr_coefficients", "ycbcr_positioning", "ycbcr_sub_sampling"};
16
+
17
+ static VALUE new(VALUE self, VALUE input);
18
+ static VALUE dump(VALUE self);
19
+ static VALUE brackets(VALUE self, VALUE ifd_symbol);
20
+ static void each_content(ExifContent *ec, void *user_data);
21
+ static void each_entry(ExifEntry *, void *user_data);
22
+ static VALUE exif_entry_to_rb_value(ExifEntry *);
8
23
 
9
24
  void init_data(){
10
- rb_cData = rb_define_class_under(rb_mExif, "Data", rb_cObject);
11
- IFD2SYM[EXIF_IFD_0] = INT2NUM(0);
12
- IFD2SYM[EXIF_IFD_1] = INT2NUM(1);
13
- IFD2SYM[EXIF_IFD_EXIF] = ID2SYM(rb_intern("exif"));
14
- IFD2SYM[EXIF_IFD_GPS] = ID2SYM(rb_intern("gps"));
15
- IFD2SYM[EXIF_IFD_INTEROPERABILITY] = ID2SYM(rb_intern("interoperability"));
16
- int length = sizeof(attrs) / sizeof(char*);
17
- for(int i = 0; i < length; ++i) rb_define_attr(rb_cData, attrs[i], 1, 0);
18
- rb_define_attr(rb_cData, "contents", 1, 0);
19
- rb_define_alias(rb_cData, "to_h", "contents");
20
- rb_define_singleton_method(rb_cData, "new", rb_new, 1);
21
- rb_define_method(rb_cData, "dump", rb_dump, 0);
22
- rb_define_method(rb_cData, "[]", rb_value, 1);
25
+ int length;
26
+
27
+ rb_cExifData = rb_define_class_under(rb_mExif, "Data", rb_cObject);
28
+ length = sizeof(attr_readers) / sizeof(char*);
29
+ for(int i = 0; i < length; ++i) rb_define_attr(rb_cExifData, attr_readers[i], 1, 0);
30
+ rb_define_alias(rb_cExifData, "to_h", "ifds");
31
+ rb_define_singleton_method(rb_cExifData, "new", new, 1);
32
+ rb_define_method(rb_cExifData, "dump", dump, 0);
33
+ rb_define_method(rb_cExifData, "[]", brackets, 1);
23
34
  }
24
35
 
25
- VALUE rb_new(VALUE self, VALUE file_path){
26
- Check_Type(file_path, T_STRING);
27
- ExifData *ed = exif_data_new_from_file(StringValueCStr(file_path));
28
- if(!ed) rb_raise(rb_eRuntimeError, "File not readable or no EXIF data in file.");
36
+ VALUE new(VALUE self, VALUE input){
37
+ ExifData* ed;
38
+ VALUE read_data;
39
+
40
+ switch (TYPE(input)) {
41
+ case T_STRING:
42
+ read_data = input;
43
+ break;
44
+ case T_FILE:
45
+ read_data = rb_funcall(input, rb_intern("read"), 0);
46
+ break;
47
+ default:
48
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String or IO)", rb_obj_classname(input));
49
+ }
50
+
51
+ ExifLoader *loader = exif_loader_new();
52
+ exif_loader_write(loader, (unsigned char*)RSTRING_PTR(read_data), RSTRING_LEN(read_data));
53
+ ed = exif_loader_get_data(loader);
54
+ exif_loader_unref (loader);
55
+ if(!ed) rb_raise(rb_eNotReadble, "File not readable or no EXIF data in file.");
56
+
57
+
29
58
  VALUE rb_data = Data_Wrap_Struct(self, NULL, exif_data_free, ed);
30
- rb_iv_set(rb_data, "@contents", rb_hash_new());
59
+ rb_iv_set(rb_data, "@ifds", rb_hash_new());
31
60
  exif_data_foreach_content(ed, each_content, &rb_data);
32
61
  return rb_data;
33
62
  }
34
63
 
35
- VALUE rb_dump(VALUE self){
64
+ static VALUE dump(VALUE self){
36
65
  ExifData *ed;
37
66
  Data_Get_Struct(self, ExifData, ed);
38
67
  exif_data_dump(ed);
39
68
  return Qnil;
40
69
  }
41
70
 
42
- VALUE rb_value(VALUE self, VALUE key){
43
- VALUE rb_contents = rb_iv_get(self, "@contents");
44
- return rb_hash_aref(rb_contents, key);
71
+ static VALUE brackets(VALUE self, VALUE ifd_symbol){
72
+ return rb_hash_aref(rb_iv_get(self, "@ifds"), ifd_symbol);
45
73
  }
46
74
 
47
- void each_content(ExifContent *ec, void *self_ptr){
48
- VALUE *self = (VALUE*)self_ptr;
49
- VALUE rb_contents = rb_iv_get(*self, "@contents");
50
- Check_Type(rb_contents, T_HASH);
51
- ExifIfd ifd = exif_content_get_ifd(ec);
52
- VALUE ifd_name = IFD2SYM[ifd]; //rb_str_new_cstr(exif_ifd_get_name(ifd));
53
- if(ifd == EXIF_IFD_COUNT) rb_raise(rb_eRuntimeError, "Con't get IFD.");
54
- else rb_hash_aset(rb_contents, ifd_name, rb_hash_new());
55
- exif_content_foreach_entry(ec, each_entry, self);
75
+ static void each_content(ExifContent *ec, void *self_ptr){
76
+ VALUE *self;
77
+ ExifIfd ifd;
78
+
79
+ ifd = exif_content_get_ifd(ec);
80
+ if(ifd == EXIF_IFD_COUNT) rb_raise(rb_eIFDNotFound, "Con't get IFD.");
81
+ rb_hash_aset(rb_iv_get(*(VALUE*)self_ptr, "@ifds"), ID2SYM(rb_intern(ifd_name_mapping[ifd])), rb_hash_new());
82
+ exif_content_foreach_entry(ec, each_entry, self_ptr);
56
83
  }
57
84
 
58
- void each_entry(ExifEntry *ee, void *self_ptr){
59
- VALUE *self = (VALUE*)self_ptr;
60
- VALUE rb_contents = rb_iv_get(*self, "@contents");
61
- ExifIfd ifd = exif_entry_get_ifd(ee);
62
- const char *attr_name = attr_string(ifd, ee->tag);
63
- VALUE tag_name = ID2SYM(rb_intern(attr_name + 1));
64
- char buf[500];
65
- exif_entry_get_value(ee, buf, sizeof(buf));
85
+ static void each_entry(ExifEntry *entry, void *self_ptr){
66
86
  VALUE value;
67
- switch(ee->format){
68
- // case EXIF_FORMAT_BYTE:
69
- // break;
70
- // case EXIF_FORMAT_ASCII:
71
- // break;
72
- case EXIF_FORMAT_SHORT:
73
- value = INT2NUM(atoi(buf));
74
- break;
75
- case EXIF_FORMAT_LONG:
76
- value = INT2NUM(atol(buf));
77
- break;
78
- // case EXIF_FORMAT_RATIONAL:
79
- // break;
80
- // case EXIF_FORMAT_SBYTE:
81
- // break;
82
- // case EXIF_FORMAT_UNDEFINED:
83
- // break;
84
- // case EXIF_FORMAT_SSHORT:
85
- // break;
86
- // case EXIF_FORMAT_SLONG:
87
- // break;
88
- // case EXIF_FORMAT_SRATIONAL:
89
- // break;
90
- case EXIF_FORMAT_FLOAT:
91
- value = rb_float_new(atof(buf));
92
- break;
93
- case EXIF_FORMAT_DOUBLE:
94
- value = rb_float_new(atof(buf));
95
- break;
96
- default:
97
- value = process_value(self, ifd, ee->tag, buf);
98
- }
99
- rb_hash_aset(rb_hash_aref(rb_contents, IFD2SYM[ifd]), tag_name, value);
100
- rb_hash_aset(rb_contents, tag_name, value);
101
- rb_iv_set(*self, attr_name, value);
102
- }
87
+ const char *ivar_name;
103
88
 
104
- VALUE process_value(VALUE *self_ptr, ExifIfd ifd, ExifTag tag, char *buf){
105
- ExifData *ed;
106
- Data_Get_Struct(*self_ptr, ExifData, ed);
107
- switch((int)tag){
108
- case EXIF_TAG_DATE_TIME:
109
- case EXIF_TAG_DATE_TIME_ORIGINAL:
110
- case EXIF_TAG_DATE_TIME_DIGITIZED:
111
- {
112
- struct tm timer;
113
- // "2013:09:10 16:31:21"
114
- buf[4] = buf[7] = buf[10] = buf[13] = buf[16] = '\0';
115
- timer.tm_year = atoi(buf) - 1900;
116
- timer.tm_mon = atoi(buf + 5) - 1;
117
- timer.tm_mday = atoi(buf + 8);
118
- timer.tm_hour = atoi(buf + 11);
119
- timer.tm_min = atoi(buf + 14);
120
- timer.tm_sec = atoi(buf + 17);
121
- return rb_time_new(mktime(&timer), 0);
122
- break;
123
- }
124
- case EXIF_TAG_GPS_LATITUDE: // EXIF_TAG_INTEROPERABILITY_INDEX
125
- case EXIF_TAG_GPS_LONGITUDE: // EXIF_TAG_INTEROPERABILITY_VERSION
126
- {
127
- if(ifd != EXIF_IFD_GPS) break;
128
- char *l = buf, *r = buf + 1;
129
- double degrees, minutes, seconds;
130
- // "121, 30.7476, 0"
131
- while(*r != ',') r++;
132
- *r = '\0'; r++;
133
- degrees = atof(l); l = r;
134
- while(*r != ',') r++;
135
- *r = '\0';
136
- minutes = atof(l); l = r + 1;
137
- seconds = atof(l);
138
- ExifTag ref_tag = tag == EXIF_TAG_GPS_LATITUDE ? EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF;
139
- ExifEntry *entry = exif_content_get_entry(ed->ifd[EXIF_IFD_GPS], ref_tag);
140
- char ref_value; exif_entry_get_value(entry, &ref_value, 1);
141
- double degree = (degrees * 3600 + minutes * 60 + seconds) / 3600;
142
- if(ref_value == 'S' || ref_value == 'W') degree *= -1;
143
- return rb_float_new(degree);
144
- }
89
+ ivar_name = exif_entry_to_ivar(entry);
90
+ value = exif_entry_to_rb_value(entry);
91
+ rb_hash_aset(
92
+ rb_hash_aref(
93
+ rb_iv_get(*(VALUE*)self_ptr, "@ifds"),
94
+ ID2SYM(rb_intern(ifd_name_mapping[exif_entry_get_ifd(entry)]))
95
+ ),
96
+ ID2SYM(rb_intern(ivar_name + 1)),
97
+ value
98
+ );
99
+ if(TYPE(rb_ivar_defined(*(VALUE*)self_ptr, rb_intern(ivar_name))) == T_FALSE){
100
+ rb_iv_set(*(VALUE*)self_ptr, ivar_name, value);
145
101
  }
146
- return rb_str_new_cstr(buf);
147
102
  }
148
103
 
149
- const char* attr_string(ExifIfd ifd, ExifTag tag){
150
- switch((int)tag){
151
- case EXIF_TAG_INTEROPERABILITY_INDEX: /* EXIF_TAG_GPS_LATITUDE_REF */
152
- return ifd == EXIF_IFD_GPS ? "@gps_latitude_ref" : "@interoperability_index";
153
- break;
154
- case EXIF_TAG_INTEROPERABILITY_VERSION: /* EXIF_TAG_GPS_LATITUDE */
155
- return ifd == EXIF_IFD_GPS ? "@gps_latitude" : "@interoperability_version";
156
- break;
157
- case EXIF_TAG_NEW_SUBFILE_TYPE:
158
- return "@new_subfile_type";
159
- break;
160
- case EXIF_TAG_IMAGE_WIDTH:
161
- return "@image_width";
162
- break;
163
- case EXIF_TAG_IMAGE_LENGTH:
164
- return "@image_length";
165
- break;
166
- case EXIF_TAG_BITS_PER_SAMPLE:
167
- return "@bits_per_sample";
168
- break;
169
- case EXIF_TAG_COMPRESSION:
170
- return "@compression";
171
- break;
172
- case EXIF_TAG_PHOTOMETRIC_INTERPRETATION:
173
- return "@photometric_interpretation";
174
- break;
175
- case EXIF_TAG_FILL_ORDER:
176
- return "@fill_order";
177
- break;
178
- case EXIF_TAG_DOCUMENT_NAME:
179
- return "@document_name";
180
- break;
181
- case EXIF_TAG_IMAGE_DESCRIPTION:
182
- return "@image_description";
183
- break;
184
- case EXIF_TAG_MAKE:
185
- return "@make";
186
- break;
187
- case EXIF_TAG_MODEL:
188
- return "@model";
189
- break;
190
- case EXIF_TAG_STRIP_OFFSETS:
191
- return "@strip_offsets";
192
- break;
193
- case EXIF_TAG_ORIENTATION:
194
- return "@orientation";
195
- break;
196
- case EXIF_TAG_SAMPLES_PER_PIXEL:
197
- return "@samples_per_pixel";
198
- break;
199
- case EXIF_TAG_ROWS_PER_STRIP:
200
- return "@rows_per_strip";
201
- break;
202
- case EXIF_TAG_STRIP_BYTE_COUNTS:
203
- return "@strip_byte_counts";
204
- break;
205
- case EXIF_TAG_X_RESOLUTION:
206
- return "@x_resolution";
207
- break;
208
- case EXIF_TAG_Y_RESOLUTION:
209
- return "@y_resolution";
210
- break;
211
- case EXIF_TAG_PLANAR_CONFIGURATION:
212
- return "@planar_configuration";
213
- break;
214
- case EXIF_TAG_RESOLUTION_UNIT:
215
- return "@resolution_unit";
216
- break;
217
- case EXIF_TAG_TRANSFER_FUNCTION:
218
- return "@transfer_function";
219
- break;
220
- case EXIF_TAG_SOFTWARE:
221
- return "@software";
222
- break;
223
- case EXIF_TAG_DATE_TIME:
224
- return "@date_time";
225
- break;
226
- case EXIF_TAG_ARTIST:
227
- return "@artist";
228
- break;
229
- case EXIF_TAG_WHITE_POINT:
230
- return "@white_point";
231
- break;
232
- case EXIF_TAG_PRIMARY_CHROMATICITIES:
233
- return "@primary_chromaticities";
234
- break;
235
- case EXIF_TAG_SUB_IFDS:
236
- return "@sub_ifds";
237
- break;
238
- case EXIF_TAG_TRANSFER_RANGE:
239
- return "@transfer_range";
240
- break;
241
- case EXIF_TAG_JPEG_PROC:
242
- return "@jpeg_proc";
243
- break;
244
- case EXIF_TAG_JPEG_INTERCHANGE_FORMAT:
245
- return "@jpeg_interchange_format";
246
- break;
247
- case EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
248
- return "@jpeg_interchange_format_length";
249
- break;
250
- case EXIF_TAG_YCBCR_COEFFICIENTS:
251
- return "@ycbcr_coefficients";
252
- break;
253
- case EXIF_TAG_YCBCR_SUB_SAMPLING:
254
- return "@ycbcr_sub_sampling";
255
- break;
256
- case EXIF_TAG_YCBCR_POSITIONING:
257
- return "@ycbcr_positioning";
258
- break;
259
- case EXIF_TAG_REFERENCE_BLACK_WHITE:
260
- return "@reference_black_white";
261
- break;
262
- case EXIF_TAG_XML_PACKET:
263
- return "@xml_packet";
264
- break;
265
- case EXIF_TAG_RELATED_IMAGE_FILE_FORMAT:
266
- return "@related_image_file_format";
267
- break;
268
- case EXIF_TAG_RELATED_IMAGE_WIDTH:
269
- return "@related_image_width";
270
- break;
271
- case EXIF_TAG_RELATED_IMAGE_LENGTH:
272
- return "@related_image_length";
273
- break;
274
- case EXIF_TAG_CFA_REPEAT_PATTERN_DIM:
275
- return "@cfa_repeat_pattern_dim";
276
- break;
277
- case EXIF_TAG_CFA_PATTERN:
278
- return "@cfa_pattern";
279
- break;
280
- case EXIF_TAG_BATTERY_LEVEL:
281
- return "@battery_level";
282
- break;
283
- case EXIF_TAG_COPYRIGHT:
284
- return "@copyright";
285
- break;
286
- case EXIF_TAG_EXPOSURE_TIME:
287
- return "@exposure_time";
288
- break;
289
- case EXIF_TAG_FNUMBER:
290
- return "@fnumber";
291
- break;
292
- case EXIF_TAG_IPTC_NAA:
293
- return "@iptc_naa";
294
- break;
295
- case EXIF_TAG_IMAGE_RESOURCES:
296
- return "@image_resources";
297
- break;
298
- case EXIF_TAG_EXIF_IFD_POINTER:
299
- return "@exif_ifd_pointer";
300
- break;
301
- case EXIF_TAG_INTER_COLOR_PROFILE:
302
- return "@inter_color_profile";
303
- break;
304
- case EXIF_TAG_EXPOSURE_PROGRAM:
305
- return "@exposure_program";
306
- break;
307
- case EXIF_TAG_SPECTRAL_SENSITIVITY:
308
- return "@spectral_sensitivity";
309
- break;
310
- case EXIF_TAG_GPS_INFO_IFD_POINTER:
311
- return "@gps_info_ifd_pointer";
312
- break;
313
- case EXIF_TAG_ISO_SPEED_RATINGS:
314
- return "@iso_speed_ratings";
315
- break;
316
- case EXIF_TAG_OECF:
317
- return "@oecf";
318
- break;
319
- case EXIF_TAG_TIME_ZONE_OFFSET:
320
- return "@time_zone_offset";
321
- break;
322
- case EXIF_TAG_EXIF_VERSION:
323
- return "@exif_version";
324
- break;
325
- case EXIF_TAG_DATE_TIME_ORIGINAL:
326
- return "@date_time_original";
327
- break;
328
- case EXIF_TAG_DATE_TIME_DIGITIZED:
329
- return "@date_time_digitized";
330
- break;
331
- case EXIF_TAG_COMPONENTS_CONFIGURATION:
332
- return "@components_configuration";
333
- break;
334
- case EXIF_TAG_COMPRESSED_BITS_PER_PIXEL:
335
- return "@compressed_bits_per_pixel";
336
- break;
337
- case EXIF_TAG_SHUTTER_SPEED_VALUE:
338
- return "@shutter_speed_value";
339
- break;
340
- case EXIF_TAG_APERTURE_VALUE:
341
- return "@aperture_value";
342
- break;
343
- case EXIF_TAG_BRIGHTNESS_VALUE:
344
- return "@brightness_value";
345
- break;
346
- case EXIF_TAG_EXPOSURE_BIAS_VALUE:
347
- return "@exposure_bias_value";
348
- break;
349
- case EXIF_TAG_MAX_APERTURE_VALUE:
350
- return "@max_aperture_value";
351
- break;
352
- case EXIF_TAG_SUBJECT_DISTANCE:
353
- return "@subject_distance";
354
- break;
355
- case EXIF_TAG_METERING_MODE:
356
- return "@metering_mode";
357
- break;
358
- case EXIF_TAG_LIGHT_SOURCE:
359
- return "@light_source";
360
- break;
361
- case EXIF_TAG_FLASH:
362
- return "@flash";
363
- break;
364
- case EXIF_TAG_FOCAL_LENGTH:
365
- return "@focal_length";
366
- break;
367
- case EXIF_TAG_SUBJECT_AREA:
368
- return "@subject_area";
369
- break;
370
- case EXIF_TAG_TIFF_EP_STANDARD_ID:
371
- return "@tiff_ep_standard_id";
372
- break;
373
- case EXIF_TAG_MAKER_NOTE:
374
- return "@maker_note";
375
- break;
376
- case EXIF_TAG_USER_COMMENT:
377
- return "@user_comment";
378
- break;
379
- case EXIF_TAG_SUB_SEC_TIME:
380
- return "@sub_sec_time";
381
- break;
382
- case EXIF_TAG_SUB_SEC_TIME_ORIGINAL:
383
- return "@sub_sec_time_original";
384
- break;
385
- case EXIF_TAG_SUB_SEC_TIME_DIGITIZED:
386
- return "@sub_sec_time_digitized";
387
- break;
388
- case EXIF_TAG_XP_TITLE:
389
- return "@xp_title";
390
- break;
391
- case EXIF_TAG_XP_COMMENT:
392
- return "@xp_comment";
393
- break;
394
- case EXIF_TAG_XP_AUTHOR:
395
- return "@xp_author";
396
- break;
397
- case EXIF_TAG_XP_KEYWORDS:
398
- return "@xp_keywords";
399
- break;
400
- case EXIF_TAG_XP_SUBJECT:
401
- return "@xp_subject";
402
- break;
403
- case EXIF_TAG_FLASH_PIX_VERSION:
404
- return "@flash_pix_version";
405
- break;
406
- case EXIF_TAG_COLOR_SPACE:
407
- return "@color_space";
408
- break;
409
- case EXIF_TAG_PIXEL_X_DIMENSION:
410
- return "@pixel_x_dimension";
411
- break;
412
- case EXIF_TAG_PIXEL_Y_DIMENSION:
413
- return "@pixel_y_dimension";
414
- break;
415
- case EXIF_TAG_RELATED_SOUND_FILE:
416
- return "@related_sound_file";
417
- break;
418
- case EXIF_TAG_INTEROPERABILITY_IFD_POINTER:
419
- return "@interoperability_ifd_pointer";
420
- break;
421
- case EXIF_TAG_FLASH_ENERGY:
422
- return "@flash_energy";
423
- break;
424
- case EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE:
425
- return "@spatial_frequency_response";
426
- break;
427
- case EXIF_TAG_FOCAL_PLANE_X_RESOLUTION:
428
- return "@focal_plane_x_resolution";
429
- break;
430
- case EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION:
431
- return "@focal_plane_y_resolution";
432
- break;
433
- case EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT:
434
- return "@focal_plane_resolution_unit";
435
- break;
436
- case EXIF_TAG_SUBJECT_LOCATION:
437
- return "@subject_location";
438
- break;
439
- case EXIF_TAG_EXPOSURE_INDEX:
440
- return "@exposure_index";
441
- break;
442
- case EXIF_TAG_SENSING_METHOD:
443
- return "@sensing_method";
444
- break;
445
- case EXIF_TAG_FILE_SOURCE:
446
- return "@file_source";
447
- break;
448
- case EXIF_TAG_SCENE_TYPE:
449
- return "@scene_type";
450
- break;
451
- case EXIF_TAG_NEW_CFA_PATTERN:
452
- return "@new_cfa_pattern";
453
- break;
454
- case EXIF_TAG_CUSTOM_RENDERED:
455
- return "@custom_rendered";
456
- break;
457
- case EXIF_TAG_EXPOSURE_MODE:
458
- return "@exposure_mode";
459
- break;
460
- case EXIF_TAG_WHITE_BALANCE:
461
- return "@white_balance";
462
- break;
463
- case EXIF_TAG_DIGITAL_ZOOM_RATIO:
464
- return "@digital_zoom_ratio";
465
- break;
466
- case EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM:
467
- return "@focal_length_in_35mm_film";
468
- break;
469
- case EXIF_TAG_SCENE_CAPTURE_TYPE:
470
- return "@scene_capture_type";
471
- break;
472
- case EXIF_TAG_GAIN_CONTROL:
473
- return "@gain_control";
474
- break;
475
- case EXIF_TAG_CONTRAST:
476
- return "@contrast";
477
- break;
478
- case EXIF_TAG_SATURATION:
479
- return "@saturation";
480
- break;
481
- case EXIF_TAG_SHARPNESS:
482
- return "@sharpness";
483
- break;
484
- case EXIF_TAG_DEVICE_SETTING_DESCRIPTION:
485
- return "@device_setting_description";
486
- break;
487
- case EXIF_TAG_SUBJECT_DISTANCE_RANGE:
488
- return "@subject_distance_range";
489
- break;
490
- case EXIF_TAG_IMAGE_UNIQUE_ID:
491
- return "@image_unique_id";
492
- break;
493
- case EXIF_TAG_GAMMA:
494
- return "@gamma";
495
- break;
496
- case EXIF_TAG_PRINT_IMAGE_MATCHING:
497
- return "@print_image_matching";
498
- break;
499
- case EXIF_TAG_PADDING:
500
- return "@padding";
501
- break;
502
- case EXIF_TAG_GPS_VERSION_ID:
503
- return "@gps_version_id";
504
- break;
505
- case EXIF_TAG_GPS_LONGITUDE_REF:
506
- return "@gps_longitude_ref";
507
- break;
508
- case EXIF_TAG_GPS_LONGITUDE:
509
- return "@gps_longitude";
510
- break;
511
- case EXIF_TAG_GPS_ALTITUDE_REF:
512
- return "@gps_altitude_ref";
513
- break;
514
- case EXIF_TAG_GPS_ALTITUDE:
515
- return "@gps_altitude";
516
- break;
517
- case EXIF_TAG_GPS_TIME_STAMP:
518
- return "@gps_time_stamp";
519
- break;
520
- case EXIF_TAG_GPS_SATELLITES:
521
- return "@gps_satellites";
522
- break;
523
- case EXIF_TAG_GPS_STATUS:
524
- return "@gps_status";
525
- break;
526
- case EXIF_TAG_GPS_MEASURE_MODE:
527
- return "@gps_measure_mode";
528
- break;
529
- case EXIF_TAG_GPS_DOP:
530
- return "@gps_dop";
531
- break;
532
- case EXIF_TAG_GPS_SPEED_REF:
533
- return "@gps_speed_ref";
534
- break;
535
- case EXIF_TAG_GPS_SPEED:
536
- return "@gps_speed";
537
- break;
538
- case EXIF_TAG_GPS_TRACK_REF:
539
- return "@gps_track_ref";
540
- break;
541
- case EXIF_TAG_GPS_TRACK:
542
- return "@gps_track";
543
- break;
544
- case EXIF_TAG_GPS_IMG_DIRECTION_REF:
545
- return "@gps_img_direction_ref";
546
- break;
547
- case EXIF_TAG_GPS_IMG_DIRECTION:
548
- return "@gps_img_direction";
549
- break;
550
- case EXIF_TAG_GPS_MAP_DATUM:
551
- return "@gps_map_datum";
552
- break;
553
- case EXIF_TAG_GPS_DEST_LATITUDE_REF:
554
- return "@gps_dest_latitude_ref";
555
- break;
556
- case EXIF_TAG_GPS_DEST_LATITUDE:
557
- return "@gps_dest_latitude";
558
- break;
559
- case EXIF_TAG_GPS_DEST_LONGITUDE_REF:
560
- return "@gps_dest_longitude_ref";
561
- break;
562
- case EXIF_TAG_GPS_DEST_LONGITUDE:
563
- return "@gps_dest_longitude";
564
- break;
565
- case EXIF_TAG_GPS_DEST_BEARING_REF:
566
- return "@gps_dest_bearing_ref";
567
- break;
568
- case EXIF_TAG_GPS_DEST_BEARING:
569
- return "@gps_dest_bearing";
570
- break;
571
- case EXIF_TAG_GPS_DEST_DISTANCE_REF:
572
- return "@gps_dest_distance_ref";
573
- break;
574
- case EXIF_TAG_GPS_DEST_DISTANCE:
575
- return "@gps_dest_distance";
576
- break;
577
- case EXIF_TAG_GPS_PROCESSING_METHOD:
578
- return "@gps_processing_method";
104
+ static VALUE exif_entry_to_rb_value(ExifEntry *entry){
105
+ ExifData *data;
106
+ ExifByteOrder order;
107
+ ExifRational rational;
108
+ ExifSRational srational;
109
+ VALUE ret;
110
+ size_t len, i;
111
+ unsigned char size;
112
+ struct tm tm = {};
113
+
114
+ data = entry->parent->parent;
115
+ order = exif_data_get_byte_order(data);
116
+ ret = Qnil;
117
+ size = exif_format_get_size(entry->format);
118
+
119
+ switch(entry->format){
120
+ case EXIF_FORMAT_UNDEFINED:
121
+ ret = rb_str_new((const char*)entry->data, entry->size);
122
+ break;
123
+ case EXIF_FORMAT_BYTE:
124
+ if(entry->components > 1){
125
+ ret = rb_ary_new2(entry->components);
126
+ for (i = 0; i < entry->components; i++)
127
+ rb_ary_push(ret, INT2FIX((uint8_t)entry->data[i]));
128
+ }else ret = INT2FIX((uint8_t)entry->data[0]);
129
+ case EXIF_FORMAT_SBYTE:
130
+ if(entry->components > 1){
131
+ ret = rb_ary_new2(entry->components);
132
+ for (i = 0; i < entry->components; i++)
133
+ rb_ary_push(ret, INT2FIX((int8_t)entry->data[i]));
134
+ }else ret = INT2FIX((int8_t)entry->data[0]);
579
135
  break;
580
- case EXIF_TAG_GPS_AREA_INFORMATION:
581
- return "@gps_area_information";
136
+ case EXIF_FORMAT_SHORT:
137
+ if(entry->components > 1){
138
+ ret = rb_ary_new2(entry->components);
139
+ for(i = 0; i < entry->components; i++)
140
+ rb_ary_push(ret, INT2FIX(exif_get_short(entry->data + i*size, order)));
141
+ }else ret = INT2FIX(exif_get_short(entry->data, order));
142
+ break;
143
+ case EXIF_FORMAT_SSHORT:
144
+ if(entry->components > 1){
145
+ ret = rb_ary_new2(entry->components);
146
+ for(i = 0; i < entry->components; i++)
147
+ rb_ary_push(ret, INT2FIX(exif_get_sshort(entry->data + i*size, order)));
148
+ }else ret = INT2FIX(exif_get_sshort(entry->data, order));
582
149
  break;
583
- case EXIF_TAG_GPS_DATE_STAMP:
584
- return "@gps_date_stamp";
150
+ case EXIF_FORMAT_LONG:
151
+ if(entry->components > 1){
152
+ ret = rb_ary_new2(entry->components);
153
+ for(i = 0; i < entry->components; i++)
154
+ rb_ary_push(ret, ULONG2NUM(exif_get_long(entry->data + i*size, order)));
155
+ }else ret = ULONG2NUM(exif_get_long(entry->data, order));
156
+ break;
157
+ case EXIF_FORMAT_SLONG:
158
+ if(entry->components > 1){
159
+ ret = rb_ary_new2(entry->components);
160
+ for(i = 0; i < entry->components; i++)
161
+ rb_ary_push(ret, LONG2NUM(exif_get_slong(entry->data + i*size, order)));
162
+ }else ret = LONG2NUM(exif_get_slong(entry->data, order));
163
+ break;
164
+ case EXIF_FORMAT_ASCII:
165
+ ret = rb_str_new2((const char *)entry->data);
166
+ break;
167
+ case EXIF_FORMAT_RATIONAL:
168
+ if(entry->components > 1){
169
+ ret = rb_ary_new2(entry->components);
170
+ for(i = 0; i < entry->components; i++){
171
+ rational = exif_get_rational(entry->data + i * size, order);
172
+ rb_ary_push(ret, rb_rational_new(ULONG2NUM(rational.numerator), ULONG2NUM(rational.denominator)));
173
+ }
174
+ } else {
175
+ rational = exif_get_rational(entry->data, order);
176
+ ret = rb_rational_new(ULONG2NUM(rational.numerator), ULONG2NUM(rational.denominator));
177
+ }
178
+ break;
179
+ case EXIF_FORMAT_SRATIONAL:
180
+ if(entry->components > 1){
181
+ ret = rb_ary_new2(entry->components);
182
+ for(int i = 0; i < entry->components; i++){
183
+ srational = exif_get_srational(entry->data + i * size, order);
184
+ rb_ary_push(ret, rb_rational_new(LONG2FIX(srational.numerator), LONG2FIX(srational.denominator)));
185
+ }
186
+ } else {
187
+ srational = exif_get_srational(entry->data, order);
188
+ ret = rb_rational_new(LONG2FIX(srational.numerator), LONG2FIX(srational.denominator));
189
+ }
585
190
  break;
586
- case EXIF_TAG_GPS_DIFFERENTIAL:
587
- return "@gps_differential";
191
+ case EXIF_FORMAT_DOUBLE:
192
+ case EXIF_FORMAT_FLOAT:
193
+ ret = rb_float_new(*(double*)entry->data);
588
194
  break;
589
195
  }
590
- return NULL;
591
- }
196
+
197
+ return ret;
198
+ }