Class: MiniExiftool

Inherits:
Object
  • Object
show all
Defined in:
lib/mini_exiftool.rb

Overview

Simple OO access to the Exiftool command-line application.

Defined Under Namespace

Classes: Error, TagHash

Constant Summary collapse

VERSION =
'1.6.0'
@@cmd =

Name of the Exiftool command-line application

'exiftool'
@@opts =

Hash of the standard options used when call MiniExiftool.new

{ :numerical => false, :composite => true, :convert_encoding => false, :ignore_minor_errors => false, :timestamps => Time }

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename = nil, opts = {}) ⇒ MiniExiftool

opts support at the moment

  • :numerical for numerical values, default is false

  • :composite for including composite tags while loading, default is true

  • :convert_encoding convert encoding (See -L-option of the exiftool command-line application, default is false)

  • :ignore_minor_errors ignore minor errors (See -m-option

of the exiftool command-line application, default is false)

  • :timestamps generating DateTime objects instead of Time objects if set to DateTime, default is Time

    ATTENTION: Time objects are created using Time.local therefore they use your local timezone, DateTime objects instead are created without timezone!



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/mini_exiftool.rb', line 52

def initialize filename=nil, opts={}
  opts = @@opts.merge opts
  @numerical = opts[:numerical]
  @composite = opts[:composite]
  @convert_encoding = opts[:convert_encoding]
  @ignore_minor_errors = opts[:ignore_minor_errors]
  @timestamps = opts[:timestamps]
  @coord_format = opts[:coord_format]
  @values = TagHash.new
  @tag_names = TagHash.new
  @changed_values = TagHash.new
  @errors = TagHash.new
  load filename unless filename.nil?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object (private)



329
330
331
332
333
334
335
336
# File 'lib/mini_exiftool.rb', line 329

def method_missing symbol, *args
  tag_name = symbol.id2name
  if tag_name.sub!(/=$/, '')
    self[tag_name] = args.first
  else
    self[tag_name]
  end
end

Instance Attribute Details

#compositeObject

Returns the value of attribute composite.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def composite
  @composite
end

#convert_encodingObject

Returns the value of attribute convert_encoding.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def convert_encoding
  @convert_encoding
end

#errorsObject

Returns the value of attribute errors.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def errors
  @errors
end

#filenameObject (readonly)

Returns the value of attribute filename.



33
34
35
# File 'lib/mini_exiftool.rb', line 33

def filename
  @filename
end

#ignore_minor_errorsObject

Returns the value of attribute ignore_minor_errors.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def ignore_minor_errors
  @ignore_minor_errors
end

#numericalObject

Returns the value of attribute numerical.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def numerical
  @numerical
end

#timestampsObject

Returns the value of attribute timestamps.



34
35
36
# File 'lib/mini_exiftool.rb', line 34

def timestamps
  @timestamps
end

Class Method Details

.all_tagsObject

Returns a set of all known tags of Exiftool.



244
245
246
247
248
249
# File 'lib/mini_exiftool.rb', line 244

def self.all_tags
  unless defined? @@all_tags
    @@all_tags = pstore_get :all_tags
  end
  @@all_tags
end

.commandObject

Returns the command name of the called Exiftool application.



229
230
231
# File 'lib/mini_exiftool.rb', line 229

def self.command
  @@cmd
end

.command=(cmd) ⇒ Object

Setting the command name of the called Exiftool application.



234
235
236
# File 'lib/mini_exiftool.rb', line 234

def self.command= cmd
  @@cmd = cmd
end

.exiftool_versionObject

Returns the version of the Exiftool command-line application.



268
269
270
271
272
273
274
# File 'lib/mini_exiftool.rb', line 268

def self.exiftool_version
  output = `#{MiniExiftool.command} -ver 2>&1`
  unless $?.exitstatus == 0
    raise MiniExiftool::Error.new("Command '#{MiniExiftool.command}' not found")
  end
  output.chomp!
end

.from_hash(hash) ⇒ Object

Create a MiniExiftool instance from a hash. Default value conversions will be applied if neccesary.



216
217
218
219
220
# File 'lib/mini_exiftool.rb', line 216

def self.from_hash hash
  instance = MiniExiftool.new
  instance.initialize_from_hash hash
  instance
end

.from_yaml(yaml) ⇒ Object

Create a MiniExiftool instance from YAML data created with MiniExiftool#to_yaml



224
225
226
# File 'lib/mini_exiftool.rb', line 224

def self.from_yaml yaml
  MiniExiftool.from_hash YAML.load(yaml)
end

.optsObject

Returns the options hash.



239
240
241
# File 'lib/mini_exiftool.rb', line 239

def self.opts
  @@opts
end

.original_tag(tag) ⇒ Object

Returns the original Exiftool name of the given tag



260
261
262
263
264
265
# File 'lib/mini_exiftool.rb', line 260

def self.original_tag tag
  unless defined? @@all_tags_map
    @@all_tags_map = pstore_get :all_tags_map
  end
  @@all_tags_map[tag]
end

.unify(tag) ⇒ Object



276
277
278
# File 'lib/mini_exiftool.rb', line 276

def self.unify tag
  tag.to_s.gsub(/[-_]/,'').downcase
end

.writable_tagsObject

Returns a set of all possible writable tags of Exiftool.



252
253
254
255
256
257
# File 'lib/mini_exiftool.rb', line 252

def self.writable_tags
  unless defined? @@writable_tags
    @@writable_tags = pstore_get :writable_tags
  end
  @@writable_tags
