module FilePipeline::FileOperations::ExifManipulable

Mixin with methods to facilitate work with Exif metadata.

Public Class Methods

file_tags() click to toggle source

Returns an Array of tags to be ignored during comparison. These can be merged with an ExifManipulable including FileOperation's options to skip tags (e.g. the skip_tags option in ExifRestoration).

The included tags relate to the file properties (e.g. filesize, MIME-type) that will have been altered by any prior operation, such as file format conversions.

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 16
def self.file_tags
  %w[FileSize FileModifyDate FileAccessDate FileInodeChangeDate
     FilePermissions FileType FileTypeExtension MIMEType]
end

Public Instance Methods

delete_tags(out_file, tags_to_delete) click to toggle source

Redacts (deletes) all tags_to_delete in out_file.

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 31
def delete_tags(out_file, tags_to_delete)
  exif, = read_exif out_file
  values = exif.select { |tag| tags_to_delete.include? tag }
  values_to_delete = values.transform_values { nil }
  return 'Info: nothing to delete.' if values.empty?

  log, = write_exif out_file, values_to_delete
  [log, values]
end
missing_exif_fields(this_exif, other_exif) click to toggle source

Compares to hashes with exif tags and values and returns a hash with the tags that are present in other_exif but absent in this_exif.

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 44
def missing_exif_fields(this_exif, other_exif)
  other_exif.delete_if do |tag, _|
    this_exif.key?(tag) || options[:skip_tags].include?(tag)
  end
end
parse_exif_errors(error_messages, exif) click to toggle source

Takes an array of error_messages and a hash (exif) with tags and their values and parses errors where tags could not be written.

Returns an array with a log (any messages that were not errors where a tag could not be written) and data (a hash with any tags that could not be written, and the associated values from exif)

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 58
def parse_exif_errors(errs, values)
  errs.each_with_object(LogDataParser.template) do |message, info|
    errors, data = info
    tag = ExifManipulable.parse_tag_error(message)
    if tag
      data.store tag, values[tag]
      next info
    end
    errors << ExifManipulable.strip_path(message)
    info
  end
end
read_exif(*files) click to toggle source

Reads exif information for one or more files. Returns an array of hashes, one for each file, with tags and their values.

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 73
def read_exif(*files)
  file_paths = files.map { |f| File.expand_path(f) }
  results, errors = MultiExiftool.read file_paths
  raise 'Error reading Exif' unless errors.empty?

  results.map(&:to_h)
end
write_exif(out_file, values) click to toggle source

Writes values (a hash with exif tags as keys) to out_file.

Returns an array with a log (an array of messages - strings) and a hash with all tags/values that could not be written.

# File lib/file_pipeline/file_operations/exif_manipulable.rb, line 85
def write_exif(out_file, values)
  writer = MultiExiftool::Writer.new
  writer.filenames = Dir[File.expand_path(out_file)]
  writer.overwrite_original = true
  writer.values = values
  return if writer.write

  parse_exif_errors(writer.errors, values)
end