locked
EXIF Data from JPG File RRS feed

  • Question

  • Hello,

    I have created a PS script that reads the GPS Latitude and Longitude from a JPG file. 

    In some cases, the GPS coordinates do not match with the picture's properties.

    Function Get-EXIFDataFromJPGFile
       {
    
        <#
        .NOTES
        =============================================================================================================================================
        Created with:     Windows PowerShell ISE
        Created on:       06-July-2020
        Created by:       Willem-Jan Vroom
        Organization:     
        Functionname:     Get-EXIFDataFromJPGFile
        =============================================================================================================================================
        .SYNOPSIS
    
        This function reads the latitude and longitude data from a JPG file.
        If no valid data is found, the return codes will be 1024 and 1024.
        This code is based on 
        http://www.forensicexpedition.com/2017/08/03/imagemapper-a-powershell-metadata-and-geo-maping-tool-for-images/
    
        #>
    
        Param
         (
          [String] $FileName
         )
        
        
        $img    = New-Object -TypeName system.drawing.bitmap -ArgumentList $FileName
        $Encode = New-Object System.Text.ASCIIEncoding
        $GPSInfo = $true
        $GPSLat  = ""
        $GPSLon  = ""
          
        # =============================================================================================================================================
        # Try to get the latitude (N or S) from the image.
        # If not successfull then this information is not in the image
        # and quit with the numbers 1024 and 1024. 
        # =============================================================================================================================================
    
        Try
         {
          
          $LatNS = $Encode.GetString($img.GetPropertyItem(1).Value)
         }
          Catch
         {
          $GPSInfo = $False
         }
                    
        If ($GPSInfo -eq $true)
         {
          [double]$LatDeg = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 0))  / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 4)))
          [double]$LatMin = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 8))  / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 12)))
          [double]$LatSec = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 16)) / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(2).Value, 20)))
        
          $LonEW = $Encode.GetString($img.GetPropertyItem(3).Value)
          [double]$LonDeg = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 0))  / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 4)))
          [double]$LonMin = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 8))  / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 12)))
          [double]$LonSec = (([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 16)) / ([Decimal][System.BitConverter]::ToInt32($img.GetPropertyItem(4).Value, 20)))
    
    
    
          #$GPSLat = $($LatDeg.ToString("###")) + "º "+$($LatMin.ToString("##"))+"' "+$($LatSec.ToString("##"))+ $([char]34) + " "+$LatNS
          #$GPSLon = $($LonDeg.ToString("###")) + "º "+$($LonMin.ToString("##"))+"' "+$($LonSec.ToString("##"))+ $([char]34) + " "+$LonEW
    
          $GPSLat = "$([int]$LatDeg)º $([int]$LatMin)' $([int]$LatSec)$([char]34) $LatNS"
          $GPSLon = "$([int]$LonDeg)º $([int]$LonMin)' $([int]$LonSec)$([char]34) $LonEW"
    
          Write-Verbose "    The picture $FileName has the following GPS coordinates:"
          Write-Verbose "       $GPSLat"        
          Write-Verbose "       $GPSLon"
    
        # =============================================================================================================================================
        # Convert the latitude and longitude to numbers that Google Maps recognizes.
        # =============================================================================================================================================
    
          $LatOrt = 0
          $LonOrt = 0
    
          If ($LatNS -eq 'S')
           {
            $LatOrt = "-"   
           }
          If ($LonEW -eq 'W')
           {
            $LonOrt = "-"
           }
    
          $LatDec = ($LatDeg + ($LatMin/60) + ($LatSec/3600))
          $LonDec = ($LonDeg + ($LonMin/60) + ($LonSec/3600))
    
          $LatOrt = $LatOrt + $LatDec
          $LonOrt = $LonOrt + $LonDec
    
        # =============================================================================================================================================
        # The numbers that where returned contained a decimal comma instead of a decimal point. 
        # So the en-US culture is forced to get the correct number notation.
        # =============================================================================================================================================
        
          $LatOrt = $LatOrt.ToString([cultureinfo]::GetCultureInfo('en-US'))
          $LonOrt = $LonOrt.ToString([cultureinfo]::GetCultureInfo('en-US'))
    
          Write-Verbose "    The picture $FileName has the following decimal coordinates:"
          Write-Verbose "      $LatOrt"
          Write-Verbose "      $LonOrt"
        }
         else
        {
         
       # =============================================================================================================================================
       # Ohoh... No GPS information in this picture.
       # =============================================================================================================================================
         
         Write-Verbose "    The picture $FileName does not contain GPS information."
         $LatOrt = "1024"
         $LonOrt = "1024"
        }
    
        Return $LatOrt,$LonOrt,$GPSLat,$GPSLon
      }
    
      Add-Type -AssemblyName System.Drawing
      Get-EXIFDataFromJPGFile "C:\TMP\WP_20170426_15_30_51_Pro.jpg"

    The output is:

    47º 33' -21" N 
    7º 35' -13" E 

    But if you check the picture's properties and check the coordinates, it says:

    47;33;21.9
    7;35;30.6

    But.... there are also pictures where the output matches. EXIF version is in both cases the same.

    So my question is: why does in some cases the EXIF information not match, thus the information from the function is not equal to the EXIF information the picture's properties.

    With kind regards,

    Willem-Jan

    Thursday, July 9, 2020 12:18 PM