end

Instance Method Details

#[](tag) ⇒ Object

Returns the value of a tag.



108
109
110
# File 'lib/mini_exiftool.rb', line 108

def [] tag
  @changed_values[tag] || @values[tag]
end

#[]=(tag, val) ⇒ Object

Set the value of a tag.



113
114
115
# File 'lib/mini_exiftool.rb', line 113

def []=(tag, val)
  @changed_values[tag] = val
end

#changed?(tag = false) ⇒ Boolean

Returns true if any tag value is changed or if the value of a given tag is changed.

Returns:

  • (Boolean)


119
120
121
122
123
124
125
# File 'lib/mini_exiftool.rb', line 119

def changed? tag=false
  if tag
    @changed_values.include? tag
  else
    !@changed_values.empty?
  end
end

#changed_tagsObject

Returns an array of all changed tags.



145
146
147
# File 'lib/mini_exiftool.rb', line 145

def changed_tags
  @changed_values.keys.map { |key| MiniExiftool.original_tag(key) }
end

#initialize_from_hash(hash) ⇒ Object

:nodoc:



67
68
69
70
71
72
73
# File 'lib/mini_exiftool.rb', line 67

def initialize_from_hash hash # :nodoc:
  hash.each_pair do |tag,value|
    set_value tag, perform_conversions(value)
  end
  set_attributes_by_heuristic
  self
end

#load(filename) ⇒ Object

Load the tags of filename.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/mini_exiftool.rb', line 76

def load filename
  MiniExiftool.setup
  unless filename && File.exist?(filename)
    raise MiniExiftool::Error.new("File '#{filename}' does not exist.")
  end
  if File.directory?(filename)
    raise MiniExiftool::Error.new("'#{filename}' is a directory.")
  end
  @filename = filename
  @values.clear
  @tag_names.clear
  @changed_values.clear
  opt_params = ''
  opt_params << (@numerical ? '-n ' : '')
  opt_params << (@composite ? '' : '-e ')
  opt_params << (@convert_encoding ? '-L ' : '')
  opt_params << (@coord_format ? "-c \"#{@coord_format}\"" : '')
  cmd = %Q(#@@cmd -q -q -s -t #{opt_params} #{@@sep_op} #{Shellwords.escape(filename)})
  if run(cmd)
    parse_output
  else
    raise MiniExiftool::Error.new(@error_text)
  end
  self
end

#reloadObject

Reload the tags of an already read file.



103
104
105
# File 'lib/mini_exiftool.rb', line 103

def reload
  load @filename
end

#revert(tag = nil) ⇒ Object

Revert all changes or the change of a given tag.



128
129
130
131
132
133
134
135
136
137
# File 'lib/mini_exiftool.rb', line 128

def revert tag=nil
  if tag
    val = @changed_values.delete(tag)
    res = val != nil
  else
    res = @changed_values.size > 0
    @changed_values.clear
  end
  res
end

#saveObject

Save the changes to the file.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/mini_exiftool.rb', line 150

def save
  MiniExiftool.setup
  return false if @changed_values.empty?
  @errors.clear
  temp_file = Tempfile.new('mini_exiftool')
  temp_file.close
  temp_filename = temp_file.path
  FileUtils.cp filename, temp_filename
  all_ok = true
  @changed_values.each do |tag, val|
    original_tag = MiniExiftool.original_tag(tag)
    arr_val = val.kind_of?(Array) ? val : [val]
    arr_val.map! {|e| convert e}
    tag_params = ''
    arr_val.each do |v|
      tag_params << %Q(-#{original_tag}=#{Shellwords.escape(v.to_s)} )
    end
    opt_params = ''
    opt_params << (arr_val.detect {|x| x.kind_of?(Numeric)} ? '-n ' : '')
    opt_params << (@convert_encoding ? '-L ' : '')
    opt_params << (@ignore_minor_errors ? '-m' : '')
    cmd = %Q(#@@cmd -q -P -overwrite_original #{opt_params} #{tag_params} #{temp_filename})
    if convert_encoding && cmd.respond_to?(:encode)
      cmd.encode('ISO-8859-1')
    end
    result = run(cmd)
    unless result
      all_ok = false
      @errors[tag] = @error_text.gsub(/Nothing to do.\n\z/, '').chomp
    end
  end
  if all_ok
    FileUtils.cp temp_filename, filename
    reload
  end
  temp_file.delete
  all_ok
end

#save!Object



189
190
191
192
193
194
195
196
197
# File 'lib/mini_exiftool.rb', line 189

def save!
  unless save
    err = []
    self.errors.each do |key, value|
      err << "(#{key}) #{value}"
    end
    raise MiniExiftool::Error.new("MiniExiftool couldn't save. The following errors occurred: #{err.empty? ? "None" : err.join(", ")}")
  end
end

#tagsObject

Returns an array of the tags (original tag names) of the read file.



140
141
142
# File 'lib/mini_exiftool.rb', line 140

def tags
  @values.keys.map { |key| @tag_names[key] }
end

#to_hashObject

Returns a hash of the original loaded values of the MiniExiftool instance.



201
202
203
204
205
206
207
# File 'lib/mini_exiftool.rb', line 201

def to_hash
  result = {}
  @values.each do |k,v|
    result[@tag_names[k]] = v
  end
  result
end

#to_yamlObject

Returns a YAML representation of the original loaded values of the MiniExiftool instance.



211
212
213
# File 'lib/mini_exiftool.rb', line 211

def to_yaml
  to_hash.to_yaml
end