mini_exiftool 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +15 -0
- data/README +3 -47
- data/Rakefile +1 -1
- data/Tutorial +110 -0
- data/examples/external_photo.rb +21 -0
- data/examples/print_portraits.rb +26 -0
- data/examples/shift_time.rb +29 -0
- data/lib/mini_exiftool.rb +73 -41
- data/test/test_class_methods.rb +61 -0
- data/test/test_composite.rb +23 -0
- data/test/test_read.rb +1 -44
- data/test/test_read_numerical.rb +33 -0
- data/test/test_save.rb +56 -0
- data/test/test_write.rb +6 -22
- metadata +15 -4
- data/test/test_other.rb +0 -28
data/Changelog
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
Version 0.3.0
|
2
|
+
- Documentation completed and a Mini Tutorial added
|
3
|
+
- Interface changes:
|
4
|
+
- Test if a value for a tag can be saved is now done in
|
5
|
+
MiniExiftool#save
|
6
|
+
=> There is no check at the moment you set a value:
|
7
|
+
the tag occurs in MiniExiftool#changed_values
|
8
|
+
=> While calling MiniExiftool#save errors can occur (see next point)
|
9
|
+
- MiniExiftool#save is a transaction: if one or more error occurs th file is
|
10
|
+
not changed! In such a case the errors can be found in MiniExiftool#errors
|
11
|
+
- Parameter opts of MiniExiftool.initialize is now a Hash with two options:
|
12
|
+
- :numerical => read metadata as numerical values
|
13
|
+
- :composite => read also composite tags
|
14
|
+
- Tests added
|
15
|
+
|
1
16
|
Version 0.2.0
|
2
17
|
- Better error handling (i.e. error messages)
|
3
18
|
- Checking if the exiftool command can be executed at loading the lib
|
data/README
CHANGED
@@ -19,51 +19,7 @@ Copyright (c) 2007 by Jan Friedrich
|
|
19
19
|
Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 2.1,
|
20
20
|
February 1999
|
21
21
|
|
22
|
-
==
|
22
|
+
== Usage
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
# copy the original test file therewith the original isn't changed
|
27
|
-
# and the tests work
|
28
|
-
require 'fileutils'
|
29
|
-
FileUtils.cp('test/data/test.jpg', './test.jpg')
|
30
|
-
|
31
|
-
mini_exiftool = MiniExiftool.new 'test.jpg'
|
32
|
-
|
33
|
-
# different methods to read information
|
34
|
-
|
35
|
-
mini_exiftool['Orientation'] # ==> 'Horizontal (normal)'
|
36
|
-
mini_exiftool['ISO'] # ==> 400
|
37
|
-
mini_exiftool['iso'] # ==> 400
|
38
|
-
mini_exiftool['DateTimeOriginal'].class # ==> Time
|
39
|
-
|
40
|
-
mini_exiftool.orientation # ==> 'Horizontal (normal)'
|
41
|
-
mini_exiftool.iso # ==> 400
|
42
|
-
mini_exiftool.datetimeoriginal.class # ==> Time
|
43
|
-
mini_exiftool.date_time_original.class # ==> Time
|
44
|
-
|
45
|
-
# numerical access
|
46
|
-
|
47
|
-
mini_exiftool_num = MiniExiftool.new 'test.jpg', :numerical
|
48
|
-
mini_exiftool_num['Orientation'] # ==> 1
|
49
|
-
|
50
|
-
|
51
|
-
# write access
|
52
|
-
|
53
|
-
mini_exiftool_num['Orientation'] = 2
|
54
|
-
mini_exiftool_num['ISO'] = 200
|
55
|
-
mini_exiftool_num['Orientation'] # ==> 2
|
56
|
-
mini_exiftool_num['ISO'] # ==> 200
|
57
|
-
mini_exiftool_num.reload
|
58
|
-
mini_exiftool_num['Orientation'] # ==> 1
|
59
|
-
mini_exiftool_num['ISO'] # ==> 400
|
60
|
-
|
61
|
-
mini_exiftool_num['Orientation'] = 2
|
62
|
-
mini_exiftool_num['ISO'] = 200
|
63
|
-
mini_exiftool_num.changed? # ==> true
|
64
|
-
mini_exiftool_num.changed_tags # ==> ["ISO", "Orientation"]
|
65
|
-
mini_exiftool_num.save
|
66
|
-
mini_exiftool_num.changed? # ==> false
|
67
|
-
mini_exiftool_num.changed_tags # ==> []
|
68
|
-
mini_exiftool_num['Orientation'] # ==> 2
|
69
|
-
mini_exiftool_num['ISO'] # ==> 200
|
24
|
+
For further information about using MiniExiftool read the Tutorial and
|
25
|
+
have a look at the examples in directory examples.
|
data/Rakefile
CHANGED
@@ -60,7 +60,7 @@ GENERAL_RDOC_OPTS = {
|
|
60
60
|
}
|
61
61
|
|
62
62
|
# Additional RDoc formatted files, besides the Ruby source files.
|
63
|
-
RDOC_FILES = FileList["README"]
|
63
|
+
RDOC_FILES = FileList["README", 'Tutorial']
|
64
64
|
# Remove the following line if you don't want to extract RDoc from
|
65
65
|
# the extension C sources.
|
66
66
|
RDOC_FILES.include(EXT_SOURCES)
|
data/Tutorial
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
= Mini Tutorial
|
2
|
+
|
3
|
+
|
4
|
+
== Installation
|
5
|
+
|
6
|
+
* Installing the Exiftool command-line application from Phil Harvay
|
7
|
+
(see http://www.sno.phy.queensu.ca/~phil/exiftool/install.html)
|
8
|
+
* Installing the Ruby library (<code>gem install mini_exiftool</code>)
|
9
|
+
|
10
|
+
|
11
|
+
== Lesson 1: Reading Meta Data
|
12
|
+
|
13
|
+
=== A Simple Example
|
14
|
+
|
15
|
+
require 'rubygems'
|
16
|
+
require 'mini_exiftool'
|
17
|
+
|
18
|
+
photo = MiniExiftool.new 'photo.jpg'
|
19
|
+
puts photo['DateTimeOriginal']
|
20
|
+
|
21
|
+
|
22
|
+
=== Smart Tag Names
|
23
|
+
In the example above we use <code>photo['DateTimeOriginal']</code> to
|
24
|
+
get the value for the time the photo was taken. But tag names are not
|
25
|
+
case sensitive and additional underlines are also irrelevant. So
|
26
|
+
following expressions are equivalent:
|
27
|
+
photo['DateTimeOriginal']
|
28
|
+
photo['datetimeoriginal']
|
29
|
+
photo['date_time_original']
|
30
|
+
|
31
|
+
|
32
|
+
=== Nicer Access Via Dynamic Methods
|
33
|
+
|
34
|
+
Using the []-method is the safest way to access to values of tags
|
35
|
+
(e. g. Self-timer you can only access this way) but the smarter way is
|
36
|
+
using dynamic method access. You can write:
|
37
|
+
photo.datetimeoriginal
|
38
|
+
or also
|
39
|
+
photo.date_time_original
|
40
|
+
|
41
|
+
|
42
|
+
=== Value Types
|
43
|
+
|
44
|
+
Following types of values are at the moment supported:
|
45
|
+
* Array (e. g. SubjectLocation => 1504 1000 256 304)
|
46
|
+
* Fixnum (e. g. ISO => 400)
|
47
|
+
* Float (e. g. FNumber => 9.5)
|
48
|
+
* String (e. g. Model => DYNAX 7D)
|
49
|
+
* Time (e. g. DateTimeOriginal => 2005:09:13 20:08:50)
|
50
|
+
|
51
|
+
The Exiftool command-line application has an option (-n) to get values
|
52
|
+
as numbers if possible, in MiniExiftool you can do this with setting
|
53
|
+
the <code>:numerical</code> option to +true+ while generating a new
|
54
|
+
instance with new or using the <code>numerical=</code>-method
|
55
|
+
combining with calling <code>reload</code>.
|
56
|
+
|
57
|
+
Let's make an example:
|
58
|
+
# standard: numerical is false
|
59
|
+
photo = MiniExiftool.new 'photo.jpg'
|
60
|
+
photo.exposure_time # => '1/16' (String)
|
61
|
+
# now with numerical is true
|
62
|
+
photo.numerical = true
|
63
|
+
photo.reload
|
64
|
+
photo.exposure_time # => 0.01666667 (Float)
|
65
|
+
This behaviour can be useful if you want to do calculations on the
|
66
|
+
value, if you only want to show the value the standard behaviour is
|
67
|
+
maybe better.
|
68
|
+
|
69
|
+
|
70
|
+
=== Further Example
|
71
|
+
|
72
|
+
For understanding reading access to meta data also have a look at the
|
73
|
+
example file <code>print_portraits.rb</code> in the +examples+
|
74
|
+
directory.
|
75
|
+
|
76
|
+
|
77
|
+
== Lesson 2: Writing Meta Data
|
78
|
+
|
79
|
+
|
80
|
+
=== Also A Very Simple Example
|
81
|
+
|
82
|
+
require 'rubygems'
|
83
|
+
require 'mini_exiftool'
|
84
|
+
|
85
|
+
photo = MiniExiftool.new 'photo.jpg'
|
86
|
+
photo.comment = 'hello world'
|
87
|
+
photo.save
|
88
|
+
|
89
|
+
|
90
|
+
=== Save Is Atomar
|
91
|
+
|
92
|
+
If you have changed serval values and call the +save+-method either
|
93
|
+
all changes will be written to the file or nothing. The return value
|
94
|
+
of the +save+-method is +true+ if all values are written to the file
|
95
|
+
otherwise save returns +false+. In the last case you can use the
|
96
|
+
+errors+-method which returns a hash of the tags which values couldn't
|
97
|
+
be writed with an error message for each of them.
|
98
|
+
|
99
|
+
|
100
|
+
=== Interesting Methods
|
101
|
+
|
102
|
+
Have a look at the <code>changed?</code>-method for checking if the
|
103
|
+
value of a specific tag is changed or a changing in general is
|
104
|
+
done. In the same way the +revert+-method reverts the value of a
|
105
|
+
specific tag or in general all changes.
|
106
|
+
|
107
|
+
|
108
|
+
=== Further Example
|
109
|
+
|
110
|
+
See <code>shift_time.rb</code> in the +examples+ directory.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'mini_exiftool'
|
4
|
+
|
5
|
+
unless ARGV.size == 1
|
6
|
+
puts "usage: ruby #{__FILE__} URI"
|
7
|
+
puts " i.e.: ruby #{__FILE__} http://www.23hq.com/janfri/photo/1535332/large"
|
8
|
+
exit -1
|
9
|
+
end
|
10
|
+
|
11
|
+
# Fetch an external photo
|
12
|
+
filename = open(ARGV.first).path
|
13
|
+
|
14
|
+
# Read the metadata
|
15
|
+
photo = MiniExiftool.new filename
|
16
|
+
|
17
|
+
# Print the metadata
|
18
|
+
photo.tags.sort.each do |tag|
|
19
|
+
# puts "#{tag}: #{photo[tag]}"
|
20
|
+
puts tag.ljust(28) + photo[tag].to_s
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mini_exiftool'
|
3
|
+
|
4
|
+
unless ARGV.size > 0
|
5
|
+
puts "usage: ruby #{__FILE__} FILES"
|
6
|
+
puts " i.e.: ruby #{__FILE__} *.jpg"
|
7
|
+
exit -1
|
8
|
+
end
|
9
|
+
|
10
|
+
# Loop at all given files
|
11
|
+
ARGV.each do |filename|
|
12
|
+
# If a given file isn't a photo MiniExiftool new method will throw
|
13
|
+
# an exception this we will catch
|
14
|
+
begin
|
15
|
+
photo = MiniExiftool.new filename
|
16
|
+
height = photo.image_height
|
17
|
+
width = photo.image_width
|
18
|
+
# We define portait as a photo wich ratio of height to width is
|
19
|
+
# larger than 0.7
|
20
|
+
if height / width > 0.7
|
21
|
+
puts filename
|
22
|
+
end
|
23
|
+
rescue MiniExiftool::Error => e
|
24
|
+
$stderr.puts e.message
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'mini_exiftool'
|
3
|
+
|
4
|
+
if ARGV.size < 2
|
5
|
+
puts "usage: ruby #{__FILE__} [+|-]SECONDS FILES"
|
6
|
+
puts " i.e.: ruby #{__FILE__} 3600 *.jpg"
|
7
|
+
exit -1
|
8
|
+
end
|
9
|
+
|
10
|
+
delta = ARGV.shift.to_i
|
11
|
+
|
12
|
+
ARGV.each do |filename|
|
13
|
+
begin
|
14
|
+
photo = MiniExiftool.new filename
|
15
|
+
rescue MiniExiftool::Error => e
|
16
|
+
$stderr.puts e.message
|
17
|
+
exit -1
|
18
|
+
end
|
19
|
+
time = photo.date_time_original
|
20
|
+
# time is a Time object, so we can use the methods of it :)
|
21
|
+
photo.date_time_original = time + delta
|
22
|
+
save_ok = photo.save
|
23
|
+
if save_ok
|
24
|
+
fmt = '%Y-%m-%d %H:%M:%S'
|
25
|
+
puts "#{filename} changed: #{time.strftime(fmt)} -> #{(time + delta).strftime(fmt)}"
|
26
|
+
else
|
27
|
+
puts "#{filename} could not be changed"
|
28
|
+
end
|
29
|
+
end
|
data/lib/mini_exiftool.rb
CHANGED
@@ -19,32 +19,45 @@ require 'set'
|
|
19
19
|
# Simple OO access to the Exiftool command-line application.
|
20
20
|
class MiniExiftool
|
21
21
|
|
22
|
-
# Name of the
|
22
|
+
# Name of the Exiftool command-line application
|
23
23
|
@@cmd = 'exiftool'
|
24
24
|
|
25
25
|
attr_reader :filename
|
26
|
-
attr_accessor :numerical
|
26
|
+
attr_accessor :numerical, :composite, :errors
|
27
27
|
|
28
|
-
VERSION = '0.
|
28
|
+
VERSION = '0.3.0'
|
29
29
|
|
30
|
-
# opts at the moment
|
31
|
-
#
|
32
|
-
|
33
|
-
|
30
|
+
# opts support at the moment
|
31
|
+
# * <code>:numerical</code> for numerical values, default is +false+
|
32
|
+
# * <code>:composite</code> for including composite tags while loading,
|
33
|
+
# default is +false+
|
34
|
+
def initialize filename, opts={}
|
35
|
+
std_opts = {:numerical => false, :composite => false}
|
36
|
+
opts = std_opts.update opts
|
37
|
+
@numerical = opts[:numerical]
|
38
|
+
@composite = opts[:composite]
|
39
|
+
@values = TagHash.new
|
40
|
+
@tag_names = TagHash.new
|
41
|
+
@changed_values = TagHash.new
|
42
|
+
@errors = TagHash.new
|
34
43
|
load filename
|
35
44
|
end
|
36
45
|
|
37
46
|
# Load the tags of filename
|
38
47
|
def load filename
|
39
|
-
|
48
|
+
if filename.nil? || !File.exists?(filename)
|
40
49
|
raise MiniExiftool::Error.new("File '#{filename}' does not exist.")
|
50
|
+
elsif File.directory?(filename)
|
51
|
+
raise MiniExiftool::Error.new("'#{filename}' is a directory.")
|
41
52
|
end
|
42
53
|
@filename = filename
|
43
|
-
@values
|
44
|
-
@tag_names
|
45
|
-
@changed_values
|
46
|
-
opt_params =
|
47
|
-
|
54
|
+
@values.clear
|
55
|
+
@tag_names.clear
|
56
|
+
@changed_values.clear
|
57
|
+
opt_params = ''
|
58
|
+
opt_params << (@numerical ? '-n ' : '')
|
59
|
+
opt_params << (@composite ? '' : '-e ')
|
60
|
+
cmd = %Q(#@@cmd -q -q -s -t #{opt_params} "#{filename}")
|
48
61
|
if run(cmd)
|
49
62
|
parse_output
|
50
63
|
else
|
@@ -60,19 +73,12 @@ class MiniExiftool
|
|
60
73
|
|
61
74
|
# Returns the value of a tag
|
62
75
|
def [] tag
|
63
|
-
|
64
|
-
@changed_values[unified_tag] || @values[unified_tag]
|
76
|
+
@changed_values[tag] || @values[tag]
|
65
77
|
end
|
66
78
|
|
67
79
|
# Set the value of a tag
|
68
80
|
def []=(tag, val)
|
69
|
-
|
70
|
-
converted_val = convert val
|
71
|
-
opt_params = converted_val.kind_of?(Numeric) ? '-n' : ''
|
72
|
-
cmd = %Q(#@@cmd -q -q -P -overwrite_original #{opt_params} -#{unified_tag}="#{converted_val}" "#{temp_filename}")
|
73
|
-
if run(cmd)
|
74
|
-
@changed_values[unified_tag] = val
|
75
|
-
end
|
81
|
+
@changed_values[tag] = val
|
76
82
|
end
|
77
83
|
|
78
84
|
# Return true if any tag value is changed or if the value of a
|
@@ -88,8 +94,7 @@ class MiniExiftool
|
|
88
94
|
# Revert all changes or the change of a given tag
|
89
95
|
def revert tag=nil
|
90
96
|
if tag
|
91
|
-
|
92
|
-
val = @changed_values.delete(unified_tag)
|
97
|
+
val = @changed_values.delete(tag)
|
93
98
|
res = val != nil
|
94
99
|
else
|
95
100
|
res = @changed_values.size > 0
|
@@ -110,17 +115,29 @@ class MiniExiftool
|
|
110
115
|
|
111
116
|
# Save the changes to the file
|
112
117
|
def save
|
113
|
-
|
118
|
+
return false if @changed_values.empty?
|
119
|
+
@errors.clear
|
120
|
+
temp_file = Tempfile.new('mini_exiftool')
|
121
|
+
temp_file.close
|
122
|
+
temp_filename = temp_file.path
|
123
|
+
FileUtils.cp filename, temp_filename
|
124
|
+
all_ok = true
|
114
125
|
@changed_values.each do |tag, val|
|
115
|
-
unified_tag = unify tag
|
116
126
|
converted_val = convert val
|
117
127
|
opt_params = converted_val.kind_of?(Numeric) ? '-n' : ''
|
118
|
-
cmd = %Q(#@@cmd -q -
|
119
|
-
run(cmd)
|
120
|
-
result
|
128
|
+
cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} -#{tag}="#{converted_val}" "#{temp_filename}")
|
129
|
+
result = run(cmd)
|
130
|
+
unless result
|
131
|
+
all_ok = false
|
132
|
+
@errors[tag] = @error_text.gsub(/Nothing to do.\n\z/, '').chomp
|
133
|
+
end
|
134
|
+
end
|
135
|
+
if all_ok
|
136
|
+
FileUtils.cp temp_filename, filename
|
137
|
+
reload
|
121
138
|
end
|
122
|
-
|
123
|
-
|
139
|
+
temp_file.delete
|
140
|
+
all_ok
|
124
141
|
end
|
125
142
|
|
126
143
|
# Returns the command name of the called Exiftool application
|
@@ -151,11 +168,10 @@ class MiniExiftool
|
|
151
168
|
# Returns the version of the Exiftool command-line application
|
152
169
|
def self.exiftool_version
|
153
170
|
output = `#{MiniExiftool.command} -ver 2>&1`
|
154
|
-
|
155
|
-
return output
|
156
|
-
else
|
171
|
+
unless $?.exitstatus == 0
|
157
172
|
raise MiniExiftool::Error.new("Command '#{MiniExiftool.command}' not found")
|
158
173
|
end
|
174
|
+
output.chomp!
|
159
175
|
end
|
160
176
|
|
161
177
|
private
|
@@ -175,10 +191,6 @@ class MiniExiftool
|
|
175
191
|
end
|
176
192
|
end
|
177
193
|
|
178
|
-
def unify name
|
179
|
-
name.gsub(/[_\-]/, '').downcase
|
180
|
-
end
|
181
|
-
|
182
194
|
def convert val
|
183
195
|
case val
|
184
196
|
when Time
|
@@ -199,9 +211,8 @@ class MiniExiftool
|
|
199
211
|
def parse_output
|
200
212
|
@output.each_line do |line|
|
201
213
|
tag, value = parse_line line
|
202
|
-
|
203
|
-
@
|
204
|
-
@values[unified_tag] = value
|
214
|
+
@tag_names[tag] = tag
|
215
|
+
@values[tag] = value
|
205
216
|
end
|
206
217
|
end
|
207
218
|
|
@@ -236,6 +247,27 @@ class MiniExiftool
|
|
236
247
|
@temp_filename
|
237
248
|
end
|
238
249
|
|
250
|
+
# Hash with indifferent access:
|
251
|
+
# DateTimeOriginal == datetimeoriginal == date_time_original
|
252
|
+
class TagHash < Hash
|
253
|
+
def[] k
|
254
|
+
super(unify(k))
|
255
|
+
end
|
256
|
+
def []= k, v
|
257
|
+
super(unify(k), v)
|
258
|
+
end
|
259
|
+
def delete k
|
260
|
+
super(unify(k))
|
261
|
+
end
|
262
|
+
|
263
|
+
private
|
264
|
+
def unify tag
|
265
|
+
tag.gsub(/[-_]/,'').downcase
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
# Exception class
|
239
271
|
class MiniExiftool::Error < Exception; end
|
240
272
|
|
241
273
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'mini_exiftool'
|
2
|
+
require 'test/unit'
|
3
|
+
begin
|
4
|
+
require 'turn'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
class TestClassMethods < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def test_new
|
11
|
+
assert_raises MiniExiftool::Error do
|
12
|
+
MiniExiftool.new nil
|
13
|
+
end
|
14
|
+
assert_raises MiniExiftool::Error do
|
15
|
+
MiniExiftool.new ''
|
16
|
+
end
|
17
|
+
assert_raises MiniExiftool::Error do
|
18
|
+
MiniExiftool.new 'not_existing_file'
|
19
|
+
end
|
20
|
+
assert_raises MiniExiftool::Error do
|
21
|
+
MiniExiftool.new '.' # directory
|
22
|
+
end
|
23
|
+
begin
|
24
|
+
MiniExiftool.new 'not_existing_file'
|
25
|
+
rescue MiniExiftool::Error => e
|
26
|
+
assert_match /File 'not_existing_file' does not exist/, e.message
|
27
|
+
end
|
28
|
+
assert_raises MiniExiftool::Error do
|
29
|
+
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
30
|
+
end
|
31
|
+
begin
|
32
|
+
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
33
|
+
rescue MiniExiftool::Error => e
|
34
|
+
assert_match /Error: Unknown (?:image|file) type/, e.message
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_command
|
39
|
+
cmd = MiniExiftool.command
|
40
|
+
assert_equal 'exiftool', cmd
|
41
|
+
MiniExiftool.command = 'non_existend'
|
42
|
+
assert_equal 'non_existend', MiniExiftool.command
|
43
|
+
assert_raises MiniExiftool::Error do
|
44
|
+
met = MiniExiftool.new(File.join(File.dirname(__FILE__),
|
45
|
+
'data/test.jpg'))
|
46
|
+
end
|
47
|
+
MiniExiftool.command = cmd
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_writable_tags
|
51
|
+
w_tags = MiniExiftool.writable_tags
|
52
|
+
assert w_tags.include?('ISO')
|
53
|
+
assert_equal false, w_tags.include?('xxxxxx')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_exiftool_version
|
57
|
+
v = MiniExiftool.exiftool_version
|
58
|
+
assert_match /\A\d+\.\d+\z/, v
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'mini_exiftool'
|
2
|
+
require 'test/unit'
|
3
|
+
begin
|
4
|
+
require 'turn'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
class TestComposite < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@data_dir = File.dirname(__FILE__) + '/data'
|
12
|
+
@filename_test = @data_dir + '/test.jpg'
|
13
|
+
@mini_exiftool = MiniExiftool.new @filename_test
|
14
|
+
@mini_exiftool_c = MiniExiftool.new @filename_test, :composite => true
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_composite_tags
|
18
|
+
assert_equal false, @mini_exiftool.tags.include?('Aperture')
|
19
|
+
assert_equal true, @mini_exiftool_c.tags.include?('Aperture')
|
20
|
+
assert_equal 9.5, @mini_exiftool_c['Aperture']
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/test/test_read.rb
CHANGED
@@ -11,32 +11,6 @@ class TestRead < Test::Unit::TestCase
|
|
11
11
|
@data_dir = File.dirname(__FILE__) + '/data'
|
12
12
|
@filename_test = @data_dir + '/test.jpg'
|
13
13
|
@mini_exiftool = MiniExiftool.new @filename_test
|
14
|
-
@mini_exiftool_num = MiniExiftool.new @filename_test, :numerical
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_initialize
|
18
|
-
assert_raises MiniExiftool::Error do
|
19
|
-
MiniExiftool.new ''
|
20
|
-
end
|
21
|
-
assert_raises MiniExiftool::Error do
|
22
|
-
MiniExiftool.new 'not_existing_file'
|
23
|
-
end
|
24
|
-
begin
|
25
|
-
MiniExiftool.new 'not_existing_file'
|
26
|
-
rescue MiniExiftool::Error => e
|
27
|
-
assert_match /File 'not_existing_file' does not exist/, e.message
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_wrong_file
|
32
|
-
assert_raises MiniExiftool::Error do
|
33
|
-
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
34
|
-
end
|
35
|
-
begin
|
36
|
-
MiniExiftool.new __FILE__ # file type wich Exiftool can not handle
|
37
|
-
rescue MiniExiftool::Error => e
|
38
|
-
assert_match /Error: Unknown image type/, e.message
|
39
|
-
end
|
40
14
|
end
|
41
15
|
|
42
16
|
def test_access
|
@@ -46,15 +20,8 @@ class TestRead < Test::Unit::TestCase
|
|
46
20
|
assert_equal 400, @mini_exiftool.iso
|
47
21
|
end
|
48
22
|
|
49
|
-
def test_access_numerical
|
50
|
-
assert_equal 'DYNAX 7D', @mini_exiftool_num['Model']
|
51
|
-
assert_equal 'MLT0', @mini_exiftool_num['maker_note_version']
|
52
|
-
assert_equal 'MLT0', @mini_exiftool_num.maker_note_version
|
53
|
-
assert_equal 400, @mini_exiftool_num.iso
|
54
|
-
end
|
55
|
-
|
56
23
|
def test_tags
|
57
|
-
assert @
|
24
|
+
assert @mini_exiftool.tags.include?('FileSize')
|
58
25
|
end
|
59
26
|
|
60
27
|
def test_conversion
|
@@ -66,14 +33,4 @@ class TestRead < Test::Unit::TestCase
|
|
66
33
|
assert_kind_of Array, @mini_exiftool['SubjectLocation']
|
67
34
|
end
|
68
35
|
|
69
|
-
def test_conversion_numerical
|
70
|
-
assert_kind_of String, @mini_exiftool_num.model
|
71
|
-
assert_kind_of Time, @mini_exiftool_num['DateTimeOriginal']
|
72
|
-
assert_kind_of Float, @mini_exiftool_num['MaxApertureValue']
|
73
|
-
assert_kind_of Fixnum, @mini_exiftool_num.flash
|
74
|
-
assert_kind_of String, @mini_exiftool_num.exif_version
|
75
|
-
assert_kind_of Fixnum, @mini_exiftool_num['ExposureCompensation']
|
76
|
-
assert_kind_of Array, @mini_exiftool_num['SubjectLocation']
|
77
|
-
end
|
78
|
-
|
79
36
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'mini_exiftool'
|
2
|
+
require 'test/unit'
|
3
|
+
begin
|
4
|
+
require 'turn'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
class TestReadNumerical < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@data_dir = File.dirname(__FILE__) + '/data'
|
12
|
+
@filename_test = @data_dir + '/test.jpg'
|
13
|
+
@mini_exiftool_num = MiniExiftool.new @filename_test, :numerical => true
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_access_numerical
|
17
|
+
assert_equal 'DYNAX 7D', @mini_exiftool_num['Model']
|
18
|
+
assert_equal 'MLT0', @mini_exiftool_num['maker_note_version']
|
19
|
+
assert_equal 'MLT0', @mini_exiftool_num.maker_note_version
|
20
|
+
assert_equal 400, @mini_exiftool_num.iso
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_conversion_numerical
|
24
|
+
assert_kind_of String, @mini_exiftool_num.model
|
25
|
+
assert_kind_of Time, @mini_exiftool_num['DateTimeOriginal']
|
26
|
+
assert_kind_of Float, @mini_exiftool_num['MaxApertureValue']
|
27
|
+
assert_kind_of Fixnum, @mini_exiftool_num.flash
|
28
|
+
assert_kind_of String, @mini_exiftool_num.exif_version
|
29
|
+
assert_kind_of Fixnum, @mini_exiftool_num['ExposureCompensation']
|
30
|
+
assert_kind_of Array, @mini_exiftool_num['SubjectLocation']
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/test/test_save.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'mini_exiftool'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'test/unit'
|
6
|
+
begin
|
7
|
+
require 'turn'
|
8
|
+
rescue LoadError
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestSave < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@temp_file = Tempfile.new('test')
|
15
|
+
@temp_file.close
|
16
|
+
@temp_filename = @temp_file.path
|
17
|
+
@org_filename = File.dirname(__FILE__) + '/data/test.jpg'
|
18
|
+
FileUtils.cp(@org_filename, @temp_filename)
|
19
|
+
@mini_exiftool = MiniExiftool.new @temp_filename
|
20
|
+
@mini_exiftool_num = MiniExiftool.new @temp_filename, :numerical => true
|
21
|
+
@org_md5 = Digest::MD5.hexdigest(File.read(@org_filename))
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_allowed_value
|
25
|
+
@mini_exiftool_num['Orientation'] = 2
|
26
|
+
result = @mini_exiftool_num.save
|
27
|
+
assert_equal true, result
|
28
|
+
assert_equal @org_md5, Digest::MD5.hexdigest(File.read(@org_filename))
|
29
|
+
assert_not_equal @org_md5, Digest::MD5.hexdigest(File.read(@temp_filename))
|
30
|
+
assert_equal false, @mini_exiftool_num.changed?
|
31
|
+
result = @mini_exiftool_num.save
|
32
|
+
assert_equal false, result
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_non_allowed_value
|
36
|
+
@mini_exiftool['Orientation'] = 'some string'
|
37
|
+
result = @mini_exiftool.save
|
38
|
+
assert_equal false, result
|
39
|
+
assert_equal 1, @mini_exiftool.errors.size
|
40
|
+
assert_equal("Can't convert IFD0:Orientation (not in PrintConv)",
|
41
|
+
@mini_exiftool.errors['Orientation'])
|
42
|
+
assert @mini_exiftool.changed?
|
43
|
+
assert @mini_exiftool.changed_tags.include?('Orientation')
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_no_changing_of_file_when_error
|
47
|
+
@mini_exiftool['ISO'] = 800
|
48
|
+
@mini_exiftool['Orientation'] = 'some value'
|
49
|
+
@mini_exiftool['ExposureTime'] = '1/30'
|
50
|
+
result = @mini_exiftool.save
|
51
|
+
assert_equal false, result
|
52
|
+
assert_equal @org_md5, Digest::MD5.hexdigest(File.read(@org_filename))
|
53
|
+
assert_equal @org_md5, Digest::MD5.hexdigest(File.read(@temp_filename))
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/test/test_write.rb
CHANGED
@@ -17,7 +17,7 @@ class TestWrite < Test::Unit::TestCase
|
|
17
17
|
@org_filename = File.dirname(__FILE__) + '/data/test.jpg'
|
18
18
|
FileUtils.cp(@org_filename, @temp_filename)
|
19
19
|
@mini_exiftool = MiniExiftool.new @temp_filename
|
20
|
-
@mini_exiftool_num = MiniExiftool.new @temp_filename, :numerical
|
20
|
+
@mini_exiftool_num = MiniExiftool.new @temp_filename, :numerical => true
|
21
21
|
end
|
22
22
|
|
23
23
|
def teardown
|
@@ -27,7 +27,7 @@ class TestWrite < Test::Unit::TestCase
|
|
27
27
|
def test_access_existing_tags
|
28
28
|
assert_equal 'Horizontal (normal)', @mini_exiftool['Orientation']
|
29
29
|
@mini_exiftool['Orientation'] = 'some string'
|
30
|
-
assert_equal '
|
30
|
+
assert_equal 'some string', @mini_exiftool['Orientation']
|
31
31
|
assert_equal false, @mini_exiftool.changed?('Orientation')
|
32
32
|
@mini_exiftool['Orientation'] = 2
|
33
33
|
assert_equal 2, @mini_exiftool['Orientation']
|
@@ -52,11 +52,11 @@ class TestWrite < Test::Unit::TestCase
|
|
52
52
|
assert_equal 'Rotate 180', @mini_exiftool['Orientation']
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
55
|
+
def test_access_non_writable_tags
|
56
56
|
@mini_exiftool_num['FileSize'] = 1
|
57
|
-
assert_equal
|
58
|
-
@mini_exiftool_num['
|
59
|
-
assert_equal
|
57
|
+
assert_equal true, @mini_exiftool_num.changed?
|
58
|
+
@mini_exiftool_num['SomeNonWritableName'] = 'test'
|
59
|
+
assert_equal true, @mini_exiftool_num.changed?
|
60
60
|
end
|
61
61
|
|
62
62
|
def test_time_conversion
|
@@ -113,20 +113,4 @@ class TestWrite < Test::Unit::TestCase
|
|
113
113
|
assert_equal false, res
|
114
114
|
end
|
115
115
|
|
116
|
-
def test_save
|
117
|
-
org_md5 = Digest::MD5.hexdigest(File.read(@org_filename))
|
118
|
-
temp_md5 = Digest::MD5.hexdigest(File.read(@temp_filename))
|
119
|
-
assert_equal org_md5, temp_md5
|
120
|
-
@mini_exiftool_num['Orientation'] = 2
|
121
|
-
result = @mini_exiftool_num.save
|
122
|
-
assert_equal true, result
|
123
|
-
org_md5_2 = Digest::MD5.hexdigest(File.read(@org_filename))
|
124
|
-
assert_equal org_md5, org_md5_2
|
125
|
-
temp_md5_2 = Digest::MD5.hexdigest(File.read(@temp_filename))
|
126
|
-
assert_not_equal temp_md5, temp_md5_2
|
127
|
-
assert_equal false, @mini_exiftool_num.changed?
|
128
|
-
result = @mini_exiftool_num.save
|
129
|
-
assert_equal false, result
|
130
|
-
end
|
131
|
-
|
132
116
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.1
|
|
3
3
|
specification_version: 1
|
4
4
|
name: mini_exiftool
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-03-29 00:00:00 +02:00
|
8
8
|
summary: A library for nice OO access to the Exiftool command-line application written by Phil Harvey.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -33,7 +33,13 @@ files:
|
|
33
33
|
- test/test_write.rb
|
34
34
|
- test/test_read.rb
|
35
35
|
- test/test_special.rb
|
36
|
-
- test/
|
36
|
+
- test/test_class_methods.rb
|
37
|
+
- test/test_save.rb
|
38
|
+
- test/test_composite.rb
|
39
|
+
- test/test_read_numerical.rb
|
40
|
+
- examples/external_photo.rb
|
41
|
+
- examples/print_portraits.rb
|
42
|
+
- examples/shift_time.rb
|
37
43
|
- Rakefile
|
38
44
|
- COPYING
|
39
45
|
- Changelog
|
@@ -41,11 +47,15 @@ files:
|
|
41
47
|
- test/data/Canon.jpg
|
42
48
|
- test/data/INFORMATION
|
43
49
|
- README
|
50
|
+
- Tutorial
|
44
51
|
test_files:
|
45
52
|
- test/test_write.rb
|
46
53
|
- test/test_read.rb
|
47
54
|
- test/test_special.rb
|
48
|
-
- test/
|
55
|
+
- test/test_class_methods.rb
|
56
|
+
- test/test_save.rb
|
57
|
+
- test/test_composite.rb
|
58
|
+
- test/test_read_numerical.rb
|
49
59
|
rdoc_options:
|
50
60
|
- --title
|
51
61
|
- MiniExiftool API documentation
|
@@ -53,6 +63,7 @@ rdoc_options:
|
|
53
63
|
- README
|
54
64
|
extra_rdoc_files:
|
55
65
|
- README
|
66
|
+
- Tutorial
|
56
67
|
executables: []
|
57
68
|
|
58
69
|
extensions: []
|
data/test/test_other.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'mini_exiftool'
|
2
|
-
require 'test/unit'
|
3
|
-
begin
|
4
|
-
require 'turn'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
|
8
|
-
class TestOther < Test::Unit::TestCase
|
9
|
-
|
10
|
-
def test_command
|
11
|
-
cmd = MiniExiftool.command
|
12
|
-
assert_equal 'exiftool', cmd
|
13
|
-
MiniExiftool.command = 'non_existend'
|
14
|
-
assert_equal 'non_existend', MiniExiftool.command
|
15
|
-
assert_raises MiniExiftool::Error do
|
16
|
-
met = MiniExiftool.new(File.join(File.dirname(__FILE__),
|
17
|
-
'data/test.jpg'))
|
18
|
-
end
|
19
|
-
MiniExiftool.command = cmd
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_writable_tags
|
23
|
-
w_tags = MiniExiftool.writable_tags
|
24
|
-
assert w_tags.include?('ISO')
|
25
|
-
assert_equal false, w_tags.include?('xxxxxx')
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|