exifparser 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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +33 -0
- data/Rakefile +1 -0
- data/exifparser.gemspec +23 -0
- data/lib/exifparser.rb +265 -0
- data/lib/exifparser/makernote/canon.rb +502 -0
- data/lib/exifparser/makernote/fujifilm.rb +415 -0
- data/lib/exifparser/makernote/minolta.rb +84 -0
- data/lib/exifparser/makernote/mk_nikonflensname.rb +39 -0
- data/lib/exifparser/makernote/nikon.rb +267 -0
- data/lib/exifparser/makernote/nikon2.rb +581 -0
- data/lib/exifparser/makernote/nikonflensname.rb +438 -0
- data/lib/exifparser/makernote/olympus.rb +225 -0
- data/lib/exifparser/makernote/prove.rb +84 -0
- data/lib/exifparser/makernote/sigma.rb +237 -0
- data/lib/exifparser/pre-setup.rb +1 -0
- data/lib/exifparser/scan.rb +278 -0
- data/lib/exifparser/tag.rb +2298 -0
- data/lib/exifparser/thumbnail.rb +76 -0
- data/lib/exifparser/utils.rb +88 -0
- data/lib/exifparser/version.rb +3 -0
- data/sample/exifview.rb +279 -0
- metadata +96 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# mk_nikonflensname.rb
|
4
|
+
#
|
5
|
+
# .. makes the Ruby source code of hash table: Nikon EXIF LensParameters => Lens model name.
|
6
|
+
# This is for Exif::Makernote::Tag::LensParameters class
|
7
|
+
# in exifparser/nmakernote/nikon2.rb
|
8
|
+
#
|
9
|
+
# usage : ruby mk_nikonlens_hash.rb nikonmn.cpp >nikonflensname.rb
|
10
|
+
# ("nikonmn.cpp" is a exiv2(http://www.exiv2.org/)'s nikon makernote module source code. )
|
11
|
+
#
|
12
|
+
# Copyright (c) 2009 N.KASHIJUKU <n-kashi[at]whi.m-net.ne.jp>
|
13
|
+
# You can redistribute it and/or modify it under GPL2.
|
14
|
+
#
|
15
|
+
print <<TEOS
|
16
|
+
module Exif
|
17
|
+
module Tag
|
18
|
+
module NikonFmount
|
19
|
+
LensName = {
|
20
|
+
TEOS
|
21
|
+
|
22
|
+
open(ARGV[0], "r") do |file|
|
23
|
+
file.each_line do |s|
|
24
|
+
if (/^\{(0x..),(0x..),(0x..),(0x..),(0x..),(0x..),(0x..),0x..,0x..,0x..,0x.., \"(.*)\", ".*", "(.*)"\}/ =~ s) != nil
|
25
|
+
str = %Q[ \[#{$1}, #{$2}, #{$3}, #{$4}, #{$5}, #{$6}, #{$7}\] => "#{$8} #{$9}"]
|
26
|
+
str.sub!("f/", "F") if str.include?("Nikon")
|
27
|
+
print str + ",\n"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
print <<EEOS
|
33
|
+
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] => ""
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
EEOS
|
39
|
+
|
@@ -0,0 +1,267 @@
|
|
1
|
+
#
|
2
|
+
# exifparser/makernote/nikon.rb -
|
3
|
+
#
|
4
|
+
# Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
|
5
|
+
#
|
6
|
+
# $Revision: 1.1.1.1 $
|
7
|
+
# $Date: 2002/12/16 07:59:00 $
|
8
|
+
#
|
9
|
+
require 'exifparser/tag'
|
10
|
+
require 'exifparser/utils'
|
11
|
+
|
12
|
+
module Exif
|
13
|
+
|
14
|
+
module Tag
|
15
|
+
|
16
|
+
module MakerNote
|
17
|
+
|
18
|
+
#
|
19
|
+
# 0x0003 - Quality
|
20
|
+
#
|
21
|
+
class Quality < Base
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
n = @formatted.to_i - 1
|
25
|
+
(s, q) = n.divmod(3)
|
26
|
+
|
27
|
+
f =
|
28
|
+
case s
|
29
|
+
when 0
|
30
|
+
'VGA'
|
31
|
+
when 1
|
32
|
+
'SVGA'
|
33
|
+
when 2
|
34
|
+
'SXGA'
|
35
|
+
when 3
|
36
|
+
'UXGA'
|
37
|
+
else
|
38
|
+
'Unknown size'
|
39
|
+
end
|
40
|
+
|
41
|
+
f << ' ' <<
|
42
|
+
case q
|
43
|
+
when 0
|
44
|
+
'Basic'
|
45
|
+
when 1
|
46
|
+
'Normal'
|
47
|
+
when 2
|
48
|
+
'Fine'
|
49
|
+
else
|
50
|
+
'Unknown quality'
|
51
|
+
end
|
52
|
+
f
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# 0x0004 - ColorMode
|
59
|
+
#
|
60
|
+
class ColorMode < Base
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
case @formatted
|
64
|
+
when 1
|
65
|
+
'Color'
|
66
|
+
when 2
|
67
|
+
'Monochrome'
|
68
|
+
else
|
69
|
+
'Unknown'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
76
|
+
# 0x0005 - ImageAdjustment
|
77
|
+
#
|
78
|
+
class ImageAdjustment < Base
|
79
|
+
|
80
|
+
def to_s
|
81
|
+
case @formatted
|
82
|
+
when 0
|
83
|
+
'Normal'
|
84
|
+
when 1
|
85
|
+
'Bright+'
|
86
|
+
when 2
|
87
|
+
'Bright-'
|
88
|
+
when 3
|
89
|
+
'Contrast+'
|
90
|
+
when 4
|
91
|
+
'Contrast-'
|
92
|
+
else
|
93
|
+
'Unknown'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# 0x0006 - CCDSensitivity
|
101
|
+
#
|
102
|
+
class CCDSensitivity < Base
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
case @formatted
|
106
|
+
when 0
|
107
|
+
'ISO80'
|
108
|
+
when 2
|
109
|
+
'ISO160'
|
110
|
+
when 4
|
111
|
+
'ISO320'
|
112
|
+
when 5
|
113
|
+
'ISO100'
|
114
|
+
else
|
115
|
+
"Unknown(#{@formatted})"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# 0x0007 - WhiteBalance
|
123
|
+
#
|
124
|
+
class WhiteBalance < Base
|
125
|
+
|
126
|
+
def to_s
|
127
|
+
case @formatted
|
128
|
+
when 0
|
129
|
+
'Auto'
|
130
|
+
when 1
|
131
|
+
'Preset'
|
132
|
+
when 2
|
133
|
+
'Daylight'
|
134
|
+
when 3
|
135
|
+
'Incandescense'
|
136
|
+
when 4
|
137
|
+
'Fluorescence'
|
138
|
+
when 5
|
139
|
+
'Cloudy'
|
140
|
+
when 6
|
141
|
+
'SpeedLight'
|
142
|
+
else
|
143
|
+
"Unknown(#{@formatted})"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# 0x0008 - Focus
|
151
|
+
#
|
152
|
+
class Focus < Base
|
153
|
+
|
154
|
+
def to_s
|
155
|
+
n = @formatted.numerator
|
156
|
+
d = @formatted.denominator
|
157
|
+
(n == 1 && d == 0) ? 'Pan Focus' : "#{n}/#{d}"
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# 0x000a - DigitalZoom
|
164
|
+
#
|
165
|
+
class DigitalZoom < Base
|
166
|
+
|
167
|
+
def to_s
|
168
|
+
n = @formatted.numerator
|
169
|
+
d = @formatted.denominator
|
170
|
+
(n == 0 && d == 100) ? 'None' : "%0.1f"%[n.to_f/d.to_f]
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
#
|
176
|
+
# 0x000b - Converter
|
177
|
+
#
|
178
|
+
class Converter < Base
|
179
|
+
|
180
|
+
def to_s
|
181
|
+
case @formatted
|
182
|
+
when 0
|
183
|
+
'None'
|
184
|
+
when 1
|
185
|
+
'Fisheye'
|
186
|
+
else
|
187
|
+
'Unknown'
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
NikonIFDTable = {
|
196
|
+
0x0003 => MakerNote::Quality,
|
197
|
+
0x0004 => MakerNote::ColorMode,
|
198
|
+
0x0005 => MakerNote::ImageAdjustment,
|
199
|
+
0x0006 => MakerNote::CCDSensitivity,
|
200
|
+
0x0007 => MakerNote::WhiteBalance,
|
201
|
+
0x0008 => MakerNote::Focus,
|
202
|
+
0x000a => MakerNote::DigitalZoom,
|
203
|
+
0x000b => MakerNote::Converter
|
204
|
+
}
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
class Nikon
|
209
|
+
|
210
|
+
def initialize(fin, tiff_origin, dataPos, byteOrder_module)
|
211
|
+
@fin = fin
|
212
|
+
@tiffHeader0 = tiff_origin
|
213
|
+
@dataPos = dataPos
|
214
|
+
@byteOrder_module = byteOrder_module
|
215
|
+
self.extend @byteOrder_module
|
216
|
+
end
|
217
|
+
|
218
|
+
def scan_IFD
|
219
|
+
#
|
220
|
+
# Nikon MakerNote starts from 8 byte from the origin.
|
221
|
+
#
|
222
|
+
@fin.pos = @dataPos + 8
|
223
|
+
#
|
224
|
+
# get the number of tags
|
225
|
+
#
|
226
|
+
num_dirs = decode_ushort(fin_read_n(2))
|
227
|
+
|
228
|
+
#
|
229
|
+
# now scan them
|
230
|
+
#
|
231
|
+
1.upto(num_dirs) {
|
232
|
+
curpos_tag = @fin.pos
|
233
|
+
tag = parseTagID(fin_read_n(2))
|
234
|
+
tagclass = Tag.find(tag.hex, Tag::NikonIFDTable)
|
235
|
+
unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))]
|
236
|
+
count = decode_ulong(fin_read_n(4))
|
237
|
+
tagdata = fin_read_n(4)
|
238
|
+
obj = tagclass.new(tag, "MakerNote", count)
|
239
|
+
obj.extend formatter, @byteOrder_module
|
240
|
+
obj.pos = curpos_tag
|
241
|
+
if unit * count > 4
|
242
|
+
curpos = @fin.pos
|
243
|
+
begin
|
244
|
+
@fin.pos = @tiffHeader0 + decode_ulong(tagdata)
|
245
|
+
obj.dataPos = @fin.pos
|
246
|
+
obj.data = fin_read_n(unit*count)
|
247
|
+
ensure
|
248
|
+
@fin.pos = curpos
|
249
|
+
end
|
250
|
+
else
|
251
|
+
obj.dataPos = @fin.pos - 4
|
252
|
+
obj.data = tagdata
|
253
|
+
end
|
254
|
+
obj.processData
|
255
|
+
yield obj
|
256
|
+
}
|
257
|
+
end
|
258
|
+
|
259
|
+
private
|
260
|
+
|
261
|
+
def fin_read_n(n)
|
262
|
+
@fin.read(n)
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
@@ -0,0 +1,581 @@
|
|
1
|
+
#
|
2
|
+
# exif/makernote/nikon2.rb
|
3
|
+
#
|
4
|
+
# $Revision: 1.3 $
|
5
|
+
# $Date: 2003/04/27 13:54:52 $
|
6
|
+
#
|
7
|
+
#== Reference
|
8
|
+
#
|
9
|
+
#http://www.ba.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html
|
10
|
+
#
|
11
|
+
require 'exifparser/tag'
|
12
|
+
require 'exifparser/utils'
|
13
|
+
require 'exifparser/makernote/nikonflensname'
|
14
|
+
|
15
|
+
module Exif
|
16
|
+
#
|
17
|
+
# Tags used in Nikon Makernote
|
18
|
+
#
|
19
|
+
module Tag
|
20
|
+
|
21
|
+
module MakerNote
|
22
|
+
#
|
23
|
+
# Shared Datas between Tags
|
24
|
+
#
|
25
|
+
module SharedData
|
26
|
+
@@nikon_serial_no = nil # written by NikonCameaSerialNumber Tag
|
27
|
+
@@release_count = nil # written by ReleaseCount Tag
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Subclass for Tags need shared datas
|
32
|
+
#
|
33
|
+
class NikonBase < Base
|
34
|
+
include SharedData
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# 0x0001 - Data Version
|
39
|
+
#
|
40
|
+
class DataVersion < Base
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
#
|
45
|
+
# 0x0002 - ISOUsed
|
46
|
+
#
|
47
|
+
# class ISOUsed < Base
|
48
|
+
# end
|
49
|
+
|
50
|
+
#
|
51
|
+
# 0x0003 - ColorMode
|
52
|
+
#
|
53
|
+
class ColorMode < Base
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# 0x0004 - ImageQuality
|
58
|
+
#
|
59
|
+
class ImageQuality < Base
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# 0x0005 - Whitebalance
|
64
|
+
#
|
65
|
+
class Whitebalance < Base
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# 0x0006 - ImageSharpening
|
70
|
+
#
|
71
|
+
class ImageSharpening < Base
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# 0x0007 - FocusingMode
|
76
|
+
#
|
77
|
+
class FocusingMode < Base
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# 0x0008 - FlashSetting
|
82
|
+
#
|
83
|
+
class FlashSetting < Base
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# 0x0009 - SpeedlightMode
|
88
|
+
#
|
89
|
+
class SpeedlightMode < Base
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# 0x000d - ProgramShift
|
94
|
+
#
|
95
|
+
class ProgramShift < Base
|
96
|
+
|
97
|
+
def to_s
|
98
|
+
case @formatted
|
99
|
+
when [0xfc, 0x01, 0x06, 0x00]
|
100
|
+
"-2/3EV"
|
101
|
+
when [0xfd, 0x01, 0x06, 0x00]
|
102
|
+
"-1/2EV"
|
103
|
+
when [0xfe, 0x01, 0x06, 0x00]
|
104
|
+
"-1/3EV"
|
105
|
+
when [0x00, 0x01, 0x06, 0x00]
|
106
|
+
"+0EV"
|
107
|
+
when [0x02, 0x01, 0x06, 0x00]
|
108
|
+
"+1/3EV"
|
109
|
+
when [0x03, 0x01, 0x06, 0x00]
|
110
|
+
"+1/2EV"
|
111
|
+
when [0x04, 0x01, 0x06, 0x00]
|
112
|
+
"+2/3EV"
|
113
|
+
else
|
114
|
+
""
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# 0x000e - ExposureDifference
|
122
|
+
#
|
123
|
+
class ExposureDifference < Base
|
124
|
+
|
125
|
+
def to_s
|
126
|
+
case @formatted
|
127
|
+
when [0xf7, 0x01, 0x0c, 0x00]
|
128
|
+
"-2/3EV"
|
129
|
+
when [0xf9, 0x01, 0x0c, 0x00]
|
130
|
+
"-1/2EV"
|
131
|
+
when [0xfc, 0x01, 0x0c, 0x00]
|
132
|
+
"-1/3EV"
|
133
|
+
when [0x00, 0x01, 0x0c, 0x00]
|
134
|
+
"+0EV"
|
135
|
+
when [0x04, 0x01, 0x0c, 0x00]
|
136
|
+
"+1/3EV"
|
137
|
+
when [0x06, 0x01, 0x0c, 0x00]
|
138
|
+
"+1/2EV"
|
139
|
+
when [0x08, 0x01, 0x0c, 0x00]
|
140
|
+
"+2/3EV"
|
141
|
+
else
|
142
|
+
""
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
#
|
149
|
+
# 0x000f - ISOSelection
|
150
|
+
#
|
151
|
+
class ISOSelection < Base
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# 0x0010 - DataDump
|
156
|
+
#
|
157
|
+
class DataDump < Base
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# 0x0012 - Speedlight Bias
|
162
|
+
#
|
163
|
+
class SpeedlightBias < Base
|
164
|
+
|
165
|
+
def to_s
|
166
|
+
case @formatted
|
167
|
+
when [0xfc, 0x01, 0x06, 0x00]
|
168
|
+
"-2/3EV"
|
169
|
+
when [0xfd, 0x01, 0x06, 0x00]
|
170
|
+
"-1/2EV"
|
171
|
+
when [0xfe, 0x01, 0x06, 0x00]
|
172
|
+
"-1/3EV"
|
173
|
+
when [0x00, 0x01, 0x06, 0x00]
|
174
|
+
"+0EV"
|
175
|
+
when [0x02, 0x01, 0x06, 0x00]
|
176
|
+
"+1/3EV"
|
177
|
+
when [0x03, 0x01, 0x06, 0x00]
|
178
|
+
"+1/2EV"
|
179
|
+
when [0x04, 0x01, 0x06, 0x00]
|
180
|
+
"+2/3EV"
|
181
|
+
else
|
182
|
+
""
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
#
|
189
|
+
# 0x001d - NikonCameraSerialNumber
|
190
|
+
#
|
191
|
+
class NikonCameraSerialNumber < NikonBase
|
192
|
+
|
193
|
+
def processData
|
194
|
+
super
|
195
|
+
@@nikon_serial_no = @formatted # This value is used for LensParamaters tag.
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
#
|
201
|
+
# 0x0022 ActiveD_Lighting
|
202
|
+
#
|
203
|
+
class ActiveD_Lighting < Base
|
204
|
+
|
205
|
+
def to_s
|
206
|
+
case @formatted
|
207
|
+
when 0
|
208
|
+
"Off"
|
209
|
+
when 1
|
210
|
+
"Low"
|
211
|
+
when 3
|
212
|
+
"Normal"
|
213
|
+
when 5
|
214
|
+
"Hight"
|
215
|
+
when 7
|
216
|
+
"Extra High"
|
217
|
+
when 65535
|
218
|
+
"Auto"
|
219
|
+
else
|
220
|
+
""
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
#
|
227
|
+
# 0x0023 - PictureControl
|
228
|
+
#
|
229
|
+
class PictureControl < Base
|
230
|
+
def to_s
|
231
|
+
@formatted[4,20].pack('C*')
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
#
|
236
|
+
# 0x0080 - ImageAdjustment
|
237
|
+
#
|
238
|
+
class ImageAdjustment < Base
|
239
|
+
end
|
240
|
+
|
241
|
+
#
|
242
|
+
# 0x0081 - Tone Compensation
|
243
|
+
#
|
244
|
+
class ToneCompensation < Base
|
245
|
+
end
|
246
|
+
|
247
|
+
#
|
248
|
+
# 0x0082 - Adapter
|
249
|
+
#
|
250
|
+
class Adapter < Base
|
251
|
+
end
|
252
|
+
|
253
|
+
#
|
254
|
+
# 0x0083 - LensType
|
255
|
+
#
|
256
|
+
class LensType < Base
|
257
|
+
def to_s
|
258
|
+
data = @formatted[0]
|
259
|
+
isVR = (data[3] == 1 ? "Yes":"No")
|
260
|
+
isG = (data[2] == 1 ? "Yes":"No")
|
261
|
+
isD = (data[1] == 1 ? "Yes":"No")
|
262
|
+
isMF = (data[0] == 1 ? "Yes":"No")
|
263
|
+
"VR:#{isVR}, G:#{isG}, D:#{isD}, MF:#{isMF}"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
#
|
268
|
+
# 0x0084 - LensSpecification
|
269
|
+
#
|
270
|
+
class LensSpecification < Base
|
271
|
+
def processData
|
272
|
+
@formatted = []
|
273
|
+
partition_data(@count) do |data|
|
274
|
+
@formatted.push _formatData(data)
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def to_s
|
279
|
+
if @formatted[0] != @formatted[1]
|
280
|
+
"#{@formatted[0]}-#{@formatted[1]}mm, F#{@formatted[2].to_f}-#{@formatted[3].to_f}"
|
281
|
+
else
|
282
|
+
"#{@formatted[0]}mm, F#{@formatted[2].to_f} (Prime Lens)"
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
#
|
288
|
+
# 0x0085 - ManualForcusDistance
|
289
|
+
#
|
290
|
+
class ManualForcusDistance < Base
|
291
|
+
end
|
292
|
+
|
293
|
+
#
|
294
|
+
# 0x0086 - DigitalZoom
|
295
|
+
#
|
296
|
+
class DigitalZoom < Base
|
297
|
+
end
|
298
|
+
|
299
|
+
#
|
300
|
+
# 0x0088 - AFFocusPosition
|
301
|
+
#
|
302
|
+
class AFFocusPosition < Base
|
303
|
+
end
|
304
|
+
|
305
|
+
#
|
306
|
+
# 0x008D - CameraColorMode
|
307
|
+
#
|
308
|
+
class CameraColorMode < Base
|
309
|
+
end
|
310
|
+
|
311
|
+
#
|
312
|
+
# 0x008F - SceneMode
|
313
|
+
#
|
314
|
+
class SceneMode < Base
|
315
|
+
end
|
316
|
+
|
317
|
+
#
|
318
|
+
# 0x0090 - LightSource
|
319
|
+
#
|
320
|
+
class LightSource < Base
|
321
|
+
end
|
322
|
+
|
323
|
+
#
|
324
|
+
# 0x0095 - LongtimeExposureNR
|
325
|
+
#
|
326
|
+
class LongtimeExposureNR < Base
|
327
|
+
end
|
328
|
+
|
329
|
+
#
|
330
|
+
# 0x0098 - LensParamaters
|
331
|
+
#
|
332
|
+
class LensParameters < NikonBase
|
333
|
+
def _format0(data)
|
334
|
+
data.unpack("C*").collect{|e| e.to_i}
|
335
|
+
end
|
336
|
+
|
337
|
+
def to_hex
|
338
|
+
str = ""
|
339
|
+
@formatted.each do |dat|
|
340
|
+
str += sprintf("%02x ", dat)
|
341
|
+
end
|
342
|
+
return str
|
343
|
+
end
|
344
|
+
|
345
|
+
XLAT0 = [0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
|
346
|
+
0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
|
347
|
+
0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
|
348
|
+
0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
|
349
|
+
0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
|
350
|
+
0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
|
351
|
+
0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
|
352
|
+
0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
|
353
|
+
0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
|
354
|
+
0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
|
355
|
+
0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
|
356
|
+
0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
|
357
|
+
0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
|
358
|
+
0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
|
359
|
+
0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
|
360
|
+
0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7]
|
361
|
+
|
362
|
+
XLAT1 = [0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
|
363
|
+
0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
|
364
|
+
0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
|
365
|
+
0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
|
366
|
+
0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
|
367
|
+
0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
|
368
|
+
0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
|
369
|
+
0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
|
370
|
+
0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
|
371
|
+
0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
|
372
|
+
0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
|
373
|
+
0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
|
374
|
+
0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
|
375
|
+
0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
|
376
|
+
0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
|
377
|
+
0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f]
|
378
|
+
|
379
|
+
def to_s
|
380
|
+
data = @formatted
|
381
|
+
lens_data = ""
|
382
|
+
version = data[0, 4].pack('C*')
|
383
|
+
case version
|
384
|
+
when "0100"
|
385
|
+
lens_data = data[6, 7]
|
386
|
+
|
387
|
+
when "0101"
|
388
|
+
lens_data = data[11, 7]
|
389
|
+
|
390
|
+
when "0201", "0202", "0203"
|
391
|
+
decryptted = decrypt_data(data[4..(data.length - 1)], @@nikon_serial_no, @@release_count)
|
392
|
+
lens_data = decryptted[7, 7]
|
393
|
+
|
394
|
+
when "0204"
|
395
|
+
decryptted = decrypt_data(data[4..(data.length - 1)], @@nikon_serial_no, @@release_count)
|
396
|
+
lens_data = decryptted[8, 7]
|
397
|
+
end
|
398
|
+
|
399
|
+
return "" if lens_data.length == 0
|
400
|
+
|
401
|
+
self.extend NikonFmount
|
402
|
+
ret = Tag::NikonFmount::LensName[lens_data]
|
403
|
+
return ret != nil ? ret : ""
|
404
|
+
|
405
|
+
end
|
406
|
+
|
407
|
+
def decrypt_data(data, serial, count)
|
408
|
+
serialno = serial.to_i
|
409
|
+
if serialno == 0
|
410
|
+
if serial[0,3] == "D50"
|
411
|
+
serialno = 0x22
|
412
|
+
else
|
413
|
+
serialno = 0x60
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
key = 0
|
418
|
+
4.times do |i|
|
419
|
+
key ^= ((count >> (i*8)) & 0xff)
|
420
|
+
end
|
421
|
+
|
422
|
+
ci = XLAT0[serialno & 0xff]
|
423
|
+
cj = XLAT1[key]
|
424
|
+
ck = 0x60;
|
425
|
+
pdata = []
|
426
|
+
|
427
|
+
data.each do |dat|
|
428
|
+
cj += ((ci * ck) & 0xff)
|
429
|
+
cj &= 0xff
|
430
|
+
ck += 1
|
431
|
+
pdata.push(dat ^= cj)
|
432
|
+
end
|
433
|
+
|
434
|
+
return pdata
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
#
|
439
|
+
# 0x00a7 - ReleaseCount
|
440
|
+
#
|
441
|
+
class ReleaseCount < NikonBase
|
442
|
+
def processData
|
443
|
+
super
|
444
|
+
@@release_count = @formatted # This value is used for LensParamaters tag.
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
#
|
449
|
+
# 0x00a9 - ImageOptimization
|
450
|
+
#
|
451
|
+
class ImageOptimization < Base
|
452
|
+
end
|
453
|
+
|
454
|
+
#
|
455
|
+
# 0x00aa - Saturation
|
456
|
+
#
|
457
|
+
class Saturation < Base
|
458
|
+
end
|
459
|
+
|
460
|
+
end
|
461
|
+
|
462
|
+
|
463
|
+
Nikon2IFDTable = {
|
464
|
+
0x0001 => MakerNote::DataVersion,
|
465
|
+
# 0x0002 => MakerNote::ISOUsed,
|
466
|
+
0x0003 => MakerNote::ColorMode,
|
467
|
+
0x0004 => MakerNote::ImageQuality,
|
468
|
+
0x0005 => MakerNote::Whitebalance,
|
469
|
+
0x0006 => MakerNote::ImageSharpening,
|
470
|
+
0x0007 => MakerNote::FocusingMode,
|
471
|
+
0x0008 => MakerNote::FlashSetting,
|
472
|
+
0x0009 => MakerNote::SpeedlightMode,
|
473
|
+
0x000d => MakerNote::ProgramShift,
|
474
|
+
0x000e => MakerNote::ExposureDifference,
|
475
|
+
0x000f => MakerNote::ISOSelection,
|
476
|
+
0x0010 => MakerNote::DataDump,
|
477
|
+
0x0012 => MakerNote::SpeedlightBias,
|
478
|
+
0x001d => MakerNote::NikonCameraSerialNumber,
|
479
|
+
0x0022 => MakerNote::ActiveD_Lighting,
|
480
|
+
0x0023 => MakerNote::PictureControl,
|
481
|
+
0x0080 => MakerNote::ImageAdjustment,
|
482
|
+
0x0081 => MakerNote::ToneCompensation,
|
483
|
+
0x0082 => MakerNote::Adapter,
|
484
|
+
0x0083 => MakerNote::LensType,
|
485
|
+
0x0084 => MakerNote::LensSpecification,
|
486
|
+
0x0085 => MakerNote::ManualForcusDistance,
|
487
|
+
0x0086 => MakerNote::DigitalZoom,
|
488
|
+
0x0088 => MakerNote::AFFocusPosition,
|
489
|
+
0x008D => MakerNote::CameraColorMode,
|
490
|
+
0x008F => MakerNote::SceneMode,
|
491
|
+
0x0090 => MakerNote::LightSource,
|
492
|
+
0x0095 => MakerNote::LongtimeExposureNR,
|
493
|
+
0x0098 => MakerNote::LensParameters,
|
494
|
+
0x00a7 => MakerNote::ReleaseCount,
|
495
|
+
0x00a9 => MakerNote::ImageOptimization,
|
496
|
+
0x00aa => MakerNote::Saturation
|
497
|
+
|
498
|
+
}
|
499
|
+
|
500
|
+
end
|
501
|
+
|
502
|
+
class Nikon2
|
503
|
+
|
504
|
+
def initialize(fin, tiff_origin, dataPos, byteOrder_module)
|
505
|
+
@fin = fin
|
506
|
+
@tiffHeader0 = tiff_origin
|
507
|
+
@dataPos = dataPos
|
508
|
+
@nikonOffset = 0
|
509
|
+
|
510
|
+
@fin.pos = dataPos
|
511
|
+
magic = fin_read_n(6)
|
512
|
+
|
513
|
+
if magic == "Nikon\000"
|
514
|
+
@nikonOffset = 18 # D100, E5700, etc..
|
515
|
+
fin_read_n(4)
|
516
|
+
@tiffHeader0 = @fin.pos
|
517
|
+
bo = @fin.read(2)
|
518
|
+
case bo
|
519
|
+
when "MM"
|
520
|
+
byteOrder_module = Utils::Decode::Motorola
|
521
|
+
when "II"
|
522
|
+
byteOrder_module = Utils::Decode::Intel
|
523
|
+
else
|
524
|
+
raise RuntimeError, "Unknown byte order"
|
525
|
+
end
|
526
|
+
end
|
527
|
+
@byteOrder_module = byteOrder_module
|
528
|
+
self.extend @byteOrder_module
|
529
|
+
end
|
530
|
+
|
531
|
+
def scan_IFD
|
532
|
+
#
|
533
|
+
# Nikon D1 series MakerNote starts from 0 byte from the origin.
|
534
|
+
#
|
535
|
+
@fin.pos = @dataPos + @nikonOffset
|
536
|
+
|
537
|
+
#
|
538
|
+
# get the number of tags
|
539
|
+
#
|
540
|
+
num_dirs = decode_ushort(fin_read_n(2))
|
541
|
+
|
542
|
+
#
|
543
|
+
# now scan them
|
544
|
+
#
|
545
|
+
1.upto(num_dirs) {
|
546
|
+
curpos_tag = @fin.pos
|
547
|
+
tag = parseTagID(fin_read_n(2))
|
548
|
+
tagclass = Tag.find(tag.hex, Tag::Nikon2IFDTable)
|
549
|
+
unit, formatter = Tag::Format::Unit[decode_ushort(fin_read_n(2))]
|
550
|
+
count = decode_ulong(fin_read_n(4))
|
551
|
+
tagdata = fin_read_n(4)
|
552
|
+
obj = tagclass.new(tag, "MakerNote", count)
|
553
|
+
obj.extend formatter, @byteOrder_module
|
554
|
+
obj.pos = curpos_tag
|
555
|
+
if unit * count > 4
|
556
|
+
curpos = @fin.pos
|
557
|
+
begin
|
558
|
+
@fin.pos = @tiffHeader0 + decode_ulong(tagdata)
|
559
|
+
obj.dataPos = @fin.pos
|
560
|
+
obj.data = fin_read_n(unit*count)
|
561
|
+
ensure
|
562
|
+
@fin.pos = curpos
|
563
|
+
end
|
564
|
+
else
|
565
|
+
obj.dataPos = @fin.pos - 4
|
566
|
+
obj.data = tagdata
|
567
|
+
end
|
568
|
+
obj.processData
|
569
|
+
yield obj
|
570
|
+
}
|
571
|
+
end
|
572
|
+
|
573
|
+
private
|
574
|
+
|
575
|
+
def fin_read_n(n)
|
576
|
+
@fin.read(n)
|
577
|
+
end
|
578
|
+
|
579
|
+
end
|
580
|
+
|
581
|
+
end
|