Answers

  • The simple answer is that you are extracting a different set of properties from the ones that another system is extracting.

    Different cameras may use different versions of the JPEG tagging spec.  You have to align the extraction to the supported version which is somewhere in the metadata header.

    Post your issue in a JPEG forum where there will be developers who know how to do this.  I have done it in part but haven't looked at this for years.

    There are now many Net libraries available for manipulating JPEG and other media formats.


    \_(ツ)_/

    • Proposed as answer by Willem-Jan (Teconomy) Thursday, July 9, 2020 8:34 PM
    • Marked as answer by jrv Thursday, July 23, 2020 5:42 AM
    Thursday, July 9, 2020 6:19 PM

All replies

  • The simple answer is that you are extracting a different set of properties from the ones that another system is extracting.

    Different cameras may use different versions of the JPEG tagging spec.  You have to align the extraction to the supported version which is somewhere in the metadata header.

    Post your issue in a JPEG forum where there will be developers who know how to do this.  I have done it in part but haven't looked at this for years.

    There are now many Net libraries available for manipulating JPEG and other media formats.


    \_(ツ)_/

    • Proposed as answer by Willem-Jan (Teconomy) Thursday, July 9, 2020 8:34 PM
    • Marked as answer by jrv Thursday, July 23, 2020 5:42 AM
    Thursday, July 9, 2020 6:19 PM
  • Hello,

    Thanks for your feedback. I have checked with other images and only the images from a Lumia 930 have the incorrect GPS details. It is in the image, so the data is 'correct'. I will make a notification that this GPS information is inaccurate. This cannot be solved as the GPS information is hardcoded in the picture.

    With kind regards,

    Willem-Jan

    Thursday, July 9, 2020 8:34 PM
  • That Nokia uses a very old JPEG version. It is not used by any newer cameras or phones.  Using a full JPEG library can solve this as it can decode old versions and can discriminate manufacturer variations.  That is how commercial tools are able to read this information.


    \_(ツ)_/

    Thursday, July 9, 2020 10:05 PM
  • Hi,
    As this thread has been quiet for a while, so here is a quick question.Was your issue resolved? 
    If you resolved it using our solution, please "mark it as answer" to help other community members find the helpful reply quickly.
    If you resolve it using your own solution, please share your experience and solution here. It will be very beneficial for other community members who have similar questions.
    If no, please reply and tell us the current situation in order to provide further help.
    Best Regards,
    Yang Yang

    Please remember to mark the replies as answers if they help.
    If you have feedback for TechNet Subscriber Support, contact tnmff@microsoft.com.

    Thursday, July 23, 2020 5:34 AM