Gdal reads the GPS coordinate information in JPG files

Source: Internet
Author: User

Currently, many cameras support retaining GPS information when taking photos. This information is generally stored in the EXIF information of JPG images. The following describes how to use the gdal library to read the GPS information in JPG images and parse the longitude and latitude coordinates.

First, it is also the most commonly used tool, gdalinfo, to see where the GPS information is. The following figure shows the information output using gdalinfo, as shown in figure 1.

Driver: JPEG/JPEG JFIFFiles: C:\Users\LiMinlu\Desktop\DSCN8806.JPGSize is 4608, 3456Coordinate System is `'Metadata:  EXIF_ColorSpace=1  EXIF_ComponentsConfiguration=0x1 0x2 0x3 00  EXIF_CompressedBitsPerPixel=(2)  EXIF_Contrast=0  EXIF_CustomRendered=0  EXIF_DateTime=2013:03:18 16:06:49  EXIF_DateTimeDigitized=2013:03:18 16:06:49  EXIF_DateTimeOriginal=2013:03:18 16:06:49  EXIF_DigitalZoomRatio=(0)  EXIF_ExifVersion=0230  EXIF_ExposureBiasValue=(0)  EXIF_ExposureMode=0  EXIF_ExposureProgram=2  EXIF_ExposureTime=(0.00625)  EXIF_FileSource=0x3  EXIF_Flash=24  EXIF_FlashpixVersion=0100  EXIF_FNumber=(3.9)  EXIF_FocalLength=(5)  EXIF_FocalLengthIn35mmFilm=28  EXIF_GainControl=4  EXIF_GPSAltitude=(55.6)  EXIF_GPSAltitudeRef=00  EXIF_GPSDateStamp=2013:03:18  EXIF_GPSImgDirection=(33.96)  EXIF_GPSImgDirectionRef=T  EXIF_GPSLatitude=(39) (53) (41.298)  EXIF_GPSLatitudeRef=N  EXIF_GPSLongitude=(116) (17) (28.344)  EXIF_GPSLongitudeRef=E  EXIF_GPSMapDatum=WGS-84     EXIF_GPSSatellites=03  EXIF_GPSTimeStamp=(8) (5) (41.02)  EXIF_GPSVersionID=0x2 0x3 00 00  EXIF_ImageDescription=                                 EXIF_Interoperability_Index=R98  EXIF_Interoperability_Version=0x30 0x31 0x30 0x30  EXIF_ISOSpeedRatings=125  EXIF_LightSource=0  EXIF_Make=NIKON  EXIF_MakerNote=Nikon  EXIF_MaxApertureValue=(3.9)  EXIF_MeteringMode=5  EXIF_Model=COOLPIX AW100s   EXIF_Orientation=1  EXIF_PixelXDimension=4608  EXIF_PixelYDimension=3456  EXIF_ResolutionUnit=2  EXIF_Saturation=0  EXIF_SceneCaptureType=0  EXIF_SceneType=0x1  EXIF_Sharpness=0  EXIF_Software=COOLPIX AW100sV1.0               EXIF_SubjectDistanceRange=2  EXIF_UserComment=                                                                                                                         EXIF_WhiteBalance=0  EXIF_XResolution=(300)  EXIF_YCbCrPositioning=2  EXIF_YResolution=(300)Image Structure Metadata:  COMPRESSION=JPEG  INTERLEAVE=PIXEL  SOURCE_COLOR_SPACE=YCbCrCorner Coordinates:Upper Left  (    0.0,    0.0)Lower Left  (    0.0, 3456.0)Upper Right ( 4608.0,    0.0)Lower Right ( 4608.0, 3456.0)Center      ( 2304.0, 1728.0)Band 1 Block=4608x1 Type=Byte, ColorInterp=Red  Image Structure Metadata:    COMPRESSION=JPEGBand 2 Block=4608x1 Type=Byte, ColorInterp=Green  Image Structure Metadata:    COMPRESSION=JPEGBand 3 Block=4608x1 Type=Byte, ColorInterp=Blue  Image Structure Metadata:    COMPRESSION=JPEG
Figure 1 output information of gdalinfo

From the output, we can see that the GPS information stored in JPG is stored in the metadata information starting with exif_gps. Once we know the storage location, we can write a program to parse it. The first thing we need to do is to extract GPS information from so many EXIF messages. The Code is as follows:

char** papszMetadata = poDataset->GetMetadata( NULL ) ;char** papszMetadataGPS = NULL;if( CSLCount(papszMetadata) > 0 ){for(int i = 0; papszMetadata[i] != NULL; i++ ){if(EQUALN(papszMetadata[i], "EXIF_GPS", 8)){papszMetadataGPS = CSLAddString( papszMetadataGPS, papszMetadata[i]);printf( "  %s\n", papszMetadata[i] );}}}

The above code roughly explains how to obtain metadata information from podataset and determine whether the number of metadata is greater than 0, that is, whether metadata exists; finally, metadata starting with exif_gps is extracted and stored in the New String Array Through the Function Limit n. The metadata extracted from the above Code is as follows:

  EXIF_GPSAltitude=(55.6)  EXIF_GPSAltitudeRef=00  EXIF_GPSDateStamp=2013:03:18  EXIF_GPSImgDirection=(33.96)  EXIF_GPSImgDirectionRef=T  EXIF_GPSLatitude=(39) (53) (41.298)  EXIF_GPSLatitudeRef=N  EXIF_GPSLongitude=(116) (17) (28.344)  EXIF_GPSLongitudeRef=E  EXIF_GPSMapDatum=WGS-84     EXIF_GPSSatellites=03  EXIF_GPSTimeStamp=(8) (5) (41.02)  EXIF_GPSVersionID=0x2 0x3 00 00

Refer to this page (http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/gps.html) for the meaning of the beginning of these exif_gps ). Through this page, we can know that the coordinates we want to obtain are the values in the following metadata. The meanings of the identifiers are described below.

Exif_gpsaltitude = (55.6) -- altitude exif_gpsaltituderef = 00 -- altitude reference value (which should be horizontal elevation) exif_gpslatitude = (39) (53) (41.298) -- latitude information exif_gpslatituderef = n -- latitude, N is north latitude, S is south latitude exif_gpslong== (116) (17) (28.344) -- longitude information exif_gpslongituderef = e -- longitude ID, e is the east longitude, W is the western longitude exif_gpsmapdatum = WGS-84-reference elliptical, this should be WGS84

The longitude and latitude information are expressed in the degree and second format. You can easily parse the format and its meaning. The following is a parsed function that uses the split function and the lexical_cast function in the boost library.

# Include "gdal_priv.h" # include <vector> # include <string> using namespace STD; # include "Boost/lexical_cast.hpp" # include "Boost/algorithm/string. HPP "using namespace boost; using namespace boost: algorithm; bool extractgpsinfo (char ** papszmetadata, double & dlon, double & dlat, double & dhgt) {If (cslcount (papszmetadata) <= 0) return false; char ** papszmeta1_ps = NULL; For (INT I = 0; papszmetadata [I]! = NULL; I ++) {If (equaln (papszmetadata [I], "exif_gps", 8) papszmetadatagps = csladdstring (papszmetadatagps, papszmetadata [I]);} int igpscount = cslcount (papszmeta1_ps); If (igpscount <= 0) {csldestroy (papszmeta1_ps); Return false;} bool bisnorth = true; bool biseast = true; for (INT I = 0; papszmeta1_ps [I]! = NULL; I ++) {vector <string> vsplitstr; split (vsplitstr, papszmeta1_ps [I], is_any_of ("= ")); // use = to split the string if (vsplitstr. empty () | vsplitstr. size ()! = 2) continue; string strname = vsplitstr [0]; // retrieve the identifier string strvalue = vsplitstr [1]; // retrieve the value if (strname. empty () | strvalue. empty () continue; If (strname = "exif_gpsaltitude") // obtain the elevation of {vector <string> vsplitvalue; split (vsplitvalue, strvalue, is_any_of ("()"), token_compress_on); // use () to split the string if (vsplitvalue. size ()! = 3) dhgt = 0; elsedhgt = lexical_cast <double> (vsplitvalue [1]);} else if (strname = "exif_gpslongpolling ") // obtain the longitude {vector <string> vsplitvalue; split (vsplitvalue, strvalue, is_any_of ("()"), token_compress_on); // use () to split the string if (vsplitvalue. size ()! = 5) dlon = 0; elsedlon = lexical_cast <double> (vsplitvalue [1]) + lexical_cast <double> (vsplitvalue [2]) /60.0 + lexical_cast <double> (vsplitvalue [3])/3600.0;} else if (strname = "exif_gpslatitude") // obtain the latitude {vector <string> vsplitvalue; split (vsplitvalue, strvalue, is_any_of ("()"), token_compress_on); // use () to split the string if (vsplitvalue. size ()! = 5) dlat = 0; elsedlat = lexical_cast <double> (vsplitvalue [1]) + lexical_cast <double> (vsplitvalue [2]) /60.0 + lexical_cast <double> (vsplitvalue [3])/3600.0;} else if (strname = "exif_gpslongpolling ") // obtain the longitude {If (strvalue = "e") biseast = true; elsebiseast = false;} else if (strname = "exif_gpslatitude ") // obtain the latitude {If (strvalue = "N") bisnorth = true; elsebisnorth = false ;}} dlon = biseast? Dlon:-1.0 * dlon; dlat = bisnorth? Dlat:-1.0 * dlat; return true ;}

Note that the above Code contains the following sentence: "Split (vsplitvalue, strvalue, is_any_of (" () "), token_compress_on); // use () to split the string ", it is reasonable to say that this sentence should remove the arc and space. I did remove it when executing it on the local machine, but added two empty strings to the end of the parsed string vector, so we have to start from 1. Output 2 after resolution.

Figure 2 resolved coordinate information

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.