extexif 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/ChangeLog ADDED
@@ -0,0 +1,18 @@
1
+ Thu May 22 21:30:00 2007 Rakuto Furutani <rakuto@gmail.com>
2
+ * exif.c : support to fetch Exif GPS data.
3
+
4
+ Wed Dec 11 20:21:22 2002 Ryuichi Tamura <r-tam@fsinet.or.jp>
5
+
6
+ * exif.c (rb_exif_get_tag) : now need not pass hexadecimal number
7
+ as string object. pass it as it is.
8
+
9
+ * exif.c (rb_exif_get_tag) : search only for tags available in
10
+ libexif to improve search performance.
11
+
12
+ * Version 0.1.2
13
+
14
+ Mon Nov 11 22:48:17 2002 Ryuichi Tamura <r-tam@fsinet.or.jp>
15
+
16
+ * exif.c (rb_exif_get_tag) : return nil if return value is empty.
17
+
18
+ * Version 0.1.1.
data/ext/Makefile ADDED
@@ -0,0 +1,149 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/lib/ruby/1.8/i486-linux
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ prefix = $(DESTDIR)/usr
11
+ exec_prefix = $(DESTDIR)/usr
12
+ sitedir = $(DESTDIR)/usr/local/lib/site_ruby
13
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
14
+ docdir = $(datarootdir)/doc/$(PACKAGE)
15
+ dvidir = $(docdir)
16
+ datarootdir = $(prefix)/share
17
+ archdir = $(rubylibdir)/$(arch)
18
+ sbindir = $(exec_prefix)/sbin
19
+ psdir = $(docdir)
20
+ localedir = $(datarootdir)/locale
21
+ htmldir = $(docdir)
22
+ datadir = $(prefix)/share
23
+ includedir = $(prefix)/include
24
+ infodir = $(datarootdir)/info
25
+ sysconfdir = $(DESTDIR)/etc
26
+ mandir = $(datadir)/man
27
+ libdir = $(DESTDIR)/usr/lib
28
+ sharedstatedir = $(prefix)/com
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ pdfdir = $(docdir)
31
+ sitearchdir = $(sitelibdir)/$(sitearch)
32
+ bindir = $(exec_prefix)/bin
33
+ localstatedir = $(DESTDIR)/var
34
+ sitelibdir = $(sitedir)/$(ruby_version)
35
+ libexecdir = $(exec_prefix)/libexec
36
+
37
+ CC = gcc
38
+ LIBRUBY = $(LIBRUBY_SO)
39
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
40
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
41
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
42
+
43
+ RUBY_EXTCONF_H =
44
+ CFLAGS = -fPIC -Wall -g -fno-strict-aliasing -O2 -fPIC
45
+ INCFLAGS = -I. -I. -I/usr/lib/ruby/1.8/i486-linux -I.
46
+ CPPFLAGS = -DHAVE_LIBEXIF_EXIF_IFD_H -DHAVE_LIBEXIF_EXIF_DATA_H -DHAVE_LIBEXIF_EXIF_UTILS_H -DHAVE_LIBEXIF_EXIF_TAG_H -I/usr/local/include
47
+ CXXFLAGS = $(CFLAGS)
48
+ DLDFLAGS = -rdynamic -Wl,-export-dynamic
49
+ LDSHARED = $(CC) -shared
50
+ AR = ar
51
+ EXEEXT =
52
+
53
+ RUBY_INSTALL_NAME = ruby1.8
54
+ RUBY_SO_NAME = ruby1.8
55
+ arch = i486-linux
56
+ sitearch = i486-linux
57
+ ruby_version = 1.8
58
+ ruby = /usr/bin/ruby1.8
59
+ RUBY = $(ruby)
60
+ RM = rm -f
61
+ MAKEDIRS = mkdir -p
62
+ INSTALL = /usr/bin/install -c
63
+ INSTALL_PROG = $(INSTALL) -m 0755
64
+ INSTALL_DATA = $(INSTALL) -m 644
65
+ COPY = cp
66
+
67
+ #### End of system configuration section. ####
68
+
69
+ preload =
70
+
71
+ libpath = /usr/local/lib $(libdir)
72
+ LIBPATH = -L"/usr/local/lib" -L"$(libdir)"
73
+ DEFFILE =
74
+
75
+ CLEANFILES =
76
+ DISTCLEANFILES =
77
+
78
+ extout =
79
+ extout_prefix =
80
+ target_prefix =
81
+ LOCAL_LIBS =
82
+ LIBS = $(LIBRUBYARG_SHARED) -lexif -lpthread -ldl -lcrypt -lm -lc
83
+ SRCS = exif.c
84
+ OBJS = exif.o
85
+ TARGET = exif
86
+ DLLIB = $(TARGET).so
87
+ EXTSTATIC =
88
+ STATIC_LIB =
89
+
90
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
91
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
92
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
93
+
94
+ TARGET_SO = $(DLLIB)
95
+ CLEANLIBS = $(TARGET).so $(TARGET).il? $(TARGET).tds $(TARGET).map
96
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
97
+
98
+ all: $(DLLIB)
99
+ static: $(STATIC_LIB)
100
+
101
+ clean:
102
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
103
+
104
+ distclean: clean
105
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
106
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
107
+
108
+ realclean: distclean
109
+ install: install-so install-rb
110
+
111
+ install-so: $(RUBYARCHDIR)
112
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
113
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
114
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
115
+ install-rb: pre-install-rb install-rb-default
116
+ install-rb-default: pre-install-rb-default
117
+ pre-install-rb: Makefile
118
+ pre-install-rb-default: Makefile
119
+ $(RUBYARCHDIR):
120
+ $(MAKEDIRS) $@
121
+
122
+ site-install: site-install-so site-install-rb
123
+ site-install-so: install-so
124
+ site-install-rb: install-rb
125
+
126
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
127
+
128
+ .cc.o:
129
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
130
+
131
+ .cxx.o:
132
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
133
+
134
+ .cpp.o:
135
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
136
+
137
+ .C.o:
138
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
139
+
140
+ .c.o:
141
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
142
+
143
+ $(DLLIB): $(OBJS)
144
+ @-$(RM) $@
145
+ $(LDSHARED) $(DLDFLAGS) $(LIBPATH) -o $@ $(OBJS) $(LOCAL_LIBS) $(LIBS)
146
+
147
+
148
+
149
+ $(OBJS): ruby.h defines.h
data/ext/README ADDED
@@ -0,0 +1,30 @@
1
+ = ruby-libexif - an interface to libexif library
2
+
3
+ libexif is a library for parsing, editing, and saving EXIF data.
4
+ You can retrieve useful information from EXIF tags contained in
5
+ images created by recording equipments(for example, digital camera).
6
+ For more information, please refer ((<URL:http://libexif.sourceforge.net/>))
7
+
8
+ == Requirements
9
+
10
+ * ruby-1.6 or heigher
11
+ * libexif-0.5.6 (or heigher)
12
+
13
+ == Install
14
+
15
+ $ ruby extconf.rb
16
+ $ su
17
+ # make site-install
18
+
19
+ == Author
20
+
21
+ Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
22
+ See 'COPYING' file for license information.
23
+
24
+ == Homepage
25
+
26
+ ((<URL:http://tam.0xfa.com/ruby-libexif/>))
27
+
28
+ == Bugs
29
+
30
+ methods to edit the value of EXIF tag is not yet implemented.
data/ext/exif.c ADDED
@@ -0,0 +1,653 @@
1
+ /******************************************************************************
2
+ vim:sts=4:ts=4:sw=4
3
+
4
+ exif.c - ruby interface to libexif library
5
+
6
+ Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
7
+
8
+ Deried & Copyrth (C) 2007 Rakuto Furutani <rfurutani@uievolution.com>
9
+
10
+
11
+ *******************************************************************************/
12
+ #include <ruby.h>
13
+ #include <libexif/exif-tag.h>
14
+ #include <libexif/exif-data.h>
15
+ #include <libexif/exif-utils.h>
16
+
17
+ #define Get_Exif(obj, exif) { \
18
+ Data_Get_Struct((obj), Exif, (exif)); \
19
+ if (!(exif)->ed) \
20
+ rb_raise(eExifError, "should set data first"); \
21
+ }
22
+
23
+
24
+ typedef struct _Exif Exif;
25
+
26
+ struct _Exif {
27
+ ExifData *ed;
28
+ int ifd;
29
+ };
30
+
31
+ #define IFD_RB_DEFAULT (EXIF_IFD_0 - 1)
32
+
33
+ static VALUE cExif, mExifByteOrder, mExifIfd;
34
+ static VALUE eExifError, eExifInvalidFormat;
35
+ static VALUE eExifInvalidIFD, eExifTagNotFound, eExifThumbnailNotFound;
36
+
37
+ static void
38
+ rb_exif_free(Exif *exif)
39
+ {
40
+ if (exif){
41
+ exif_data_free(exif->ed);
42
+ exif->ed = NULL;
43
+ free(exif);
44
+ }
45
+ }
46
+
47
+ static VALUE
48
+ rb_exif_s_new(int argc, VALUE *argv, VALUE klass)
49
+ {
50
+ VALUE obj;
51
+ Exif *exif;
52
+ exif = ALLOC(Exif);
53
+ exif->ed = NULL;
54
+ exif->ifd = IFD_RB_DEFAULT;
55
+ obj = Data_Wrap_Struct(klass, 0, rb_exif_free, exif);
56
+ rb_obj_call_init(obj, argc, argv);
57
+ return obj;
58
+ }
59
+
60
+ static ExifData *
61
+ rb_exif_data_new_from_file(VALUE fpath)
62
+ {
63
+ ExifData *data;
64
+ Check_Type(fpath, T_STRING);
65
+ data = exif_data_new_from_file(RSTRING(fpath)->ptr);
66
+ if (!data){
67
+ FILE *f;
68
+ f = fopen(RSTRING(fpath)->ptr,"rb");
69
+ if (!f)
70
+ rb_raise(rb_eArgError, "unable to open file - '%s'",
71
+ RSTRING(fpath)->ptr);
72
+ fclose(f);
73
+ rb_raise(eExifInvalidFormat,
74
+ "'%s' does not contain EXIF data", RSTRING(fpath)->ptr);
75
+ }
76
+ return data;
77
+ }
78
+
79
+
80
+ static VALUE
81
+ rb_exif_initialize(int argc, VALUE *argv, VALUE obj)
82
+ {
83
+ VALUE fpath;
84
+ Exif *exif;
85
+ Data_Get_Struct(obj, Exif, exif);
86
+ if (rb_scan_args(argc, argv, "01", &fpath) == 1) {
87
+ exif->ed = rb_exif_data_new_from_file(fpath);
88
+ }
89
+ else {
90
+ exif->ed = exif_data_new();
91
+ }
92
+ return Qnil;
93
+ }
94
+
95
+ static void
96
+ rb_exif_data_new_from_data(ExifData *ed, VALUE str)
97
+ {
98
+ Check_Type(str, T_STRING);
99
+ if (ed){
100
+ exif_data_free(ed);
101
+ ed = NULL;
102
+ }
103
+ ed = exif_data_new_from_data((unsigned char *)RSTRING(str)->ptr, RSTRING(str)->len);
104
+ }
105
+
106
+ static VALUE
107
+ rb_exif_set_data(VALUE obj, VALUE str)
108
+ {
109
+ Exif *exif;
110
+ Data_Get_Struct(obj, Exif, exif);
111
+ rb_exif_data_new_from_data(exif->ed, str);
112
+ return obj;
113
+ }
114
+
115
+ static VALUE
116
+ rb_exif_get_byte_order(VALUE obj)
117
+ {
118
+ Exif *exif;
119
+ Get_Exif(obj, exif);
120
+ return FIX2INT(exif_data_get_byte_order(exif->ed));
121
+ }
122
+
123
+ static VALUE
124
+ rb_exif_set_byte_order(VALUE obj, VALUE byteorder)
125
+ {
126
+ Exif *exif;
127
+ Get_Exif(obj, exif);
128
+ exif_data_set_byte_order(exif->ed, FIX2INT(byteorder));
129
+ return obj;
130
+ }
131
+
132
+ static void
133
+ rb_exif_yield_tag_value(ExifEntry *entry, void *data)
134
+ {
135
+ VALUE k, v;
136
+ char buf[7];
137
+ char value[1024];
138
+ unsigned char *ids = data;
139
+ memset(buf, 0, sizeof(buf));
140
+ sprintf(buf, "0x%04x", entry->tag);
141
+ k = *ids ? rb_str_new2(buf) : rb_str_new2(exif_tag_get_title(entry->tag));
142
+ v = rb_str_new2(exif_entry_get_value(entry, value, sizeof(value)));
143
+ rb_yield(rb_assoc_new(k, v));
144
+ }
145
+
146
+
147
+ static void
148
+ rb_exif_data_foreach_content_func(ExifContent *content, void *data)
149
+ {
150
+ exif_content_foreach_entry(content, rb_exif_yield_tag_value, data);
151
+ }
152
+
153
+ static VALUE
154
+ rb_exif_each(int argc, VALUE *argv, VALUE obj)
155
+ {
156
+ Exif *exif;
157
+ VALUE use_tag_id;
158
+ unsigned char ids = 0;
159
+ if (rb_scan_args(argc, argv, "01", &use_tag_id) == 1){
160
+ ids = FIX2UINT(use_tag_id);
161
+ }
162
+ Get_Exif(obj, exif);
163
+ exif_data_foreach_content(exif->ed, rb_exif_data_foreach_content_func, &ids);
164
+ return obj;
165
+ }
166
+
167
+ static ExifIfd exif_ifd_from_string (const char *);
168
+
169
+ static VALUE
170
+ rb_exif_set_ifd(VALUE obj, VALUE ifd)
171
+ {
172
+ Exif *exif;
173
+ int i;
174
+ Get_Exif(obj, exif);
175
+ switch(TYPE(ifd)){
176
+ case T_FIXNUM:
177
+ i = FIX2INT(ifd);
178
+ if (i < IFD_RB_DEFAULT || i > EXIF_IFD_INTEROPERABILITY){
179
+ rb_raise(rb_eRuntimeError, "wrong constant");
180
+ }
181
+ break;
182
+ case T_STRING:
183
+ i = exif_ifd_from_string(RSTRING(ifd)->ptr);
184
+ if (i == -1){
185
+ rb_raise(rb_eRuntimeError, "unknown IFD: '%s'", RSTRING(ifd)->ptr);
186
+ }
187
+ break;
188
+ default:
189
+ rb_raise(rb_eTypeError, "wrong type of an argument");
190
+ break;
191
+ }
192
+ exif->ifd = i;
193
+ return obj;
194
+ }
195
+
196
+ static VALUE
197
+ rb_exif_get_ifd(VALUE obj)
198
+ {
199
+ Exif *exif;
200
+ const char *name;
201
+ Get_Exif(obj, exif);
202
+ name = exif_ifd_get_name(exif->ifd);
203
+ if (!name)
204
+ return Qnil;
205
+ return rb_str_new2(name);
206
+ }
207
+
208
+ static ExifTag exif_tag_from_string (const char *);
209
+ static ExifTag exif_tag_from_tagid (ExifTag);
210
+
211
+ static VALUE
212
+ rb_exif_get_tag(VALUE obj, VALUE tagid)
213
+ {
214
+ Exif *exif;
215
+ ExifTag tag;
216
+ ExifEntry *e;
217
+ const char *found;
218
+ int i;
219
+ char value[1024];
220
+
221
+ Get_Exif(obj, exif);
222
+ switch (TYPE(tagid)) {
223
+ case T_STRING:
224
+ tag = exif_tag_from_string(RSTRING(tagid)->ptr);
225
+ if (!tag){
226
+ rb_raise(eExifError, "invalid tag: '%s'", RSTRING(tagid)->ptr);
227
+ }
228
+ break;
229
+ case T_FIXNUM:
230
+ tag = exif_tag_from_tagid(FIX2INT(tagid));
231
+ if (!tag){
232
+ rb_raise(eExifError, "invalid tag: 0x%04x", tagid);
233
+ }
234
+ break;
235
+ default:
236
+ rb_raise(rb_eTypeError, "wrong type of arguments");
237
+ break;
238
+ }
239
+ if (exif->ifd >= 0){
240
+ e = exif_content_get_entry(exif->ed->ifd[exif->ifd], tag);
241
+ if (!e){
242
+ rb_raise(eExifTagNotFound,
243
+ "IFD '%s' does not contain tag '%s'(0x%04x)",
244
+ exif_ifd_get_name(exif->ifd), exif_tag_get_title(tag), tag);
245
+ }
246
+ return rb_str_new2(exif_entry_get_value(e, value, sizeof(value)));
247
+ }
248
+ for (i = 0; i < EXIF_IFD_COUNT; i++){
249
+ e = exif_content_get_entry(exif->ed->ifd[i], tag);
250
+ if (e)
251
+ break;
252
+ }
253
+ found = exif_entry_get_value(e, value, sizeof(value));
254
+ return found ? rb_str_new2(found) : Qnil;
255
+ }
256
+
257
+ static void
258
+ rb_exif_set_tag_0(ExifData *ed, ExifEntry *e, VALUE val)
259
+ {
260
+ ExifByteOrder o;
261
+ o = exif_data_get_byte_order(ed);
262
+ /* exif_entry_dump(e, 1); */
263
+
264
+ }
265
+
266
+ static VALUE
267
+ rb_exif_set_tag(VALUE obj, VALUE tagid, VALUE val)
268
+ {
269
+ Exif *exif;
270
+ ExifTag tag;
271
+ ExifEntry *e;
272
+
273
+ rb_raise(rb_eNotImpError, "soryy, not yet implemented");
274
+ Check_Type(tagid, T_STRING);
275
+ Check_Type(val, T_STRING);
276
+ Get_Exif(obj, exif);
277
+ tag = exif_tag_from_string(RSTRING(tagid)->ptr);
278
+ if (!tag || !exif_tag_get_name(tag)){
279
+ rb_raise(eExifError, "invalid tag: '%s'", RSTRING(tagid)->ptr);
280
+ }
281
+ e = exif_content_get_entry(exif->ed->ifd[exif->ifd], tag);
282
+ if (!e){
283
+ e = exif_entry_new();
284
+ exif_content_add_entry(exif->ed->ifd[exif->ifd], e);
285
+ exif_entry_initialize(e, tag);
286
+ }
287
+ rb_exif_set_tag_0(exif->ed, e, val);
288
+ return obj;
289
+ }
290
+ static VALUE
291
+ rb_exif_list_tags_at_ifd(VALUE obj, VALUE ifd)
292
+ {
293
+ Exif *exif;
294
+ unsigned int tag;
295
+ int i;
296
+ const char *name;
297
+ char buf[7];
298
+ VALUE ret = rb_ary_new();
299
+ i = FIX2INT(ifd);
300
+ if (i < EXIF_IFD_0 || i > EXIF_IFD_INTEROPERABILITY){
301
+ rb_raise(rb_eRuntimeError, "wrong constant");
302
+ }
303
+ Get_Exif(obj, exif);
304
+ for (tag = 0; tag < 0xffff; tag++) {
305
+ name = exif_tag_get_title(tag);
306
+ if (!name)
307
+ continue;
308
+ if (exif_content_get_entry(exif->ed->ifd[i], tag)){
309
+ memset(buf, 0, sizeof(buf));
310
+ sprintf(buf, "0x%04x", tag);
311
+ rb_ary_push(ret, rb_assoc_new(rb_str_new2(name), rb_str_new2(buf)));
312
+ }
313
+ }
314
+ return ret;
315
+ }
316
+
317
+ static VALUE
318
+ rb_exif_s_get_tag_description(VALUE klass, VALUE tagid)
319
+ {
320
+ ExifTag tag;
321
+ VALUE cdr;
322
+ char buf[7];
323
+ switch (TYPE(tagid)){
324
+ case T_FIXNUM:
325
+ tag = FIX2INT(tagid);
326
+ if (!exif_tag_get_name(tag))
327
+ rb_raise(eExifError, "invalid tag id: 0x%04x(%d)",
328
+ FIX2INT(tagid), FIX2INT(tagid));
329
+ break;
330
+ case T_STRING:
331
+ tag = exif_tag_from_string(RSTRING(tagid)->ptr);
332
+ if (!tag || !exif_tag_get_name(tag)) {
333
+ rb_raise(eExifError, "invalid tag: '%s'", RSTRING(tagid)->ptr);
334
+ }
335
+ break;
336
+ default:
337
+ rb_raise(rb_eTypeError, "wrong type of an argument");
338
+ break;
339
+ }
340
+ memset(buf, 0, sizeof(buf));
341
+ sprintf(buf, "0x%04x", tag);
342
+ cdr = rb_ary_new();
343
+ rb_ary_push(cdr, rb_str_new2(exif_tag_get_name(tag)));
344
+ rb_ary_push(cdr, rb_str_new2(exif_tag_get_description(tag)));
345
+ rb_ary_push(cdr, rb_str_new2(buf));
346
+ return rb_assoc_new(rb_str_new2(exif_tag_get_title(tag)), cdr);
347
+ }
348
+
349
+ static VALUE
350
+ rb_exif_extract_thumbnail(VALUE obj, VALUE dest)
351
+ {
352
+ Exif *exif;
353
+ Get_Exif(obj, exif);
354
+ if (!exif->ed->data)
355
+ rb_raise(eExifThumbnailNotFound, "thumbnail not found");
356
+ rb_funcall(dest, rb_intern("<<"), 1, rb_str_new((char *)exif->ed->data, exif->ed->size));
357
+ return obj;
358
+ }
359
+
360
+ static VALUE
361
+ rb_exif_set_thumbnail(VALUE obj, VALUE src)
362
+ {
363
+ Exif *exif;
364
+ Get_Exif(obj, exif);
365
+ if (exif->ed->data){
366
+ free(exif->ed->data);
367
+ exif->ed->data = NULL;
368
+ exif->ed->size = 0;
369
+ }
370
+ Check_Type(src, T_STRING);
371
+ exif->ed->size = RSTRING(src)->len;
372
+ exif->ed->data = xmalloc(sizeof(char)*exif->ed->size);
373
+ MEMMOVE(exif->ed->data, RSTRING(src)->ptr, char, exif->ed->size);
374
+ return obj;
375
+ }
376
+
377
+
378
+ #define N_(val) val
379
+ #define GPS_SUPPORT
380
+
381
+ static struct {
382
+ ExifTag tag;
383
+ const char *name;
384
+ const char *title;
385
+ } ExifTagTable[] = {
386
+ {EXIF_TAG_INTEROPERABILITY_INDEX, "InteroperabilityIndex",
387
+ "InteroperabilityIndex"},
388
+ {EXIF_TAG_INTEROPERABILITY_VERSION, "InteroperabilityVersion",
389
+ "InteroperabilityVersion"},
390
+ {EXIF_TAG_IMAGE_WIDTH, "ImageWidth", N_("Image Width")},
391
+ {EXIF_TAG_IMAGE_LENGTH, "ImageLength", N_("Image Length")},
392
+ {EXIF_TAG_BITS_PER_SAMPLE, "BitsPerSample", N_("Bits per Sample")},
393
+ {EXIF_TAG_COMPRESSION, "Compression", N_("Compression")},
394
+ {EXIF_TAG_PHOTOMETRIC_INTERPRETATION, "PhotometricInterpretation",
395
+ N_("Photometric Interpretation")},
396
+ {EXIF_TAG_FILL_ORDER, "FillOrder", N_("Fill Order")},
397
+ {EXIF_TAG_DOCUMENT_NAME, "DocumentName", N_("Document Name")},
398
+ {EXIF_TAG_IMAGE_DESCRIPTION, "ImageDescription", N_("Image Description")},
399
+ {EXIF_TAG_MAKE, "Make", N_("Manufacturer")},
400
+ {EXIF_TAG_MODEL, "Model", N_("Model")},
401
+ {EXIF_TAG_STRIP_OFFSETS, "StripOffsets", N_("Strip Offsets")},
402
+ {EXIF_TAG_ORIENTATION, "Orientation", N_("Orientation")},
403
+ {EXIF_TAG_SAMPLES_PER_PIXEL, "SamplesPerPixel",
404
+ N_("Samples per Pixel")},
405
+ {EXIF_TAG_ROWS_PER_STRIP, "RowsPerStrip", N_("Rows per Strip")},
406
+ {EXIF_TAG_STRIP_BYTE_COUNTS, "StripByteCounts", N_("Strip Byte Count")},
407
+ {EXIF_TAG_X_RESOLUTION, "XResolution", N_("x-Resolution")},
408
+ {EXIF_TAG_Y_RESOLUTION, "YResolution", N_("y-Resolution")},
409
+ {EXIF_TAG_PLANAR_CONFIGURATION, "PlanarConfiguration",
410
+ N_("Planar Configuration")},
411
+ {EXIF_TAG_RESOLUTION_UNIT, "ResolutionUnit", N_("Resolution Unit")},
412
+ {EXIF_TAG_TRANSFER_FUNCTION, "TransferFunction",
413
+ N_("Transfer Function")},
414
+ {EXIF_TAG_SOFTWARE, "Software", N_("Software")},
415
+ {EXIF_TAG_DATE_TIME, "DateTime", N_("Date and Time")},
416
+ {EXIF_TAG_ARTIST, "Artist", N_("Artist")},
417
+ {EXIF_TAG_WHITE_POINT, "WhitePoint", N_("White Point")},
418
+ {EXIF_TAG_PRIMARY_CHROMATICITIES, "PrimaryChromaticities",
419
+ N_("Primary Chromaticities")},
420
+ {EXIF_TAG_TRANSFER_RANGE, "TransferRange", N_("Transfer Range")},
421
+ {EXIF_TAG_JPEG_PROC, "JPEGProc", "JPEGProc"},
422
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT, "JPEGInterchangeFormat",
423
+ N_("JPEG Interchange Format")},
424
+ {EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
425
+ "JPEGInterchangeFormatLength", N_("JPEG Interchange Format Length")},
426
+ {EXIF_TAG_YCBCR_COEFFICIENTS, "YCbCrCoefficients",
427
+ N_("YCbCr Coefficients")},
428
+ {EXIF_TAG_YCBCR_SUB_SAMPLING, "YCbCrSubSampling",
429
+ N_("YCbCr Sub-Sampling")},
430
+ {EXIF_TAG_YCBCR_POSITIONING, "YCbCrPositioning",
431
+ N_("YCbCr Positioning")},
432
+ {EXIF_TAG_REFERENCE_BLACK_WHITE, "ReferenceBlackWhite",
433
+ N_("Reference Black/White")},
434
+ {EXIF_TAG_RELATED_IMAGE_FILE_FORMAT, "RelatedImageFileFormat",
435
+ "RelatedImageFileFormat"},
436
+ {EXIF_TAG_RELATED_IMAGE_WIDTH, "RelatedImageWidth",
437
+ "RelatedImageWidth"},
438
+ {EXIF_TAG_RELATED_IMAGE_LENGTH, "RelatedImageLength",
439
+ "RelatedImageLength"},
440
+ {EXIF_TAG_CFA_REPEAT_PATTERN_DIM, "CFARepeatPatternDim",
441
+ "CFARepeatPatternDim"},
442
+ {EXIF_TAG_CFA_PATTERN, "CFAPattern",
443
+ N_("CFA Pattern")},
444
+ {EXIF_TAG_BATTERY_LEVEL, "BatteryLevel", N_("Battery Level")},
445
+ {EXIF_TAG_COPYRIGHT, "Copyright", N_("Copyright")},
446
+ {EXIF_TAG_EXPOSURE_TIME, "ExposureTime", N_("Exposure Time")},
447
+ {EXIF_TAG_FNUMBER, "FNumber", "FNumber"},
448
+ {EXIF_TAG_IPTC_NAA, "IPTC/NAA", "IPTC/NAA"},
449
+ {EXIF_TAG_EXIF_IFD_POINTER, "ExifIFDPointer", "ExifIFDPointer"},
450
+ {EXIF_TAG_INTER_COLOR_PROFILE, "InterColorProfile",
451
+ "InterColorProfile"},
452
+ {EXIF_TAG_EXPOSURE_PROGRAM, "ExposureProgram", "ExposureProgram"},
453
+ {EXIF_TAG_SPECTRAL_SENSITIVITY, "SpectralSensitivity",
454
+ N_("Spectral Sensitivity")},
455
+ {EXIF_TAG_GPS_INFO_IFD_POINTER, "GPSInfoIFDPointer",
456
+ "GPSInfoIFDPointer"},
457
+ #ifdef GPS_SUPPORT
458
+ {EXIF_TAG_GPS_VERSION_ID, "GPSVersionID", N_("GPS tag version")},
459
+ {EXIF_TAG_GPS_LATITUDE_REF, "GPSLatutideRef", N_("North or South latitude")},
460
+ {EXIF_TAG_GPS_LATITUDE, "GPSLatitude", N_("Latitude")},
461
+ {EXIF_TAG_GPS_LONGITUDE_REF, "GPSLongitudeRef", N_("East or West longitude")},
462
+ {EXIF_TAG_GPS_LONGITUDE, "GPSLongitude", N_("Longitude")},
463
+ {EXIF_TAG_GPS_ALTITUDE_REF, "GPSAltitudeRef", N_("Altitude reference")},
464
+ {EXIF_TAG_GPS_ALTITUDE , "GPSAltitude", N_("Altitude")},
465
+ {EXIF_TAG_GPS_TIME_STAMP, "GPSTimeStamp", N_("GPS time (atomic clock)")},
466
+ {EXIF_TAG_GPS_SATELLITES, "GPSSatellites", N_("GPS satellites used for measurement")},
467
+ {EXIF_TAG_GPS_STATUS, "GPSStatus", N_(" GPS receiver status")},
468
+ {EXIF_TAG_GPS_MEASURE_MODE, "GPSMessureMode", N_("GPS measurement mode")},
469
+ {EXIF_TAG_GPS_DOP, "GPSDOP", N_("Measurement precision")},
470
+ {EXIF_TAG_GPS_SPEED_REF, "GPSSpeedRef", N_("Speed unit")},
471
+ {EXIF_TAG_GPS_SPEED, "GPSSpeed", N_("Speed of GPS receiver")},
472
+ {EXIF_TAG_GPS_TRACK_REF, "GPSTrackRef", N_("Reference for direction of movement")},
473
+ {EXIF_TAG_GPS_TRACK, "GPSTrack", N_("Direction of movement")},
474
+ {EXIF_TAG_GPS_IMG_DIRECTION_REF, "GPSImgDirectionRef", N_("Reference for direction of image")},
475
+ {EXIF_TAG_GPS_IMG_DIRECTION, "GPSImgDirection", N_("Direction of image")},
476
+ {EXIF_TAG_GPS_MAP_DATUM, "GPSMapDatum", N_("Geodetic survey data used")},
477
+ {EXIF_TAG_GPS_DEST_LATITUDE_REF, "GPSDestLatitudeRef", N_("Reference for latitude of destination")},
478
+ {EXIF_TAG_GPS_DEST_LATITUDE, "GPSDestLatitude", N_("Latitude of destination")},
479
+ {EXIF_TAG_GPS_DEST_LONGITUDE_REF, "GPSDestLongitudeRef", N_("Reference for longitude of destination")},
480
+ {EXIF_TAG_GPS_DEST_LONGITUDE, "GPSDestLongitude", N_("Longitude of destination")},
481
+ {EXIF_TAG_GPS_DEST_BEARING_REF, "GPSDestBearingRef", N_("Reference for bearing of destination")},
482
+ {EXIF_TAG_GPS_DEST_BEARING, "GPSDestBearing", N_("Bearing of destination")},
483
+ {EXIF_TAG_GPS_DEST_DISTANCE_REF, "GPSDestDistanceRef", N_("Reference for distance to destination")},
484
+ {EXIF_TAG_GPS_DEST_DISTANCE, "GPSDestDistance", N_("Distance to destination")},
485
+ {EXIF_TAG_GPS_PROCESSING_METHOD, "GPSProcessingMethod", N_("Name of GPS processing method")},
486
+ {EXIF_TAG_GPS_AREA_INFORMATION, "GPSAreaInformation", N_("Name of GPS area")},
487
+ {EXIF_TAG_GPS_DATE_STAMP, "GPSDateStamp", N_("GPS date")},
488
+ {EXIF_TAG_GPS_DIFFERENTIAL, "GPSDifferential", N_("GPS differential correction")},
489
+ #endif
490
+
491
+ {EXIF_TAG_ISO_SPEED_RATINGS, "ISOSpeedRatings",
492
+ N_("ISO Speed Ratings")},
493
+ {EXIF_TAG_OECF, "OECF", "OECF"},
494
+ {EXIF_TAG_EXIF_VERSION, "ExifVersion", N_("Exif Version")},
495
+ {EXIF_TAG_DATE_TIME_ORIGINAL, "DateTimeOriginal",
496
+ N_("Date and Time (original)")},
497
+ {EXIF_TAG_DATE_TIME_DIGITIZED, "DateTimeDigitized",
498
+ N_("Date and Time (digitized)")},
499
+ {EXIF_TAG_COMPONENTS_CONFIGURATION, "ComponentsConfiguration",
500
+ "ComponentsConfiguration"},
501
+ {EXIF_TAG_COMPRESSED_BITS_PER_PIXEL, "CompressedBitsPerPixel",
502
+ N_("Compressed Bits per Pixel")},
503
+ {EXIF_TAG_SHUTTER_SPEED_VALUE, "ShutterSpeedValue",
504
+ N_("Shutter speed")},
505
+ {EXIF_TAG_APERTURE_VALUE, "ApertureValue", N_("Aperture")},
506
+ {EXIF_TAG_BRIGHTNESS_VALUE, "BrightnessValue", N_("Brightness")},
507
+ {EXIF_TAG_EXPOSURE_BIAS_VALUE, "ExposureBiasValue",
508
+ N_("Exposure Bias")},
509
+ {EXIF_TAG_MAX_APERTURE_VALUE, "MaxApertureValue", "MaxApertureValue"},
510
+ {EXIF_TAG_SUBJECT_DISTANCE, "SubjectDistance",
511
+ N_("Subject Distance")},
512
+ {EXIF_TAG_METERING_MODE, "MeteringMode", N_("Metering Mode")},
513
+ {EXIF_TAG_LIGHT_SOURCE, "LightSource", N_("Light Source")},
514
+ {EXIF_TAG_FLASH, "Flash", N_("Flash")},
515
+ {EXIF_TAG_FOCAL_LENGTH, "FocalLength", N_("Focal Length")},
516
+ {EXIF_TAG_MAKER_NOTE, "MakerNote", N_("Maker Note")},
517
+ {EXIF_TAG_USER_COMMENT, "UserComment", N_("User Comment")},
518
+ {EXIF_TAG_SUBSEC_TIME, "SubsecTime", "SubsecTime"},
519
+ {EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "SubSecTimeOriginal",
520
+ "SubSecTimeOriginal"},
521
+ {EXIF_TAG_SUB_SEC_TIME_DIGITIZED, "SubSecTimeDigitized",
522
+ "SubSecTimeDigitized"},
523
+ {EXIF_TAG_FLASH_PIX_VERSION, "FlashPixVersion", "FlashPixVersion"},
524
+ {EXIF_TAG_COLOR_SPACE, "ColorSpace", N_("Color Space")},
525
+ {EXIF_TAG_PIXEL_X_DIMENSION, "PixelXDimension", "PixelXDimension"},
526
+ {EXIF_TAG_PIXEL_Y_DIMENSION, "PixelYDimension", "PixelYDimension"},
527
+ {EXIF_TAG_RELATED_SOUND_FILE, "RelatedSoundFile",
528
+ "RelatedSoundFile"},
529
+ {EXIF_TAG_INTEROPERABILITY_IFD_POINTER, "InteroperabilityIFDPointer",
530
+ "InteroperabilityIFDPointer"},
531
+ {EXIF_TAG_FLASH_ENERGY, "FlashEnergy", N_("Flash Energy")},
532
+ {EXIF_TAG_SPATIAL_FREQUENCY_RESPONSE, "SpatialFrequencyResponse",
533
+ N_("Spatial Frequency Response")},
534
+ {EXIF_TAG_FOCAL_PLANE_X_RESOLUTION, "FocalPlaneXResolution",
535
+ N_("Focal Plane x-Resolution")},
536
+ {EXIF_TAG_FOCAL_PLANE_Y_RESOLUTION, "FocalPlaneYResolution",
537
+ N_("Focal Plane y-Resolution")},
538
+ {EXIF_TAG_FOCAL_PLANE_RESOLUTION_UNIT, "FocalPlaneResolutionUnit",
539
+ N_("Focal Plane Resolution Unit")},
540
+ {EXIF_TAG_SUBJECT_LOCATION, "SubjectLocation",
541
+ N_("Subject Location")},
542
+ {EXIF_TAG_EXPOSURE_INDEX, "ExposureIndex", N_("Exposure index")},
543
+ {EXIF_TAG_SENSING_METHOD, "SensingMethod", N_("Sensing Method")},
544
+ {EXIF_TAG_FILE_SOURCE, "FileSource", N_("File Source")},
545
+ {EXIF_TAG_SCENE_TYPE, "SceneType", N_("Scene Type")},
546
+ {EXIF_TAG_NEW_CFA_PATTERN, "CFAPattern",
547
+ N_("CFA Pattern")},
548
+ {EXIF_TAG_SUBJECT_AREA, "SubjectArea", N_("Subject Area")},
549
+ {EXIF_TAG_CUSTOM_RENDERED, "CustomRendered", N_("Custom Rendered")},
550
+ {EXIF_TAG_EXPOSURE_MODE, "ExposureMode", N_("Exposure Mode")},
551
+ {EXIF_TAG_WHITE_BALANCE, "WhiteBalance", N_("White Balance")},
552
+ {EXIF_TAG_DIGITAL_ZOOM_RATIO, "DigitalZoomRatio",
553
+ N_("Digital Zoom Ratio")},
554
+ {EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM, "FocalLengthIn35mmFilm",
555
+ N_("Focal Length In 35mm Film")},
556
+ {EXIF_TAG_SCENE_CAPTURE_TYPE, "SceneCaptureType",
557
+ N_("Scene Capture Type")},
558
+ {EXIF_TAG_GAIN_CONTROL, "GainControl", N_("Gain Control")},
559
+ {EXIF_TAG_CONTRAST, "Contrast", N_("Contrast")},
560
+ {EXIF_TAG_SATURATION, "Saturation", N_("Saturation")},
561
+ {EXIF_TAG_SHARPNESS, "Sharpness", N_("Sharpness")},
562
+ {EXIF_TAG_DEVICE_SETTING_DESCRIPTION, "DeviceSettingDescription",
563
+ N_("Device Setting Description")},
564
+ {EXIF_TAG_SUBJECT_DISTANCE_RANGE, "SubjectDistanceRange",
565
+ N_("Subject Distance Range")},
566
+ {EXIF_TAG_IMAGE_UNIQUE_ID, "ImageUniqueID", N_("Image Unique ID")},
567
+ {-1, NULL, NULL}
568
+ };
569
+
570
+
571
+ static ExifTag
572
+ exif_tag_from_string (const char *str)
573
+ {
574
+ int i;
575
+
576
+ if (!str)
577
+ return 0;
578
+ /* Is the string a tag's name or title? */
579
+ for (i = 0; ExifTagTable[i].name != NULL; i++) {
580
+ if (!strcmp (str, ExifTagTable[i].name))
581
+ return (ExifTagTable[i].tag);
582
+ if (!strcmp (str, ExifTagTable[i].title))
583
+ return (ExifTagTable[i].tag);
584
+ }
585
+ return 0;
586
+ }
587
+
588
+ static ExifTag
589
+ exif_tag_from_tagid(ExifTag tag)
590
+ {
591
+ int i;
592
+ for (i = 0; ExifTagTable[i].tag != -1; i++) {
593
+ if (ExifTagTable[i].tag == tag)
594
+ return tag;
595
+ }
596
+ return 0;
597
+ }
598
+
599
+
600
+ static ExifIfd
601
+ exif_ifd_from_string (const char *string)
602
+ {
603
+ unsigned int i;
604
+
605
+ if (!string)
606
+ return (-1);
607
+
608
+ for (i = 0; i < EXIF_IFD_COUNT; i++) {
609
+ if (!strcmp (string, exif_ifd_get_name (i)))
610
+ return (i);
611
+ }
612
+
613
+ return (-1);
614
+ }
615
+
616
+ void
617
+ Init_exif(void)
618
+ {
619
+ cExif = rb_define_class("Exif", rb_cObject);
620
+ eExifError = rb_define_class_under(cExif, "Error", rb_eRuntimeError);
621
+ eExifInvalidFormat = rb_define_class_under(cExif, "NotExifFormat", eExifError);
622
+ eExifInvalidIFD = rb_define_class_under(eExifError, "InvalidIFD", eExifError);
623
+ eExifTagNotFound = rb_define_class_under(eExifError, "TagNotFound", eExifError);
624
+ eExifThumbnailNotFound = rb_define_class_under(eExifError, "ThumbnailNotFound", eExifError);
625
+
626
+ rb_define_singleton_method(cExif, "new", rb_exif_s_new, -1);
627
+ rb_define_private_method(cExif, "initialize", rb_exif_initialize, -1);
628
+ rb_define_method(cExif, "data=", rb_exif_set_data, 1);
629
+ rb_define_alias(cExif, "<<", "data=");
630
+ rb_define_method(cExif, "each_entry", rb_exif_each, -1);
631
+ rb_define_method(cExif, "byte_order", rb_exif_get_byte_order, 0);
632
+ rb_define_method(cExif, "byte_order=", rb_exif_set_byte_order, 1);
633
+ rb_define_method(cExif, "ifd=", rb_exif_set_ifd, 1);
634
+ rb_define_method(cExif, "ifd", rb_exif_get_ifd, 0);
635
+ rb_define_method(cExif, "[]", rb_exif_get_tag, 1);
636
+ rb_define_method(cExif, "[]=", rb_exif_set_tag, 2);
637
+ rb_define_singleton_method(cExif, "[]", rb_exif_s_get_tag_description, 1);
638
+ rb_define_method(cExif, "list_tags", rb_exif_list_tags_at_ifd, 1);
639
+ rb_define_method(cExif, "extract_thumbnail", rb_exif_extract_thumbnail, 1);
640
+ rb_define_alias(cExif, "thumbnail", "extract_thumbnail");
641
+ rb_define_method(cExif, "thumbnail=", rb_exif_set_thumbnail, 1);
642
+
643
+ mExifByteOrder = rb_define_module_under(cExif, "ByteOrder");
644
+ rb_define_const(mExifByteOrder, "MOTOROLA", INT2FIX(EXIF_BYTE_ORDER_MOTOROLA));
645
+ rb_define_const(mExifByteOrder, "INTEL", INT2FIX(EXIF_BYTE_ORDER_INTEL));
646
+ mExifIfd = rb_define_module_under(cExif, "IFD");
647
+ rb_define_const(mExifIfd, "Zero", INT2FIX(EXIF_IFD_0));
648
+ rb_define_const(mExifIfd, "One", INT2FIX(EXIF_IFD_1));
649
+ rb_define_const(mExifIfd, "EXIF", INT2FIX(EXIF_IFD_EXIF));
650
+ rb_define_const(mExifIfd, "GPS", INT2FIX(EXIF_IFD_GPS));
651
+ rb_define_const(mExifIfd, "Interoperability", INT2FIX(EXIF_IFD_INTEROPERABILITY));
652
+ rb_define_const(mExifIfd, "Any", INT2FIX(IFD_RB_DEFAULT));
653
+ }