关闭

Android中通过Exifinterface读取图片地理位置信息

标签: android高德地图地理位置图片exif
11408人阅读 评论(7) 收藏 举报
分类:

效果图:
这里写图片描述

一、了解Exif

EXIF(Exchangeable Image File)是“可交换图像文件”的缩写,是一种图像文件格式,它的数据存储与JPEG格式是完全相同的,当中包含了专门为数码相机的照片而定制的元数据,可以记录数码照片拍摄时的光圈、快门、白平衡、ISO、焦距、日期时间等各种和拍摄条件以及相机品牌、型号、色彩编码、拍摄时录制的声音以及GPS全球定位系统数据、缩略图等。
Exif 文件实际是JPEG文件的一种,遵从JPEG标准,只是在文件头信息中增加了有关拍摄信息的内容和索引图。所以你可以使用任何支持JPEG格式的图像工具软件观看 Exif 文件,但图像一旦被修改,Exif 信息可能会永久丢失,故编辑 Exif 必须使用专门的软件。
目前能够正确读取并识别的厂商注释等信息的Exif 查看/编辑软件比较少:主要有ExifTool、MagicEXIF等。

二、学习ExifInterface

Android2.0后新增的一个类
相关Tag:
TAG_DATETIME时间日期
  TAG_FLASH闪光灯
  TAG_GPS_LATITUDE纬度
  TAG_GPS_LATITUDE_REF纬度参考
  TAG_GPS_LONGITUDE经度
  TAG_GPS_LONGITUDE_REF经度参考
  TAG_IMAGE_LENGTH图片长
  TAG_IMAGE_WIDTH图片宽
  TAG_MAKE设备制造商
  TAG_MODEL设备型号
  TAG_ORIENTATION方向
  TAG_WHITE_BALANCE白平衡

/**
 * This is a class for reading and writing Exif tags in a JPEG file.
 */

Exifinterface

三、简单应用

根据选择的本地图片的exif信息,读取到地理位置的经纬度,然后使用高德地图反地理编码解析出地理位置名称,如果图片中没有包含或者无法包含经纬度信息,那么就在用户发起拍照请求时通过高德定位SDK拿到相关信息。以前没注意到有这么个类,先记录下,待会抽空来完善优化下流程和代码。

定位(获取当前位置)有两种方法:
1、通过LocationManager,其实就是通过GPS获取

Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

但是这样貌似不行,可能由于google被墙或者这个方法的权限问题,导致这个location为null

2、通过高德地图定位SDK的AMapLocationClient

    //声明定位回调监听器
    public AMapLocationListener mLocationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation amapLocation) {
            if (amapLocation != null) {
                if (amapLocation.getErrorCode() == 0) {
                    //定位成功回调信息,设置相关消息
                    amapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
                    currentLat = amapLocation.getLatitude();//获取纬度
                    currentLon = amapLocation.getLongitude();//获取经度
                }
            }
        }
    };

初始化定位、设置定位监听器后并启动定位mLocationClient.startLocation()后确实可以拿到当前经纬度,但在我的demo里,试了下太耗时(还没深原因),但是如果在一个完整的项目里,可以这样做。

