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
         |