2019独角兽企业重金招聘Python工程师标准>>>
最近两天做了一个需求,从APP端上传的照片信息里面读取出GPS位置信息,然后翻译成可读的地点信息。
总结一下,分为三步:
(1)提取图片中的GPS信息,使用到了metadata-extractor;
(2)把物理设备的GPS坐标转换为高德的坐标;
(3)调用地图API传参数。
一.提取图片EXIF块中的GPS信息
(1)添加依赖:metadata-extractor
com.drewnoakes
metadata-extractor
2.11.0
(2)使用ImageMetadataReader的readMetadata(File)方法:
Metadata metaData = null;
try {
metaData = ImageMetadataReader.readMetadata(file);
} catch (Exception e) {
// To do deal exception
}
Collection directory = metaData.getDirectoriesOfType(GpsDirectory.class);
Iterator 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":{
// 省略详情
}
}
}
代码已经上传到了 这里 可以下载。