Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Photoshop loosing GPS precision

Community Beginner ,
Jun 11, 2020 Jun 11, 2020

hi,

 

I need to place on the series of images a text layer with precise GPS data from jpeg exif. I am using script which reads latitude and longitude from the image with:

doc.info.exif[2][1]  - for latitude,
doc.info.exif[4][1]  - for longitude.
The problem is that Photoshop reads only dd,mm.mm. "Seconds" position is always equal to 0. That means that max resolution I get is 1/100 of the minute which is approx. 18.5 meters on the ground.
In "File info" however I can see that there are coordinates available in much higher resolution:
dd,mm,ss.ss (eg: 53d31'34.78"). 1/100 of the second is equal to 0.3m on the ground!
The format which Photoshop returns latitude and longitude is quite strange: dd.dd mm.mm ss.ss (eg: 52.00 12.50' 0.00") and doesn't make sense. Why is there fractional value of degree and minutes when "minute" is 1/60 of deg and "second" is  1/60 of minute? This is the same coordinate as above and makes much more sense: dd mm ss.ss (eg. 52 12' 30.00") - 0.50' minute is equal to 30" thats why 0.50' = 30".
How can I get higher precision value for longitude and latitude?
TOPICS
Actions and scripting
648
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
LEGEND ,
Jun 11, 2020 Jun 11, 2020

Possibly you can fetch that data via ActionManager or/and ExternalObject.AdobeXMPScript

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 11, 2020 Jun 11, 2020

I found a Shaun Ivory (shaun@ivory.org) script years ago that seems to get the  latitude and longitude better. It seems to get  Photoshop latitude or longitude, formatted like  this:   Example: 47.00 38.00' 33.60" then converts it to the decimal form: Example: 47.642667  

 

I did not write the script  I just used a sledge hammer on it . It had a dialog to that gave you a choice of 3 different website mapping site to use. All seemed to have been changed only Google map still seem to work.  So I bypass displaying the script dialog and went straight to Google Map. You may be able to find what you need in the script.

 

 

 

 

// Open Map from GPS Location.jsx
// Version 1.0
// Shaun Ivory (shaun@ivory.org)
//
// Feel free to modify this script.  If you do anything interesting with it,
// please let me know.

// JJMack I just used my sledge hammer on Shaun's Photoshop script 
// I sucked in his include file and removed his include statement
// then I commented out his dialog and just Goolge Map the GPS location

/*
<javascriptresource>
<about>$$$/JavaScripts/GoogleMapGPS/About=JJMack's Google Map GPS.^r^rCopyright 2014 Mouseprints.^r^rScript utility for action.^rNOTE:Modified Shaun's Ivory just Google Map GPS location</about>
<category>JJMack's Action Utility</category>
</javascriptresource>
*/

//
// Constants which identify the different mapping sites
//
c_MapWebsites =
[
    "google",
    "mappoint",
    "virtualearth"
];

var c_nDefaultMapWebsiteIndex = 2;
var c_strTemporaryUrlFile = "~/TemporaryPhotoshopMapUrl.url";

var c_strPhotoCaption = "Photo%20Location";
// EXIF constants
c_ExifGpsLatitudeRef   = "GPS Latitude Ref"
c_ExifGpsLatitude      = "GPS Latitude"
c_ExifGpsLongitudeRef  = "GPS Longitude Ref"
c_ExifGpsLongitude     = "GPS Longitude"
c_ExifGpsAltitudeRef   = "GPS Altitude Ref"
c_ExifGpsAltitude      = "GPS Altitude"
c_ExifGpsTimeStamp     = "GPS Time Stamp"
c_ExifMake             = "Make"
c_ExifModel            = "Model"
c_ExifExposureTime     = "Exposure Time"
c_ExifAperture         = "F-Stop"
c_ExifExposureProgram  = "Exposure Program"
c_ExifIsoSpeedRating   = "ISO Speed Ratings"
c_ExifDateTimeOriginal = "Date Time Original"
c_ExifMaxApertureValue = "Max Aperture Value"
c_ExifMeteringMode     = "Metering Mode"
c_ExifLightSource      = "Light Source"
c_ExifFlash            = "Flash"
c_ExifFocalLength      = "Focal Length"
c_ExifColorSpace       = "Color Space"
c_ExifWidth            = "Pixel X Dimension"
c_ExifHeight           = "Pixel Y Dimension"

function GetRawExifValueIfPresent(strExifValueName)
{
    // Empty string means it wasn't found
    var strResult = new String("");

    // Make sure there is a current document
    if (app.documents.length)
    {
        // Loop through each element in the EXIF properties array
        for (nCurrentElement = 0, nCount = 0; nCurrentElement < activeDocument.info.exif.length; ++nCurrentElement)
        {
            // Get the current element as a string
            var strCurrentRecord = new String(activeDocument.info.exif[nCurrentElement]);

            // Find the first comma
            var nComma = strCurrentRecord.indexOf(",");
            if (nComma >= 0)
            {
                // Everything before the comma is the field name
                var strCurrentExifName = strCurrentRecord.substr(0, nComma);

                // Is it a valid string?
                if (strCurrentExifName.length)
                {
                    // Is this our element?
                    if (strCurrentExifName == strExifValueName)
                    {
                        // Everything after the comma is the value, so
                        // save it and exit the loop
                        strResult = strCurrentRecord.substr(nComma + 1);
                        break;
                    }
                }
            }
        }
    }
    return strResult;
}

//
// Convert a Photoshop latitude or longitude, formatted like 
// this:
//
//      Example: 47.00 38.00' 33.60"
//
// to the decimal form:
//
//      Example: 47.642667
//
// It returns an empty string if the string is in an unexpected
// form.
//
function ConvertLatitudeOrLongitudeToDecimal(strLatLong)
{
    var nResult = 0.0;

    // Copy the input string
    var strSource = new String(strLatLong);

    // Find the first space
    nIndex = strSource.indexOf(" ");
    if (nIndex >= 0)
    {
        // Copy up to the first space
        strDegrees = strSource.substr(0, nIndex);

        // Skip this part, plus the space
        strSource = strSource.substr(nIndex + 1);

        // Find the tick mark
        nIndex = strSource.indexOf("'");
        if (nIndex >= 0)
        {
            // Copy up to the tick mark
            strMinutes = strSource.substr(0, nIndex);

            // Skip this chunk, plus the tick and space
            strSource = strSource.substr(nIndex + 2);

            // Find the seconds mark: "
            nIndex = strSource.indexOf("\"");
            if (nIndex >= 0)
            {
                // Copy up to the seconds
                strSeconds = strSource.substr(0, nIndex);

                // Convert to numbers
                var nDegrees = parseFloat(strDegrees);
                var nMinutes = parseFloat(strMinutes);
                var nSeconds = parseFloat(strSeconds);

                // Use the correct symbols
                nResult = nDegrees + (nMinutes / 60.0) + (nSeconds / 3600.0);
            }
        }
    }

    return nResult;
}

function GetDecimalLatitudeOrLongitude(strExifLatOrLong, strExifLatOrLongRef, strResult)
{
    var strResult = "";

    // Get the exif values
    strLatOrLong = GetRawExifValueIfPresent(strExifLatOrLong);
    strLatOrLongRef = GetRawExifValueIfPresent(strExifLatOrLongRef);
	//alert(strLatOrLong, strLatOrLongRef);
    // If we were able to read them
    if (strLatOrLong.length && strLatOrLongRef.length)
    {
        // Parse and convert to a decimal
        var nResult = ConvertLatitudeOrLongitudeToDecimal(strLatOrLong);

        // If we are in the southern or western hemisphere, negate the result
        if (strLatOrLongRef[0] == 'S' || strLatOrLongRef[0] == 'W')
        {
            nResult *= -1;
        }

        strResult = nResult.toString();
		GPSinfo = GPSinfo + strLatOrLong + " " + strLatOrLongRef + "  ";
    }
    return strResult;
}

function CreateGoogleMapsUrl(strLatitude, strLongitude)
{
    return "http://maps.google.com/maps?ll=" + strLatitude + "," + strLongitude + "&spn=0.01,0.01";
}

function CreateMappointUrl(strLatitude, strLongitude)
{
    return "http://mappoint.msn.com/map.aspx?L=USA&C=" + strLatitude + "%2c" + strLongitude + "&A=50&P=|" + strLatitude + "%2c" + strLongitude + "|39|" + c_strPhotoCaption +"|L1|"
}

function CreateVirtualEarthUrl(strLatitude, strLongitude)
{
    return "http://virtualearth.msn.com/default.aspx?v=2&style=h&lvl=17&cp=" + strLatitude + "~" + strLongitude + "&sp=an." + strLatitude + "_" + strLongitude + "_" + c_strPhotoCaption + "_";
}

function CMapSiteSelection()
{
    // Initialize default map provider
    this.Site = c_MapWebsites[c_nDefaultMapWebsiteIndex];
    return this;
}

function ShowMyDialog(strLatitude, strLongitude)
{
    // Use the default website
    var strCurrentSite = c_MapWebsites[c_nDefaultMapWebsiteIndex];

    dlgMain = new Window("dialog", "Choose a Map Website");

    // Add the top group
    dlgMain.TopGroup = dlgMain.add("group");
	dlgMain.TopGroup.orientation = "row";
	dlgMain.TopGroup.alignChildren = "top";
	dlgMain.TopGroup.alignment = "fill";

    // Add the left group
    dlgMain.TopGroup.LeftGroup = dlgMain.TopGroup.add("group");
    dlgMain.TopGroup.LeftGroup.orientation = "column";
    dlgMain.TopGroup.LeftGroup.alignChildren = "left";
    dlgMain.TopGroup.LeftGroup.alignment = "fill";

    dlgMain.AspectRatioGroup = dlgMain.TopGroup.LeftGroup.add("panel", undefined, "Map Website");
    dlgMain.AspectRatioGroup.alignment = "fill";
    dlgMain.AspectRatioGroup.orientation = "column";
    dlgMain.AspectRatioGroup.alignChildren = "left";

    // Add radio buttons
    dlgMain.virtualEarth = dlgMain.AspectRatioGroup.add("radiobutton", undefined, "Windows Live Local (aka Virtual Earth)");
    dlgMain.virtualEarth.onClick = function virtualEarthOnClick()
    {
        strCurrentSite = "virtualearth";
    }

    dlgMain.mappoint = dlgMain.AspectRatioGroup.add("radiobutton", undefined, "MSN Maps && Directions (aka MapPoint)");
    dlgMain.mappoint.onClick = function mappointOnClick()
    {
        strCurrentSite = "mappoint";
    }

    dlgMain.google = dlgMain.AspectRatioGroup.add("radiobutton", undefined, "Google Local (aka Google Maps)");
    dlgMain.google.onClick = function googleOnClick()
    {
        strCurrentSite = "google";
    }

    // Set the checked radio button
    if (strCurrentSite == "google")
    {
        dlgMain.google.value = true;
    }
    else if (strCurrentSite == "mappoint")
    {
        dlgMain.mappoint.value = true;
    }
    else
    {
        dlgMain.virtualEarth.value = true;
    }

    // Add the button group
    dlgMain.TopGroup.RightGroup = dlgMain.TopGroup.add("group");
    dlgMain.TopGroup.RightGroup.orientation = "column";
    dlgMain.TopGroup.RightGroup.alignChildren = "left";
    dlgMain.TopGroup.RightGroup.alignment = "fill";

    // Add the buttons
    dlgMain.btnOpenSite = dlgMain.TopGroup.RightGroup.add("button", undefined, "Open");
    dlgMain.btnClose = dlgMain.TopGroup.RightGroup.add("button", undefined, "Exit");

    dlgMain.btnClose.onClick = function()
    { 
        dlgMain.close(true);
    }

    dlgMain.btnOpenSite.onClick = function()
    {
        // Which website?
        var strUrl = "";
        switch (strCurrentSite)
        {
        case "mappoint":
            strUrl = CreateMappointUrl(strLatitude, strLongitude);
            break;

        case "google":
            strUrl = CreateGoogleMapsUrl(strLatitude, strLongitude);
            break;

        case "virtualearth":
        default:
            strUrl = CreateVirtualEarthUrl(strLatitude, strLongitude);
            break;

        }

        // Create the URL file and launch it
        var fileUrlShortcut = new File(c_strTemporaryUrlFile);
        fileUrlShortcut.open('w');
        fileUrlShortcut.writeln("[InternetShortcut]")
        fileUrlShortcut.writeln("URL=" + strUrl);
        fileUrlShortcut.execute();
    }

    // Set the button characteristics
    dlgMain.cancelElement = dlgMain.btnClose;
    dlgMain.defaultElement = dlgMain.btnOpenSite;

    dlgMain.center();
    return dlgMain.show();
}
function GoogleMap(strLatitude, strLongitude)
{ 
	strUrl = CreateGoogleMapsUrl(strLatitude, strLongitude)
		try{
		var URL = new File(Folder.temp + "/GoogleMapIt.html");
		URL.open("w");
		URL.writeln('<html><HEAD><meta HTTP-EQUIV="REFRESH" content="0; ' + strUrl + ' "></HEAD></HTML>');
		/*
		URL.writeln("<!DOCTYPE html>");
		URL.writeln("<html><head>");
		URL.writeln('<meta name="viewport" content="initial-scale=1.0, user-scalable=no">');
		URL.writeln('<meta charset="utf-8">');
		URL.writeln("<title>Simple markers</title>");
		URL.writeln("<style>html, body, #map-canvas {height: 100%;margin: 0px;padding: 0px}</style>");
		URL.writeln('<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>');
		URL.writeln("<script>function initialize() {");
		URL.writeln("var myLatlng = new google.maps.LatLng(" + strLatitude +"," +  strLongitude + ",true);");
		URL.writeln("var mapOptions = {zoom: 15,center: myLatlng,mapTypeId: google.maps.MapTypeId.ROADMAP}");
		URL.writeln("var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);");
		URL.writeln("var marker = new google.maps.Marker({position: myLatlng,map: map,title: 'My Picture Name'});}");
		URL.writeln("google.maps.event.addDomListener(window, 'load', initialize);");
		URL.writeln('</script></head><body><div id="map-canvas"></div></body></html>');
		*/
		URL.close();
		URL.execute();   // The temp file is created but this fails to open the users default browser using Photoshop CC prior Photoshop versions work
	}catch(e){
		alert("Error, Can Not Open.");
	};

}

function OpenMapUrl()
{
    // Get the latitude
    var strDecimalLatitude = GetDecimalLatitudeOrLongitude(c_ExifGpsLatitude, c_ExifGpsLatitudeRef);
    if (strDecimalLatitude.length)
    {
        // Get the longitude
        var strDecimalLongitude = GetDecimalLatitudeOrLongitude(c_ExifGpsLongitude, c_ExifGpsLongitudeRef);
        if (strDecimalLongitude.length)
        {
            //ShowMyDialog(strDecimalLatitude, strDecimalLongitude);
			//GoogleMap(strDecimalLatitude, strDecimalLongitude);
			alert(GPSinfo + "\nLatitude=" + strDecimalLatitude + " Longitude=" + strDecimalLongitude);
        }
    }
}

function Main()
{
    if (app.documents.length > 0)
    {
        OpenMapUrl();
    }
    else
    {
        alert("You don't have an image opened.  Please open an image before running this script.");
    }
}
var GPSinfo = "";
Main();

 

 

 

Hacked it for you and it looks like LB is just west of 0...

Capture.jpg

 

 

 

 

JJMack
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 12, 2020 Jun 12, 2020

also found a Bridge script ShowOnGoogleMaps.jsx 

JJMack
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 12, 2020 Jun 12, 2020
LATEST

Removed the dead code in my hack.

 

//  GPS Location.jsx
// Version 1.0
// Shaun Ivory (shaun@ivory.org)
//
// Feel free to modify this script.  If you do anything interesting with it,
// please let me know.

// JJMack I just used my sledge hammer on Shaun's Photoshop script 

//
// Globals
//

var GPSinfo = "";
var c_strPhotoCaption = "Photo%20Location";
// EXIF constants
c_ExifGpsLatitudeRef   = "GPS Latitude Ref"
c_ExifGpsLatitude      = "GPS Latitude"
c_ExifGpsLongitudeRef  = "GPS Longitude Ref"
c_ExifGpsLongitude     = "GPS Longitude"
c_ExifGpsAltitudeRef   = "GPS Altitude Ref"
c_ExifGpsAltitude      = "GPS Altitude"
c_ExifGpsTimeStamp     = "GPS Time Stamp"
c_ExifMake             = "Make"
c_ExifModel            = "Model"
c_ExifExposureTime     = "Exposure Time"
c_ExifAperture         = "F-Stop"
c_ExifExposureProgram  = "Exposure Program"
c_ExifIsoSpeedRating   = "ISO Speed Ratings"
c_ExifDateTimeOriginal = "Date Time Original"
c_ExifMaxApertureValue = "Max Aperture Value"
c_ExifMeteringMode     = "Metering Mode"
c_ExifLightSource      = "Light Source"
c_ExifFlash            = "Flash"
c_ExifFocalLength      = "Focal Length"
c_ExifColorSpace       = "Color Space"
c_ExifWidth            = "Pixel X Dimension"
c_ExifHeight           = "Pixel Y Dimension"

function GetRawExifValueIfPresent(strExifValueName)
{
    // Empty string means it wasn't found
    var strResult = new String("");
    // Make sure there is a current document
    if (app.documents.length) {
        // Loop through each element in the EXIF properties array
        for (nCurrentElement = 0, nCount = 0; nCurrentElement < activeDocument.info.exif.length; ++nCurrentElement) {
            // Get the current element as a string
            var strCurrentRecord = new String(activeDocument.info.exif[nCurrentElement]);
            // Find the first comma
            var nComma = strCurrentRecord.indexOf(",");
            if (nComma >= 0) {
                // Everything before the comma is the field name
                var strCurrentExifName = strCurrentRecord.substr(0, nComma);
                // Is it a valid string?
                if (strCurrentExifName.length) {
                    // Is this our element?
                    if (strCurrentExifName == strExifValueName) {
                        // Everything after the comma is the value, so
                        // save it and exit the loop
                        strResult = strCurrentRecord.substr(nComma + 1);
                        break;
                    }
                }
            }
        }
    }
    return strResult;
}
// Convert a Photoshop latitude or longitude, formatted like 
// this:
//      Example: 47.00 38.00' 33.60"
// to the decimal form:
//      Example: 47.642667
// It returns an empty string if the string is in an unexpected form.
function ConvertLatitudeOrLongitudeToDecimal(strLatLong) {
    var nResult = 0.0;
    // Copy the input string
    var strSource = new String(strLatLong);
    // Find the first space
    nIndex = strSource.indexOf(" ");
    if (nIndex >= 0) {
        // Copy up to the first space
        strDegrees = strSource.substr(0, nIndex);
        // Skip this part, plus the space
        strSource = strSource.substr(nIndex + 1);
        // Find the tick mark
        nIndex = strSource.indexOf("'");
        if (nIndex >= 0) {
            // Copy up to the tick mark
            strMinutes = strSource.substr(0, nIndex);
            // Skip this chunk, plus the tick and space
            strSource = strSource.substr(nIndex + 2);
            // Find the seconds mark: "
            nIndex = strSource.indexOf("\"");
            if (nIndex >= 0) {
                // Copy up to the seconds
                strSeconds = strSource.substr(0, nIndex);
                // Convert to numbers
                var nDegrees = parseFloat(strDegrees);
                var nMinutes = parseFloat(strMinutes);
                var nSeconds = parseFloat(strSeconds);
                // Use the correct symbols
                nResult = nDegrees + (nMinutes / 60.0) + (nSeconds / 3600.0);
            }
        }
    }
    return nResult;
}

function GetDecimalLatitudeOrLongitude(strExifLatOrLong, strExifLatOrLongRef, strResult) {
    var strResult = "";
    // Get the exif values
    strLatOrLong = GetRawExifValueIfPresent(strExifLatOrLong);
    strLatOrLongRef = GetRawExifValueIfPresent(strExifLatOrLongRef);
    // If we were able to read them
    if (strLatOrLong.length && strLatOrLongRef.length) {
        // Parse and convert to a decimal
        var nResult = ConvertLatitudeOrLongitudeToDecimal(strLatOrLong);
        // If we are in the southern or western hemisphere, negate the result
        if (strLatOrLongRef[0] == 'S' || strLatOrLongRef[0] == 'W') { nResult *= -1; }
        strResult = nResult.toString();
		GPSinfo = GPSinfo + strLatOrLong.substr(0, strLatOrLong.indexOf(",")) + " " + strLatOrLongRef.substr(0, strLatOrLongRef.indexOf(",")) + "              ";
    }
    return strResult;
}

function GetGPS() {
    // Get the latitude
    var strDecimalLatitude = GetDecimalLatitudeOrLongitude(c_ExifGpsLatitude, c_ExifGpsLatitudeRef);
    if (strDecimalLatitude.length) {
        // Get the longitude
        var strDecimalLongitude = GetDecimalLatitudeOrLongitude(c_ExifGpsLongitude, c_ExifGpsLongitudeRef);
        if (strDecimalLongitude.length) { alert("Latitude " + strDecimalLatitude + " Longitude " + strDecimalLongitude + "\n" + GPSinfo ); }
    }
}

function Main() {
    if (app.documents.length > 0) {GetGPS();}
    else {alert("You don't have an image opened.  Please open an image before running this script.");}
}

Main();

 

JJMack
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines