#------------------------------------------------------------------------------ # File: locator.config # # Description: Definition for a Composite "Locator" tag to geocode latitude # and longitude as a grid square locator (Maidenhead Locator) # mainly used by Amateur Radio operators. # # Notes: The latitude and longitude should be expressed in decimal # degrees with sign (see CoordFormat in %Image::ExifTool::UserDefined::Options). # # The precision of the grid square is defined by the # -UserParam LocatorPrecision, which can have the values: # # 2 (field) # 4 (square) # 6 (subsquare) # 8 (extended square) # 10 (extended subsquare) # # If no precision is specified, the default value is 6 (subsquare). # # Requires the n2l subroutine. # # To see the grid square locator in a map go to # https://dxcluster.ha8tks.hu/hamgeocoding/ and type the grid # locator returned by the Locator tag. # # Tested with ExifTool 12.78 on macOS 12.6.3. # # References: Edmund T. Tyson, N5JTY (1992, January) Conversion Between Geodetic # and Grid Locator Systems. QST 29-30, 43. # # https://en.wikipedia.org/wiki/Maidenhead_Locator_System # # Examples: # > exiftool -config locator.config -gpslatitude -gpslongitude -locator -userparam locatorprecision=4 image.jpg # # GPS Latitude : +38.861903 # GPS Longitude : -77.116753 # Locator : FM18 # # > exiftool -config locator.config -gpslatitude -gpslongitude -locator image.jpg # # GPS Latitude : +38.861903 # GPS Longitude : -77.116753 # Locator : FM18ku # # Revisions: 2024/03/11 - Christian W. Correa (HK4QWC) Created #------------------------------------------------------------------------------ use POSIX qw/floor/; sub n2l { my ($number) = @_; my $index = { 0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd', 4 => 'e', 5 => 'f', 6 => 'g', 7 => 'h', 8 => 'i', 9 => 'j', 10 => 'k', 11 => 'l', 12 => 'm', 13 => 'n', 14 => 'o', 15 => 'p', 16 => 'q', 17 => 'r', 18 => 's', 19 => 't', 20 => 'u', 21 => 'v', 22 => 'w', 23 => 'x' }; return $index->{$number}; } %Image::ExifTool::UserDefined = ( 'Image::ExifTool::Composite' => { Locator => { Require => { 0 => 'Composite:GPSLatitude', 1 => 'Composite:GPSLongitude', }, ValueConv => q { my $locatorPrecision = $self->Options(UserParam => 'LocatorPrecision'); $locatorPrecision or ($locatorPrecision = 6); # the default locator precision is 6 (subsquare) my $locator; # To avoid negative numbers, the Prime Meridian has a false easting of 180° and the equator has a false northing of 90° my $lat = $val[0] + "90"; my $lng = $val[1] + "180"; # Compute Field $lat = ($lat / "10") + "0.0000001"; $lng = ($lng / "20") + "0.0000001"; $locator .= uc(n2l(floor($lng))).uc(n2l(floor($lat))); # Compute Square $lat = "10" * ($lat - floor($lat)); $lng = "10" * ($lng - floor($lng)); $locator .= floor($lng).floor($lat); # Compute Subsquare $lat = "24" * ($lat - floor($lat)); $lng = "24" * ($lng - floor($lng)); $locator .= n2l(floor($lng)).n2l(floor($lat)); # Compute Extended square $lat = "10" * ($lat - floor($lat)); $lng = "10" * ($lng - floor($lng)); $locator .= floor($lng).floor($lat); # Compute Extended Subsquare $lat = "24" * ($lat - floor($lat)); $lng = "24" * ($lng - floor($lng)); $locator .= n2l(floor($lng)).n2l(floor($lat)); return substr $locator, 0, $locatorPrecision; }, }, }, ); %Image::ExifTool::UserDefined::Options = ( CoordFormat => '%+.6f',# change default GPS coordinate format ); 1; #end