public LatLng getPhotoLocation(String imagePath) {
        LogUtil.i("TAG", "getPhotoLocation==" + imagePath);
        LatLng latLng = null;

        try {
            ExifInterface exifInterface = new ExifInterface(imagePath);
            String datetime = exifInterface.getAttribute(ExifInterface.TAG_DATETIME);// 拍摄时间
            String deviceName = exifInterface.getAttribute(ExifInterface.TAG_MAKE);// 设备品牌
            String deviceModel = exifInterface.getAttribute(ExifInterface.TAG_MODEL); // 设备型号
            String latValue = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
            String lngValue = exifInterface.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
            String latRef = exifInterface.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
            String lngRef = exifInterface.getAttribute
                    (ExifInterface.TAG_GPS_LONGITUDE_REF);
            if (latValue != null && latRef != null && lngValue != null && lngRef != null) {
                try {
                    output1 = convertRationalLatLonToFloat(latValue, latRef);
                    output2 = convertRationalLatLonToFloat(lngValue, lngRef);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                }
            }

            Toast.makeText(TestActivity.this, deviceName + ":" + deviceModel, Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            e.printStackTrace();
        }

        Toast.makeText(TestActivity.this, output1 + ";" + output1 , Toast.LENGTH_LONG).show();

        latLng = new LatLng(output1 , output1 );
        return latLng;
    }

    private static float convertRationalLatLonToFloat(
            String rationalString, String ref) {

        String[] parts = rationalString.split(",");

        String[] pair;
        pair = parts[0].split("/");
        double degrees = Double.parseDouble(pair[0].trim())
                / Double.parseDouble(pair[1].trim());

        pair = parts[1].split("/");
        double minutes = Double.parseDouble(pair[0].trim())
                / Double.parseDouble(pair[1].trim());

        pair = parts[2].split("/");
        double seconds = Double.parseDouble(pair[0].trim())
                / Double.parseDouble(pair[1].trim());

        double result = degrees + (minutes / 60.0) + (seconds / 3600.0);
        if ((ref.equals("S") || ref.equals("W"))) {
            return (float) -result;
        }
        return (float) result;
    }

这里写图片描述

四、总结

经过简单测试了魅蓝note2、努比亚、华为P6三款机型,得出结论:
1、在拍照的照片识别中,只有努比亚不可以读取图片的经纬度信息,但是可以读取机型等信息。
2、在选取本地图库的照片(由本机相机拍照所得)识别中,同上。
3、在选取本地图库的图片(由非本机相机所得,比如网络下载、裁剪等渠道而来)识别中,都无法读取相关信息。
4、以上3条可以总结为1条,只能识别那些带有exif信息的图片

五、样例下载

1、下载地址点这里,代码很少,仅供参考。
csdn的代码下载下来可能不一定能跑起来,为此今天(2018-02-05)我简单更新了代码托管在了github上,地址在这里:https://github.com/xmliu/xmPhoto
2、声明:demo是一个android module,可以直接复制到现有的project下;测试时记得开启手机的GPS权限。
3、要修改的地方:打包签名的keystore需要换成自己的;高德地图key需要自己根据keystore重新申请。

3
1
查看评论

如何通过一张图片找到你的位置?

灵感来自读《社会工程:安全体系中的人性漏洞》
  • think_ycx
  • think_ycx
  • 2016-02-23 22:18
  • 7471

Android中通过Exifinterface读取图片地理位置信息

  • 2016-05-19 10:33
  • 11.21MB
  • 下载

调戏微信朋友圈定位算法,巧用图片位置信息更改朋友圈定位信息

调戏微信定位算法的灵感来源于一次发带GPS信息图片的朋友圈。发现微信的定位逻辑是:如果定位之前先选择了带有GPS信息的照片,那么定位信息是先从照片引用的,如果发现没信息再从GPS或基站定位。   首先看看效果:   定位信息显示“吉尔吉斯斯坦”。可是叶子竹还在学校用功读书呢。这...
  • huzexin
  • huzexin
  • 2016-05-01 12:00
  • 25630

微信能从图片获取位置信息,原理其实很简单

在微信朋友圈上传图片时,点击位置可以自动识别照片拍摄的地理位置 过去我们发送朋友圈时,可以显示自己所在的位置信息,而现在自动读取照片拍摄位置让不少人联想到了图像识别技术。事实上,微信所做的并没有这么复杂,有业内人士告诉新功能是基于图片位置信息(即Exif的GPS定位信息)实现的。 什么是Exif?...
  • yubingdian2011
  • yubingdian2011
  • 2016-08-25 15:51
  • 23775

android:如何从照片中获取拍摄地址信息

在开发中遇到一个需求,需要解析拿到照片拍摄时的地址信息,在网上有很多网站提供照片上传后解析出照片的具体信息,很详细。android也很给力,提供ExifInterface ,可以获取到拍摄照片时的很多信息。TAG_DATETIME 时间日期 TAG_FLASH 闪光灯 TAG_GPS_LATITUD...
  • qq_17326933
  • qq_17326933
  • 2015-08-29 20:50
  • 4996

Android 获取手机本地图片所在的位置

Android、道友们在做需求的时候、可能会需要展示图片的拍摄位置坐标
  • qq_28195645
  • qq_28195645
  • 2016-05-13 10:32
  • 1357

Android中通过Exifinterface读取图片地理位置信息

/** * 获取照片其他附属属性 * * @param uri */ public void getImageExifInterfaceData(Uri uri) { ExifInterface exifInterface = null; try { Stri...
  • xizhilang201
  • xizhilang201
  • 2016-12-27 09:19
  • 798

Android之拍照和相册选取图片并裁剪得到路径

拍照和相册选取图片并裁剪得到图片的相应路径上传服务器、
  • Android_Cll
  • Android_Cll
  • 2017-03-28 11:18
  • 13418

JPEG图像获取GPS数据

背景周一来到实验室本来要做项目,这个月快到月底了,想赶快写,要不然导师就要催。导师突然交给任务,让完成一个基于c++的JPEG图像获取GPS数据的小程序,他说很小,很简单,让我赶快写。让我做的事情如下图: 就是要获取如图所示的GPS数据。TUA,我哪会啊,根本是一头雾水啊,但是还是给应承下来。...
  • z_x_b5
  • z_x_b5
  • 2015-10-26 21:09
  • 1165

Android将地理位置存储到图片扩展信息EXIF

图片EXIF
  • goumiaoqiong
  • goumiaoqiong
  • 2016-08-06 15:26
  • 1168
    个人资料
    • 访问:177686次
    • 积分:2802
    • 等级:
    • 排名:第15109名
    • 原创:58篇
    • 转载:5篇
    • 译文:0篇
    • 评论:52条
    联系我吧
    我的App
    博客专栏
    文章分类