GDAL读取jpg文件中GPS坐标信息

原创 2013年04月26日 21:18:44

在目前很多相机都支持在拍照的时候保留GPS信息,这些信息一般都是存储在jpg图像的exif信息中。下面内容主要说明如何使用GDAL库来读取jpg图像中的GPS信息并解析经纬度坐标。

首先,还是最常用的工具,gdalinfo,来查看这个GPS信息到底在什么地方。下面是使用gdalinfo输出的信息,图1为截图。

Driver: JPEG/JPEG JFIF
Files: C:\Users\LiMinlu\Desktop\DSCN8806.JPG
Size is 4608, 3456
Coordinate 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=YCbCr
Corner 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=JPEG
Band 2 Block=4608x1 Type=Byte, ColorInterp=Green
  Image Structure Metadata:
    COMPRESSION=JPEG
Band 3 Block=4608x1 Type=Byte, ColorInterp=Blue
  Image Structure Metadata:
    COMPRESSION=JPEG
图1 GDALINFO 输出的信息
从上面的输出信息可以看出,jpg中存储GPS的信息是以EXIF_GPS***开头的元数据信息里面所存储。知道了存储位置我们就可以写程序来解析了,首先要做的是从这么多一大堆的EXIF信息中提取GPS的信息,代码如下:

	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] );
			}
		}
	}
大概解释一下上面的代码,首先从poDataset 中获取元数据信息;然后判断元数据的个数是否大于0,也就是判断是否存在元数据;最后通过函数EQUALN来提取EXIF_GPS开头的元数据存放在新的字符串数组中。通过上面的代码提取之后的元数据如下:

  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_GPS开头的含义可以参考这个页面http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/gps.html)。通过这个页面可以得知,我们要获取的坐标就是下面这几个元数据里面的值,标识的含义见后面。

  EXIF_GPSAltitude=(55.6)              ——海拔
  EXIF_GPSAltitudeRef=00               ——海拔参考值(应该就是水平面高程)
  EXIF_GPSLatitude=(39) (53) (41.298)  ——纬度信息
  EXIF_GPSLatitudeRef=N                ——纬度标识,N为北纬,S为南纬
  EXIF_GPSLongitude=(116) (17) (28.344)——经度信息
  EXIF_GPSLongitudeRef=E               ——经度标识,E为东经,W为西经
  EXIF_GPSMapDatum=WGS-84              ——参考椭球,这个应该都是WGS84吧
其中经度和纬度信息是使用度分秒格式表示。知道了格式及其含义,就可以很方便的解析了。下面是一个解析的函数,使用了boost库中的split函数和lexical_cast函数。

#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** papszMetadataGPS = NULL;
	for(int i = 0; papszMetadata[i] != NULL; i++ )
	{
		if(EQUALN(papszMetadata[i], "EXIF_GPS", 8))
			papszMetadataGPS = CSLAddString( papszMetadataGPS, papszMetadata[i]);
	}

	int iGPSCount = CSLCount(papszMetadataGPS);
	if (iGPSCount <=0)
	{
		CSLDestroy( papszMetadataGPS );
		return false;
	}
	
	bool bIsNorth = true;
	bool bIsEast = true;

	for(int i = 0; papszMetadataGPS[i] != NULL; i++ )
	{
		vector<string> vSplitStr;
		split(vSplitStr, papszMetadataGPS[i], is_any_of("="));	//使用=拆分字符串
		if(vSplitStr.empty() || vSplitStr.size() != 2)
			continue;

		string strName = vSplitStr[0];	//取出标识符
		string strValue = vSplitStr[1];	//取出值
		if(strName.empty() || strValue.empty())
			continue;

		if(strName == "EXIF_GPSAltitude")	//获取海拔
		{
			vector<string> vSplitValue;
			split(vSplitValue, strValue, is_any_of("( )"), token_compress_on);	//使用( )拆分字符串
			if(vSplitValue.size() != 3)
				dHgt = 0;
			else
				dHgt = lexical_cast<double>(vSplitValue[1]);
		}
		else if(strName == "EXIF_GPSLongitude")		//获取经度
		{
			vector<string> vSplitValue;
			split(vSplitValue, strValue, is_any_of("( )"), token_compress_on);	//使用( )拆分字符串
			if(vSplitValue.size() != 5)
				dLon = 0;
			else
				dLon = lexical_cast<double>(vSplitValue[1]) + lexical_cast<double>(vSplitValue[2]) / 60.0 + lexical_cast<double>(vSplitValue[3]) / 3600.0;
		}
		else if(strName == "EXIF_GPSLatitude")	//获取纬度
		{
			vector<string> vSplitValue;
			split(vSplitValue, strValue, is_any_of("( )"), token_compress_on);	//使用( )拆分字符串
			if(vSplitValue.size() != 5)
				dLat = 0;
			else
				dLat = lexical_cast<double>(vSplitValue[1]) + lexical_cast<double>(vSplitValue[2]) / 60.0 + lexical_cast<double>(vSplitValue[3]) / 3600.0;
		}
		else if(strName == "EXIF_GPSLongitude")		//获取经度
		{
			if (strValue == "E")
				bIsEast = true;
			else
				bIsEast = false;
		}
		else if(strName == "EXIF_GPSLatitude")	//获取纬度
		{
			if (strValue == "N")
				bIsNorth = true;
			else
				bIsNorth = false;
		}
	}

	dLon = bIsEast ? dLon : -1.0*dLon;
	dLat = bIsNorth ? dLat : -1.0*dLat;

	return true;
}
需要注意的是,上面的代码中有句“split(vSplitValue, strValue, is_any_of("( )"), token_compress_on); //使用( )拆分字符串”,按理说这句应该会把括弧和空格去掉,我本机执行的时候确实去掉了,但是在解析后的字符串vector中的收尾增加了两个空字符串,所以下面只好从1开始了。解析后的输出如图2所示。


