mini_exiftool 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +38 -29
- data/Rakefile +12 -14
- data/lib/mini_exiftool.rb +37 -16
- data/test/data/Bad_PreviewIFD.jpg +0 -0
- data/test/data/test.jpg.json +106 -0
- data/test/test_from_hash.rb +22 -0
- data/test/test_save.rb +12 -0
- metadata +50 -67
- data/.yardopts +0 -1
- data/Manifest +0 -27
- data/TODO +0 -2
- data/Tutorial.rdoc +0 -139
- data/examples/external_photo.rb +0 -22
- data/examples/print_portraits.rb +0 -27
- data/examples/shift_time.rb +0 -30
- data/mini_exiftool.gemspec +0 -31
- data/setup.rb +0 -1586
data/Changelog
CHANGED
@@ -1,71 +1,80 @@
|
|
1
|
-
|
1
|
+
1.6.0
|
2
|
+
- Type conversion in MiniExiftool.from_hash.
|
3
|
+
Thanks to Ethan Soutar-Rau for the merge request.
|
4
|
+
- Switching to rim. (No longer troubles with echoe.)
|
5
|
+
- Exiftool version detection delayed.
|
6
|
+
Thanks to Sebastian Skałacki for the merge request.
|
7
|
+
- New method MiniExiftool#save!
|
8
|
+
Cherry-picked commit from Wil Gieseler.
|
9
|
+
|
10
|
+
1.5.1
|
2
11
|
- Make rational values work on Ruby 1.8.7.
|
3
12
|
|
4
|
-
|
13
|
+
1.5.0
|
5
14
|
- Supporting exiftool command-line option -m.
|
6
15
|
rubyforge request [#29587]
|
7
16
|
Thanks to Michael Grove for reporting.
|
8
17
|
- Supporting rational values.
|
9
18
|
|
10
|
-
|
19
|
+
1.4.4
|
11
20
|
- Fix escaping of values for older versions of Shellwords.
|
12
21
|
|
13
|
-
|
22
|
+
1.4.3
|
14
23
|
- Fixing rubyforge bug [#29596] (Quotes in values)
|
15
24
|
Thanks to Michael Grove for reporting
|
16
25
|
|
17
|
-
|
26
|
+
1.4.2
|
18
27
|
- Add .yardopts file to gem.
|
19
28
|
|
20
|
-
|
29
|
+
1.4.1
|
21
30
|
- Update documentation for using yard.
|
22
31
|
|
23
|
-
|
32
|
+
1.4.0
|
24
33
|
- Allow symbols for tag access with [].
|
25
34
|
- Refactoring tests.
|
26
35
|
|
27
|
-
|
36
|
+
1.3.1
|
28
37
|
- Remove TestEscapeFilename test and releating test photo
|
29
38
|
because the latter produces errors on windows systems.
|
30
39
|
- Version check in prerelease task.
|
31
40
|
|
32
|
-
|
41
|
+
1.3.0
|
33
42
|
- MiniExiftool is now ready for Ruby 1.9
|
34
43
|
All tests in the test suite pass. :)
|
35
44
|
|
36
|
-
|
45
|
+
1.2.2
|
37
46
|
- Fixing ptore directory naming convention for darwin.
|
38
47
|
Thanks to Denis Barushev for the hint.
|
39
48
|
|
40
|
-
|
49
|
+
1.2.1
|
41
50
|
- Switching to echoe.
|
42
51
|
- Update e-mail address.
|
43
52
|
|
44
|
-
|
53
|
+
1.2.0
|
45
54
|
- Fixing time zone handling.
|
46
55
|
Thanks to ccoenen for the hint.
|
47
56
|
|
48
|
-
|
57
|
+
1.1.0
|
49
58
|
- Escaping filenames in shell commands
|
50
59
|
Thanks to Michael Hoy for the hint and implementing a patch which was
|
51
60
|
the base for this fix.
|
52
61
|
|
53
|
-
|
62
|
+
1.0.2
|
54
63
|
- Fixing warings
|
55
64
|
Thanks to Peter-Hinrich Krogmann for the hint.
|
56
65
|
|
57
|
-
|
66
|
+
1.0.1
|
58
67
|
- Fixing bug [#22726]
|
59
68
|
Making MiniExiftool::Error public.
|
60
69
|
Thanks to Mathias Stjernstrom for sending a patch.
|
61
70
|
|
62
|
-
|
71
|
+
1.0.0
|
63
72
|
- Be aware changing in the interface:
|
64
73
|
- List tags (e.g. Keywords, SupplementalCategories) are now handled as
|
65
74
|
arrays.
|
66
75
|
- Tag SubjectLocation is not longer an array value but a string value!
|
67
76
|
|
68
|
-
|
77
|
+
0.7.0
|
69
78
|
- Changing composite behaviour: Composite tags are now included as standard!
|
70
79
|
- New method MiniExiftool.opts which returns a hash of the standard
|
71
80
|
options used for MiniExiftool.new
|
@@ -73,7 +82,7 @@ v0.7.0
|
|
73
82
|
of the exiftool command-line application (see online documentation for it)
|
74
83
|
Thanks to Henning Kulander for the causing of this change.
|
75
84
|
|
76
|
-
|
85
|
+
0.6.0
|
77
86
|
- New methods for serialization:
|
78
87
|
- MiniExiftool.from_hash
|
79
88
|
- MiniExiftool.from_yaml
|
@@ -83,20 +92,20 @@ v0.6.0
|
|
83
92
|
- Refactoring of tests
|
84
93
|
- Small documetation update
|
85
94
|
|
86
|
-
|
95
|
+
0.5.1
|
87
96
|
- Warning "parenthesize argument(s) for future version" removed
|
88
97
|
Thanks to Greg from knobby.ws
|
89
98
|
|
90
|
-
|
99
|
+
0.5.0
|
91
100
|
- New option :timestamps to create DateTime objects instead of Time objects
|
92
101
|
for timestamps (Fixing bug #16328)
|
93
102
|
- Invalid values of timestamps (i.e. 0000:00:00 00:00:00) are now mapped
|
94
103
|
to false
|
95
104
|
|
96
|
-
|
105
|
+
0.4.1
|
97
106
|
- Compatibility for Ruby 1.9
|
98
107
|
|
99
|
-
|
108
|
+
0.4.0
|
100
109
|
- MiniExiftool::Error inherits now from StandardError
|
101
110
|
- Alternative installation via setup.rb
|
102
111
|
- Bugfix
|
@@ -106,10 +115,10 @@ v0.4.0
|
|
106
115
|
- Interna: Original tag names (all and writable) are now saved via pstore in
|
107
116
|
a file for better performance
|
108
117
|
|
109
|
-
|
118
|
+
0.3.1
|
110
119
|
- Typos fixed
|
111
120
|
|
112
|
-
|
121
|
+
0.3.0
|
113
122
|
- Documentation completed and a Mini Tutorial added
|
114
123
|
- Interface changes:
|
115
124
|
- Test if a value for a tag can be saved is now done in
|
@@ -124,27 +133,27 @@ v0.3.0
|
|
124
133
|
- :composite => read also composite tags
|
125
134
|
- Tests added
|
126
135
|
|
127
|
-
|
136
|
+
0.2.0
|
128
137
|
- Better error handling (i.e. error messages)
|
129
138
|
- Checking if the exiftool command can be executed at loading the lib
|
130
139
|
- New class method exiftool_version
|
131
140
|
- Added tests
|
132
141
|
- Documentation completed
|
133
142
|
|
134
|
-
|
143
|
+
0.1.2
|
135
144
|
- Bugfix for Windows (Tempfile)
|
136
145
|
Thanks to Jérome Soika for testing
|
137
146
|
- Regexes optimized (a little bit)
|
138
147
|
- New class-method MiniExiftool.writable_tags
|
139
148
|
|
140
|
-
|
149
|
+
0.1.1
|
141
150
|
- Fixing bug [#8073]
|
142
151
|
Handling the '-' in tag Self-timer
|
143
152
|
Thanks to Eric Young
|
144
153
|
|
145
|
-
|
154
|
+
0.1.0
|
146
155
|
- New method "revert"
|
147
156
|
- More tests
|
148
157
|
|
149
|
-
|
158
|
+
0.0.1
|
150
159
|
- Initial release
|
data/Rakefile
CHANGED
@@ -1,12 +1,18 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'rim'
|
2
|
+
require 'rim/check_version'
|
3
|
+
require 'rim/gem'
|
4
|
+
require 'rim/test'
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
+
$:.unshift 'lib'
|
7
|
+
require 'mini_exiftool'
|
8
|
+
|
9
|
+
Rim.setup do |p|
|
10
|
+
p.name = 'mini_exiftool'
|
11
|
+
p.version = MiniExiftool::VERSION
|
12
|
+
p.authors = 'Jan Friedrich'
|
6
13
|
p.email = 'janfri26@gmail.com'
|
7
14
|
p.summary = 'This library is wrapper for the Exiftool command-line application (http://www.sno.phy.queensu.ca/~phil/exiftool).'
|
8
|
-
p.
|
9
|
-
p.rdoc_files = %w(README.rdoc Tutorial.rdoc lib/*.rb)
|
15
|
+
p.homepage = 'http://gitorious.org/mini_exiftool'
|
10
16
|
p.install_message = %q{
|
11
17
|
+-----------------------------------------------------------------------+
|
12
18
|
| Please ensure you have installed exiftool and it's found in your PATH |
|
@@ -14,12 +20,4 @@ Echoe.new('mini_exiftool') do |p|
|
|
14
20
|
| http://www.sno.phy.queensu.ca/~phil/exiftool/install.html |
|
15
21
|
+-----------------------------------------------------------------------+
|
16
22
|
}
|
17
|
-
p.changelog = 'Changelog'
|
18
|
-
task :prerelease do
|
19
|
-
require "#{File.dirname(__FILE__)}/lib/mini_exiftool"
|
20
|
-
unless p.version == MiniExiftool::VERSION
|
21
|
-
$stderr.puts "Version conflict: Release version is #{p.version} but MiniExiftool::VERSION is #{MiniExiftool::VERSION}."
|
22
|
-
exit(1)
|
23
|
-
end
|
24
|
-
end
|
25
23
|
end
|
data/lib/mini_exiftool.rb
CHANGED
@@ -33,7 +33,7 @@ class MiniExiftool
|
|
33
33
|
attr_reader :filename
|
34
34
|
attr_accessor :numerical, :composite, :convert_encoding, :ignore_minor_errors, :errors, :timestamps
|
35
35
|
|
36
|
-
VERSION = '1.
|
36
|
+
VERSION = '1.6.0'
|
37
37
|
|
38
38
|
# +opts+ support at the moment
|
39
39
|
# * <code>:numerical</code> for numerical values, default is +false+
|
@@ -65,7 +65,7 @@ class MiniExiftool
|
|
65
65
|
|
66
66
|
def initialize_from_hash hash # :nodoc:
|
67
67
|
hash.each_pair do |tag,value|
|
68
|
-
set_value tag, value
|
68
|
+
set_value tag, perform_conversions(value)
|
69
69
|
end
|
70
70
|
set_attributes_by_heuristic
|
71
71
|
self
|
@@ -73,6 +73,7 @@ class MiniExiftool
|
|
73
73
|
|
74
74
|
# Load the tags of filename.
|
75
75
|
def load filename
|
76
|
+
MiniExiftool.setup
|
76
77
|
unless filename && File.exist?(filename)
|
77
78
|
raise MiniExiftool::Error.new("File '#{filename}' does not exist.")
|
78
79
|
end
|
@@ -145,6 +146,7 @@ class MiniExiftool
|
|
145
146
|
|
146
147
|
# Save the changes to the file.
|
147
148
|
def save
|
149
|
+
MiniExiftool.setup
|
148
150
|
return false if @changed_values.empty?
|
149
151
|
@errors.clear
|
150
152
|
temp_file = Tempfile.new('mini_exiftool')
|
@@ -182,6 +184,16 @@ class MiniExiftool
|
|
182
184
|
all_ok
|
183
185
|
end
|
184
186
|
|
187
|
+
def save!
|
188
|
+
unless save
|
189
|
+
err = []
|
190
|
+
self.errors.each do |key, value|
|
191
|
+
err << "(#{key}) #{value}"
|
192
|
+
end
|
193
|
+
raise MiniExiftool::Error.new("MiniExiftool couldn't save. The following errors occurred: #{err.empty? ? "None" : err.join(", ")}")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
185
197
|
# Returns a hash of the original loaded values of the MiniExiftool
|
186
198
|
# instance.
|
187
199
|
def to_hash
|
@@ -198,7 +210,7 @@ class MiniExiftool
|
|
198
210
|
to_hash.to_yaml
|
199
211
|
end
|
200
212
|
|
201
|
-
# Create a MiniExiftool instance from a hash
|
213
|
+
# Create a MiniExiftool instance from a hash. Default value conversions will be applied if neccesary.
|
202
214
|
def self.from_hash hash
|
203
215
|
instance = MiniExiftool.new
|
204
216
|
instance.initialize_from_hash hash
|
@@ -270,15 +282,20 @@ class MiniExiftool
|
|
270
282
|
private
|
271
283
|
############################################################################
|
272
284
|
|
273
|
-
@@
|
274
|
-
|
285
|
+
@@setup_done = false
|
286
|
+
def self.setup
|
287
|
+
return if @@setup_done
|
288
|
+
@@error_file = Tempfile.new 'errors'
|
289
|
+
@@error_file.close
|
275
290
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
291
|
+
if Float(exiftool_version) < 7.41
|
292
|
+
@@separator = ', '
|
293
|
+
@@sep_op = ''
|
294
|
+
else
|
295
|
+
@@separator = '@@'
|
296
|
+
@@sep_op = '-sep @@'
|
297
|
+
end
|
298
|
+
@@setup_done = true
|
282
299
|
end
|
283
300
|
|
284
301
|
def run cmd
|
@@ -325,7 +342,14 @@ class MiniExiftool
|
|
325
342
|
|
326
343
|
def parse_line line
|
327
344
|
if line =~ /^([^\t]+)\t(.*)$/
|
328
|
-
tag, value = $1, $2
|
345
|
+
tag, value = $1, perform_conversions($2)
|
346
|
+
else
|
347
|
+
raise MiniExiftool::Error.new("Malformed line #{line.inspect} of exiftool output.")
|
348
|
+
end
|
349
|
+
return [tag, value]
|
350
|
+
end
|
351
|
+
|
352
|
+
def perform_conversions(value)
|
329
353
|
case value
|
330
354
|
when /^\d{4}:\d\d:\d\d \d\d:\d\d:\d\d/
|
331
355
|
s = value.sub(/^(\d+):(\d+):/, '\1-\2-')
|
@@ -353,10 +377,7 @@ class MiniExiftool
|
|
353
377
|
when /#{@@separator}/
|
354
378
|
value = value.split @@separator
|
355
379
|
end
|
356
|
-
|
357
|
-
raise MiniExiftool::Error.new("Malformed line #{line.inspect} of exiftool output.")
|
358
|
-
end
|
359
|
-
return [tag, value]
|
380
|
+
value
|
360
381
|
end
|
361
382
|
|
362
383
|
def set_value tag, value
|
Binary file
|
@@ -0,0 +1,106 @@
|
|
1
|
+
[{
|
2
|
+
"SourceFile": "test/data/test.jpg",
|
3
|
+
"ExifToolVersion": 8.77,
|
4
|
+
"FileName": "test.jpg",
|
5
|
+
"Directory": "test/data",
|
6
|
+
"FileSize": "46 kB",
|
7
|
+
"FileModifyDate": "2012:07:05 20:28:24-07:00",
|
8
|
+
"FilePermissions": "rw-r--r--",
|
9
|
+
"FileType": "JPEG",
|
10
|
+
"MIMEType": "image/jpeg",
|
11
|
+
"JFIFVersion": 1.01,
|
12
|
+
"ExifByteOrder": "Big-endian (Motorola, MM)",
|
13
|
+
"ImageDescription": "KONICA MINOLTA DIGITAL CAMERA",
|
14
|
+
"Make": "KONICA MINOLTA",
|
15
|
+
"Model": "DYNAX 7D",
|
16
|
+
"Orientation": "Horizontal (normal)",
|
17
|
+
"XResolution": 72,
|
18
|
+
"YResolution": 72,
|
19
|
+
"ResolutionUnit": "inches",
|
20
|
+
"Software": "DYNAX 7D v1.10",
|
21
|
+
"ModifyDate": "2005:09:13 20:08:50",
|
22
|
+
"YCbCrPositioning": "Centered",
|
23
|
+
"ExposureTime": "1/60",
|
24
|
+
"FNumber": 9.5,
|
25
|
+
"ExposureProgram": "Program AE",
|
26
|
+
"ISO": 400,
|
27
|
+
"ExifVersion": "0221",
|
28
|
+
"DateTimeOriginal": "2005:09:13 20:08:50",
|
29
|
+
"CreateDate": "2005:09:13 20:08:50",
|
30
|
+
"ComponentsConfiguration": "Y, Cb, Cr, -",
|
31
|
+
"BrightnessValue": 4.5,
|
32
|
+
"ExposureCompensation": -1,
|
33
|
+
"MaxApertureValue": 4.5,
|
34
|
+
"MeteringMode": "Multi-segment",
|
35
|
+
"LightSource": "Unknown",
|
36
|
+
"Flash": "Off, Did not fire",
|
37
|
+
"FocalLength": "75.0 mm",
|
38
|
+
"SubjectArea": "1504 1000 256 304",
|
39
|
+
"MakerNoteVersion": "MLT0",
|
40
|
+
"MinoltaImageSize": "Large",
|
41
|
+
"WhiteBalance": "Auto",
|
42
|
+
"FocusMode": "AF-A",
|
43
|
+
"AFPoints": "Center",
|
44
|
+
"FlashMode": "Normal",
|
45
|
+
"ISOSetting": 400,
|
46
|
+
"FreeMemoryCardImages": 202,
|
47
|
+
"HueAdjustment": 0,
|
48
|
+
"Rotation": "Horizontal (normal)",
|
49
|
+
"ImageNumber": 6,
|
50
|
+
"NoiseReduction": "Unknown (2)",
|
51
|
+
"ImageNumber2": 50,
|
52
|
+
"ZoneMatchingOn": "Off",
|
53
|
+
"CompressedImageSize": 1598477,
|
54
|
+
"PreviewImageStart": 39152,
|
55
|
+
"PreviewImageLength": 0,
|
56
|
+
"SceneMode": "Standard",
|
57
|
+
"ColorMode": "Natural sRGB",
|
58
|
+
"MinoltaQuality": "Fine",
|
59
|
+
"FlashExposureComp": 0,
|
60
|
+
"Teleconverter": "None",
|
61
|
+
"ImageStabilization": "On",
|
62
|
+
"ZoneMatching": "ISO Setting Used",
|
63
|
+
"ColorTemperature": 0,
|
64
|
+
"LensType": "Minolta AF 28-135mm F4-4.5 or Sigma Lens",
|
65
|
+
"UserComment": "",
|
66
|
+
"FlashpixVersion": "0100",
|
67
|
+
"ColorSpace": "sRGB",
|
68
|
+
"ExifImageWidth": 3008,
|
69
|
+
"ExifImageHeight": 2000,
|
70
|
+
"CustomRendered": "Normal",
|
71
|
+
"ExposureMode": "Auto",
|
72
|
+
"DigitalZoomRatio": 0,
|
73
|
+
"FocalLengthIn35mmFormat": "112 mm",
|
74
|
+
"SceneCaptureType": "Standard",
|
75
|
+
"GainControl": "Low gain up",
|
76
|
+
"Contrast": "Normal",
|
77
|
+
"Saturation": "Normal",
|
78
|
+
"Sharpness": "Normal",
|
79
|
+
"PrintIMVersion": "0300",
|
80
|
+
"Compression": "JPEG (old-style)",
|
81
|
+
"ThumbnailOffset": 39274,
|
82
|
+
"ThumbnailLength": 1820,
|
83
|
+
"CurrentIPTCDigest": "dd8d51d28ddf04f08f870e5ff2f64d01",
|
84
|
+
"Keywords": ["Orange","Rot"],
|
85
|
+
"ApplicationRecordVersion": 4,
|
86
|
+
"SupplementalCategories": "Natur",
|
87
|
+
"XMPToolkit": "Image::ExifTool 7.03",
|
88
|
+
"Title": "Abenddämmerung",
|
89
|
+
"ImageWidth": 300,
|
90
|
+
"ImageHeight": 199,
|
91
|
+
"EncodingProcess": "Baseline DCT, Huffman coding",
|
92
|
+
"BitsPerSample": 8,
|
93
|
+
"ColorComponents": 3,
|
94
|
+
"YCbCrSubSampling": "YCbCr4:2:0 (2 2)",
|
95
|
+
"Aperture": 9.5,
|
96
|
+
"ImageSize": "300x199",
|
97
|
+
"LensID": "Minolta AF 28-135mm F4-4.5",
|
98
|
+
"ScaleFactor35efl": 1.5,
|
99
|
+
"ShutterSpeed": "1/60",
|
100
|
+
"ThumbnailImage": "(Binary data 1820 bytes)",
|
101
|
+
"CircleOfConfusion": "0.020 mm",
|
102
|
+
"FOV": "18.3 deg",
|
103
|
+
"FocalLength35efl": "75.0 mm (35 mm equivalent: 112.0 mm)",
|
104
|
+
"HyperfocalDistance": "29.43 m",
|
105
|
+
"LightValue": 10.4
|
106
|
+
}]
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'helpers_for_test'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class TestFromHash < TestCase
|
5
|
+
def setup
|
6
|
+
@data_dir = File.dirname(__FILE__) + '/data'
|
7
|
+
hash_data = JSON.parse(File.read( @data_dir + '/test.jpg.json')).first
|
8
|
+
@mini_exiftool = MiniExiftool.from_hash hash_data
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_conversion
|
12
|
+
assert_kind_of String, @mini_exiftool.model
|
13
|
+
assert_kind_of Time, @mini_exiftool['DateTimeOriginal']
|
14
|
+
assert_kind_of Float, @mini_exiftool['MaxApertureValue']
|
15
|
+
assert_kind_of String, @mini_exiftool.flash
|
16
|
+
assert_kind_of Fixnum, @mini_exiftool['ExposureCompensation']
|
17
|
+
assert_kind_of String, (@mini_exiftool['SubjectLocation'] || @mini_exiftool['SubjectArea'])
|
18
|
+
assert_kind_of Array, @mini_exiftool['Keywords']
|
19
|
+
assert_kind_of String, @mini_exiftool['SupplementalCategories']
|
20
|
+
assert_kind_of Rational, @mini_exiftool.shutterspeed
|
21
|
+
end
|
22
|
+
end
|