读取图片EXIF块中GPS信息,转换为高德地图API坐标

    最近两天做了一个需求,从APP端上传的照片信息里面读取出GPS位置信息,然后翻译成可读的地点信息。

    总结一下,分为三步:

    (1)提取图片中的GPS信息,使用到了metadata-extractor;

    (2)把物理设备的GPS坐标转换为高德的坐标;

    (3)调用地图API传参数。

一.提取图片EXIF块中的GPS信息

        (1)添加依赖:metadata-extractor

    <dependency>
      <groupId>com.drewnoakes</groupId>
      <artifactId>metadata-extractor</artifactId>
      <version>2.11.0</version>
    </dependency>

        (2)使用ImageMetadataReaderreadMetadata(File)方法:

        Metadata metaData = null;
		try {
			metaData = ImageMetadataReader.readMetadata(file);
		} catch (Exception e) { 
            // To do deal exception
		}
		Collection<GpsDirectory> directory = metaData.getDirectoriesOfType(GpsDirectory.class);
		Iterator<GpsDirectory> it = directory.iterator();
		while(it.hasNext()){
			GpsDirectory next = it.next();
			String latitude = next.getString(GpsDirectory.TAG_LATITUDE);
			String longitude = next.getString(GpsDirectory.TAG_LONGITUDE);
		}

二.处理原始GPS数据,转换为高德坐标

        取出的经纬度格式是这样的:29/1 26/1 3010/100,因此后续需要自己做一下格式化处理。

        (1)转化为10进制格式:

        String[] number = primaryLati.split(" ");
		String[] hs = number[0].split("/");// 度
		String[] ms = number[1].split("/");// 分
		String[] ss = number[2].split("/");// 秒
		double md = Double.valueOf(ms[0])/Double.valueOf(ms[1]) + Double.valueOf(ss[0])/(Double.valueOf(ss[1])*60);// 秒转分
		double sd = Double.valueOf(hs[0])/Double.valueOf(hs[1]) + md/60;// 分转度

        (2)把物理机器坐标转化为高德地图坐标:

    private static double pi = Math.PI;
	private static double a = 6378245.0;
	private static double ee = 0.00669342162296594323;

	/**
	 * 坐标转高德地图坐标
	 * @param wgLat
	 * @param wgLng
	 * @return
	 */
	public static double[] transLatLng(double wgLat, double wgLng) {
		double[] ds = new double[2];
		double dLat = transLat(wgLng - 105.0, wgLat - 35.0, pi);
		double dLng = transLng(wgLng - 105.0, wgLat - 35.0, pi);
		double radLat = wgLat / 180.0 * pi;
		double magic = Math.sin(radLat);
		magic = 1 - ee * magic * magic;
		double sqrtMagic = Math.sqrt(magic);
		dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
		dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
		ds[0] = wgLat + dLat;
		ds[1] = wgLng + dLng;
		return ds;
	}

	/**
	 * 纬度转换
	 * @param x
	 * @param y
	 * @param pi
	 * @return
	 */
	private static double transLat(double x, double y, double pi) {
		double ret;
		ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2
				* Math.sqrt(Math.abs(x));
		ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
		ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
		return ret;
	}
	
	/**
	 * 经度转换
	 * @param x
	 * @param y
	 * @param pi
	 * @return
	 */
	private static double transLng(double x, double y, double pi) {
		double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1
				* Math.sqrt(Math.abs(x));
		ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
		ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
		ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0
				* pi)) * 2.0 / 3.0;
		return ret;
	}

三.调用高德地图逆地理编码接口

        接口地址:http://restapi.amap.com/v3/geocode/regeo?parameters

        传参示例:

http://restapi.amap.com/v3/geocode/regeo?key=高德地图密钥&location=经度,纬度&poitype=&radius=&extensions=&batch=false&roadlevel=0

        返回结果:取到结果里面的formatted_address即可。

{
    "status":"1",
    "info":"OK",
    "infocode":"10000",
    "regeocode":{
        "formatted_address":"上海市青浦区徐泾镇虹桥世界中心L2B停车场虹桥世界中心",
        "addressComponent":{
           // 省略详情
        }
    }
}

        代码已经上传到了 这里 可以下载。

猜你喜欢

转载自my.oschina.net/jacktanger/blog/1820443
今日推荐