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,76 @@
|
|
1
|
+
#
|
2
|
+
# exifparser/thumbnail.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
|
+
|
10
|
+
module Exif
|
11
|
+
|
12
|
+
class Parser
|
13
|
+
|
14
|
+
alias orig_thumbnail thumbnail
|
15
|
+
|
16
|
+
#
|
17
|
+
# redefine method.
|
18
|
+
#
|
19
|
+
def thumbnail
|
20
|
+
Thumbnail.new(@result[:IFD1], @data)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# APIs are subject to change.
|
27
|
+
#
|
28
|
+
class Thumbnail
|
29
|
+
|
30
|
+
def initialize(ifd1, data)
|
31
|
+
@ifd1 = ifd1
|
32
|
+
@data = data
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
@data.size
|
37
|
+
end
|
38
|
+
|
39
|
+
def write(dest)
|
40
|
+
dest << @data
|
41
|
+
end
|
42
|
+
|
43
|
+
def width
|
44
|
+
search_tag('ImageWidth')
|
45
|
+
end
|
46
|
+
|
47
|
+
def height
|
48
|
+
search_tag('ImageLength')
|
49
|
+
end
|
50
|
+
alias length height
|
51
|
+
|
52
|
+
def bits_per_sample
|
53
|
+
search_tag('BitsPerSample')
|
54
|
+
end
|
55
|
+
|
56
|
+
def compression
|
57
|
+
search_tag('Compression')
|
58
|
+
end
|
59
|
+
|
60
|
+
def photometric_interpretation
|
61
|
+
search_tag('PhotometricInterpretation')
|
62
|
+
end
|
63
|
+
|
64
|
+
def strip_offsets
|
65
|
+
search_tag('StripOffsets')
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def search_tag(tag)
|
71
|
+
@ifd1.find { |t| t.name == tag }
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#
|
2
|
+
# exifparser/utils.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
|
+
|
10
|
+
module Exif
|
11
|
+
|
12
|
+
#
|
13
|
+
# utility module that will be included in some classes.
|
14
|
+
#
|
15
|
+
module Utils
|
16
|
+
|
17
|
+
module Decode
|
18
|
+
|
19
|
+
module Motorola
|
20
|
+
|
21
|
+
def byte_order
|
22
|
+
:motorola
|
23
|
+
end
|
24
|
+
|
25
|
+
def decode_ubytes(str)
|
26
|
+
str.unpack('C*')
|
27
|
+
end
|
28
|
+
|
29
|
+
def decode_ushort(str)
|
30
|
+
str[0,2].unpack('n').first
|
31
|
+
end
|
32
|
+
|
33
|
+
def decode_ulong(str)
|
34
|
+
str[0,4].unpack('N').first
|
35
|
+
end
|
36
|
+
|
37
|
+
def decode_sshort(str)
|
38
|
+
str[0,2].unpack('n').pack('s').unpack('s').first
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode_slong(str)
|
42
|
+
str[0,4].unpack('N').pack('l').unpack('l').first
|
43
|
+
end
|
44
|
+
|
45
|
+
def parseTagID(str)
|
46
|
+
sprintf("0x%02x%02x", *(str.unpack("C*")))
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
module Intel
|
53
|
+
|
54
|
+
def byte_order
|
55
|
+
:intel
|
56
|
+
end
|
57
|
+
|
58
|
+
def decode_ubytes(str)
|
59
|
+
str.unpack('C*')
|
60
|
+
end
|
61
|
+
|
62
|
+
def decode_ushort(str)
|
63
|
+
str[0,2].unpack('v').first
|
64
|
+
end
|
65
|
+
|
66
|
+
def decode_ulong(str)
|
67
|
+
str[0,4].unpack('V').first
|
68
|
+
end
|
69
|
+
|
70
|
+
def decode_sshort(str)
|
71
|
+
str[0,2].unpack('s').first
|
72
|
+
end
|
73
|
+
|
74
|
+
def decode_slong(str)
|
75
|
+
str[0,4].unpack('l').first
|
76
|
+
end
|
77
|
+
|
78
|
+
def parseTagID(str)
|
79
|
+
"0x" + str.unpack("C*").reverse.collect{ |e| sprintf("%02x", e) }.join("")
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/sample/exifview.rb
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# exifview.rb - display EXIF information as well as EXIF image
|
4
|
+
#
|
5
|
+
# Copyright (C) 2002 Ryuichi Tamura (r-tam@fsinet.or.jp)
|
6
|
+
#
|
7
|
+
# $Revision: 1.3 $
|
8
|
+
# $Date: 2002/12/17 05:16:34 $
|
9
|
+
#
|
10
|
+
# Requirements: gtk2
|
11
|
+
#
|
12
|
+
require 'exifparser'
|
13
|
+
require 'observer'
|
14
|
+
require 'gtk2'
|
15
|
+
|
16
|
+
module Exif
|
17
|
+
|
18
|
+
class Parser
|
19
|
+
|
20
|
+
def each_values
|
21
|
+
tags.each do |tag|
|
22
|
+
next if tag == Tag::Exif::MakerNote
|
23
|
+
yield tag.name, tag.tagID.to_s, tag.format, tag.IFD, tag.to_s
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
module ExifView
|
32
|
+
|
33
|
+
class SelectedFile
|
34
|
+
include Observable
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@fpath = nil
|
38
|
+
end
|
39
|
+
attr_reader :fpath
|
40
|
+
|
41
|
+
def filename=(filename)
|
42
|
+
@fpath = File.expand_path(filename)
|
43
|
+
begin
|
44
|
+
exif = ExifParser.new(@fpath)
|
45
|
+
changed
|
46
|
+
rescue
|
47
|
+
changed(false)
|
48
|
+
raise
|
49
|
+
end
|
50
|
+
notify_observers(@fpath, exif)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
DisplayImage = SelectedFile.new
|
56
|
+
|
57
|
+
#
|
58
|
+
# Error dialog
|
59
|
+
#
|
60
|
+
class ErrorDialog < ::Gtk::Dialog
|
61
|
+
|
62
|
+
def initialize(msg)
|
63
|
+
super()
|
64
|
+
self.set_default_size(200, 100)
|
65
|
+
self.set_title("ExifView: Error")
|
66
|
+
button = Gtk::Button.new("dismiss")
|
67
|
+
button.flags |= Gtk::Widget::CAN_DEFAULT
|
68
|
+
button.signal_connect("clicked") do destroy end
|
69
|
+
self.action_area.pack_start(button, 0)
|
70
|
+
button.grab_default
|
71
|
+
label = Gtk::Label.new(msg)
|
72
|
+
vbox.pack_start(label)
|
73
|
+
button.show
|
74
|
+
label.show
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
#
|
80
|
+
# File selection
|
81
|
+
#
|
82
|
+
class FileSelectionWidget < ::Gtk::FileSelection
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
super('File selection')
|
86
|
+
history_pulldown
|
87
|
+
self.signal_connect('destroy') { destroy }
|
88
|
+
self.ok_button.signal_connect('clicked') {
|
89
|
+
catch(:read_error) {
|
90
|
+
begin
|
91
|
+
DisplayImage.filename = self.filename
|
92
|
+
rescue
|
93
|
+
ErrorDialog.new($!.message).show
|
94
|
+
throw :read_error
|
95
|
+
end
|
96
|
+
destroy
|
97
|
+
}
|
98
|
+
}
|
99
|
+
self.cancel_button.signal_connect('clicked') { destroy }
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# MenuItem: Open
|
106
|
+
#
|
107
|
+
class OpenMenuItemWidget < ::Gtk::MenuItem
|
108
|
+
|
109
|
+
def initialize
|
110
|
+
super('Open')
|
111
|
+
@filesel = nil
|
112
|
+
self.signal_connect('activate') {
|
113
|
+
@filesel = FileSelectionWidget.new
|
114
|
+
@filesel.show
|
115
|
+
}
|
116
|
+
end
|
117
|
+
attr_reader :filesel
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# MenuItem: Quit
|
123
|
+
#
|
124
|
+
class QuitMenuItemWidget < ::Gtk::MenuItem
|
125
|
+
|
126
|
+
def initialize
|
127
|
+
super('Quit')
|
128
|
+
self.signal_connect('activate') { Gtk.main_quit }
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Menu Bar
|
135
|
+
#
|
136
|
+
class MenuBarWidget < ::Gtk::MenuBar
|
137
|
+
|
138
|
+
def initialize
|
139
|
+
super()
|
140
|
+
@item_open = OpenMenuItemWidget.new
|
141
|
+
@item_quit = QuitMenuItemWidget.new
|
142
|
+
menu = Gtk::Menu.new
|
143
|
+
menu.append(@item_open)
|
144
|
+
menu.append(@item_quit)
|
145
|
+
filemenu = Gtk::MenuItem.new("File")
|
146
|
+
filemenu.set_submenu(menu)
|
147
|
+
self.append(filemenu)
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
class ImageWindow < ::Gtk::ScrolledWindow
|
153
|
+
|
154
|
+
def initialize
|
155
|
+
super(nil, nil)
|
156
|
+
DisplayImage.add_observer(self)
|
157
|
+
@filename = nil
|
158
|
+
@image = Gtk::Image.new
|
159
|
+
@vbox = Gtk::VBox.new(false, 0)
|
160
|
+
self.add_with_viewport(@vbox)
|
161
|
+
self.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC)
|
162
|
+
@vbox.pack_start(@image, false, false, 0)
|
163
|
+
end
|
164
|
+
attr_reader :filename
|
165
|
+
|
166
|
+
def update(*args)
|
167
|
+
@filename, = *args
|
168
|
+
@image.set(filename)
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
class ExifDataWindow < ::Gtk::ScrolledWindow
|
174
|
+
|
175
|
+
def initialize
|
176
|
+
super(nil, nil)
|
177
|
+
DisplayImage.add_observer(self)
|
178
|
+
@model, @treeview = setup_columns()
|
179
|
+
end
|
180
|
+
|
181
|
+
def setup_columns
|
182
|
+
model = Gtk::ListStore.new(String, String, String, String, String)
|
183
|
+
# tagname, tag_id, ifd_name, value, respectedly
|
184
|
+
treeview = Gtk::TreeView.new(model)
|
185
|
+
cols = []; i = 0
|
186
|
+
[["Name", 0], ["Number", 1], ["Format", 2],
|
187
|
+
["IFD", 3], ["Value", 4]].each do |e|
|
188
|
+
treeview.insert_column(
|
189
|
+
Gtk::TreeViewColumn.new(e[0], Gtk::CellRendererText.new,
|
190
|
+
{:text => e[1]}), e[1] )
|
191
|
+
end
|
192
|
+
treeview.selection.set_mode(Gtk::SELECTION_SINGLE)
|
193
|
+
self.add_with_viewport(treeview)
|
194
|
+
[model, treeview]
|
195
|
+
end
|
196
|
+
|
197
|
+
def update(*args)
|
198
|
+
fpath, exif = *args
|
199
|
+
@model.clear
|
200
|
+
exif.each_values do |e|
|
201
|
+
set_row(*e)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
private
|
206
|
+
|
207
|
+
def set_row(tagname, tag_id, tag_format, ifd_name, value)
|
208
|
+
iter = @model.append
|
209
|
+
iter.set_value(0, tagname)
|
210
|
+
iter.set_value(1, tag_id)
|
211
|
+
iter.set_value(2, tag_format)
|
212
|
+
iter.set_value(3, ifd_name)
|
213
|
+
iter.set_value(4, value)
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
|
218
|
+
class MainWindow < ::Gtk::Window
|
219
|
+
|
220
|
+
def initialize(*args)
|
221
|
+
super(*args)
|
222
|
+
DisplayImage.add_observer(self)
|
223
|
+
# Components lower: Exif data
|
224
|
+
@exifdata = ExifDataWindow.new
|
225
|
+
|
226
|
+
# Components middle: Image
|
227
|
+
@image = ImageWindow.new
|
228
|
+
|
229
|
+
# Components upper: Menu bar
|
230
|
+
@menubar = MenuBarWidget.new
|
231
|
+
|
232
|
+
# VBox creation
|
233
|
+
@vbox = Gtk::VBox.new(false, 0)
|
234
|
+
|
235
|
+
# signal connection for toplevel window
|
236
|
+
self.signal_connect('destroy') { exit }
|
237
|
+
self.signal_connect('delete_event') { exit }
|
238
|
+
end
|
239
|
+
|
240
|
+
def initialize_display
|
241
|
+
set_appearance()
|
242
|
+
self.show_all
|
243
|
+
end
|
244
|
+
|
245
|
+
def update(*args)
|
246
|
+
filename, = *args
|
247
|
+
self.set_title("ExifView: #{filename}")
|
248
|
+
end
|
249
|
+
|
250
|
+
private
|
251
|
+
|
252
|
+
def set_appearance
|
253
|
+
# self
|
254
|
+
self.set_size_request(640,480)
|
255
|
+
self.set_title("ExifView #{@image.filename}")
|
256
|
+
self.add(@vbox)
|
257
|
+
# menubar
|
258
|
+
@vbox.pack_start(@menubar, false, false, 0)
|
259
|
+
# image display
|
260
|
+
@vbox.pack_start(@image, true, true, 0)
|
261
|
+
# exif data display
|
262
|
+
@vbox.pack_start(@exifdata, true, true, 0)
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
if $0 == __FILE__
|
270
|
+
Gtk.init
|
271
|
+
#
|
272
|
+
# Main
|
273
|
+
#
|
274
|
+
filename = ARGV.shift
|
275
|
+
window = ExifView::MainWindow.new(Gtk::Window::TOPLEVEL)
|
276
|
+
ExifView::DisplayImage.filename = filename if filename
|
277
|
+
window.initialize_display
|
278
|
+
Gtk.main
|
279
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: exifparser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- kp
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: Exif tag parser written in pure Ruby
|
42
|
+
email:
|
43
|
+
- knomura.1394@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- Gemfile
|
50
|
+
- LICENSE.txt
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- exifparser.gemspec
|
54
|
+
- lib/exifparser.rb
|
55
|
+
- lib/exifparser/makernote/canon.rb
|
56
|
+
- lib/exifparser/makernote/fujifilm.rb
|
57
|
+
- lib/exifparser/makernote/minolta.rb
|
58
|
+
- lib/exifparser/makernote/mk_nikonflensname.rb
|
59
|
+
- lib/exifparser/makernote/nikon.rb
|
60
|
+
- lib/exifparser/makernote/nikon2.rb
|
61
|
+
- lib/exifparser/makernote/nikonflensname.rb
|
62
|
+
- lib/exifparser/makernote/olympus.rb
|
63
|
+
- lib/exifparser/makernote/prove.rb
|
64
|
+
- lib/exifparser/makernote/sigma.rb
|
65
|
+
- lib/exifparser/pre-setup.rb
|
66
|
+
- lib/exifparser/scan.rb
|
67
|
+
- lib/exifparser/tag.rb
|
68
|
+
- lib/exifparser/thumbnail.rb
|
69
|
+
- lib/exifparser/utils.rb
|
70
|
+
- lib/exifparser/version.rb
|
71
|
+
- sample/exifview.rb
|
72
|
+
homepage: ''
|
73
|
+
licenses:
|
74
|
+
- Ruby
|
75
|
+
metadata: {}
|
76
|
+
post_install_message:
|
77
|
+
rdoc_options: []
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
requirements: []
|
91
|
+
rubyforge_project:
|
92
|
+
rubygems_version: 2.0.3
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Exif tag parser written in pure Ruby
|
96
|
+
test_files: []
|