现在的很多照片都可以带坐标,出去旅游的时候,如果将这些照片跟拍摄位置结合就可以使用照片定位,并且查看当地的风景。
这些照片存储着坐标信息,其实不仅仅是坐标信息,还有很多其他的,这类照被称为Extif格式。
Exif是英文Exchangeable Image File(可交换图像文件)的缩写,最初由日本电子工业发展协会(JEIDA --Japan Electronic Industry Development Association) 制订,目前的最新版本是发表于2002年04月的2.21 版。国际标准化组织(ISO)正在制订的相机文件设计标准(DCF -- Design role for Camera File system)可能以Exif2.1为基础。
Exif 文件实际是JPEG文件的一种,遵从JPEG标准,只是在文件头信息中增加了有关拍摄信息的内容和索引图。所以你可以使用任何支持JPEG格式的图像工具软件观看或修改Exif文件,但,打开时可能看不到Exif信息,一旦修改,Exif信息可能丢失。
简单来说,EXIF 信息就是由数码相机在拍摄过程中采集一系列的信息,然后把信息放置在我们熟知的 JPEG/TIFF 文件的头部,也就是说 EXIF 信息是镶嵌在 JPEG/TIFF 图像文件格式内的一组拍摄参数,主要包括摄影时的光圈、快门、ISO、时间等各种与当时摄影条件相关的讯息,相机品牌型号,色彩编码,拍摄时录制的声音以及全球定位系统(GPS)等信息。简单的说,它就好像是傻瓜相机的日期打印功能一样,只不过 EXIF 信息所记录的资讯更为详尽和完备。
下面是解析这里照片的核心代码,我是在WPF中将照片拖放的,然后里面调用坐标解析函数,如下:
private void _mapControl_Drop(object sender, DragEventArgs e) { //拖放的数据都存在e.Data中 if (e.Data == null) { return; } IDataObject data = e.Data; //IDataObject.GetData(DataFormats.FileDrop) - 返回被拖放的外部文件的 FileInfo 数组 string[] files = (string[])data.GetData(DataFormats.FileDrop); foreach (string fileInfo in files) { if (Path.GetExtension(fileInfo).Equals(".jpg", StringComparison.OrdinalIgnoreCase)) { // FileInfo fi = new FileInfo(fileInfo); System.Drawing.Image theImage = System.Drawing.Image.FromFile(fileInfo); // http://www.exiv2.org/tags.html PropertyItem[] pt = theImage.PropertyItems; double x = 0; double y = 0; double z; PictureMarkerSymbol pPicTure = new PictureMarkerSymbol(); for (int i = 0; i < pt.Length; i++) { PropertyItem p = pt[i]; switch (pt[i].Id) { // 纬度 case 2: x = GPSLatitude(p); break; case 4: // y = GPSLongitude(p); break; case 6: // z = GPSAltitude(p); break; default: break; } } Graphic pGraphic = new Graphic(); pPicTure.Source = new BitmapImage(new Uri(fileInfo, UriKind.Absolute)); //偏移距离 pPicTure.OffsetX = 0.1; pPicTure.OffsetY = 0.1; pGraphic.MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(pGraphic_MouseLeftButtonDown); // pGraphic.MouseEnter += new System.Windows.Input.MouseEventHandler(pGraphic_MouseEnter); pGraphic.Geometry = new MapPoint(y, x); pGraphic.Symbol = pPicTure; pGraphicsLayer.Graphics.Add(pGraphic); pPicTure.Width = pPicTure.Source.Width/5; pPicTure.Height= pPicTure.Source.Height/5; } else { MessageBox.Show(fileInfo + " is not supported image file!"); } } // _mapControl.Extent = pGraphicsLayer.FullExtent; } ╰醉意人间╮ 8:42:18 private double GPSLatitude(PropertyItem pi) { double latitude = 0; double deg = BitConverter.ToUInt32(pi.Value, 0); uint deg_div = BitConverter.ToUInt32(pi.Value, 4); double min = BitConverter.ToUInt32(pi.Value, 8); uint min_div = BitConverter.ToUInt32(pi.Value, 12); double mmm = BitConverter.ToUInt32(pi.Value, 16); uint mmm_div = BitConverter.ToUInt32(pi.Value, 20); double m = 0; if (deg_div != 0 || deg != 0) { m = (deg / deg_div); } if (min_div != 0 || min != 0) { m = m + (min / min_div) / 60; } if (mmm_div != 0 || mmm != 0) { m = m + (mmm / mmm_div / 3600); } latitude = m; return latitude; } private double GPSLongitude(PropertyItem pi) { double Longitude; double deg = BitConverter.ToUInt32(pi.Value, 0); uint deg_div = BitConverter.ToUInt32(pi.Value, 4); double min = BitConverter.ToUInt32(pi.Value, 8); uint min_div = BitConverter.ToUInt32(pi.Value, 12); double mmm = BitConverter.ToUInt32(pi.Value, 16); uint mmm_div = BitConverter.ToUInt32(pi.Value, 20); double m = 0; if (deg_div != 0 || deg != 0) //36.26.0140 { m = (deg / deg_div); } if (min_div != 0 || min != 0) { m = m + (min / min_div) / 60; } if (mmm_div != 0 || mmm != 0) //36.26.0140 { m = m + (mmm / mmm_div / 3600); } Longitude = m; return Longitude; } private double GPSAltitude(PropertyItem pi) { double deg = BitConverter.ToUInt32(pi.Value, 0); uint deg_div = BitConverter.ToUInt32(pi.Value, 4); double m = 0; if (deg_div != 0 || deg != 0) { m = (deg / deg_div); } return m; }