exiftool 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/README.md +113 -0
- data/Rakefile +17 -0
- data/exiftool.gemspec +30 -0
- data/lib/exiftool.rb +73 -0
- data/lib/exiftool/parser.rb +62 -0
- data/lib/exiftool/result.rb +32 -0
- data/lib/exiftool/version.rb +3 -0
- data/test/Canon 20D.jpg +0 -0
- data/test/Canon 20D.jpg.yaml +225 -0
- data/test/Droid X.jpg +0 -0
- data/test/Droid X.jpg.yaml +89 -0
- data/test/IMG_2452.jpg +0 -0
- data/test/IMG_2452.jpg.yaml +211 -0
- data/test/exiftoolr_test.rb +87 -0
- data/test/faces.jpg +0 -0
- data/test/faces.jpg.yaml +318 -0
- data/test/iPhone 4S.jpg +0 -0
- data/test/iPhone 4S.jpg.yaml +82 -0
- data/test/parser_test.rb +58 -0
- data/test/test_helper.rb +14 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 97cc49e13b847ed687dca2430f6e3974d1327998
|
4
|
+
data.tar.gz: 7a6c7e780ad4962983b491c517d2f4a8a890264b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 614fee303365b7d799ebf3d29109502194ed89f35685f4dfabe45a729fd184a23e3d657bc4c91270e5c9ffdda7873f613956c4fa511bfa067f52996500f93f28
|
7
|
+
data.tar.gz: 97ad66d4cab65ea08313ae3b24222852ab9477113deb276eecb88dbda568d59833ddcd164485a5d68857cbca6393729443ddd792d9924d136785c4d1873136f9
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# Ruby wrapper for ExifTool
|
2
|
+
|
3
|
+
[](http://travis-ci.org/mceachen/exiftool)
|
4
|
+
[](http://rubygems.org/gems/exiftool)
|
5
|
+
[](https://codeclimate.com/github/mceachen/exiftool)
|
6
|
+
|
7
|
+
This gem is the simplest thing that could possibly work that
|
8
|
+
reads the output of [exiftool](http://www.sno.phy.queensu.ca/~phil/exiftool)
|
9
|
+
and renders it into a ruby hash, with correctly typed values and symbolized keys.
|
10
|
+
|
11
|
+
Rubies 1.9 and later are supported.
|
12
|
+
|
13
|
+
## Features
|
14
|
+
|
15
|
+
* GPS latitude and longitude values are parsed as signed floats,
|
16
|
+
where north and east are positive, and west and south are negative.
|
17
|
+
* Values like shutter speed and exposure time are rendered as Rationals,
|
18
|
+
which lets the caller show them as fractions (1/250) or as comparable numeric instances.
|
19
|
+
* String values like "interop" and "serial number" are kept as strings
|
20
|
+
(which preserves zero prefixes)
|
21
|
+
* Timestamps are attempted to be interpreted with correct timezones and sub-second resolution, if
|
22
|
+
the header contains that data.
|
23
|
+
Please note that EXIF headers don't always include a timezone offset, so we just adopt the system
|
24
|
+
timezone, which may, of course, be wrong.
|
25
|
+
* No method_missing madness
|
26
|
+
|
27
|
+
## Usage
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require 'Exiftool'
|
31
|
+
e = Exiftool.new("path/to/iPhone 4S.jpg")
|
32
|
+
e.to_hash
|
33
|
+
# => {:make => "Apple", :gps_longitude => -122.47566667, …
|
34
|
+
e.to_display_hash
|
35
|
+
# => {"Make" => "Apple", "GPS Longitude" => -122.47566667, …
|
36
|
+
```
|
37
|
+
|
38
|
+
### Multiple file support
|
39
|
+
|
40
|
+
This gem supports Exiftool's multiget, which lets you fetch metadata for many files at once.
|
41
|
+
|
42
|
+
This can be dramatically more efficient (like, 60x faster) than spinning up the ```exiftool```
|
43
|
+
process for each file.
|
44
|
+
|
45
|
+
Supply an array to the Exiftool initializer, then use ```.result_for```:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'Exiftool'
|
49
|
+
e = Exiftool.new(Dir["**/*.jpg"])
|
50
|
+
result = e.result_for("path/to/iPhone 4S.jpg")
|
51
|
+
result.to_hash
|
52
|
+
# => {:make => "Apple", :gps_longitude => -122.47566667, …
|
53
|
+
result[:gps_longitude]
|
54
|
+
# => -122.47566667
|
55
|
+
|
56
|
+
e.files_with_results
|
57
|
+
# => ["path/to/iPhone 4S.jpg", "path/to/Droid X.jpg", …
|
58
|
+
```
|
59
|
+
|
60
|
+
### When things go wrong
|
61
|
+
|
62
|
+
* ```Exiftool::NoSuchFile``` is raised if the provided filename doesn't exist.
|
63
|
+
* ```Exiftool::ExiftoolNotInstalled``` is raised if ```exiftool``` isn't in your ```PATH```.
|
64
|
+
* If ExifTool has a problem reading EXIF data, no exception is raised, but ```#errors?``` will return true:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
Exiftool.new("Gemfile").errors?
|
68
|
+
#=> true
|
69
|
+
```
|
70
|
+
|
71
|
+
## Installation
|
72
|
+
|
73
|
+
First [install ExifTool](http://www.sno.phy.queensu.ca/~phil/exiftool/install.html).
|
74
|
+
|
75
|
+
Then, add this your Gemfile:
|
76
|
+
|
77
|
+
gem 'exiftool'
|
78
|
+
|
79
|
+
and then run ```bundle```.
|
80
|
+
|
81
|
+
## Change history
|
82
|
+
|
83
|
+
### 0.2.0
|
84
|
+
|
85
|
+
* Renamed from exiftoolr to exiftool
|
86
|
+
|
87
|
+
### 0.1.0
|
88
|
+
|
89
|
+
* Better timestamp parsing—now both sub-second and timezone offsets are handled correctly
|
90
|
+
* Switched to minitest-spec
|
91
|
+
* Ruby 1.8.7 is no longer supported, hence the minor version uptick.
|
92
|
+
|
93
|
+
### 0.0.9
|
94
|
+
|
95
|
+
* Explicitly added MIT licensing to the gemspec.
|
96
|
+
|
97
|
+
### 0.0.8
|
98
|
+
|
99
|
+
* Extracted methods in parsing to make the code complexity lower. FOUR DOT OH GPA
|
100
|
+
|
101
|
+
### 0.0.7
|
102
|
+
|
103
|
+
* Added warning values for EXIF headers that are corrupt
|
104
|
+
* Made initialize gracefully accept an empty array, or an array of Pathname instances
|
105
|
+
* Added support for ruby 1.9.3 and exiftool v8.15 (Ubuntu Natty) and v8.85 (current stable version)
|
106
|
+
|
107
|
+
### 0.0.5
|
108
|
+
|
109
|
+
Fixed homepage URL in gemspec
|
110
|
+
|
111
|
+
### 0.0.4
|
112
|
+
|
113
|
+
Added support for multiple file fetching (which is *much* faster for large directories)
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
require 'yard'
|
4
|
+
YARD::Rake::YardocTask.new do |t|
|
5
|
+
t.files = ['lib/**/*.rb', 'README.md']
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'rake/testtask'
|
9
|
+
|
10
|
+
Rake::TestTask.new do |t|
|
11
|
+
t.libs.push "lib"
|
12
|
+
t.libs.push "test"
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => :test
|
data/exiftool.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'exiftool/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'exiftool'
|
8
|
+
spec.version = Exiftool::VERSION
|
9
|
+
spec.authors = ['Matthew McEachen']
|
10
|
+
spec.email = %w(matthew-github@mceachen.org)
|
11
|
+
spec.homepage = 'https://github.com/mceachen/exiftoolr'
|
12
|
+
spec.summary = %q{Multiget ExifTool wrapper for ruby}
|
13
|
+
spec.description = %q{Multiget ExifTool wrapper for ruby}
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split("\n")
|
17
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.requirements << 'ExifTool (see http://www.sno.phy.queensu.ca/~phil/exiftool/)'
|
22
|
+
|
23
|
+
spec.add_dependency 'json'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'bundler'
|
26
|
+
spec.add_development_dependency 'yard'
|
27
|
+
spec.add_development_dependency 'minitest'
|
28
|
+
spec.add_development_dependency 'minitest-great_expectations'
|
29
|
+
spec.add_development_dependency 'minitest-reporters' unless ENV['CI']
|
30
|
+
end
|
data/lib/exiftool.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'exiftool/result'
|
4
|
+
|
5
|
+
class Exiftool
|
6
|
+
class NoSuchFile < StandardError ; end
|
7
|
+
class NotAFile < StandardError ; end
|
8
|
+
class ExiftoolNotInstalled < StandardError ; end
|
9
|
+
|
10
|
+
def self.exiftool_installed?
|
11
|
+
exiftool_version > 0
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.exiftool_version
|
15
|
+
@@exiftool_version ||= `exiftool -ver 2> /dev/null`.to_f
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.expand_path(filename)
|
19
|
+
raise(NoSuchFile, filename) unless File.exist?(filename)
|
20
|
+
raise(NotAFile, filename) unless File.file?(filename)
|
21
|
+
File.expand_path(filename)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(filenames, exiftool_opts = '')
|
25
|
+
@file2result = {}
|
26
|
+
filenames = [filenames] if filenames.is_a?(String)
|
27
|
+
unless filenames.empty?
|
28
|
+
escaped_filenames = filenames.collect do |f|
|
29
|
+
Shellwords.escape(self.class.expand_path(f.to_s))
|
30
|
+
end.join(" ")
|
31
|
+
# I'd like to use -dateformat, but it doesn't support timezone offsets properly,
|
32
|
+
# nor sub-second timestamps.
|
33
|
+
cmd = "exiftool #{exiftool_opts} -j -coordFormat \"%.8f\" #{escaped_filenames} 2> /dev/null"
|
34
|
+
json = `#{cmd}`
|
35
|
+
raise ExiftoolNotInstalled if json == ""
|
36
|
+
JSON.parse(json).each do |raw|
|
37
|
+
result = Result.new(raw)
|
38
|
+
@file2result[result.source_file] = result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def result_for(filename)
|
44
|
+
@file2result[self.class.expand_path(filename)]
|
45
|
+
end
|
46
|
+
|
47
|
+
def files_with_results
|
48
|
+
@file2result.values.collect { |r| r.source_file unless r.errors? }.compact
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_hash
|
52
|
+
first.to_hash
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_display_hash
|
56
|
+
first.to_display_hash
|
57
|
+
end
|
58
|
+
|
59
|
+
def symbol_display_hash
|
60
|
+
first.symbol_display_hash
|
61
|
+
end
|
62
|
+
|
63
|
+
def errors?
|
64
|
+
@file2result.values.any? { |ea| ea.errors? }
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def first
|
70
|
+
raise InvalidArgument, 'use #result_for when multiple filenames are used' if @file2result.size > 1
|
71
|
+
@file2result.values.first
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'rational'
|
3
|
+
|
4
|
+
class Exiftool
|
5
|
+
class Parser
|
6
|
+
|
7
|
+
WORD_BOUNDARY_RES = [/([A-Z\d]+)([A-Z][a-z])/, /([a-z\d])([A-Z])/]
|
8
|
+
FRACTION_RE = /^(\d+)\/(\d+)$/
|
9
|
+
|
10
|
+
attr_reader :key, :display_key, :sym_key, :raw_value
|
11
|
+
|
12
|
+
def initialize(key, raw_value)
|
13
|
+
@key = key
|
14
|
+
@display_key = WORD_BOUNDARY_RES.inject(key) { |k, regex| k.gsub(regex, '\1 \2') }
|
15
|
+
@sym_key = display_key.downcase.gsub(' ', '_').to_sym
|
16
|
+
@raw_value = raw_value
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
20
|
+
for_lat_long ||
|
21
|
+
for_date ||
|
22
|
+
for_fraction ||
|
23
|
+
raw_value
|
24
|
+
rescue StandardError => e
|
25
|
+
"Warning: Parsing '#{raw_value}' for attribute '#{key}' raised #{e.message}"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def for_lat_long
|
31
|
+
if sym_key == :gps_latitude || sym_key == :gps_longitude
|
32
|
+
value, direction = raw_value.split(" ")
|
33
|
+
if value =~ /\A\d+\.?\d*\z/
|
34
|
+
value.to_f * (['S', 'W'].include?(direction) ? -1 : 1)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def for_date
|
40
|
+
if raw_value.is_a?(String) && display_key =~ /\bdate\b/i
|
41
|
+
try_parse { Time.strptime(raw_value, '%Y:%m:%d %H:%M:%S%z') } ||
|
42
|
+
try_parse { Time.strptime(raw_value, '%Y:%m:%d %H:%M:%S') } ||
|
43
|
+
try_parse { Time.strptime(raw_value, '%Y:%m:%d %H:%M:%S.%L%z') } ||
|
44
|
+
try_parse { Time.strptime(raw_value, '%Y:%m:%d %H:%M:%S.%L') } ||
|
45
|
+
try_parse { Time.parse(raw_value) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def try_parse
|
50
|
+
yield
|
51
|
+
rescue ArgumentError
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def for_fraction
|
56
|
+
if raw_value.is_a?(String)
|
57
|
+
scan = raw_value.scan(FRACTION_RE).first
|
58
|
+
v = Rational(*scan.map { |ea| ea.to_i }) unless scan.nil?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'exiftool/parser'
|
2
|
+
|
3
|
+
class Exiftool
|
4
|
+
class Result
|
5
|
+
attr_reader :to_hash, :to_display_hash, :symbol_display_hash
|
6
|
+
|
7
|
+
def initialize(raw_hash)
|
8
|
+
@raw_hash = raw_hash
|
9
|
+
@to_hash = {}
|
10
|
+
@to_display_hash = {}
|
11
|
+
@symbol_display_hash = {}
|
12
|
+
@raw_hash.each do |key, raw_value|
|
13
|
+
p = Parser.new(key, raw_value)
|
14
|
+
@to_hash[p.sym_key] = p.value
|
15
|
+
@to_display_hash[p.display_key] = p.value
|
16
|
+
@symbol_display_hash[p.sym_key] = p.display_key
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](key)
|
21
|
+
@to_hash[key]
|
22
|
+
end
|
23
|
+
|
24
|
+
def source_file
|
25
|
+
self[:source_file]
|
26
|
+
end
|
27
|
+
|
28
|
+
def errors?
|
29
|
+
self[:error] == 'Unknown file type' || self[:warning] == 'Unsupported file type'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/test/Canon 20D.jpg
ADDED
Binary file
|
@@ -0,0 +1,225 @@
|
|
1
|
+
---
|
2
|
+
:source_file: /Users/mrm/Dropbox/code/exiftoolr/test/Canon 20D.jpg
|
3
|
+
:exif_tool_version: 9.31
|
4
|
+
:file_name: Canon 20D.jpg
|
5
|
+
:directory: /Users/mrm/Dropbox/code/exiftoolr/test
|
6
|
+
:file_size: 2.9 MB
|
7
|
+
:file_modify_date: 2012-02-23 05:22:17.000000000 +00:00
|
8
|
+
:file_access_date: 2013-07-14 20:25:41.000000000 +00:00
|
9
|
+
:file_inode_change_date: 2013-02-16 19:21:59.000000000 +00:00
|
10
|
+
:file_permissions: rw-r--r--
|
11
|
+
:file_type: JPEG
|
12
|
+
:mime_type: image/jpeg
|
13
|
+
:exif_byte_order: Little-endian (Intel, II)
|
14
|
+
:make: Canon
|
15
|
+
:model: Canon EOS 20D
|
16
|
+
:orientation: Horizontal (normal)
|
17
|
+
:x_resolution: 72
|
18
|
+
:y_resolution: 72
|
19
|
+
:resolution_unit: inches
|
20
|
+
:modify_date: 2004-09-19 12:25:20.000000000 +00:00
|
21
|
+
:y_cb_cr_positioning: Co-sited
|
22
|
+
:exposure_time: !ruby/object:Rational
|
23
|
+
denominator: 250
|
24
|
+
numerator: 1
|
25
|
+
:f_number: 9.0
|
26
|
+
:exposure_program: Program AE
|
27
|
+
:iso: 200
|
28
|
+
:exif_version: '0221'
|
29
|
+
:date_time_original: 2004-09-19 12:25:20.000000000 +00:00
|
30
|
+
:create_date: 2004-09-19 12:25:20.000000000 +00:00
|
31
|
+
:components_configuration: Y, Cb, Cr, -
|
32
|
+
:shutter_speed_value: !ruby/object:Rational
|
33
|
+
denominator: 250
|
34
|
+
numerator: 1
|
35
|
+
:aperture_value: 9.0
|
36
|
+
:flash: Off, Did not fire
|
37
|
+
:focal_length: 85.0 mm
|
38
|
+
:macro_mode: Normal
|
39
|
+
:self_timer: 'Off'
|
40
|
+
:quality: Fine
|
41
|
+
:canon_flash_mode: 'Off'
|
42
|
+
:continuous_drive: Single
|
43
|
+
:focus_mode: One-shot AF
|
44
|
+
:record_mode: JPEG
|
45
|
+
:canon_image_size: Large
|
46
|
+
:easy_mode: Manual
|
47
|
+
:digital_zoom: None
|
48
|
+
:contrast: '+1'
|
49
|
+
:saturation: '+1'
|
50
|
+
:sharpness: '+1'
|
51
|
+
:metering_mode: Evaluative
|
52
|
+
:focus_range: Not Known
|
53
|
+
:canon_exposure_mode: Program AE
|
54
|
+
:lens_type: Unknown (-1)
|
55
|
+
:max_focal_length: 85 mm
|
56
|
+
:min_focal_length: 17 mm
|
57
|
+
:focal_units: 1/mm
|
58
|
+
:max_aperture: 5.6
|
59
|
+
:min_aperture: 32
|
60
|
+
:flash_activity: 0
|
61
|
+
:flash_bits: (none)
|
62
|
+
:focus_continuous: Single
|
63
|
+
:zoom_source_width: 0
|
64
|
+
:zoom_target_width: 0
|
65
|
+
:photo_effect: 'Off'
|
66
|
+
:manual_flash_output: n/a
|
67
|
+
:focal_type: Zoom
|
68
|
+
:focal_plane_x_size: 23.04 mm
|
69
|
+
:focal_plane_y_size: 15.37 mm
|
70
|
+
:auto_iso: 100
|
71
|
+
:base_iso: 200
|
72
|
+
:measured_ev: 13.25
|
73
|
+
:target_aperture: 9
|
74
|
+
:target_exposure_time: !ruby/object:Rational
|
75
|
+
denominator: 251
|
76
|
+
numerator: 1
|
77
|
+
:exposure_compensation: 0
|
78
|
+
:white_balance: Auto
|
79
|
+
:slow_shutter: None
|
80
|
+
:sequence_number: 0
|
81
|
+
:optical_zoom_code: n/a
|
82
|
+
:flash_guide_number: 0
|
83
|
+
:flash_exposure_comp: 0
|
84
|
+
:auto_exposure_bracketing: 'Off'
|
85
|
+
:aeb_bracket_value: 0
|
86
|
+
:control_mode: Camera Local Control
|
87
|
+
:measured_ev2: 13.5
|
88
|
+
:bulb_duration: 0
|
89
|
+
:camera_type: EOS Mid-range
|
90
|
+
:auto_rotate: None
|
91
|
+
:nd_filter: n/a
|
92
|
+
:self_timer2: 0
|
93
|
+
:canon_image_type: Canon EOS 20D
|
94
|
+
:canon_firmware_version: Firmware 1.0.2
|
95
|
+
:owner_name: unknown
|
96
|
+
:serial_number: 0330113864
|
97
|
+
:set_function_when_shooting: Image replay
|
98
|
+
:long_exposure_noise_reduction: 'Off'
|
99
|
+
:flash_sync_speed_av: Auto
|
100
|
+
:shutter-ae_lock: AF/AE lock
|
101
|
+
:af_assist_beam: Emits
|
102
|
+
:exposure_level_increments: 1/3 Stop
|
103
|
+
:flash_firing: Fires
|
104
|
+
:iso_expansion: 'On'
|
105
|
+
:aeb_sequence_auto_cancel: 0,-,+/Enabled
|
106
|
+
:superimposed_display: 'On'
|
107
|
+
:menu_button_display_position: Previous (top if power off)
|
108
|
+
:mirror_lockup: Disable
|
109
|
+
:af_point_selection_method: Normal
|
110
|
+
:ettlii: Evaluative
|
111
|
+
:shutter_curtain_sync: 1st-curtain sync
|
112
|
+
:safety_shift_in_av_or_tv: Disable
|
113
|
+
:lens_af_stop_button: AF stop
|
114
|
+
:add_original_decision_data: 'Off'
|
115
|
+
:canon_model_id: EOS 20D
|
116
|
+
:num_af_points: 9
|
117
|
+
:valid_af_points: 9
|
118
|
+
:canon_image_width: 3504
|
119
|
+
:canon_image_height: 2336
|
120
|
+
:af_image_width: 3504
|
121
|
+
:af_image_height: 2336
|
122
|
+
:af_area_width: 78
|
123
|
+
:af_area_height: 78
|
124
|
+
:af_area_x_positions: 8 -555 571 -931 8 947 -555 571 8
|
125
|
+
:af_area_y_positions: 504 270 270 4 4 4 -262 -262 -496
|
126
|
+
:af_points_in_focus: 4
|
127
|
+
:thumbnail_image_valid_area: 0 159 7 112
|
128
|
+
:serial_number_format: Format 2
|
129
|
+
:original_decision_data_offset: 0
|
130
|
+
:file_number: 793-9390
|
131
|
+
:bracket_mode: 'Off'
|
132
|
+
:bracket_value: 0
|
133
|
+
:bracket_shot_number: 0
|
134
|
+
:long_exposure_noise_reduction2: 'Off'
|
135
|
+
:wb_bracket_mode: 'Off'
|
136
|
+
:wb_bracket_value_ab: 0
|
137
|
+
:wb_bracket_value_gm: 0
|
138
|
+
:filter_effect: None
|
139
|
+
:toning_effect: None
|
140
|
+
:tone_curve: Standard
|
141
|
+
:sharpness_frequency: n/a
|
142
|
+
:sensor_red_level: 0
|
143
|
+
:sensor_blue_level: 0
|
144
|
+
:white_balance_red: 0
|
145
|
+
:white_balance_blue: 0
|
146
|
+
:color_temperature: 4800
|
147
|
+
:picture_style: None
|
148
|
+
:digital_gain: 0
|
149
|
+
:wb_shift_ab: 0
|
150
|
+
:wb_shift_gm: 0
|
151
|
+
:measured_rggb: 674 1024 1024 670
|
152
|
+
:vrd_offset: 0
|
153
|
+
:sensor_width: 3596
|
154
|
+
:sensor_height: 2360
|
155
|
+
:sensor_left_border: 84
|
156
|
+
:sensor_top_border: 19
|
157
|
+
:sensor_right_border: 3587
|
158
|
+
:sensor_bottom_border: 2354
|
159
|
+
:black_mask_left_border: 0
|
160
|
+
:black_mask_top_border: 0
|
161
|
+
:black_mask_right_border: 0
|
162
|
+
:black_mask_bottom_border: 0
|
163
|
+
:wb_rggb_levels_as_shot: 1973 1015 1015 1663
|
164
|
+
:color_temp_as_shot: 4662
|
165
|
+
:wb_rggb_levels_auto: 1973 1023 1023 1663
|
166
|
+
:color_temp_auto: 4662
|
167
|
+
:wb_rggb_levels_daylight: 1995 1023 1023 1509
|
168
|
+
:color_temp_daylight: 5200
|
169
|
+
:wb_rggb_levels_shade: 2292 1023 1023 1267
|
170
|
+
:color_temp_shade: 7000
|
171
|
+
:wb_rggb_levels_cloudy: 2160 1023 1023 1373
|
172
|
+
:color_temp_cloudy: 6000
|
173
|
+
:wb_rggb_levels_tungsten: 1410 1023 1023 2408
|
174
|
+
:color_temp_tungsten: 3196
|
175
|
+
:wb_rggb_levels_fluorescent: 1797 1023 1023 2058
|
176
|
+
:color_temp_fluorescent: 3952
|
177
|
+
:wb_rggb_levels_flash: 2187 1023 1023 1333
|
178
|
+
:color_temp_flash: 6309
|
179
|
+
:wb_rggb_levels_custom1: 2095 1023 1023 1316
|
180
|
+
:color_temp_custom1: 6163
|
181
|
+
:wb_rggb_levels_custom2: 1912 1023 1023 1627
|
182
|
+
:color_temp_custom2: 4792
|
183
|
+
:color_tone: Normal
|
184
|
+
:user_comment: ''
|
185
|
+
:flashpix_version: '0100'
|
186
|
+
:color_space: sRGB
|
187
|
+
:exif_image_width: 3504
|
188
|
+
:exif_image_height: 2336
|
189
|
+
:interop_index: R98 - DCF basic file (sRGB)
|
190
|
+
:interop_version: '0100'
|
191
|
+
:focal_plane_x_resolution: 2886.363636
|
192
|
+
:focal_plane_y_resolution: 2885.805763
|
193
|
+
:focal_plane_resolution_unit: inches
|
194
|
+
:custom_rendered: Normal
|
195
|
+
:exposure_mode: Auto
|
196
|
+
:scene_capture_type: Standard
|
197
|
+
:compression: JPEG (old-style)
|
198
|
+
:thumbnail_offset: 9728
|
199
|
+
:thumbnail_length: 11259
|
200
|
+
:image_width: 3504
|
201
|
+
:image_height: 2336
|
202
|
+
:encoding_process: Baseline DCT, Huffman coding
|
203
|
+
:bits_per_sample: 8
|
204
|
+
:color_components: 3
|
205
|
+
:y_cb_cr_sub_sampling: YCbCr4:2:2 (2 1)
|
206
|
+
:aperture: 9.0
|
207
|
+
:drive_mode: Single-frame Shooting
|
208
|
+
:image_size: 3504x2336
|
209
|
+
:lens: 17.0 - 85.0 mm
|
210
|
+
:lens_id: Unknown 17-85mm
|
211
|
+
:scale_factor35efl: 1.0
|
212
|
+
:shooting_mode: Program AE
|
213
|
+
:shutter_speed: !ruby/object:Rational
|
214
|
+
denominator: 250
|
215
|
+
numerator: 1
|
216
|
+
:thumbnail_image: (Binary data 11259 bytes)
|
217
|
+
:wb_rggb_levels: 1973 1015 1015 1663
|
218
|
+
:blue_balance: 1.638424
|
219
|
+
:circle_of_confusion: 0.030 mm
|
220
|
+
:fov: 23.7 deg
|
221
|
+
:focal_length35efl: '85.0 mm (35 mm equivalent: 85.6 mm)'
|
222
|
+
:hyperfocal_distance: 26.91 m
|
223
|
+
:lens35efl: '17.0 - 85.0 mm (35 mm equivalent: 17.1 - 85.6 mm)'
|
224
|
+
:light_value: 13.3
|
225
|
+
:red_balance: 1.943842
|