Class: MiniExiftool
- Inherits:
-
Object
- Object
- MiniExiftool
- Defined in:
- lib/mini_exiftool.rb
Overview
Simple OO access to the Exiftool command-line application.
Defined Under Namespace
Constant Summary collapse
- VERSION =
'2.7.1'
- @@cmd =
Name of the Exiftool command-line application
'exiftool'
- @@opts =
Hash of the standard options used when call MiniExiftool.new
{ :numerical => false, :composite => true, :fast => false, :fast2 => false, :ignore_minor_errors => false, :replace_invalid_chars => false, :timestamps => Time }
- @@fs_enc =
Encoding of the filesystem (filenames in command line)
Encoding.find('filesystem')
- @@encoding_types =
%w(exif iptc xmp png id3 pdf photoshop quicktime aiff mie vorbis)
- @@running_on_windows =
Instance Attribute Summary collapse
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#filename ⇒ Object
readonly
Returns the value of attribute filename.
-
#io ⇒ Object
readonly
Returns the value of attribute io.
Class Method Summary collapse
-
.all_tags ⇒ Object
Returns a set of all known tags of Exiftool.
-
.command ⇒ Object
Returns the command name of the called Exiftool application.
-
.command=(cmd) ⇒ Object
Setting the command name of the called Exiftool application.
- .encoding_opt(enc_type) ⇒ Object
-
.exiftool_version ⇒ Object
Returns the version of the Exiftool command-line application.
-
.from_hash(hash, opts = {}) ⇒ Object
Create a MiniExiftool instance from a hash.
-
.from_json(json, opts = {}) ⇒ Object
Create a MiniExiftool instance from JSON data.
-
.from_yaml(yaml, opts = {}) ⇒ Object
Create a MiniExiftool instance from YAML data created with MiniExiftool#to_yaml.
-
.opts ⇒ Object
Returns the options hash.
- .opts_accessor(*attrs) ⇒ Object
-
.original_tag(tag) ⇒ Object
Returns the original Exiftool name of the given tag.
- .pstore_dir ⇒ Object
- .pstore_dir=(dir) ⇒ Object
- .unify(tag) ⇒ Object
-
.writable_tags ⇒ Object
Returns a set of all possible writable tags of Exiftool.
Instance Method Summary collapse
-
#[](tag) ⇒ Object
Returns the value of a tag.
-
#[]=(tag, val) ⇒ Object
Set the value of a tag.
-
#changed?(tag = false) ⇒ Boolean
Returns true if any tag value is changed or if the value of a given tag is changed.
-
#changed_tags ⇒ Object
Returns an array of all changed tags.
- #copy_tags_from(source_filename, tags) ⇒ Object
-
#initialize(filename_or_io = nil, opts = {}) ⇒ MiniExiftool
constructor
filename_or_io
The kind of the parameter is determined via duck typing: if the argument responds toto_str
it is interpreted as filename, if it responds toread
it is interpreted es IO instance. -
#initialize_from_hash(hash) ⇒ Object
:nodoc:.
-
#initialize_from_json(json) ⇒ Object
:nodoc:.
-
#load(filename_or_io) ⇒ Object
Load the tags of filename or io.
-
#reload ⇒ Object
Reload the tags of an already read file.
-
#revert(tag = nil) ⇒ Object
Revert all changes or the change of a given tag.
-
#save ⇒ Object
Save the changes to the file.
- #save! ⇒ Object
-
#tags ⇒ Object
Returns an array of the tags (original tag names) of the read file.
-
#to_hash ⇒ Object
Returns a hash of the original loaded values of the MiniExiftool instance.
-
#to_yaml ⇒ Object
Returns a YAML representation of the original loaded values of the MiniExiftool instance.
Constructor Details
#initialize(filename_or_io = nil, opts = {}) ⇒ MiniExiftool
filename_or_io
The kind of the parameter is determined via duck typing: if the argument responds to to_str
it is interpreted as filename, if it responds to read
it is interpreted es IO instance.
ATTENTION: If using an IO instance writing of meta data is not supported!
opts
support at the moment
-
:numerical
for numerical values, default isfalse
-
:composite
for including composite tags while loading, default istrue
-
:ignore_minor_errors
ignore minor errors (See -m-option of the exiftool command-line application, default isfalse
) -
:coord_format
set format for GPS coordinates (See -c-option of the exiftool command-line application, default isnil
that means exiftool standard) -
:fast
useful when reading JPEGs over a slow network connection (See -fast-option of the exiftool command-line application, default isfalse
) -
:fast2
useful when reading JPEGs over a slow network connection (See -fast2-option of the exiftool command-line application, default isfalse
) -
:replace_invalid_chars
replace string for invalid UTF-8 characters orfalse
if no replacing should be done, default isfalse
-
:timestamps
generating DateTime objects instead of Time objects if set toDateTime
, default isTime
ATTENTION: Time objects are created using
Time.local
therefore they use your local timezone, DateTime objects instead are created without timezone! -
:exif_encoding
,:iptc_encoding
,:xmp_encoding
,:png_encoding
,:id3_encoding
,:pdf_encoding
,:photoshop_encoding
,:quicktime_encoding
,:aiff_encoding
,:mie_encoding
,:vorbis_encoding
to set this specific encoding (see -charset option of the exiftool command-line application, default isnil
: no encoding specified)
104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/mini_exiftool.rb', line 104 def initialize filename_or_io=nil, opts={} @opts = @@opts.merge opts if @opts[:convert_encoding] warn 'Option :convert_encoding is not longer supported!' warn 'Please use the String#encod* methods.' end @filename = nil @io = nil @values = TagHash.new @changed_values = TagHash.new @errors = TagHash.new load filename_or_io unless filename_or_io.nil? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(symbol, *args) ⇒ Object (private)
420 421 422 423 424 425 426 427 |
# File 'lib/mini_exiftool.rb', line 420 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
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
53 54 55 |
# File 'lib/mini_exiftool.rb', line 53 def errors @errors end |
#filename ⇒ Object (readonly)
Returns the value of attribute filename.
53 54 55 |
# File 'lib/mini_exiftool.rb', line 53 def filename @filename end |
#io ⇒ Object (readonly)
Returns the value of attribute io.
53 54 55 |
# File 'lib/mini_exiftool.rb', line 53 def io @io end |
Class Method Details
.all_tags ⇒ Object
Returns a set of all known tags of Exiftool.
326 327 328 329 330 331 |
# File 'lib/mini_exiftool.rb', line 326 def self. unless defined? @@all_tags @@all_tags = pstore_get :all_tags end @@all_tags end |
.command ⇒ Object
Returns the command name of the called Exiftool application.
311 312 313 |
# File 'lib/mini_exiftool.rb', line 311 def self.command @@cmd end |
.command=(cmd) ⇒ Object
Setting the command name of the called Exiftool application.
316 317 318 |
# File 'lib/mini_exiftool.rb', line 316 def self.command= cmd @@cmd = cmd end |
.encoding_opt(enc_type) ⇒ Object
60 61 62 |
# File 'lib/mini_exiftool.rb', line 60 def self.encoding_opt enc_type (enc_type.to_s + '_encoding').to_sym end |
.exiftool_version ⇒ Object
Returns the version of the Exiftool command-line application.
350 351 352 353 354 355 356 |
# File 'lib/mini_exiftool.rb', line 350 def self.exiftool_version Open3.popen3 "#{MiniExiftool.command} -ver" do |_inp, out, _err, _thr| out.read.chomp! end rescue SystemCallError raise MiniExiftool::Error.new("Command '#{MiniExiftool.command}' not found") end |
.from_hash(hash, opts = {}) ⇒ Object
Create a MiniExiftool instance from a hash. Default value conversions will be applied if neccesary.
290 291 292 293 294 |
# File 'lib/mini_exiftool.rb', line 290 def self.from_hash hash, opts={} instance = MiniExiftool.new nil, opts instance.initialize_from_hash hash instance end |
.from_json(json, opts = {}) ⇒ Object
Create a MiniExiftool instance from JSON data. Default value conversions will be applied if neccesary.
298 299 300 301 302 |
# File 'lib/mini_exiftool.rb', line 298 def self.from_json json, opts={} instance = MiniExiftool.new nil, opts instance.initialize_from_json json instance end |
.from_yaml(yaml, opts = {}) ⇒ Object
Create a MiniExiftool instance from YAML data created with MiniExiftool#to_yaml
306 307 308 |
# File 'lib/mini_exiftool.rb', line 306 def self.from_yaml yaml, opts={} MiniExiftool.from_hash YAML.load(yaml), opts end |
.opts ⇒ Object
Returns the options hash.
321 322 323 |
# File 'lib/mini_exiftool.rb', line 321 def self.opts @@opts end |
.opts_accessor(*attrs) ⇒ Object
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/mini_exiftool.rb', line 42 def self.opts_accessor *attrs attrs.each do |a| define_method a do @opts[a] end define_method "#{a}=" do |val| @opts[a] = val end end end |
.original_tag(tag) ⇒ Object
Returns the original Exiftool name of the given tag
342 343 344 345 346 347 |
# File 'lib/mini_exiftool.rb', line 342 def self.original_tag tag unless defined? @@all_tags_map @@all_tags_map = pstore_get :all_tags_map end @@all_tags_map[tag] end |
.pstore_dir ⇒ Object
364 365 366 367 368 369 370 371 372 |
# File 'lib/mini_exiftool.rb', line 364 def self.pstore_dir unless defined? @@pstore_dir # This will hopefully work on *NIX and Windows systems home = ENV['HOME'] || ENV['HOMEDRIVE'] + ENV['HOMEPATH'] || ENV['USERPROFILE'] subdir = @@running_on_windows ? '_mini_exiftool' : '.mini_exiftool' @@pstore_dir = File.join(home, subdir) end @@pstore_dir end |
.pstore_dir=(dir) ⇒ Object
374 375 376 |
# File 'lib/mini_exiftool.rb', line 374 def self.pstore_dir= dir @@pstore_dir = dir end |
.unify(tag) ⇒ Object
358 359 360 |
# File 'lib/mini_exiftool.rb', line 358 def self.unify tag tag.to_s.gsub(/[-_]/,'').downcase end |
.writable_tags ⇒ Object
Returns a set of all possible writable tags of Exiftool.
334 335 336 337 338 339 |
# File 'lib/mini_exiftool.rb', line 334 def self. 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.
170 171 172 |
# File 'lib/mini_exiftool.rb', line 170 def [] tag @changed_values[tag] || @values[tag] end |
#[]=(tag, val) ⇒ Object
Set the value of a tag.
175 176 177 |
# File 'lib/mini_exiftool.rb', line 175 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.
181 182 183 184 185 186 187 |
# File 'lib/mini_exiftool.rb', line 181 def changed? tag=false if tag @changed_values.include? tag else !@changed_values.empty? end end |
#changed_tags ⇒ Object
Returns an array of all changed tags.
207 208 209 |
# File 'lib/mini_exiftool.rb', line 207 def @changed_values.keys.map { |key| MiniExiftool.original_tag(key) } end |
#copy_tags_from(source_filename, tags) ⇒ Object
258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/mini_exiftool.rb', line 258 def (source_filename, ) @errors.clear unless File.exist?(source_filename) raise MiniExiftool::Error.new("Source file #{source_filename} does not exist!") end params = '-q -P -overwrite_original ' = Array().map {|t| '-' << t.to_s}.join(' ') cmd = [@@cmd, params, '-tagsFromFile', escape(source_filename).encode(@@fs_enc), .encode('UTF-8'), escape(filename).encode(@@fs_enc)].join(' ') cmd.force_encoding('UTF-8') result = run(cmd) reload result end |
#initialize_from_hash(hash) ⇒ Object
:nodoc:
118 119 120 121 122 |
# File 'lib/mini_exiftool.rb', line 118 def initialize_from_hash hash # :nodoc: set_values hash set_opts_by_heuristic self end |
#initialize_from_json(json) ⇒ Object
:nodoc:
124 125 126 127 128 129 |
# File 'lib/mini_exiftool.rb', line 124 def initialize_from_json json # :nodoc: @output = json @errors.clear parse_output self end |
#load(filename_or_io) ⇒ Object
Load the tags of filename or io.
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/mini_exiftool.rb', line 132 def load filename_or_io if filename_or_io.respond_to? :to_str # String-like unless filename_or_io && File.exist?(filename_or_io) raise MiniExiftool::Error.new("File '#{filename_or_io}' does not exist.") end if File.directory?(filename_or_io) raise MiniExiftool::Error.new("'#{filename_or_io}' is a directory.") end @filename = filename_or_io.to_str elsif filename_or_io.respond_to? :read # IO-like @io = filename_or_io @filename = '-' else raise MiniExiftool::Error.new("Could not open filename_or_io.") end @values.clear @changed_values.clear params = '-j ' params << (@opts[:numerical] ? '-n ' : '') params << (@opts[:composite] ? '' : '-e ') params << (@opts[:coord_format] ? "-c \"#{@opts[:coord_format]}\"" : '') params << (@opts[:fast] ? '-fast ' : '') params << (@opts[:fast2] ? '-fast2 ' : '') params << generate_encoding_params if run(cmd_gen(params, @filename)) parse_output else raise MiniExiftool::Error.new(@error_text) end self end |
#reload ⇒ Object
Reload the tags of an already read file.
165 166 167 |
# File 'lib/mini_exiftool.rb', line 165 def reload load @filename end |
#revert(tag = nil) ⇒ Object
Revert all changes or the change of a given tag.
190 191 192 193 194 195 196 197 198 199 |
# File 'lib/mini_exiftool.rb', line 190 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 |
#save ⇒ Object
Save the changes to the file.
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/mini_exiftool.rb', line 212 def save if @io raise MiniExiftool::Error.new('No writing support when using an IO.') end 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.encode(@@fs_enc), 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_before_save(e)} params = '-q -P -overwrite_original ' params << (arr_val.detect {|x| x.kind_of?(Numeric)} ? '-n ' : '') params << (@opts[:ignore_minor_errors] ? '-m ' : '') params << generate_encoding_params arr_val.each do |v| params << %Q(-#{original_tag}=#{escape(v)} ) end result = run(cmd_gen(params, temp_filename)) 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.encode(@@fs_enc) reload end temp_file.delete all_ok end |
#save! ⇒ Object
248 249 250 251 252 253 254 255 256 |
# File 'lib/mini_exiftool.rb', line 248 def save! unless save err = [] @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 |
#tags ⇒ Object
Returns an array of the tags (original tag names) of the read file.
202 203 204 |
# File 'lib/mini_exiftool.rb', line 202 def @values.keys.map { |key| MiniExiftool.original_tag(key) } end |
#to_hash ⇒ Object
Returns a hash of the original loaded values of the MiniExiftool instance.
274 275 276 277 278 279 280 |
# File 'lib/mini_exiftool.rb', line 274 def to_hash result = {} @values.each do |k,v| result[MiniExiftool.original_tag(k)] = v end result end |
#to_yaml ⇒ Object
Returns a YAML representation of the original loaded values of the MiniExiftool instance.
284 285 286 |
# File 'lib/mini_exiftool.rb', line 284 def to_yaml to_hash.to_yaml end |