图2 解析的坐标信息

版权声明:本文为博主原创文章,未经博主允许不得转载。

jpg图片的Exif及gps信息和示例分析

转自:http://www.verydemo.com/demo_c173_i10439.html jpg图片的Exif及gps信息和示例分析 分类: 操作系...
  • yapingmcu
  • yapingmcu
  • 2016年02月05日 17:24
  • 7846

jpg中读取GPS信息

需要读取EXIF信息,自己阅读了一些资料,现在共享一下需要注意的是,由于EXIF是一种可交换的文件格式,所以可以用在Intel系列和Motorola系列的CPU上(至于两者CPU的区别,大家可以到网上...
  • happyhell
  • happyhell
  • 2010年04月12日 09:30
  • 4438

Android操作Exif-ExifInterface全解析

简介:Exif是一种图像文件格式,它的数据存储与JPEG格式是完全相同的。实际上Exif格式就是在JPEG格式头部插入了数码照片的信息,包括拍摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍...
  • u011002668
  • u011002668
  • 2016年05月24日 16:14
  • 6361

Tiff、jpg图片怎么样添加地理坐标信息

Tiff、jpg图片怎么样添加地理坐标信息 一般,外业调查只有地图资料,如专题图、或者地形图,如何把这些地图资料的扫描地图带上坐标信息,从而内业实现信息化处理?以上问题,可以解决,但根据不同情况有不...
  • shumu_xzw
  • shumu_xzw
  • 2015年10月09日 15:53
  • 4277

如何给.JPG格式图片添加坐标信息(ArcGIS)

如何给.JPG格式图片添加坐标信息(ArcGIS)   具体到我们今天要讲的内容,就是GIS和规划、设计也是相同的,做设计的有时候会遇到一个问题,如何给一个.JPG格式的图片添加坐标信息 ...
  • chaomang
  • chaomang
  • 2013年05月10日 16:11
  • 4977

linux c exif gps 信息写入图片例子

  • 2012年05月25日 15:24
  • 12KB
  • 下载

Exif读取JPG图片信息+经纬度 ASP.NET

  • 2013年09月22日 17:16
  • 61KB
  • 下载

GPS信息读取

今天解决了下GPS相关的bug。因为时间关系,先简单记录参考的文章。       1.  GPS协议       2. GPS信息接收与解析       3. 嵌入式linuxGPS信息读取与...
  • nemo2011
  • nemo2011
  • 2014年12月26日 17:30
  • 791

读取JPG图片的Exif属性(三) - Exif属性读取GPS信息代码(C/C++实现)

Exif中GPS格式 本文是最后一篇关于Exif文章,终于要挑战最大的boss了,这个GPS信息的读取,我找了国内外很多资料都没有找 真正的实例。所以自己前两篇的基础上推断而来的。 读取JPG图片...
  • fioletfly
  • fioletfly
  • 2017年01月06日 09:12
  • 4222

jpg图片的Exif及gps信息和示例分析

http://blog.csdn.net/yapingmcu/article/details/50638713 http://blog.sina.com.cn/s/blog_651251e601...
  • zdf511391565
  • zdf511391565
  • 2016年03月22日 15:01
  • 571
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:GDAL读取jpg文件中GPS坐标信息
举报原因:
原因补充:

(最多只允许输入30个字)