phtools 0.10.0 → 0.11.1
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 +4 -4
- data/.rubocop.yml +43 -0
- data/.rubocop_todo.yml +373 -0
- data/Guardfile +6 -3
- data/History.md +4 -0
- data/TODO.md +2 -0
- data/exe/phbackup +2 -1
- data/exe/phfixdto +2 -1
- data/exe/phfixfmd +2 -1
- data/exe/phgettags +2 -1
- data/exe/phls +2 -1
- data/exe/phmove +6 -3
- data/exe/phrename +2 -1
- data/exe/phtools +3 -1
- data/lib/phbackup.rb +2 -2
- data/lib/phevent.rb +2 -1
- data/lib/phfixdto.rb +4 -3
- data/lib/phfixfmd.rb +2 -2
- data/lib/phgettags.rb +7 -7
- data/lib/phls.rb +5 -6
- data/lib/phmove.rb +12 -21
- data/lib/phrename.rb +7 -6
- data/lib/phtagset.rb +2 -1
- data/lib/phtools/error.rb +2 -1
- data/lib/phtools/exif_tagger/error.rb +1 -0
- data/lib/phtools/exif_tagger/tag_collection.rb +17 -14
- data/lib/phtools/exif_tagger/tag_writer.rb +8 -7
- data/lib/phtools/exif_tagger/tags/_tag.rb +92 -37
- data/lib/phtools/exif_tagger/tags/_tag_array_of_strings.rb +35 -0
- data/lib/phtools/exif_tagger/tags/_tag_date.rb +25 -27
- data/lib/phtools/exif_tagger/tags/_tag_hash_of_strings.rb +39 -0
- data/lib/phtools/exif_tagger/tags/_tag_string.rb +32 -0
- data/lib/phtools/exif_tagger/tags/city.rb +7 -21
- data/lib/phtools/exif_tagger/tags/coded_character_set.rb +6 -21
- data/lib/phtools/exif_tagger/tags/collections.rb +20 -26
- data/lib/phtools/exif_tagger/tags/copyright.rb +6 -22
- data/lib/phtools/exif_tagger/tags/country.rb +6 -23
- data/lib/phtools/exif_tagger/tags/country_code.rb +5 -21
- data/lib/phtools/exif_tagger/tags/create_date.rb +17 -13
- data/lib/phtools/exif_tagger/tags/creator.rb +14 -25
- data/lib/phtools/exif_tagger/tags/date_time_original.rb +18 -13
- data/lib/phtools/exif_tagger/tags/gps_created.rb +21 -44
- data/lib/phtools/exif_tagger/tags/image_unique_id.rb +12 -27
- data/lib/phtools/exif_tagger/tags/keywords.rb +15 -27
- data/lib/phtools/exif_tagger/tags/location.rb +6 -23
- data/lib/phtools/exif_tagger/tags/modify_date.rb +8 -8
- data/lib/phtools/exif_tagger/tags/state.rb +6 -23
- data/lib/phtools/exif_tagger/tags/world_region.rb +6 -22
- data/lib/phtools/exif_tagger/tags.rb +2 -1
- data/lib/phtools/exif_tagger.rb +1 -0
- data/lib/phtools/ph_file.rb +35 -14
- data/lib/phtools/runner.rb +4 -4
- data/lib/phtools/utils.rb +1 -0
- data/lib/phtools/version.rb +2 -1
- data/lib/phtools.rb +11 -9
- metadata +7 -2
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# encoding: UTF-8
|
4
|
+
# (c) ANB Andrew Bizyaev
|
5
|
+
|
6
|
+
require_relative '_tag'
|
7
|
+
|
8
|
+
module ExifTagger
|
9
|
+
module Tag
|
10
|
+
class TagHashOfStrings < Tag
|
11
|
+
private
|
12
|
+
|
13
|
+
def validate_hash_items
|
14
|
+
end
|
15
|
+
|
16
|
+
def validate_type
|
17
|
+
if @value.is_a?(Hash)
|
18
|
+
@value.each_value do |val|
|
19
|
+
validate_string_size(val)
|
20
|
+
end
|
21
|
+
unknown_keys = @value.keys - self.class::VALID_KEYS
|
22
|
+
unknown_keys.each do |k|
|
23
|
+
@errors << %(#{tag_name}: KEY '#{k}' is unknown)
|
24
|
+
end
|
25
|
+
missed_keys = self.class::VALID_KEYS - @value.keys
|
26
|
+
missed_keys.each do |k|
|
27
|
+
@errors << %(#{tag_name}: KEY '#{k}' is missed)
|
28
|
+
end
|
29
|
+
validate_hash_items if @errors.empty?
|
30
|
+
else
|
31
|
+
@errors << %(#{tag_name}: '#{@value}' is a wrong type \(#{@value.class}\))
|
32
|
+
end
|
33
|
+
return if @errors.empty?
|
34
|
+
@value_invalid << @value
|
35
|
+
@value = EMPTY
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
# encoding: UTF-8
|
4
|
+
# (c) ANB Andrew Bizyaev
|
5
|
+
|
6
|
+
require_relative '_tag'
|
7
|
+
|
8
|
+
module ExifTagger
|
9
|
+
module Tag
|
10
|
+
class TagString < Tag
|
11
|
+
private
|
12
|
+
|
13
|
+
def get_from_raw
|
14
|
+
@raw_values.each_value do |value|
|
15
|
+
return value unless Tag.empty?(value)
|
16
|
+
end
|
17
|
+
EMPTY
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_type
|
21
|
+
if @value.is_a?(String)
|
22
|
+
validate_string_size(@value)
|
23
|
+
else
|
24
|
+
@errors << %(#{tag_name}: '#{@value}' is a wrong type \(#{@value.class}\))
|
25
|
+
end
|
26
|
+
return if @errors.empty?
|
27
|
+
@value_invalid << @value
|
28
|
+
@value = EMPTY
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,38 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# MWG:City, String[0,32]
|
10
11
|
# = IPTC:City XMP-photoshop:City XMP-iptcExt:LocationShownCity
|
11
|
-
|
12
|
-
MAX_BYTESIZE = 32
|
13
|
-
EXIFTOOL_TAGS = %w(City LocationShownCity)
|
12
|
+
# Read sequence from mini_exiftool hash: City, LocationShownCity
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
class City < TagString
|
15
|
+
MAX_BYTESIZE = 32
|
16
|
+
EXIFTOOL_TAGS = %w(City LocationShownCity).freeze
|
18
17
|
|
19
18
|
private
|
20
19
|
|
21
|
-
def validate
|
22
|
-
bsize = @value.bytesize
|
23
|
-
if bsize > MAX_BYTESIZE
|
24
|
-
@errors << %(#{tag_name}: '#{@value}' ) +
|
25
|
-
%(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
|
26
|
-
@value_invalid << @value
|
27
|
-
@value = ''
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
20
|
def generate_write_script_lines
|
32
|
-
@write_script_lines
|
33
|
-
unless @value.empty?
|
34
|
-
@write_script_lines << %Q(-MWG:City=#{@value})
|
35
|
-
end
|
21
|
+
@write_script_lines << %(-MWG:City=#{@value})
|
36
22
|
end
|
37
23
|
end
|
38
24
|
end
|
@@ -1,37 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# -IPTC:CodedCharacterSet, string[0,32]!
|
10
|
-
class CodedCharacterSet < Tag
|
11
|
-
MAX_BYTESIZE = 32
|
12
|
-
EXIFTOOL_TAGS = %w(CodedCharacterSet)
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
class CodedCharacterSet < TagString
|
13
|
+
MAX_BYTESIZE = 32
|
14
|
+
EXIFTOOL_TAGS = %w(CodedCharacterSet).freeze
|
17
15
|
|
18
16
|
private
|
19
17
|
|
20
|
-
def validate
|
21
|
-
bsize = @value.bytesize
|
22
|
-
if bsize > MAX_BYTESIZE
|
23
|
-
@errors << %{#{tag_name}: '#{@value}' } +
|
24
|
-
%{is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE}}
|
25
|
-
@value_invalid << @value
|
26
|
-
@value = ''
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
18
|
def generate_write_script_lines
|
31
|
-
@write_script_lines
|
32
|
-
unless @value.empty?
|
33
|
-
@write_script_lines << %Q(-IPTC:CodedCharacterSet=#{@value})
|
34
|
-
end
|
19
|
+
@write_script_lines << %(-IPTC:CodedCharacterSet=#{@value})
|
35
20
|
end
|
36
21
|
end
|
37
22
|
end
|
@@ -1,44 +1,38 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_hash_of_strings'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
|
-
# Collections (struct+)
|
10
|
+
# XMP-mwg-coll:Collections (struct+)
|
10
11
|
# CollectionName
|
11
12
|
# CollectionURI
|
12
|
-
class Collections <
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
super
|
17
|
-
end
|
13
|
+
class Collections < TagHashOfStrings
|
14
|
+
MAX_BYTESIZE = 64
|
15
|
+
VALID_KEYS = [:collection_name, :collection_uri].freeze
|
16
|
+
EXIFTOOL_TAGS = %w(CollectionName CollectionURI).freeze
|
18
17
|
|
19
18
|
private
|
20
19
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
@value = {}
|
33
|
-
end
|
20
|
+
def get_from_raw
|
21
|
+
result = {}
|
22
|
+
v = @raw_values['CollectionName']
|
23
|
+
v = v.split('; ') if v.is_a?(String)
|
24
|
+
result[:collection_name] = v[0]
|
25
|
+
|
26
|
+
v = @raw_values['CollectionURI']
|
27
|
+
v = v.split('; ') if v.is_a?(String)
|
28
|
+
result[:collection_uri] = v[0]
|
29
|
+
|
30
|
+
result
|
34
31
|
end
|
35
32
|
|
36
33
|
def generate_write_script_lines
|
37
|
-
@write_script_lines
|
38
|
-
|
39
|
-
@write_script_lines << %Q(-XMP-mwg-coll:Collections-={CollectionName=#{@value[:collection_name]}, CollectionURI=#{@value[:collection_uri]}})
|
40
|
-
@write_script_lines << %Q(-XMP-mwg-coll:Collections+={CollectionName=#{@value[:collection_name]}, CollectionURI=#{@value[:collection_uri]}})
|
41
|
-
end
|
34
|
+
@write_script_lines << %(-XMP-mwg-coll:Collections-={CollectionName=#{@value[:collection_name]}, CollectionURI=#{@value[:collection_uri]}})
|
35
|
+
@write_script_lines << %(-XMP-mwg-coll:Collections+={CollectionName=#{@value[:collection_name]}, CollectionURI=#{@value[:collection_uri]}})
|
42
36
|
end
|
43
37
|
end
|
44
38
|
end
|
@@ -1,38 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# NMG:Copyright, string[0,128]
|
10
|
-
#
|
11
|
-
class Copyright <
|
11
|
+
# EXIF:Copyright, IPTC:CopyrightNotice, XMP-dc:Rights
|
12
|
+
class Copyright < TagString
|
12
13
|
MAX_BYTESIZE = 128
|
13
|
-
EXIFTOOL_TAGS = %w(Copyright CopyrightNotice Rights)
|
14
|
-
|
15
|
-
def initialize(value_raw = '')
|
16
|
-
super(value_raw.to_s)
|
17
|
-
end
|
14
|
+
EXIFTOOL_TAGS = %w(Copyright CopyrightNotice Rights).freeze
|
18
15
|
|
19
16
|
private
|
20
17
|
|
21
|
-
def validate
|
22
|
-
bsize = @value.bytesize
|
23
|
-
if bsize > MAX_BYTESIZE
|
24
|
-
@errors << %{#{tag_name}: '#{@value}' } +
|
25
|
-
%{is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE}}
|
26
|
-
@value_invalid << @value
|
27
|
-
@value = ''
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
18
|
def generate_write_script_lines
|
32
|
-
@write_script_lines
|
33
|
-
unless @value.empty?
|
34
|
-
@write_script_lines << %Q(-MWG:Copyright=#{@value})
|
35
|
-
end
|
19
|
+
@write_script_lines << %(-MWG:Copyright=#{@value})
|
36
20
|
end
|
37
21
|
end
|
38
22
|
end
|
@@ -1,39 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# MWG:Country, String[0,64]
|
10
|
-
#
|
11
|
-
|
12
|
-
class Country < Tag
|
11
|
+
# IPTC:Country-PrimaryLocationName, XMP-photoshop:Country, XMP-iptcExt:LocationShownCountryName
|
12
|
+
class Country < TagString
|
13
13
|
MAX_BYTESIZE = 64
|
14
|
-
EXIFTOOL_TAGS = %w(Country-PrimaryLocationName Country LocationShownCountryName)
|
15
|
-
|
16
|
-
def initialize(value_raw = '')
|
17
|
-
super(value_raw.to_s)
|
18
|
-
end
|
14
|
+
EXIFTOOL_TAGS = %w(Country-PrimaryLocationName Country LocationShownCountryName).freeze
|
19
15
|
|
20
16
|
private
|
21
17
|
|
22
|
-
def validate
|
23
|
-
bsize = @value.bytesize
|
24
|
-
if bsize > MAX_BYTESIZE
|
25
|
-
@errors << %(#{tag_name}: '#{@value}' ) +
|
26
|
-
%(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
|
27
|
-
@value_invalid << @value
|
28
|
-
@value = ''
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
18
|
def generate_write_script_lines
|
33
|
-
@write_script_lines
|
34
|
-
unless @value.empty?
|
35
|
-
@write_script_lines << %Q(-MWG:Country=#{@value})
|
36
|
-
end
|
19
|
+
@write_script_lines << %(-MWG:Country=#{@value})
|
37
20
|
end
|
38
21
|
end
|
39
22
|
end
|
@@ -1,37 +1,21 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# XMP-iptcExt:LocationShownCountryCode, String
|
10
|
-
class CountryCode <
|
11
|
+
class CountryCode < TagString
|
11
12
|
MAX_BYTESIZE = 32
|
12
|
-
EXIFTOOL_TAGS = %w(LocationShownCountryCode)
|
13
|
-
|
14
|
-
def initialize(value_raw = '')
|
15
|
-
super(value_raw.to_s)
|
16
|
-
end
|
13
|
+
EXIFTOOL_TAGS = %w(LocationShownCountryCode).freeze
|
17
14
|
|
18
15
|
private
|
19
16
|
|
20
|
-
def validate
|
21
|
-
bsize = @value.bytesize
|
22
|
-
if bsize > MAX_BYTESIZE
|
23
|
-
@errors << %(#{tag_name}: '#{@value}' ) +
|
24
|
-
%(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
|
25
|
-
@value_invalid << @value
|
26
|
-
@value = ''
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
17
|
def generate_write_script_lines
|
31
|
-
@write_script_lines
|
32
|
-
unless @value.empty?
|
33
|
-
@write_script_lines << %Q(-XMP-iptcExt:LocationShownCountryCode=#{@value})
|
34
|
-
end
|
18
|
+
@write_script_lines << %(-XMP:LocationShownCountryCode=#{@value})
|
35
19
|
end
|
36
20
|
end
|
37
21
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
@@ -7,25 +8,28 @@ require_relative '_tag_date'
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# -MWG:CreateDate:
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# IPTC:DigitalCreationTime
|
14
|
-
# XMP-xmp:CreateDate
|
11
|
+
# EXIF:CreateDate (EXIF:SubSecTimeDigitized),
|
12
|
+
# IPTC:DigitalCreationDate+IPTC:DigitalCreationTime,
|
13
|
+
# XMP-xmp:CreateDate
|
15
14
|
# creation date of the digital representation
|
16
15
|
class CreateDate < TagDate
|
17
|
-
|
16
|
+
MAX_BYTESIZE = 32
|
17
|
+
EXIFTOOL_TAGS = %w(CreateDate SubSecTimeDigitized DigitalCreationDate DigitalCreationTime).freeze
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
+
def get_from_raw
|
22
|
+
return @raw_values['CreateDate'] unless Tag.empty?(@raw_values['CreateDate'])
|
23
|
+
return make_date_from(@raw_values['DigitalCreationDate'], @raw_values['DigitalCreationTime']) unless Tag.empty?(@raw_values['DigitalCreationDate'])
|
24
|
+
EMPTY
|
25
|
+
end
|
26
|
+
|
21
27
|
def generate_write_script_lines
|
22
|
-
@write_script_lines
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@write_script_lines << %Q(-MWG:CreateDate=#{@value.strftime('%F %T')})
|
28
|
-
end
|
28
|
+
@write_script_lines << if @value.is_a?(DateTime)
|
29
|
+
%(-MWG:CreateDate=#{@value.strftime('%F %T')})
|
30
|
+
else
|
31
|
+
%(-MWG:CreateDate=#{@value})
|
32
|
+
end
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
@@ -1,41 +1,30 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_array_of_strings'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# MWG:Creator, string[0,32]+, List of strings
|
10
|
-
#
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
# EXIF:Artist, IPTC:By-line, XMP-dc:Creator
|
12
|
+
# exiftool types:
|
13
|
+
# Artist = String "aaa; bbb"
|
14
|
+
# By-line = Array ["aaa", "bbb"] OR String "aaa"
|
15
|
+
# Creator = Array ["aaa", "bbb"] OR String "aaa"
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
class Creator < TagArrayOfStrings
|
18
|
+
MAX_BYTESIZE = 32
|
19
|
+
EXIFTOOL_TAGS = %w(Artist By-line Creator).freeze
|
18
20
|
|
19
21
|
private
|
20
22
|
|
21
|
-
def validate
|
22
|
-
@value.each do |v|
|
23
|
-
bsize = v.bytesize
|
24
|
-
if bsize > MAX_BYTESIZE
|
25
|
-
@errors << %(#{tag_name}: '#{v}' ) +
|
26
|
-
%(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
|
27
|
-
@value_invalid << v
|
28
|
-
end
|
29
|
-
end
|
30
|
-
@value = @value - @value_invalid
|
31
|
-
end
|
32
|
-
|
33
23
|
def generate_write_script_lines
|
34
|
-
@
|
35
|
-
|
36
|
-
|
37
|
-
@write_script_lines << %
|
38
|
-
@write_script_lines << %Q(-MWG:Creator+=#{o})
|
24
|
+
@value.each do |o|
|
25
|
+
unless Tag.empty?(o)
|
26
|
+
@write_script_lines << %(-MWG:Creator-=#{o})
|
27
|
+
@write_script_lines << %(-MWG:Creator+=#{o})
|
39
28
|
end
|
40
29
|
end
|
41
30
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
@@ -7,25 +8,29 @@ require_relative '_tag_date'
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# -MWG:DateTimeOriginal:
|
10
|
-
# EXIF:DateTimeOriginal
|
11
|
-
# EXIF:SubSecTimeOriginal
|
12
|
-
# IPTC:DateCreated
|
13
|
-
# IPTC:TimeCreated
|
14
|
-
# XMP-photoshop:DateCreated
|
11
|
+
# EXIF:DateTimeOriginal, (EXIF:SubSecTimeOriginal), IPTC:DateCreated + IPTC:TimeCreated, XMP-photoshop:DateCreated
|
15
12
|
# creation date of the intellectual content being shown
|
16
13
|
class DateTimeOriginal < TagDate
|
17
|
-
|
14
|
+
MAX_BYTESIZE = 32
|
15
|
+
EXIFTOOL_TAGS = %w(DateTimeOriginal SubSecTimeOriginal DateCreated TimeCreated).freeze
|
18
16
|
|
19
17
|
private
|
20
18
|
|
21
|
-
def
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
@
|
26
|
-
when @value.kind_of?(DateTime) || @value.kind_of?(Time)
|
27
|
-
@write_script_lines << %Q(-MWG:DateTimeOriginal=#{@value.strftime('%F %T')})
|
19
|
+
def get_from_raw
|
20
|
+
return @raw_values['DateTimeOriginal'] unless Tag.empty?(@raw_values['DateTimeOriginal'])
|
21
|
+
unless Tag.empty?(@raw_values['DateCreated'])
|
22
|
+
return @raw_values['DateCreated'] if @raw_values['DateCreated'].is_a?(DateTime)
|
23
|
+
return make_date_from(@raw_values['DateCreated'], @raw_values['TimeCreated']) if @raw_values['DateCreated'].is_a?(String)
|
28
24
|
end
|
25
|
+
EMPTY
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_write_script_lines
|
29
|
+
@write_script_lines << if @value.is_a?(DateTime)
|
30
|
+
%(-MWG:DateTimeOriginal=#{@value.strftime('%F %T')})
|
31
|
+
else
|
32
|
+
%(-MWG:DateTimeOriginal=#{@value})
|
33
|
+
end
|
29
34
|
end
|
30
35
|
end
|
31
36
|
end
|
@@ -1,8 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_hash_of_strings'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
@@ -13,9 +14,10 @@ module ExifTagger
|
|
13
14
|
# GPSLongitudeRef (string[2] 'E' = East, 'W' = West)
|
14
15
|
# GPSAltitude (rational64u)
|
15
16
|
# GPSAltitudeRef (int8u 0 = Above Sea Level, 1 = Below Sea Level)
|
16
|
-
class GpsCreated <
|
17
|
-
|
18
|
-
|
17
|
+
class GpsCreated < TagHashOfStrings
|
18
|
+
MAX_BYTESIZE = 64
|
19
|
+
VALID_KEYS = [:gps_latitude, :gps_latitude_ref, :gps_longitude, :gps_longitude_ref, :gps_altitude, :gps_altitude_ref].freeze
|
20
|
+
VALID_VALUES = { gps_latitude_ref: %w(N S North South), gps_longitude_ref: %w(E W East West), gps_altitude_ref: ['Above Sea Level', 'Below Sea Level', '0', '1'] }.freeze
|
19
21
|
EXIFTOOL_TAGS = %w(
|
20
22
|
GPSPosition
|
21
23
|
GPSLatitude
|
@@ -24,54 +26,29 @@ module ExifTagger
|
|
24
26
|
GPSLongitudeRef
|
25
27
|
GPSAltitude
|
26
28
|
GPSAltitudeRef
|
27
|
-
)
|
28
|
-
|
29
|
-
def initialize(value_raw = {})
|
30
|
-
# TODO: value = value_raw.each { |k, v| value_raw[k] = v.to_s }
|
31
|
-
super
|
32
|
-
end
|
29
|
+
).freeze
|
33
30
|
|
34
31
|
private
|
35
32
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
end
|
45
|
-
if @errors.empty?
|
46
|
-
valid_values = ['N', 'S']
|
47
|
-
unless valid_values.include? @value[:gps_latitude_ref]
|
48
|
-
@errors << %(#{tag_name}: value of 'gps_latitude_ref' should be one of #{valid_values})
|
49
|
-
end
|
50
|
-
valid_values = ['E', 'W']
|
51
|
-
unless valid_values.include? @value[:gps_longitude_ref]
|
52
|
-
@errors << %(#{tag_name}: value of 'gps_longitude_ref' should be one of #{valid_values})
|
53
|
-
end
|
54
|
-
valid_values = ['Above Sea Level', 'Below Sea Level']
|
55
|
-
unless valid_values.include? @value[:gps_altitude_ref]
|
56
|
-
@errors << %(#{tag_name}: value of 'gps_altitude_ref' should be one of #{valid_values})
|
33
|
+
def get_from_raw
|
34
|
+
{ gps_latitude: @raw_values['GPSLatitude'], gps_latitude_ref: @raw_values['GPSLatitudeRef'], gps_longitude: @raw_values['GPSLongitude'], gps_longitude_ref: @raw_values['GPSLongitudeRef'], gps_altitude: @raw_values['GPSAltitude'], gps_altitude_ref: @raw_values['GPSAltitudeRef'] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_hash_items
|
38
|
+
VALID_VALUES.each do |vv_key, vv_val|
|
39
|
+
unless vv_val.include?(@value[vv_key])
|
40
|
+
@errors << %(#{tag_name}: value of '#{vv_key}' should be one of #{vv_val})
|
57
41
|
end
|
58
42
|
end
|
59
|
-
unless @errors.empty?
|
60
|
-
@value_invalid << @value
|
61
|
-
@value = {}
|
62
|
-
end
|
63
43
|
end
|
64
44
|
|
65
45
|
def generate_write_script_lines
|
66
|
-
@write_script_lines =
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
@write_script_lines << %Q(-GPSAltitude=#{@value[:gps_altitude]})
|
73
|
-
@write_script_lines << %Q(-GPSAltitudeRef=#{@value[:gps_altitude_ref]})
|
74
|
-
end
|
46
|
+
@write_script_lines << %(-GPSLatitude="#{@value[:gps_latitude]}")
|
47
|
+
@write_script_lines << %(-GPSLatitudeRef=#{@value[:gps_latitude_ref]})
|
48
|
+
@write_script_lines << %(-GPSLongitude="#{@value[:gps_longitude]}")
|
49
|
+
@write_script_lines << %(-GPSLongitudeRef=#{@value[:gps_longitude_ref]})
|
50
|
+
@write_script_lines << %(-GPSAltitude=#{@value[:gps_altitude]})
|
51
|
+
@write_script_lines << %(-GPSAltitudeRef=#{@value[:gps_altitude_ref]})
|
75
52
|
end
|
76
53
|
end
|
77
54
|
end
|
@@ -1,46 +1,31 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
# encoding: UTF-8
|
3
4
|
# (c) ANB Andrew Bizyaev
|
4
5
|
|
5
|
-
require_relative '
|
6
|
+
require_relative '_tag_string'
|
6
7
|
|
7
8
|
module ExifTagger
|
8
9
|
module Tag
|
9
10
|
# ImageUniqueID, String
|
10
|
-
class ImageUniqueId <
|
11
|
-
MAX_BYTESIZE = 32
|
12
|
-
EXIFTOOL_TAGS = %w(ImageUniqueID)
|
11
|
+
class ImageUniqueId < TagString
|
12
|
+
MAX_BYTESIZE = 32
|
13
|
+
EXIFTOOL_TAGS = %w(ImageUniqueID).freeze
|
13
14
|
|
14
|
-
|
15
|
-
super(value_raw.to_s)
|
16
|
-
end
|
15
|
+
private
|
17
16
|
|
18
|
-
def
|
17
|
+
def validate_vs_previous
|
19
18
|
@warnings = []
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
return if @previous.nil?
|
20
|
+
val = @previous.raw_values[EXIFTOOL_TAGS[0]]
|
21
|
+
if val =~ /(\d{8}-\S+)/
|
22
|
+
@warnings << "#{tag_name} has original value: '#{val}'"
|
23
23
|
end
|
24
24
|
@warnings.freeze
|
25
25
|
end
|
26
26
|
|
27
|
-
private
|
28
|
-
|
29
|
-
def validate
|
30
|
-
bsize = @value.bytesize
|
31
|
-
if bsize > MAX_BYTESIZE
|
32
|
-
@errors << %(#{tag_name}: '#{@value}' ) +
|
33
|
-
%(is #{bsize - MAX_BYTESIZE} bytes longer than allowed #{MAX_BYTESIZE})
|
34
|
-
@value_invalid << @value
|
35
|
-
@value = ''
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
27
|
def generate_write_script_lines
|
40
|
-
@write_script_lines
|
41
|
-
unless @value.empty?
|
42
|
-
@write_script_lines << %Q(-ImageUniqueID=#{@value})
|
43
|
-
end
|
28
|
+
@write_script_lines << %(-ImageUniqueID=#{@value})
|
44
29
|
end
|
45
30
|
end
|
46
31
|
end
|