exifparser 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,84 @@
1
+ #
2
+ #
3
+ # exifparser/makernote/prove.rb -
4
+ #
5
+ # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
6
+ #
7
+ # $Revision: 1.1.1.1 $
8
+ # $Date: 2002/12/16 07:59:00 $
9
+ #
10
+ require 'exifparser/makernote/fujifilm'
11
+ require 'exifparser/makernote/olympus'
12
+ require 'exifparser/makernote/canon'
13
+ require 'exifparser/makernote/nikon'
14
+ require 'exifparser/makernote/nikon2'
15
+ require 'exifparser/makernote/minolta'
16
+ require 'exifparser/makernote/sigma'
17
+
18
+ module Exif
19
+
20
+ module MakerNote
21
+
22
+ class NotSupportedError < RuntimeError; end
23
+
24
+ module_function
25
+
26
+ def prove(data, tag_make=nil, tag_model=nil)
27
+
28
+ make = tag_make == nil ? '' : tag_make.to_s.upcase
29
+ model = tag_model == nil ? '' : tag_model.to_s.upcase
30
+
31
+ #
32
+ # Identifier for OLYMPUS
33
+ #
34
+ if data[0..5] == "OLYMP\000"
35
+ return Olympus
36
+ #
37
+ # Identifier for FUJIFILM
38
+ #
39
+ elsif data[0..7] == "FUJIFILM"
40
+ return Fujifilm
41
+
42
+ #
43
+ # Identifier for Nikon
44
+ #
45
+
46
+ elsif make[0..4] == 'NIKON'
47
+ if data[0..5] == "Nikon\000"
48
+ if data[6] == 0x01 && data[7] == 0x00
49
+ return Nikon
50
+ end
51
+ end
52
+ return Nikon2
53
+
54
+ #
55
+ # Canon
56
+ #
57
+ elsif make[0..4] == 'CANON'
58
+ return Canon
59
+
60
+ #
61
+ # Minolta
62
+ #
63
+ elsif make[0..6] == 'MINOLTA'
64
+ return Minolta
65
+
66
+ #
67
+ # Sigma
68
+ #
69
+ elsif make[0..4] == 'SIGMA'
70
+ return Sigma
71
+
72
+ end
73
+
74
+ #
75
+ # If none above is applied, raises exception,
76
+ # which will be caught by caller's rescue statement.
77
+ #
78
+ raise NotSupportedError
79
+ end
80
+ module_function :prove
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,237 @@
1
+ #
2
+ # exifparser/makernote/sigma.rb
3
+ #
4
+ # $Revision: 1.1 $
5
+ # $Date: 2010/10/23 16:41:28 $
6
+ #
7
+ require 'exifparser/tag'
8
+ require 'exifparser/utils'
9
+
10
+ module Exif
11
+
12
+ module Tag
13
+
14
+ module MakerNote
15
+ #
16
+ # 0x0002 - SigmaSerialNo
17
+ #
18
+ # class SigmaSerialNo < Base
19
+ # end
20
+
21
+ #
22
+ # 0x0003 - DriveMode
23
+ #
24
+ class DriveMode < Base
25
+ end
26
+
27
+ #
28
+ # 0x0004 - ImageSize
29
+ #
30
+ class ImageSize < Base
31
+ end
32
+
33
+ #
34
+ # 0x0005 - AF_Mode
35
+ #
36
+ class AF_Mode < Base
37
+ end
38
+
39
+ #
40
+ # 0x0006 - AF_Setting
41
+ #
42
+ class AF_Setting < Base
43
+ end
44
+
45
+ #
46
+ # 0x0007 - White_Balance
47
+ #
48
+ class White_Balance < Base
49
+ end
50
+
51
+ #
52
+ # 0x0008 - ExposureMode
53
+ #
54
+ class ExposureMode < Base
55
+ end
56
+
57
+ #
58
+ # 0x0009 - MeteringMode
59
+ #
60
+ class MeteringMode < Base
61
+ end
62
+
63
+ #
64
+ # 0x000a - FocalLength
65
+ #
66
+ class FocalLength < Base
67
+ end
68
+
69
+ #
70
+ # 0x000b - ColorSpace
71
+ #
72
+ class ColorSpace < Base
73
+ end
74
+
75
+ #
76
+ # 0x000c - ExposureBias
77
+ #
78
+ class ExposureBias < Base
79
+ end
80
+
81
+ #
82
+ # 0x000d - Contrast
83
+ #
84
+ class Contrast < Base
85
+ end
86
+
87
+ #
88
+ # 0x000e - Shadow
89
+ #
90
+ class Shadow < Base
91
+ end
92
+
93
+ #
94
+ # 0x000f - HighLight
95
+ #
96
+ class HighLight < Base
97
+ end
98
+
99
+ #
100
+ # 0x0010 - Saturation
101
+ #
102
+ class Saturation
103
+ end
104
+
105
+ #
106
+ # 0x0011 - SharpnessBias
107
+ #
108
+ class SharpnessBias < Base
109
+ end
110
+
111
+ #
112
+ # 0x0012 - X3FillLight
113
+ #
114
+ class X3FillLight < Base
115
+ end
116
+
117
+ #
118
+ # 0x0014 - ColorControl
119
+ #
120
+ class ColorControl < Base
121
+ end
122
+
123
+ #
124
+ # 0x0015 - SettingMode
125
+ #
126
+ class SettingMode < Base
127
+ end
128
+
129
+ #
130
+ # 0x0017 - Firmware
131
+ #
132
+ class Firmware < Base
133
+ end
134
+
135
+ #
136
+ # 0x0018 - SigmaSoftware
137
+ #
138
+ class SigmaSoftware < Base
139
+ end
140
+
141
+ #
142
+ # 0x0019 - AutoBracket
143
+ #
144
+ class AutoBracket < Base
145
+ end
146
+
147
+ end
148
+
149
+ SigmaIFDTable = {
150
+ # 0x0002 => MakerNote::SigmaSerialNo,
151
+ 0x0003 => MakerNote::DriveMode,
152
+ 0x0004 => MakerNote::ImageSize,
153
+ 0x0005 => MakerNote::AF_Mode,
154
+ 0x0006 => MakerNote::AF_Setting,
155
+ 0x0007 => MakerNote::White_Balance,
156
+ 0x0008 => MakerNote::ExposureMode,
157
+ 0x0009 => MakerNote::MeteringMode,
158
+ 0x000a => MakerNote::FocalLength,
159
+ 0x000b => MakerNote::ColorSpace,
160
+ 0x000c => MakerNote::ExposureBias,
161
+ 0x000d => MakerNote::Contrast,
162
+ 0x000e => MakerNote::Shadow,
163
+ 0x000f => MakerNote::HighLight,
164
+ 0x0010 => MakerNote::Saturation,
165
+ 0x0011 => MakerNote::SharpnessBias,
166
+ 0x0012 => MakerNote::X3FillLight,
167
+ 0x0014 => MakerNote::ColorControl,
168
+ 0x0015 => MakerNote::SettingMode,
169
+ 0x0017 => MakerNote::Firmware,
170
+ 0x0018 => MakerNote::SigmaSoftware,
171
+ 0x0019 => MakerNote::AutoBracket
172
+ }
173
+
174
+ end
175
+
176
+ class Sigma
177
+
178
+ def initialize(fin, tiff_origin, dataPos, byteOrder_module)
179
+ @fin = fin
180
+ @tiffHeader0 = tiff_origin
181
+ @dataPos = dataPos
182
+ @byteOrder_module = byteOrder_module
183
+ self.extend @byteOrder_module
184
+ end
185
+
186
+ def scan_IFD
187
+ #
188
+ # Sigma MakerNote starts from 10 byte from the origin
189
+ #
190
+ @fin.pos = @dataPos + 10
191
+
192
+ #
193
+ # get the number of tags
194
+ #
195
+ numDirs = decode_ushort(fin_read_n(2))
196
+
197
+ #
198
+ # now scan them
199
+ #
200
+ 1.upto(numDirs) {
201
+ curpos_tag = @fin.pos
202
+ tag = parseTagID(fin_read_n(2))
203
+ tagclass = Tag.find(tag.hex, Tag::SigmaIFDTable)
204
+ unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))]
205
+ count = decode_ulong(fin_read_n(4))
206
+ tagdata = fin_read_n(4)
207
+
208
+ obj = tagclass.new(tag, "MakerNote", count)
209
+ obj.extend formatter, @byteOrder_module
210
+ obj.pos = curpos_tag
211
+ if unit * count > 4
212
+ curpos = @fin.pos
213
+ begin
214
+ @fin.pos = @tiffHeader0 + decode_ulong(tagdata)
215
+ obj.dataPos = @fin.pos
216
+ obj.data = fin_read_n(unit*count)
217
+ ensure
218
+ @fin.pos = curpos
219
+ end
220
+ else
221
+ obj.dataPos = @fin.pos - 4
222
+ obj.data = tagdata
223
+ end
224
+ obj.processData
225
+ yield obj
226
+ }
227
+ end
228
+
229
+ private
230
+
231
+ def fin_read_n(n)
232
+ @fin.read(n)
233
+ end
234
+
235
+ end
236
+
237
+ end
@@ -0,0 +1 @@
1
+ # pre-setup.rb - working with install.rb
@@ -0,0 +1,278 @@
1
+ #
2
+ # exifparser/scan.rb
3
+ #
4
+ # Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
5
+ #
6
+ # $Revision: 1.2 $
7
+ # $Date: 2003/04/20 19:58:31 $
8
+ #
9
+ #
10
+ require 'exifparser/utils'
11
+ require 'exifparser/tag'
12
+ require 'exifparser/makernote/prove'
13
+
14
+ module Exif
15
+
16
+ class Scanner
17
+
18
+ def initialize(fin)
19
+ @fin = fin.binmode
20
+ @result = {}
21
+ @tiffHeader0 = nil # origin at which TIFF header begins
22
+ @byteOrder_module = nil
23
+ end
24
+ attr_reader :result
25
+
26
+ def finish
27
+ @fin.close
28
+ end
29
+
30
+ def scan
31
+ tic = Time.now if $DEBUG
32
+ #
33
+ # check soi (start of image)
34
+ #
35
+ @fin.pos = 0
36
+ unless get_soi == 0xFFD8
37
+ raise RuntimeError, 'not JPEG format'
38
+ end
39
+
40
+ #
41
+ # seek app1 (EXIF signature)
42
+ #
43
+ begin
44
+ marker = get_marker
45
+ break if (marker == 0xFFE1)
46
+ size = get_marker_datasize
47
+ @fin.seek(size - 2, IO::SEEK_CUR)
48
+ end while (!@fin.eof?)
49
+
50
+ if marker != 0xFFE1
51
+ raise RuntimeError, 'not EXIF format'
52
+ end
53
+
54
+ #
55
+ # get app1 Data size
56
+ #
57
+ @result[:app1DataSize] = get_marker_datasize()
58
+ curpos = @fin.pos
59
+ @result[:app1Data] = fin_read_n(@result[:app1DataSize])
60
+ @fin.pos = curpos
61
+
62
+ #
63
+ # EXIF header must be exactly "Exif\000\000", but some model
64
+ # does not provide correct one. So we relax the condition.
65
+ #
66
+ if (h = exif_identifier()) !~ /\AExif\000/
67
+ raise RuntimeError, "Invalid EXIF header: #{h}"
68
+ end
69
+
70
+ #
71
+ # examine TIFF header
72
+ #
73
+ @tiffHeader0, tiff_header = get_tiff_header()
74
+
75
+ #
76
+ # get byte order
77
+ #
78
+ case tiff_header[0,2]
79
+ when "MM"
80
+ @byteOrder_module = Utils::Decode::Motorola
81
+ when "II"
82
+ @byteOrder_module = Utils::Decode::Intel
83
+ else
84
+ raise RuntimeError, "Unknown byte order"
85
+ end
86
+ self.extend @byteOrder_module
87
+ @result[:offset_IFD0] = decode_ulong(tiff_header[4..-1])
88
+
89
+ #
90
+ # IFD0
91
+ #
92
+ @fin.pos = @tiffHeader0 + @result[:offset_IFD0]
93
+ @result[:IFD0] = []
94
+ scan_IFD(Tag::IFD0Table, Tag::IFD0Table.name) do |tag|
95
+ @result[:IFD0].push tag
96
+ end
97
+
98
+ #
99
+ # IFD1
100
+ #
101
+ @result[:IFD1] = []
102
+ next_ifd = decode_ulong(fin_read_n(4))
103
+ if next_ifd > 0
104
+ @fin.pos = @tiffHeader0 + next_ifd
105
+ scan_IFD(Tag::IFD1Table, Tag::IFD1Table.name) do |tag|
106
+ @result[:IFD1].push tag
107
+ end
108
+ end
109
+
110
+ #
111
+ # GPS IFD
112
+ #
113
+ @result[:GPS] = []
114
+ found = @result[:IFD0].find{ |e|
115
+ e.class == Tag::GPSIFDPointer
116
+ }
117
+ if found
118
+ @result[:offset_GPS] = found.processData
119
+ @fin.pos = @tiffHeader0 + @result[:offset_GPS]
120
+ scan_IFD(Tag::GPSIFDTable, Tag::GPSIFDTable.name) do |tag|
121
+ @result[:GPS].push tag
122
+ end
123
+ end
124
+
125
+ #
126
+ # Exif IFD
127
+ #
128
+ @result[:Exif] = []
129
+ found = @result[:IFD0].find{ |e|
130
+ e.class == Tag::ExifIFDPointer
131
+ }
132
+ if found
133
+ @result[:offset_Exif] = found.processData
134
+ @fin.pos = @tiffHeader0 + @result[:offset_Exif]
135
+ scan_IFD(Tag::ExifIFDTable, Tag::ExifIFDTable.name) do |tag|
136
+ @result[:Exif].push tag
137
+ end
138
+ end
139
+
140
+ #
141
+ # Interoperability subIFD
142
+ #
143
+ @result[:Interoperability] = []
144
+ found = @result[:Exif].find {|e|
145
+ e.class == Tag::InteroperabilityIFDPointer
146
+ }
147
+ if found
148
+ @result[:offset_InteroperabilityIFD] = found.processData
149
+ @fin.pos = @tiffHeader0 + @result[:offset_InteroperabilityIFD]
150
+ scan_IFD(Tag::InteroperabilityIFDTable, Tag::InteroperabilityIFDTable.name) do |tag|
151
+ @result[:Interoperability].push tag
152
+ end
153
+ end
154
+
155
+ #
156
+ # MakerNote subIFD
157
+ #
158
+ @result[:MakerNote]=[]
159
+ found = @result[:Exif].find {|e| e.class == Tag::Exif::MakerNote }
160
+ if (found)
161
+ begin
162
+ # Because some vendors do not put any identifier in the header,
163
+ # we try to find which model is by seeing Tag::TIFF::Make, Tag::TIFF::Model.
164
+ make = @result[:IFD0].find {|e| e.class == Tag::TIFF::Make}
165
+ model = @result[:IFD0].find {|e| e.class == Tag::TIFF::Model}
166
+ # prove the maker
167
+ makernote_class = Exif::MakerNote.prove(found.data, make, model)
168
+ # set file pointer to the position where the tag was found.
169
+ @fin.pos = found.pos
170
+ makernote = makernote_class.new(@fin, @tiffHeader0, found.dataPos, @byteOrder_module)
171
+ makernote.scan_IFD do |tag|
172
+ @result[:MakerNote].push tag
173
+ end
174
+ rescue MakerNote::NotSupportedError
175
+ rescue Exception # what to do?
176
+ if $DEBUG
177
+ raise $!
178
+ end
179
+ end
180
+ end
181
+
182
+ #
183
+ # get thumbnail
184
+ #
185
+ if !@result[:IFD1].empty?
186
+ format = @result[:IFD1].find do |e|
187
+ e.class == Tag::TIFF::Compression
188
+ end.value
189
+ unless format == 6
190
+ raise NotImplementedError, "Sorry, thumbnail of other than JPEG format is not supported."
191
+ end
192
+ thumbStart = @result[:IFD1].find do |e|
193
+ e.class == Exif::Tag::TIFF::JpegInterchangeFormat
194
+ end.value
195
+ thumbLen = @result[:IFD1].find do |e|
196
+ e.class == Exif::Tag::TIFF::JpegInterchangeFormatLength
197
+ end.value
198
+ @fin.pos = @tiffHeader0 + thumbStart
199
+ # check JPEG soi maker
200
+ if get_soi != 0xFFD8
201
+ raise RuntimeError, 'not JPEG format'
202
+ end
203
+ @fin.pos = @fin.pos - 2
204
+ # now read thumbnail image
205
+ @result[:Thumbnail] = @fin.read(thumbLen)
206
+ end
207
+
208
+ # turn on if $DEBUG
209
+ toc = Time.now if $DEBUG
210
+ puts(sprintf("scan time: %1.4f sec.", toc-tic)) if $DEBUG
211
+ end
212
+
213
+ private
214
+
215
+ def fin_read_n(n)
216
+ @fin.read(n)
217
+ end
218
+
219
+ def scan_IFD(tagTable, ifdname)
220
+ num_dirs = decode_ushort(fin_read_n(2))
221
+ 1.upto(num_dirs) {
222
+ curpos_tag = @fin.pos
223
+ tag = parseTagID(fin_read_n(2))
224
+ tagclass = Tag.find(tag.hex, tagTable)
225
+ unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))]
226
+ count = decode_ulong(fin_read_n(4))
227
+ tagdata = fin_read_n(4)
228
+ next if formatter == nil
229
+ obj = tagclass.new(tag, ifdname, count)
230
+ obj.extend formatter, @byteOrder_module
231
+ obj.pos = curpos_tag
232
+ if unit * count > 4
233
+ curpos = @fin.pos
234
+ begin
235
+ @fin.pos = @tiffHeader0 + decode_ulong(tagdata)
236
+ obj.dataPos = @fin.pos
237
+ obj.data = fin_read_n(unit*count)
238
+ ensure
239
+ @fin.pos = curpos
240
+ end
241
+ else
242
+ obj.dataPos = @fin.pos - 4
243
+ obj.data = tagdata
244
+ end
245
+ obj.processData
246
+ yield obj
247
+ }
248
+ end
249
+
250
+ def get_soi
251
+ (@fin.read(1).unpack("C*")[0]) << 8 | (@fin.read(1).unpack("C*")[0])
252
+ end
253
+
254
+ def get_marker
255
+ (@fin.read(1).unpack("C*")[0]) << 8 | (@fin.read(1).unpack("C*")[0])
256
+ end
257
+
258
+ def get_marker_datasize
259
+ (@fin.read(1).unpack("C*")[0]) << 8 | (@fin.read(1).unpack("C*")[0])
260
+ end
261
+
262
+ def exif_identifier
263
+ @fin.read(6)
264
+ end
265
+
266
+ def get_tiff_header
267
+ pos = @fin.pos
268
+ [pos, fin_read_n(8)]
269
+ end
270
+
271
+ def eoi
272
+ @fin.seek(-2, IO::SEEK_END)
273
+ @fin.read(2)
274
+ end
275
+
276
+ end
277
+
278
+ end