extexif 1.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.
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
+ }