一、前言
通过Java 技术框架获取图片的详细信息。(① 手机-相册-图片详细;② 图片-右键-属性-详细信息;)
二、实操
- 解析图片的常用信息,包括地理位置信息;
- 通过第三方API(例如百度/高德/腾讯地图开放API等)根据经纬度获取具体的地址;
(1)引入Maven依赖
<!-- 核心:图片解析工具类-->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.16.0</version>
</dependency>
<!-- 辅助:工具类 hutool :https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.6</version>
</dependency>
(2)Java 完整实例代码
package edu.study.module.up.util.image;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.io.File;
import java.io.IOException;
/**
* 解析图片详细(拍摄时间,拍摄地址,标记等)信息
*/
public class ImageUtils {
public static void main(String[] args) throws Exception {
// 准备一张带有地理位置信息的图片(方便测试是否可以读取到图片的地理位置经纬度信息)
File file = new File("C:\\Users\\drew\\Pictures\\Saved Pictures\\test.jpg");
readImageInfo(file);
}
/**
* 提取照片里面的信息
*
* @param file 照片文件
* @throws ImageProcessingException
* @throws Exception
*/
private static void readImageInfo(File file) throws ImageProcessingException, Exception {
Metadata metadata = ImageMetadataReader.readMetadata(file);
System.out.println("---打印全部详情---");
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
System.out.format("[%s] - %s = %s\n", directory.getName(), tag.getTagName(), tag.getDescription());
}
if (directory.hasErrors()) {
for (String error : directory.getErrors()) {
System.err.format("ERROR: %s", error);
}
}
}
System.out.println("--打印常用信息---");
Double lat = null;
Double lng = null;
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
String tagName = tag.getTagName(); //标签名
String desc = tag.getDescription(); //标签信息
if (tagName.equals("Image Height")) {
System.err.println("图片高度: " + desc);
} else if (tagName.equals("Image Width")) {
System.err.println("图片宽度: " + desc);
} else if (tagName.equals("Date/Time Original")) {
System.err.println("拍摄时间: " + desc);
} else if (tagName.equals("GPS Latitude")) {
System.err.println("纬度 : " + desc);
System.err.println("纬度(度分秒格式) : " + pointToLatlong(desc));
lat = latLng2Decimal(desc);
} else if (tagName.equals("GPS Longitude")) {
System.err.println("经度: " + desc);
System.err.println("经度(度分秒格式): " + pointToLatlong(desc));
lng = latLng2Decimal(desc);
}
}
}
System.err.println("--经纬度转地址--");
//经纬度转地主使用百度api
convertGpsToLoaction(lat, lng);
}
/**
* 经纬度格式 转换为 度分秒格式 ,如果需要的话可以调用该方法进行转换
*
* @param point 坐标点
* @return
*/
public static String pointToLatlong(String point) {
Double du = Double.parseDouble(point.substring(0, point.indexOf("°")).trim());
Double fen = Double.parseDouble(point.substring(point.indexOf("°") + 1, point.indexOf("'")).trim());
Double miao = Double.parseDouble(point.substring(point.indexOf("'") + 1, point.indexOf("\"")).trim());
Double duStr = du + fen / 60 + miao / 60 / 60;
return duStr.toString();
}
/***
* 经纬度坐标格式转换(* °转十进制格式)
* @param gps
*/
public static double latLng2Decimal(String gps) {
String a = gps.split("°")[0].replace(" ", "");
String b = gps.split("°")[1].split("'")[0].replace(" ", "");
String c = gps.split("°")[1].split("'")[1].replace(" ", "").replace("\"", "");
double gps_dou = Double.parseDouble(a) + Double.parseDouble(b) / 60 + Double.parseDouble(c) / 60 / 60;
return gps_dou;
}
/**
* api_key:注册的百度api的key
* coords:经纬度坐标
* http://api.map.baidu.com/reverse_geocoding/v3/?ak="+api_key+"&output=json&coordtype=wgs84ll&location="+coords
* <p>
* 经纬度转地址信息
*
* @param gps_latitude 纬度
* @param gps_longitude 经度
*/
private static void convertGpsToLoaction(double gps_latitude, double gps_longitude) throws IOException {
String apiKey = "YNxcSCAphFvuPD4LwcgWXwC3SEZZc7Ra";
String res = "";
String url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak=" + apiKey
+ "&output=json&coordtype=wgs84ll&location=" + (gps_latitude + "," + gps_longitude);
System.err.println("【url】" + url);
res = HttpUtil.get(url);
JSONObject object = JSONObject.parseObject(res);
if (object.containsKey("result")) {
JSONObject result = object.getJSONObject("result");
if (result.containsKey("addressComponent")) {
JSONObject address = object.getJSONObject("result").getJSONObject("addressComponent");
System.err.println("拍摄地点:" + address.get("country") + " "
+ address.get("province") + " " + address.get("city") + " " + address.get("district") + " "
+ address.get("street") + " " + result.get("formatted_address") + " " + result.get("business"));
}
}
}
}
(3)测试
① 准备图片
准备一张带有地理位置信息的图片(见附件test.jpg):
- 设置【拍照-保存地理信息】;
- 微信-发送图片-勾选【原图】到 文件传输助手;
- 保存到电脑位置上,修改号 代码里面的 图片在电脑上的地址;
② 测试结果
---打印全部详情---
[JPEG] - Compression Type = Baseline
[JPEG] - Data Precision = 8 bits
[JPEG] - Image Height = 3000 pixels
[JPEG] - Image Width = 4000 pixels
[JPEG] - Number of Components = 3
[JPEG] - Component 1 = Y component: Quantization table 0, Sampling factors 2 horiz/2 vert
[JPEG] - Component 2 = Cb component: Quantization table 1, Sampling factors 1 horiz/1 vert
[JPEG] - Component 3 = Cr component: Quantization table 1, Sampling factors 1 horiz/1 vert
[Exif IFD0] - Image Width = 4000 pixels
[Exif IFD0] - Model = Redmi Note 7 Pro
[Exif IFD0] - Image Height = 3000 pixels
[Exif IFD0] - Orientation = Right side, top (Rotate 90 CW)
[Exif IFD0] - Date/Time = 2022:01:06 09:22:27
[Exif IFD0] - YCbCr Positioning = Center of pixel array
[Exif IFD0] - Resolution Unit = Inch
[Exif IFD0] - X Resolution = 72 dots per inch
[Exif IFD0] - Y Resolution = 72 dots per inch
[Exif IFD0] - Make = Xiaomi
[Exif SubIFD] - Unknown tag (0x9aaa) = [2176 values]
[Exif SubIFD] - ISO Speed Ratings = 192
[Exif SubIFD] - Exposure Program = Program normal
[Exif SubIFD] - F-Number = f/1.8
[Exif SubIFD] - Exposure Time = 1/33 sec
[Exif SubIFD] - Unknown tag (0x9999) = {"mirror":false,"?sensor_type":"rear","Hdr":"off","OpMode":32769,"AIScene":0,"FilterId":66048,"ZoomMultiple":1}
[Exif SubIFD] - Sensing Method = (Not defined)
[Exif SubIFD] - Unknown tag (0x8895) = 0
[Exif SubIFD] - Sub-Sec Time Digitized = 451999
[Exif SubIFD] - Sub-Sec Time Original = 451999
[Exif SubIFD] - Sub-Sec Time = 451999
[Exif SubIFD] - Focal Length = 4.7 mm
[Exif SubIFD] - Flash = Flash did not fire, auto
[Exif SubIFD] - White Balance = D65
[Exif SubIFD] - Metering Mode = Center weighted average
[Exif SubIFD] - Scene Capture Type = Standard
[Exif SubIFD] - Focal Length 35 = 25 mm
[Exif SubIFD] - Max Aperture Value = f/1.8
[Exif SubIFD] - Date/Time Digitized = 2022:01:06 09:22:27
[Exif SubIFD] - Exposure Bias Value = 0 EV
[Exif SubIFD] - Exif Image Height = 3000 pixels
[Exif SubIFD] - White Balance Mode = Auto white balance
[Exif SubIFD] - Date/Time Original = 2022:01:06 09:22:27
[Exif SubIFD] - Brightness Value = 0.86
[Exif SubIFD] - Exif Image Width = 4000 pixels
[Exif SubIFD] - Exposure Mode = Auto exposure
[Exif SubIFD] - Aperture Value = f/1.8
[Exif SubIFD] - Components Configuration = YCbCr
[Exif SubIFD] - Color Space = sRGB
[Exif SubIFD] - Scene Type = Directly photographed image
[Exif SubIFD] - Shutter Speed Value = 1/33 sec
[Exif SubIFD] - Exif Version = 2.20
[Exif SubIFD] - FlashPix Version = 1.00
[Interoperability] - Interoperability Index = Recommended Exif Interoperability Rules (ExifR98)
[Interoperability] - Interoperability Version = 1.00
[GPS] - GPS Latitude Ref = N
[GPS] - GPS Latitude = 22° 51' 55.45"
[GPS] - GPS Longitude Ref = E
[GPS] - GPS Longitude = 113° 4' 50.53"
[GPS] - GPS Altitude Ref = Sea level
[GPS] - GPS Altitude = 0 metres
[GPS] - GPS Time-Stamp = 01:22:23.000 UTC
[GPS] - GPS Processing Method = CELLID
[GPS] - GPS Date Stamp = 2022:01:06
[Exif Thumbnail] - Thumbnail Offset = 3425 bytes
[Exif Thumbnail] - Orientation = Right side, top (Rotate 90 CW)
[Exif Thumbnail] - Thumbnail Length = 12043 bytes
[Exif Thumbnail] - Compression = JPEG (old-style)
[Exif Thumbnail] - Resolution Unit = Inch
[Exif Thumbnail] - X Resolution = 72 dots per inch
[Exif Thumbnail] - Y Resolution = 72 dots per inch
[Exif Thumbnail] - Exif Image Height = 240 pixels
[Exif Thumbnail] - Exif Image Width = 320 pixels
[Huffman] - Number of Tables = 4 Huffman tables
[File Type] - Detected File Type Name = JPEG
[File Type] - Detected File Type Long Name = Joint Photographic Experts Group
[File Type] - Detected MIME Type = image/jpeg
[File Type] - Expected File Name Extension = jpg
[File] - File Name = test.jpg
[File] - File Size = 7212261 bytes
[File] - File Modified Date = 星期四 一月 06 09:23:27 +08:00 2022
--打印常用信息---
图片高度: 3000 pixels
图片宽度: 4000 pixels
图片宽度: 4000 pixels
图片高度: 3000 pixels
拍摄时间: 2022:01:06 09:22:27
纬度 : 22° 51' 55.45"
纬度(度分秒格式) : 22.865402777777778
经度: 113° 4' 50.53"
经度(度分秒格式): 113.08070277777777
--经纬度转地址--
【url】http://api.map.baidu.com/reverse_geocoding/v3/?ak=YNxcSCAphFvuPD4LwcgWXwC3SEZZc7Ra&output=json&coordtype=wgs84ll&location=22.865402777777778,113.08070277777777
拍摄地点:中国 广东省 佛山市 顺德区 龙洲西路 广东省佛山市顺德区龙洲西路75
③ 温馨提示
为了防止图片泄露个人隐私数据(地理位置信息),建议如下:
- 拍照--设置--关闭【保存地理位置信息】;
- 涉及到拍照功能,建议限制授权【设置 使用中询问保存地理信息 或 关闭地理信息授权】功能;
至此,感谢阅读🙏