multi_exiftool 0.12.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.aspell.pws +2 -1
- data/Changelog +17 -0
- data/README.md +51 -3
- data/Rakefile +3 -3
- data/lib/multi_exiftool.rb +29 -15
- data/lib/multi_exiftool/batch.rb +42 -0
- data/lib/multi_exiftool/executable.rb +12 -5
- data/lib/multi_exiftool/reader.rb +11 -3
- data/lib/multi_exiftool/writer.rb +3 -3
- data/multi_exiftool.gemspec +7 -7
- data/regtest/read_all_tags.yml +1 -1
- data/test/data/example.config +363 -0
- data/test/test_batch.rb +42 -0
- data/test/test_functional_api.rb +101 -0
- data/test/test_reader.rb +14 -0
- data/test/test_values.rb +5 -5
- metadata +10 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43d4f9d91d7d4c6321b5e9698e3aaecc38fd1044e140110f5e4ff22fdf15ee96
|
4
|
+
data.tar.gz: a9ff99dd7943f29ce6219f75a3dad31ce06c3e4abf458e50aa6c9e8903660022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 648a9ba62793a9c0215c06cc701935bd123612d7491be111e0e96398e9f2bcc42399f2bf42591ce70c2722579e04d113394832c337ca04674036c2b93f014f2b
|
7
|
+
data.tar.gz: 17d5d839ba13f1a07f2ec586c78b68bb950e54f2e6f67f2288fcdb01dda5f5ff341db462b8d103fa510eb5eb190080cf883c8d85de16fdcda89aee994414cd4a
|
data/.aspell.pws
CHANGED
data/Changelog
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
0.16.0
|
2
|
+
Add option to use config files.
|
3
|
+
|
4
|
+
0.15.0
|
5
|
+
Make multi_exiftool work with Ruby 1.9 again.
|
6
|
+
|
7
|
+
0.14.1
|
8
|
+
Fix two typos.
|
9
|
+
|
10
|
+
0.14.0
|
11
|
+
Improve api for batch processing.
|
12
|
+
|
13
|
+
0.13.0
|
14
|
+
Implement batch processing to allow to write different values to multiple file
|
15
|
+
with only one call of the ExifTool command-line application.
|
16
|
+
Update documentation.
|
17
|
+
|
1
18
|
0.12.0
|
2
19
|
Implement Values#respond_to_missing?.
|
3
20
|
Improve documentation and fix example code.
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
## Description
|
4
4
|
|
5
5
|
This library is a wrapper for the ExifTool command-line application
|
6
|
-
(
|
6
|
+
(https://exiftool.org) written by Phil Harvey.
|
7
7
|
It is designed for dealing with multiple files at once by creating
|
8
8
|
commands to call exiftool with various arguments, call it and parsing
|
9
9
|
the results.
|
@@ -60,6 +60,54 @@ else
|
|
60
60
|
end
|
61
61
|
```
|
62
62
|
|
63
|
+
If it is necessary to write different values to multiple files there is batch processing
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'multi_exiftool'
|
67
|
+
|
68
|
+
# Object oriented approach
|
69
|
+
|
70
|
+
batch = MultiExiftool::Batch.new
|
71
|
+
Dir['*.jpg'].each_with_index do |filename, i|
|
72
|
+
values = {creator: 'Jan Friedrich', copyright: 'Public Domain', comment: "This is file number #{i+1}."}
|
73
|
+
batch.write filename, values
|
74
|
+
end
|
75
|
+
if batch.execute
|
76
|
+
puts 'ok'
|
77
|
+
else
|
78
|
+
puts batch.errors
|
79
|
+
end
|
80
|
+
|
81
|
+
# Functional approach
|
82
|
+
|
83
|
+
errors = MultiExiftool.batch do
|
84
|
+
Dir['*.jpg'].each_with_index do |filename, i|
|
85
|
+
values = {creator: 'Jan Friedrich', copyright: 'Public Domain', comment: "This is file number #{i+1}."}
|
86
|
+
write filename, values
|
87
|
+
end
|
88
|
+
end
|
89
|
+
if errors.empty?
|
90
|
+
puts 'ok'
|
91
|
+
else
|
92
|
+
puts errors
|
93
|
+
end
|
94
|
+
|
95
|
+
# or alternative with block parameter as yielded Batch instance
|
96
|
+
|
97
|
+
errors = MultiExiftool.batch do |batch|
|
98
|
+
Dir['*.jpg'].each_with_index do |filename, i|
|
99
|
+
values = {creator: 'Jan Friedrich', copyright: 'Public Domain', comment: "This is file number #{i+1}."}
|
100
|
+
batch.write filename, values
|
101
|
+
end
|
102
|
+
end
|
103
|
+
if errors.empty?
|
104
|
+
puts 'ok'
|
105
|
+
else
|
106
|
+
puts errors
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
|
63
111
|
### Deleting
|
64
112
|
|
65
113
|
```ruby
|
@@ -153,7 +201,7 @@ The method Values#convert is called each time a value is fetched.
|
|
153
201
|
- Ruby 1.9.1 or higher
|
154
202
|
- An installation of the ExifTool command-line application (version 7.65 or
|
155
203
|
higher). Instructions for installation you can find under
|
156
|
-
|
204
|
+
https://exiftool.org/install.html .
|
157
205
|
- If you have problems with special characters (like German umlauts) in
|
158
206
|
filenames on windows system it is recommended to use exiftool version 9.79
|
159
207
|
or higher.
|
@@ -185,7 +233,7 @@ SemVerTag.
|
|
185
233
|
|
186
234
|
## Author
|
187
235
|
|
188
|
-
Jan Friedrich <
|
236
|
+
Jan Friedrich <janfri26@gmail.com>
|
189
237
|
|
190
238
|
## MIT License
|
191
239
|
|
data/Rakefile
CHANGED
@@ -11,8 +11,8 @@ Rim.setup do |p|
|
|
11
11
|
p.version = MultiExiftool::VERSION
|
12
12
|
p.authors = 'Jan Friedrich'
|
13
13
|
p.email = 'janfri26@gmail.com'
|
14
|
-
p.summary = 'This library is a wrapper for the ExifTool command-line application (
|
15
|
-
p.description = 'This library a
|
14
|
+
p.summary = 'This library is a wrapper for the ExifTool command-line application (https://exiftool.org).'
|
15
|
+
p.description = 'This library is a wrapper for the ExifTool command-line application (https://exiftool.org) written by Phil Harvey. It is designed for dealing with multiple files at once by creating commands to call exiftool with various arguments, call it and parsing the results.'
|
16
16
|
p.ruby_version = '>=1.9.1'
|
17
17
|
p.license = 'MIT'
|
18
18
|
p.homepage = 'https://github.com/janfri/multi_exiftool'
|
@@ -21,7 +21,7 @@ Rim.setup do |p|
|
|
21
21
|
| Please ensure you have installed exiftool version 7.65 or higher and |
|
22
22
|
| it's found in your PATH (Try "exiftool -ver" on your commandline). |
|
23
23
|
| For more details see |
|
24
|
-
|
|
24
|
+
| https://exiftool.org/install.html |
|
25
25
|
+-----------------------------------------------------------------------+
|
26
26
|
}
|
27
27
|
p.development_dependencies << %w(contest ~>0.1)
|
data/lib/multi_exiftool.rb
CHANGED
@@ -4,10 +4,11 @@
|
|
4
4
|
require_relative 'multi_exiftool/values'
|
5
5
|
require_relative 'multi_exiftool/reader'
|
6
6
|
require_relative 'multi_exiftool/writer'
|
7
|
+
require_relative 'multi_exiftool/batch'
|
7
8
|
|
8
9
|
module MultiExiftool
|
9
10
|
|
10
|
-
VERSION = '0.
|
11
|
+
VERSION = '0.16.0'
|
11
12
|
|
12
13
|
@exiftool_command = 'exiftool'
|
13
14
|
|
@@ -25,15 +26,7 @@ module MultiExiftool
|
|
25
26
|
# # error handling
|
26
27
|
# end
|
27
28
|
def read filenames, opts={}
|
28
|
-
reader = Reader.new
|
29
|
-
reader.filenames = filenames
|
30
|
-
if val = opts.delete(:tags)
|
31
|
-
reader.tags = val
|
32
|
-
end
|
33
|
-
if val = opts.delete(:group)
|
34
|
-
reader.group = val
|
35
|
-
end
|
36
|
-
reader.options = opts unless opts.empty?
|
29
|
+
reader = Reader.new(filenames, opts)
|
37
30
|
values = reader.read
|
38
31
|
[values, reader.errors]
|
39
32
|
end
|
@@ -47,10 +40,7 @@ module MultiExiftool
|
|
47
40
|
# # do error handling
|
48
41
|
# end
|
49
42
|
def write filenames, values, opts={}
|
50
|
-
writer = Writer.new
|
51
|
-
writer.filenames = filenames
|
52
|
-
writer.values = values
|
53
|
-
writer.options = opts unless opts.empty?
|
43
|
+
writer = Writer.new(filenames, values, opts)
|
54
44
|
writer.write
|
55
45
|
writer.errors
|
56
46
|
end
|
@@ -70,11 +60,35 @@ module MultiExiftool
|
|
70
60
|
# unless errors.empty?
|
71
61
|
# # do error handling
|
72
62
|
# end
|
73
|
-
def delete_values filenames,
|
63
|
+
def delete_values filenames, opts={}
|
64
|
+
tags = opts.fetch(:tags, :all)
|
74
65
|
values = Array(tags).inject(Hash.new) {|h,tag| h[tag] = nil; h}
|
75
66
|
write(filenames, values)
|
76
67
|
end
|
77
68
|
|
69
|
+
|
70
|
+
# Execute a batch of write commands
|
71
|
+
# Returns an array of the error messages
|
72
|
+
#
|
73
|
+
# Example:
|
74
|
+
# errors = MultiExiftool.batch do
|
75
|
+
# Dir['*.jpg'].each_with_index do |filename, i|
|
76
|
+
# write filename, {author: 'Jan Friedrich', comment: "This is file number #{i+1}."}
|
77
|
+
# end
|
78
|
+
# unless errors.empty?
|
79
|
+
# # do error handling
|
80
|
+
# end
|
81
|
+
def batch &block
|
82
|
+
batch = Batch.new
|
83
|
+
if block.arity == 0
|
84
|
+
batch.instance_exec &block
|
85
|
+
else
|
86
|
+
yield batch
|
87
|
+
end
|
88
|
+
batch.execute
|
89
|
+
batch.errors
|
90
|
+
end
|
91
|
+
|
78
92
|
attr_accessor :exiftool_command
|
79
93
|
attr_reader :exiftool_version
|
80
94
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'executable'
|
5
|
+
|
6
|
+
module MultiExiftool
|
7
|
+
|
8
|
+
# Allow to define a batch for different writing operations as one call of the
|
9
|
+
# ExifTool command-line application
|
10
|
+
class Batch
|
11
|
+
|
12
|
+
include Executable
|
13
|
+
|
14
|
+
# Define batch operation inside a block
|
15
|
+
def initialize &blk
|
16
|
+
@writers = []
|
17
|
+
instance_exec &blk if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
# Define a write operation for the batch.
|
21
|
+
def write filenames, values, options={}
|
22
|
+
w = MultiExiftool::Writer.new(filenames, values, options)
|
23
|
+
@writers << w
|
24
|
+
end
|
25
|
+
|
26
|
+
# Getting the command-line arguments which would be executed
|
27
|
+
# when calling #write. It could be useful for logging, debugging or
|
28
|
+
# whatever.
|
29
|
+
def exiftool_args
|
30
|
+
@writers.map {|w| w.exiftool_args + ['-execute']}.flatten
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parse_results
|
36
|
+
@errors = @stderr.read.split(/\n/)
|
37
|
+
@errors.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -9,12 +9,15 @@ module MultiExiftool
|
|
9
9
|
module Executable
|
10
10
|
|
11
11
|
attr_reader :errors
|
12
|
-
attr_accessor :filenames, :numerical, :options
|
12
|
+
attr_accessor :config, :filenames, :numerical, :options
|
13
13
|
|
14
|
-
def initialize
|
15
|
-
@options =
|
16
|
-
@filenames =
|
14
|
+
def initialize filenames=[], options={}
|
15
|
+
@options = options
|
16
|
+
@filenames = filenames
|
17
17
|
@option_mapping = {numerical: :n}
|
18
|
+
if val = options.delete(:config)
|
19
|
+
@config = val
|
20
|
+
end
|
18
21
|
end
|
19
22
|
|
20
23
|
def options
|
@@ -57,7 +60,11 @@ module MultiExiftool
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def execute_command
|
60
|
-
|
63
|
+
args = ['-@', '-']
|
64
|
+
if @config
|
65
|
+
args = ['-config', @config] + args
|
66
|
+
end
|
67
|
+
stdin, @stdout, @stderr = Open3.popen3(exiftool_command, *args)
|
61
68
|
exiftool_args.each do |part|
|
62
69
|
stdin << part
|
63
70
|
stdin << "\n"
|
@@ -15,9 +15,17 @@ module MultiExiftool
|
|
15
15
|
|
16
16
|
include Executable
|
17
17
|
|
18
|
-
def initialize
|
19
|
-
super
|
20
|
-
|
18
|
+
def initialize filenames=[], opts={}
|
19
|
+
super(filenames, opts)
|
20
|
+
if val = opts.delete(:tags)
|
21
|
+
@tags = val
|
22
|
+
else
|
23
|
+
@tags = []
|
24
|
+
end
|
25
|
+
if val = opts.delete(:group)
|
26
|
+
@group = val
|
27
|
+
end
|
28
|
+
@options = opts unless opts.empty?
|
21
29
|
end
|
22
30
|
|
23
31
|
def self.mandatory_args
|
data/multi_exiftool.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: multi_exiftool 0.
|
2
|
+
# stub: multi_exiftool 0.16.0 ruby lib
|
3
3
|
#
|
4
4
|
# This file is automatically generated by rim.
|
5
5
|
# PLEASE DO NOT EDIT IT DIRECTLY!
|
@@ -7,22 +7,22 @@
|
|
7
7
|
|
8
8
|
Gem::Specification.new do |s|
|
9
9
|
s.name = "multi_exiftool"
|
10
|
-
s.version = "0.
|
10
|
+
s.version = "0.16.0"
|
11
11
|
|
12
12
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
13
13
|
s.require_paths = ["lib"]
|
14
14
|
s.authors = ["Jan Friedrich"]
|
15
|
-
s.date = "2020-
|
16
|
-
s.description = "This library a
|
15
|
+
s.date = "2020-10-27"
|
16
|
+
s.description = "This library is a wrapper for the ExifTool command-line application (https://exiftool.org) written by Phil Harvey. It is designed for dealing with multiple files at once by creating commands to call exiftool with various arguments, call it and parsing the results."
|
17
17
|
s.email = "janfri26@gmail.com"
|
18
|
-
s.files = ["./.aspell.pws", "Changelog", "Gemfile", "LICENSE", "README.md", "Rakefile", "lib/multi_exiftool", "lib/multi_exiftool.rb", "lib/multi_exiftool/executable.rb", "lib/multi_exiftool/reader.rb", "lib/multi_exiftool/values.rb", "lib/multi_exiftool/writer.rb", "multi_exiftool.gemspec", "regtest/read_all_tags.rb", "regtest/read_all_tags.yml", "regtest/test.jpg", "test/data", "test/data/a.jpg", "test/data/b.jpg", "test/data/c.jpg", "test/helper.rb", "test/test_executable.rb", "test/test_exiftool_stuff.rb", "test/test_functional_api.rb", "test/test_reader.rb", "test/test_values.rb", "test/test_values_using_groups.rb", "test/test_writer.rb", "test/test_writer_groups.rb"]
|
18
|
+
s.files = ["./.aspell.pws", "Changelog", "Gemfile", "LICENSE", "README.md", "Rakefile", "lib/multi_exiftool", "lib/multi_exiftool.rb", "lib/multi_exiftool/batch.rb", "lib/multi_exiftool/executable.rb", "lib/multi_exiftool/reader.rb", "lib/multi_exiftool/values.rb", "lib/multi_exiftool/writer.rb", "multi_exiftool.gemspec", "regtest/read_all_tags.rb", "regtest/read_all_tags.yml", "regtest/test.jpg", "test/data", "test/data/a.jpg", "test/data/b.jpg", "test/data/c.jpg", "test/data/example.config", "test/helper.rb", "test/test_batch.rb", "test/test_executable.rb", "test/test_exiftool_stuff.rb", "test/test_functional_api.rb", "test/test_reader.rb", "test/test_values.rb", "test/test_values_using_groups.rb", "test/test_writer.rb", "test/test_writer_groups.rb"]
|
19
19
|
s.homepage = "https://github.com/janfri/multi_exiftool"
|
20
20
|
s.licenses = ["MIT"]
|
21
|
-
s.post_install_message = "\n+-----------------------------------------------------------------------+\n| Please ensure you have installed exiftool version 7.65 or higher and |\n| it's found in your PATH (Try \"exiftool -ver\" on your commandline). |\n| For more details see |\n|
|
21
|
+
s.post_install_message = "\n+-----------------------------------------------------------------------+\n| Please ensure you have installed exiftool version 7.65 or higher and |\n| it's found in your PATH (Try \"exiftool -ver\" on your commandline). |\n| For more details see |\n| https://exiftool.org/install.html |\n+-----------------------------------------------------------------------+\n "
|
22
22
|
s.required_ruby_version = Gem::Requirement.new(">= 1.9.1")
|
23
23
|
s.requirements = ["exiftool, version 7.65 or higher"]
|
24
24
|
s.rubygems_version = "3.1.2"
|
25
|
-
s.summary = "This library is a wrapper for the ExifTool command-line application (
|
25
|
+
s.summary = "This library is a wrapper for the ExifTool command-line application (https://exiftool.org)."
|
26
26
|
|
27
27
|
if s.respond_to? :specification_version then
|
28
28
|
s.specification_version = 4
|
data/regtest/read_all_tags.yml
CHANGED
@@ -0,0 +1,363 @@
|
|
1
|
+
# Copied from https://exiftool.org/config.html
|
2
|
+
|
3
|
+
#------------------------------------------------------------------------------
|
4
|
+
# File: example.config
|
5
|
+
#
|
6
|
+
# Description: Example user configuration file for Image::ExifTool
|
7
|
+
#
|
8
|
+
# Notes: This example file shows how to define your own shortcuts and
|
9
|
+
# add new EXIF, IPTC, XMP, PNG, MIE and Composite tags, as well
|
10
|
+
# as how to specify preferred lenses for the LensID tag, and
|
11
|
+
# define new file types and default ExifTool option values.
|
12
|
+
#
|
13
|
+
# Note that unknown tags may be extracted even if they aren't
|
14
|
+
# defined, but tags must be defined to be written. Also note
|
15
|
+
# that it is possible to override an existing tag definition
|
16
|
+
# with a user-defined tag.
|
17
|
+
#
|
18
|
+
# To activate this file, rename it to ".ExifTool_config" and
|
19
|
+
# place it in your home directory or the exiftool application
|
20
|
+
# directory. (On Mac and some Windows systems this must be done
|
21
|
+
# via the command line since the GUI's may not allow filenames to
|
22
|
+
# begin with a dot. Use the "rename" command in Windows or "mv"
|
23
|
+
# on the Mac.) This causes ExifTool to automatically load the
|
24
|
+
# file when run. Your home directory is determined by the first
|
25
|
+
# defined of the following environment variables:
|
26
|
+
#
|
27
|
+
# 1. EXIFTOOL_HOME
|
28
|
+
# 2. HOME
|
29
|
+
# 3. HOMEDRIVE + HOMEPATH
|
30
|
+
# 4. (the current directory)
|
31
|
+
#
|
32
|
+
# Alternatively, the -config option of the exiftool application
|
33
|
+
# may be used to load a specific configuration file (note that
|
34
|
+
# this must be the first option on the command line):
|
35
|
+
#
|
36
|
+
# exiftool -config example.config ...
|
37
|
+
#
|
38
|
+
# This example file defines the following 16 new tags as well as
|
39
|
+
# a number of Shortcut and Composite tags:
|
40
|
+
#
|
41
|
+
# 1. EXIF:NewEXIFTag
|
42
|
+
# 2. GPS:GPSPitch
|
43
|
+
# 3. GPS:GPSRoll
|
44
|
+
# 4. IPTC:NewIPTCTag
|
45
|
+
# 5. XMP-xmp:NewXMPxmpTag
|
46
|
+
# 6. XMP-exif:GPSPitch
|
47
|
+
# 7. XMP-exif:GPSRoll
|
48
|
+
# 8. XMP-xxx:NewXMPxxxTag1
|
49
|
+
# 9. XMP-xxx:NewXMPxxxTag2
|
50
|
+
# 10. XMP-xxx:NewXMPxxxTag3
|
51
|
+
# 11. XMP-xxx:NewXMPxxxStruct
|
52
|
+
# 12. PNG:NewPngTag1
|
53
|
+
# 13. PNG:NewPngTag2
|
54
|
+
# 14. PNG:NewPngTag3
|
55
|
+
# 15. MIE-Meta:NewMieTag1
|
56
|
+
# 16. MIE-Test:NewMieTag2
|
57
|
+
#
|
58
|
+
# For detailed information on the definition of tag tables and
|
59
|
+
# tag information hashes, see lib/Image/ExifTool/README.
|
60
|
+
#------------------------------------------------------------------------------
|
61
|
+
|
62
|
+
# Shortcut tags are used when extracting information to simplify
|
63
|
+
# commonly used commands. They can be used to represent groups
|
64
|
+
# of tags, or to provide an alias for a tag name.
|
65
|
+
%Image::ExifTool::UserDefined::Shortcuts = (
|
66
|
+
MyShortcut => ['exif:createdate','exposuretime','aperture'],
|
67
|
+
MyAlias => 'FocalLengthIn35mmFormat',
|
68
|
+
);
|
69
|
+
|
70
|
+
# NOTE: All tag names used in the following tables are case sensitive.
|
71
|
+
|
72
|
+
# The %Image::ExifTool::UserDefined hash defines new tags to be added
|
73
|
+
# to existing tables.
|
74
|
+
%Image::ExifTool::UserDefined = (
|
75
|
+
# All EXIF tags are added to the Main table, and WriteGroup is used to
|
76
|
+
# specify where the tag is written (default is ExifIFD if not specified):
|
77
|
+
'Image::ExifTool::Exif::Main' => {
|
78
|
+
# Example 1. EXIF:NewEXIFTag
|
79
|
+
0xd000 => {
|
80
|
+
Name => 'NewEXIFTag',
|
81
|
+
Writable => 'int16u',
|
82
|
+
WriteGroup => 'IFD0',
|
83
|
+
},
|
84
|
+
# add more user-defined EXIF tags here...
|
85
|
+
},
|
86
|
+
# the Geotag feature writes these additional GPS tags if available:
|
87
|
+
'Image::ExifTool::GPS::Main' => {
|
88
|
+
# Example 2. GPS:GPSPitch
|
89
|
+
0xd000 => {
|
90
|
+
Name => 'GPSPitch',
|
91
|
+
Writable => 'rational64s',
|
92
|
+
},
|
93
|
+
# Example 3. GPS:GPSRoll
|
94
|
+
0xd001 => {
|
95
|
+
Name => 'GPSRoll',
|
96
|
+
Writable => 'rational64s',
|
97
|
+
},
|
98
|
+
},
|
99
|
+
# IPTC tags are added to a specific record type (eg. application record):
|
100
|
+
# (Note: IPTC tag ID's are limited to the range 0-255)
|
101
|
+
'Image::ExifTool::IPTC::ApplicationRecord' => {
|
102
|
+
# Example 4. IPTC:NewIPTCTag
|
103
|
+
160 => {
|
104
|
+
Name => 'NewIPTCTag',
|
105
|
+
Format => 'string[0,16]',
|
106
|
+
},
|
107
|
+
# add more user-defined IPTC ApplicationRecord tags here...
|
108
|
+
},
|
109
|
+
# XMP tags may be added to existing namespaces:
|
110
|
+
'Image::ExifTool::XMP::xmp' => {
|
111
|
+
# Example 5. XMP-xmp:NewXMPxmpTag
|
112
|
+
NewXMPxmpTag => { Groups => { 2 => 'Author' } },
|
113
|
+
# add more user-defined XMP-xmp tags here...
|
114
|
+
},
|
115
|
+
# special Geotag tags for XMP-exif:
|
116
|
+
'Image::ExifTool::XMP::exif' => {
|
117
|
+
# Example 6. XMP-exif:GPSPitch
|
118
|
+
GPSPitch => { Writable => 'rational', Groups => { 2 => 'Location' } },
|
119
|
+
# Example 7. XMP-exif:GPSRoll
|
120
|
+
GPSRoll => { Writable => 'rational', Groups => { 2 => 'Location' } },
|
121
|
+
},
|
122
|
+
# new XMP namespaces (eg. xxx) must be added to the Main XMP table:
|
123
|
+
'Image::ExifTool::XMP::Main' => {
|
124
|
+
# namespace definition for examples 8 to 11
|
125
|
+
xxx => { # <-- must be the same as the NAMESPACE prefix
|
126
|
+
SubDirectory => {
|
127
|
+
TagTable => 'Image::ExifTool::UserDefined::xxx',
|
128
|
+
# (see the definition of this table below)
|
129
|
+
},
|
130
|
+
},
|
131
|
+
# add more user-defined XMP namespaces here...
|
132
|
+
},
|
133
|
+
# new PNG tags are added to the PNG::TextualData table:
|
134
|
+
'Image::ExifTool::PNG::TextualData' => {
|
135
|
+
# Example 12. PNG:NewPngTag1
|
136
|
+
NewPngTag1 => { },
|
137
|
+
# Example 13. PNG:NewPngTag2
|
138
|
+
NewPngTag2 => { },
|
139
|
+
# Example 14. PNG:NewPngTag3
|
140
|
+
NewPngTag3 => { },
|
141
|
+
},
|
142
|
+
# add a new MIE tag (NewMieTag1) and group (MIE-Test) to MIE-Meta
|
143
|
+
# (Note: MIE group names must NOT end with a number)
|
144
|
+
'Image::ExifTool::MIE::Meta' => {
|
145
|
+
# Example 15. MIE-Meta:NewMieTag1
|
146
|
+
NewMieTag1 => {
|
147
|
+
Writable => 'rational64u',
|
148
|
+
Units => [ 'cm', 'in' ],
|
149
|
+
},
|
150
|
+
# new MIE "Test" group for example 16
|
151
|
+
Test => {
|
152
|
+
SubDirectory => {
|
153
|
+
TagTable => 'Image::ExifTool::UserDefined::MIETest',
|
154
|
+
DirName => 'MIE-Test',
|
155
|
+
},
|
156
|
+
},
|
157
|
+
},
|
158
|
+
# Composite tags are added to the Composite table:
|
159
|
+
'Image::ExifTool::Composite' => {
|
160
|
+
# Composite tags have values that are derived from the values of
|
161
|
+
# other tags. The Require/Desire elements below specify constituent
|
162
|
+
# tags that must/may exist, and the keys of these hashes are used as
|
163
|
+
# indices in the @val array of the ValueConv expression to access the
|
164
|
+
# numerical (-n) values of these tags. Print-converted values are
|
165
|
+
# accessed via the @prt array. All Require'd tags must exist for
|
166
|
+
# the Composite tag to be evaluated. If no Require'd tags are
|
167
|
+
# specified, then at least one of the Desire'd tags must exist. See
|
168
|
+
# the Composite table in Image::ExifTool::Exif for more examples,
|
169
|
+
# and lib/Image/ExifTool/README for all of the details.
|
170
|
+
BaseName => {
|
171
|
+
Require => {
|
172
|
+
0 => 'FileName',
|
173
|
+
},
|
174
|
+
# remove the extension from FileName
|
175
|
+
ValueConv => '$val[0] =~ /(.*)\./ ? $1 : $val[0]',
|
176
|
+
},
|
177
|
+
# the next few examples demonstrate simplifications which may be
|
178
|
+
# used if only one tag is Require'd or Desire'd:
|
179
|
+
# 1) the Require lookup may be replaced with a simple tag name
|
180
|
+
# 2) "$val" may be used to represent "$val[0]" in the expression
|
181
|
+
FileExtension => {
|
182
|
+
Require => 'FileName',
|
183
|
+
ValueConv => '$val=~/\.([^.]*)$/; $1',
|
184
|
+
},
|
185
|
+
# override CircleOfConfusion tag to use D/1750 instead of D/1440
|
186
|
+
CircleOfConfusion => {
|
187
|
+
Require => 'ScaleFactor35efl',
|
188
|
+
Groups => { 2 => 'Camera' },
|
189
|
+
ValueConv => 'sqrt(24*24+36*36) / ($val * 1750)',
|
190
|
+
# an optional PrintConv may be used to format the value
|
191
|
+
PrintConv => 'sprintf("%.3f mm",$val)',
|
192
|
+
},
|
193
|
+
# generate a description for this file type
|
194
|
+
FileTypeDescription => {
|
195
|
+
Require => 'FileType',
|
196
|
+
ValueConv => 'GetFileType($val,1) || $val',
|
197
|
+
},
|
198
|
+
# calculate physical image size based on resolution
|
199
|
+
PhysicalImageSize => {
|
200
|
+
Require => {
|
201
|
+
0 => 'ImageWidth',
|
202
|
+
1 => 'ImageHeight',
|
203
|
+
2 => 'XResolution',
|
204
|
+
3 => 'YResolution',
|
205
|
+
4 => 'ResolutionUnit',
|
206
|
+
},
|
207
|
+
ValueConv => '$val[0]/$val[2] . " " . $val[1]/$val[3]',
|
208
|
+
# (the @prt array contains print-formatted values)
|
209
|
+
PrintConv => 'sprintf("%.1fx%.1f $prt[4]", split(" ",$val))',
|
210
|
+
},
|
211
|
+
# [advanced] select largest JPEG preview image
|
212
|
+
BigImage => {
|
213
|
+
Groups => { 2 => 'Preview' },
|
214
|
+
Desire => {
|
215
|
+
0 => 'JpgFromRaw',
|
216
|
+
1 => 'PreviewImage',
|
217
|
+
2 => 'OtherImage',
|
218
|
+
# (DNG and A100 ARW may be have 2 PreviewImage's)
|
219
|
+
3 => 'PreviewImage (1)',
|
220
|
+
# (if the MPF has 2 previews, MPImage3 could be the larger one)
|
221
|
+
4 => 'MPImage3',
|
222
|
+
},
|
223
|
+
# ValueConv may also be a code reference
|
224
|
+
# Inputs: 0) reference to list of values, 1) ExifTool object
|
225
|
+
ValueConv => sub {
|
226
|
+
my $val = shift;
|
227
|
+
my ($image, $bigImage, $len, $bigLen);
|
228
|
+
foreach $image (@$val) {
|
229
|
+
next unless ref $image eq 'SCALAR';
|
230
|
+
# check for JPEG image (or "Binary data" if -b not used)
|
231
|
+
next unless $$image =~ /^(\xff\xd8\xff|Binary data (\d+))/;
|
232
|
+
$len = $2 || length $$image; # get image length
|
233
|
+
# save largest image
|
234
|
+
next if defined $bigLen and $bigLen >= $len;
|
235
|
+
$bigLen = $len;
|
236
|
+
$bigImage = $image;
|
237
|
+
}
|
238
|
+
return $bigImage;
|
239
|
+
},
|
240
|
+
},
|
241
|
+
# **** ADD ADDITIONAL COMPOSITE TAG DEFINITIONS HERE ****
|
242
|
+
},
|
243
|
+
);
|
244
|
+
|
245
|
+
# This is a basic example of the definition for a new XMP namespace.
|
246
|
+
# This table is referenced through a SubDirectory tag definition
|
247
|
+
# in the %Image::ExifTool::UserDefined definition above.
|
248
|
+
# The namespace prefix for these tags is 'xxx', which corresponds to
|
249
|
+
# an ExifTool family 1 group name of 'XMP-xxx'.
|
250
|
+
%Image::ExifTool::UserDefined::xxx = (
|
251
|
+
GROUPS => { 0 => 'XMP', 1 => 'XMP-xxx', 2 => 'Image' },
|
252
|
+
NAMESPACE => { 'xxx' => 'http://ns.myname.com/xxx/1.0/' },
|
253
|
+
WRITABLE => 'string', # (default to string-type tags)
|
254
|
+
# Example 8. XMP-xxx:NewXMPxxxTag1 (an alternate-language tag)
|
255
|
+
# - replace "NewXMPxxxTag1" with your own tag name (eg. "MyTag")
|
256
|
+
NewXMPxxxTag1 => { Writable => 'lang-alt' },
|
257
|
+
# Example 9. XMP-xxx:NewXMPxxxTag2 (a string tag in the Author category)
|
258
|
+
NewXMPxxxTag2 => { Groups => { 2 => 'Author' } },
|
259
|
+
# Example 10. XMP-xxx:NewXMPxxxTag3 (an unordered List-type tag)
|
260
|
+
NewXMPxxxTag3 => { List => 'Bag' },
|
261
|
+
# Example 11. XMP-xxx:NewXMPxxxStruct (a structured tag)
|
262
|
+
# - example structured XMP tag
|
263
|
+
NewXMPxxxStruct => {
|
264
|
+
# the "Struct" entry defines the structure fields
|
265
|
+
Struct => {
|
266
|
+
# optional namespace prefix and URI for structure fields
|
267
|
+
# (required only if different than NAMESPACE above)
|
268
|
+
# --> multiple entries may exist in this namespace lookup,
|
269
|
+
# with the last one alphabetically being the default for
|
270
|
+
# the fields, but each field may have a "Namespace"
|
271
|
+
# element to specify which prefix to use
|
272
|
+
NAMESPACE => { 'test' => 'http://x.y.z/test/' },
|
273
|
+
# optional structure name (used for warning messages only)
|
274
|
+
STRUCT_NAME => 'MyStruct',
|
275
|
+
# optional rdf:type property for the structure
|
276
|
+
TYPE => 'http://x.y.z/test/xystruct',
|
277
|
+
# structure fields (very similar to tag definitions)
|
278
|
+
X => { Writable => 'integer' },
|
279
|
+
Y => { Writable => 'integer' },
|
280
|
+
# a nested structure...
|
281
|
+
Things => {
|
282
|
+
List => 'Bag',
|
283
|
+
Struct => {
|
284
|
+
NAMESPACE => { thing => 'http://x.y.z/thing/' },
|
285
|
+
What => { },
|
286
|
+
Where => { },
|
287
|
+
},
|
288
|
+
},
|
289
|
+
},
|
290
|
+
List => 'Seq', # structures may also be elements of a list
|
291
|
+
},
|
292
|
+
# Each field in the structure has a corresponding flattened tag that is
|
293
|
+
# generated automatically with an ID made from a concatenation of the
|
294
|
+
# original structure tag ID and the field name (after capitalizing the
|
295
|
+
# first letter of the field name if necessary). The Name and/or
|
296
|
+
# Description of these flattened tags may be changed if desired, but all
|
297
|
+
# other tag properties are taken from the structure field definition.
|
298
|
+
# The "Flat" flag must be used when setting the Name or Description of a
|
299
|
+
# flattened tag. For example:
|
300
|
+
NewXMPxxxStructX => { Name => 'SomeOtherName', Flat => 1 },
|
301
|
+
);
|
302
|
+
|
303
|
+
# Adding a new MIE group requires a few extra definitions
|
304
|
+
use Image::ExifTool::MIE;
|
305
|
+
%Image::ExifTool::UserDefined::MIETest = (
|
306
|
+
%Image::ExifTool::MIE::tableDefaults, # default MIE table entries
|
307
|
+
GROUPS => { 0 => 'MIE', 1 => 'MIE-Test', 2 => 'Document' },
|
308
|
+
WRITE_GROUP => 'MIE-Test',
|
309
|
+
# Example 16. MIE-Test:NewMieTag2
|
310
|
+
NewMieTag2 => { }, # new user-defined tag in MIE-Test group
|
311
|
+
);
|
312
|
+
|
313
|
+
# A special 'Lenses' list can be defined to give priority to specific lenses
|
314
|
+
# in the logic to determine a lens model for the Composite:LensID tag
|
315
|
+
@Image::ExifTool::UserDefined::Lenses = (
|
316
|
+
'Sigma AF 10-20mm F4-5.6 EX DC',
|
317
|
+
'Tokina AF193-2 19-35mm f/3.5-4.5',
|
318
|
+
);
|
319
|
+
|
320
|
+
# User-defined file types to recognize
|
321
|
+
%Image::ExifTool::UserDefined::FileTypes = (
|
322
|
+
XXX => { # <-- the extension of the new file type (case insensitive)
|
323
|
+
# BaseType specifies the format upon which this file is based (case
|
324
|
+
# sensitive). If BaseType is defined, then the file will be fully
|
325
|
+
# supported, and in this case the Magic pattern should not be defined
|
326
|
+
BaseType => 'TIFF',
|
327
|
+
MIMEType => 'image/x-xxx',
|
328
|
+
Description => 'My XXX file type',
|
329
|
+
# if the BaseType is writable by ExifTool, then the new file type
|
330
|
+
# will also be writable unless otherwise specified, like this:
|
331
|
+
Writable => 0,
|
332
|
+
},
|
333
|
+
YYY => {
|
334
|
+
# without BaseType, the file will be recognized but not supported
|
335
|
+
Magic => '0123abcd', # regular expression to match at start of file
|
336
|
+
MIMEType => 'application/test',
|
337
|
+
Description => 'My YYY file type',
|
338
|
+
},
|
339
|
+
ZZZ => {
|
340
|
+
# if neither BaseType nor Magic are defined, the file will be
|
341
|
+
# recognized by extension only. MIMEType will be application/unknown
|
342
|
+
# unless otherwise specified
|
343
|
+
Description => 'My ZZZ file type',
|
344
|
+
},
|
345
|
+
# if only BaseType is specified, then the following simplified syntax
|
346
|
+
# may be used. In this example, files with extension "TTT" will be
|
347
|
+
# processed as JPEG files
|
348
|
+
TTT => 'JPEG',
|
349
|
+
);
|
350
|
+
|
351
|
+
# Change default location for writing QuickTime tags so Keys is preferred
|
352
|
+
# (by default, the PREFERRED levels are: ItemList=2, UserData=1, Keys=0)
|
353
|
+
use Image::ExifTool::QuickTime;
|
354
|
+
$Image::ExifTool::QuickTime::Keys{PREFERRED} = 3;
|
355
|
+
|
356
|
+
# Specify default ExifTool option values
|
357
|
+
# (see the Options function documentation for available options)
|
358
|
+
%Image::ExifTool::UserDefined::Options = (
|
359
|
+
CoordFormat => '%.6f', # change default GPS coordinate format
|
360
|
+
Duplicates => 1, # make -a default for the exiftool app
|
361
|
+
GeoMaxHDOP => 4, # ignore GPS fixes with HDOP > 4
|
362
|
+
RequestAll => 3, # request additional tags not normally generated
|
363
|
+
);
|
data/test/test_batch.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'helper'
|
5
|
+
|
6
|
+
class TestBatch < Test::Unit::TestCase
|
7
|
+
|
8
|
+
MANDATORY_WRITER_ARGS = MultiExiftool::Writer.mandatory_args
|
9
|
+
|
10
|
+
context 'exiftool_args method' do
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@filenames = %w(a.jpg b.jpg c.jpg)
|
14
|
+
@multiple_values = @filenames.map do |filename|
|
15
|
+
{author: 'janfri', comment: "Comment for file #{filename}"}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
test 'only filenames and values' do
|
20
|
+
batch = MultiExiftool::Batch.new
|
21
|
+
@filenames.zip @multiple_values do |filename, values|
|
22
|
+
batch.write filename, values
|
23
|
+
end
|
24
|
+
exiftool_args = @filenames.zip(@multiple_values).map do |filename, values|
|
25
|
+
[MANDATORY_WRITER_ARGS, '-author=janfri', "-comment=Comment for file #{filename}", filename, '-execute']
|
26
|
+
end.flatten
|
27
|
+
assert_equal exiftool_args, batch.exiftool_args
|
28
|
+
end
|
29
|
+
|
30
|
+
test 'filenames, values and options' do
|
31
|
+
options = {overwrite_original: true}
|
32
|
+
batch = MultiExiftool::Batch.new
|
33
|
+
@filenames.zip @multiple_values do |filename, values|
|
34
|
+
batch.write filename, values, options
|
35
|
+
end
|
36
|
+
exiftool_args = @filenames.zip(@multiple_values).map do |filename, _values|
|
37
|
+
[MANDATORY_WRITER_ARGS, '-overwrite_original', '-author=janfri', "-comment=Comment for file #{filename}", filename, '-execute']
|
38
|
+
end.flatten
|
39
|
+
assert_equal exiftool_args, batch.exiftool_args
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/test/test_functional_api.rb
CHANGED
@@ -60,6 +60,18 @@ class TestFunctionalApi < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
+
test 'successful reading with user defined tags in config file' do
|
64
|
+
run_in_temp_dir do
|
65
|
+
values, errors = MultiExiftool.read(%w[a.jpg b.jpg c.jpg], tags: %w[basename fileextension])
|
66
|
+
assert_equal [nil, nil, nil], values.map(&:basename)
|
67
|
+
assert_equal [nil, nil, nil], values.map(&:file_extension)
|
68
|
+
assert_equal [], errors
|
69
|
+
values, errors = MultiExiftool.read(%w[a.jpg b.jpg c.jpg], config: 'example.config', tags: %w[basename fileextension])
|
70
|
+
assert_equal %w[a b c], values.map(&:basename)
|
71
|
+
assert_equal %w[jpg]*3, values.map(&:file_extension)
|
72
|
+
assert_equal [], errors
|
73
|
+
end
|
74
|
+
end
|
63
75
|
end
|
64
76
|
|
65
77
|
context 'writing' do
|
@@ -188,4 +200,93 @@ class TestFunctionalApi < Test::Unit::TestCase
|
|
188
200
|
|
189
201
|
end
|
190
202
|
|
203
|
+
context 'batch' do
|
204
|
+
|
205
|
+
setup do
|
206
|
+
@filenames = %w(a.jpg b.jpg c.jpg)
|
207
|
+
@multiple_values = @filenames.map do |fn|
|
208
|
+
{author: 'Jan Friedrich', comment: "Comment for file #{fn}"}
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'instance_exec' do
|
213
|
+
|
214
|
+
test 'only filenames and values' do
|
215
|
+
run_in_temp_dir do
|
216
|
+
filenames = @filenames
|
217
|
+
multiple_values = @multiple_values
|
218
|
+
errors = MultiExiftool.batch do
|
219
|
+
filenames.zip multiple_values do |filename, values|
|
220
|
+
write filename, values
|
221
|
+
end
|
222
|
+
end
|
223
|
+
assert_equal [], errors
|
224
|
+
values, errors = MultiExiftool.read(@filenames)
|
225
|
+
assert_equal ['Jan Friedrich'] * 3, values.map {|e| e['Author']}
|
226
|
+
assert_equal ['Comment for file a.jpg', 'Comment for file b.jpg', 'Comment for file c.jpg'], values.map {|e| e['Comment']}
|
227
|
+
assert_equal [], errors
|
228
|
+
assert_equal 3, Dir['*_original'].size
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
test 'options with boolean argument' do
|
233
|
+
run_in_temp_dir do
|
234
|
+
filenames = @filenames
|
235
|
+
multiple_values = @multiple_values
|
236
|
+
options = {overwrite_original: true}
|
237
|
+
errors = MultiExiftool.batch do
|
238
|
+
filenames.zip multiple_values do |filename, values|
|
239
|
+
write filename, values, options
|
240
|
+
end
|
241
|
+
end
|
242
|
+
assert_equal [], errors
|
243
|
+
values, errors = MultiExiftool.read(@filenames)
|
244
|
+
assert_equal ['Jan Friedrich'] * 3, values.map {|e| e['Author']}
|
245
|
+
assert_equal ['Comment for file a.jpg', 'Comment for file b.jpg', 'Comment for file c.jpg'], values.map {|e| e['Comment']}
|
246
|
+
assert_equal [], errors
|
247
|
+
assert_equal [], Dir['*_original']
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
context 'yield' do
|
254
|
+
|
255
|
+
test 'only filenames and values' do
|
256
|
+
run_in_temp_dir do
|
257
|
+
errors = MultiExiftool.batch do |batch|
|
258
|
+
@filenames.zip @multiple_values do |filename, values|
|
259
|
+
batch.write filename, values
|
260
|
+
end
|
261
|
+
end
|
262
|
+
assert_equal [], errors
|
263
|
+
values, errors = MultiExiftool.read(@filenames)
|
264
|
+
assert_equal ['Jan Friedrich'] * 3, values.map {|e| e['Author']}
|
265
|
+
assert_equal ['Comment for file a.jpg', 'Comment for file b.jpg', 'Comment for file c.jpg'], values.map {|e| e['Comment']}
|
266
|
+
assert_equal [], errors
|
267
|
+
assert_equal 3, Dir['*_original'].size
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
test 'options with boolean argument' do
|
272
|
+
run_in_temp_dir do
|
273
|
+
options = {overwrite_original: true}
|
274
|
+
errors = MultiExiftool.batch do |batch|
|
275
|
+
@filenames.zip @multiple_values do |filename, values|
|
276
|
+
batch.write filename, values, options
|
277
|
+
end
|
278
|
+
end
|
279
|
+
assert_equal [], errors
|
280
|
+
values, errors = MultiExiftool.read(@filenames)
|
281
|
+
assert_equal ['Jan Friedrich'] * 3, values.map {|e| e['Author']}
|
282
|
+
assert_equal ['Comment for file a.jpg', 'Comment for file b.jpg', 'Comment for file c.jpg'], values.map {|e| e['Comment']}
|
283
|
+
assert_equal [], errors
|
284
|
+
assert_equal [], Dir['*_original']
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
|
191
292
|
end
|
data/test/test_reader.rb
CHANGED
@@ -157,6 +157,20 @@ class TestReader < Test::Unit::TestCase
|
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
+
test 'successful reading with user defined tags in config file' do
|
161
|
+
run_in_temp_dir do
|
162
|
+
@reader.filenames = %w(a.jpg b.jpg c.jpg)
|
163
|
+
@reader.tags = %w[basename]
|
164
|
+
res = @reader.read
|
165
|
+
assert_equal [nil, nil, nil], res.map(&:basename)
|
166
|
+
assert_equal [], @reader.errors
|
167
|
+
@reader.config = 'example.config'
|
168
|
+
res = @reader.read
|
169
|
+
assert_equal %w[a b c], res.map(&:basename)
|
170
|
+
assert_equal [], @reader.errors
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
160
174
|
end
|
161
175
|
|
162
176
|
end
|
data/test/test_values.rb
CHANGED
@@ -137,19 +137,19 @@ class TestValues < Test::Unit::TestCase
|
|
137
137
|
|
138
138
|
test 'different formats as string' do
|
139
139
|
@hash.keys.each do |k|
|
140
|
-
|
140
|
+
assert_equal true, @values.has_tag?(k)
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
144
|
test 'different formats as symbol' do
|
145
145
|
@hash.keys.each do |k|
|
146
|
-
|
146
|
+
assert_equal true, @values.has_tag?(k.to_sym)
|
147
147
|
end
|
148
148
|
end
|
149
149
|
|
150
150
|
test 'non existent key' do
|
151
151
|
['iso', 'ISO', :iso, :ISO].each do |t|
|
152
|
-
|
152
|
+
assert_equal false, @values.has_tag?(t)
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
@@ -182,13 +182,13 @@ class TestValues < Test::Unit::TestCase
|
|
182
182
|
|
183
183
|
test 'existing keys' do
|
184
184
|
[:fnumber, :f_number, :FNumber, 'fnumber', 'f_number', 'FNumber', :author, :Author, 'author', 'Author'].each do |t|
|
185
|
-
|
185
|
+
assert_equal true, @values.respond_to?(t)
|
186
186
|
end
|
187
187
|
end
|
188
188
|
|
189
189
|
test 'non existing key' do
|
190
190
|
['iso', 'ISO', :iso, :ISO].each do |t|
|
191
|
-
|
191
|
+
assert_equal false, @values.respond_to?(t)
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: multi_exiftool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Friedrich
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '2'
|
83
|
-
description: This library a
|
83
|
+
description: This library is a wrapper for the ExifTool command-line application (https://exiftool.org)
|
84
84
|
written by Phil Harvey. It is designed for dealing with multiple files at once by
|
85
85
|
creating commands to call exiftool with various arguments, call it and parsing the
|
86
86
|
results.
|
@@ -96,6 +96,7 @@ files:
|
|
96
96
|
- README.md
|
97
97
|
- Rakefile
|
98
98
|
- lib/multi_exiftool.rb
|
99
|
+
- lib/multi_exiftool/batch.rb
|
99
100
|
- lib/multi_exiftool/executable.rb
|
100
101
|
- lib/multi_exiftool/reader.rb
|
101
102
|
- lib/multi_exiftool/values.rb
|
@@ -107,7 +108,9 @@ files:
|
|
107
108
|
- test/data/a.jpg
|
108
109
|
- test/data/b.jpg
|
109
110
|
- test/data/c.jpg
|
111
|
+
- test/data/example.config
|
110
112
|
- test/helper.rb
|
113
|
+
- test/test_batch.rb
|
111
114
|
- test/test_executable.rb
|
112
115
|
- test/test_exiftool_stuff.rb
|
113
116
|
- test/test_functional_api.rb
|
@@ -123,7 +126,7 @@ metadata: {}
|
|
123
126
|
post_install_message: "\n+-----------------------------------------------------------------------+\n|
|
124
127
|
Please ensure you have installed exiftool version 7.65 or higher and |\n| it's
|
125
128
|
found in your PATH (Try \"exiftool -ver\" on your commandline). |\n| For more
|
126
|
-
details see |\n|
|
129
|
+
details see |\n| https://exiftool.org/install.html
|
127
130
|
\ |\n+-----------------------------------------------------------------------+\n
|
128
131
|
\ "
|
129
132
|
rdoc_options: []
|
@@ -142,7 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
145
|
requirements:
|
143
146
|
- exiftool, version 7.65 or higher
|
144
147
|
rubygems_version: 3.1.2
|
145
|
-
signing_key:
|
148
|
+
signing_key:
|
146
149
|
specification_version: 4
|
147
|
-
summary: This library is a wrapper for the ExifTool command-line application (
|
150
|
+
summary: This library is a wrapper for the ExifTool command-line application (https://exiftool.org).
|
148
151
|
test_files: []
|