Java获取照片的Exif信息,并解析GPS
Posted 程序媛一枚~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java获取照片的Exif信息,并解析GPS相关的知识,希望对你有一定的参考价值。
Java获取照片的Exif信息,并解析GPS
❤️ 这篇博客将介绍什么EXIF,以及如何用Java语言读取Exif信息,并转换经纬度为位置信息;❤️
1. 效果图
Exif包含的信息很多,示例如下:
[JPEG] - Compression Type = Baseline
[JPEG] - Data Precision = 8 bits
[JPEG] - Image Height = 3840 pixels
[JPEG] - Image Width = 1744 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
[JFIF] - Version = 1.1
[JFIF] - Resolution Units = inch
[JFIF] - X Resolution = 96 dots
[JFIF] - Y Resolution = 96 dots
[JFIF] - Thumbnail Width Pixels = 0
[JFIF] - Thumbnail Height Pixels = 0
[Exif IFD0] - Image Width = 1744 pixels
[Exif IFD0] - Image Height = 3840 pixels
[Exif IFD0] - Bits Per Sample = 8 8 8 bits/component/pixel
[Exif IFD0] - Make = HUAWEI
[Exif IFD0] - Model = ELS-AN00
[Exif IFD0] - Orientation = Unknown (0)
[Exif IFD0] - X Resolution = 72 dots per inch
[Exif IFD0] - Y Resolution = 72 dots per inch
[Exif IFD0] - Resolution Unit = Inch
[Exif IFD0] - Software = ELS-AN00 11.0.0.176(C00E170R3P6)
[Exif IFD0] - Date/Time = 2021:05:21 07:18:02
[Exif IFD0] - YCbCr Positioning = Center of pixel array
[Exif IFD0] - Device Setting Description = 105 112 112 0
[Exif SubIFD] - Document Name =
[Exif SubIFD] - Exposure Time = 2049/500000 sec
[Exif SubIFD] - F-Number = f/1.8
[Exif SubIFD] - Exposure Program = Program normal
[Exif SubIFD] - ISO Speed Ratings = 50
[Exif SubIFD] - Exif Version = 2.10
[Exif SubIFD] - Date/Time Original = 2021:05:21 07:18:02
[Exif SubIFD] - Date/Time Digitized = 2021:05:21 07:18:02
[Exif SubIFD] - Components Configuration = YCbCr
[Exif SubIFD] - Compressed Bits Per Pixel = 0.95 bits/pixel
[Exif SubIFD] - Shutter Speed Value = 1/999963864 sec
[Exif SubIFD] - Aperture Value = f/1.8
[Exif SubIFD] - Brightness Value = 0.0
[Exif SubIFD] - Exposure Bias Value = 0 EV
[Exif SubIFD] - Max Aperture Value = f/1.8
[Exif SubIFD] - Metering Mode = Multi-segment
[Exif SubIFD] - White Balance = Daylight
[Exif SubIFD] - Flash = Flash did not fire
[Exif SubIFD] - Focal Length = 4.4 mm
[Exif SubIFD] - Makernote = 65 117 116 111 0
[Exif SubIFD] - Sub-Sec Time = 242921
[Exif SubIFD] - Sub-Sec Time Original = 242921
[Exif SubIFD] - Sub-Sec Time Digitized = 242921
[Exif SubIFD] - FlashPix Version = 1.00
[Exif SubIFD] - Color Space = sRGB
[Exif SubIFD] - Exif Image Width = 1744 pixels
[Exif SubIFD] - Exif Image Height = 3840 pixels
[Exif SubIFD] - Sensing Method = One-chip color area sensor
[Exif SubIFD] - File Source = Digital Still Camera (DSC)
[Exif SubIFD] - Scene Type = Directly photographed image
[Exif SubIFD] - Custom Rendered = Custom process
[Exif SubIFD] - Exposure Mode = Auto exposure
[Exif SubIFD] - White Balance Mode = Auto white balance
[Exif SubIFD] - Digital Zoom Ratio = 1
[Exif SubIFD] - Focal Length 35 = 18 mm
[Exif SubIFD] - Scene Capture Type = Standard
[Exif SubIFD] - Gain Control = None
[Exif SubIFD] - Contrast = None
[Exif SubIFD] - Saturation = None
[Exif SubIFD] - Sharpness = None
[Exif SubIFD] - Subject Distance Range = Unknown
[Interoperability] - Interoperability Index = Recommended Exif Interoperability Rules (ExifR98)
[Interoperability] - Interoperability Version = 1.00
[GPS] - GPS Version ID = 2.200
[GPS] - GPS Latitude Ref = N
[GPS] - GPS Latitude = 40° 4’ 22.74"
[GPS] - GPS Longitude Ref = E
[GPS] - GPS Longitude = 116° 20’ 37.01"
[GPS] - GPS Altitude Ref = Below sea level
[GPS] - GPS Altitude = 0 metres
[GPS] - GPS Time-Stamp = 23:18:01.000 UTC
[GPS] - GPS Processing Method = CELLID
[GPS] - GPS Date Stamp = 2021:05:20
[Exif Thumbnail] - Image Width = 256 pixels
[Exif Thumbnail] - Image Height = 528 pixels
[Exif Thumbnail] - Compression = JPEG (old-style)
[Exif Thumbnail] - Orientation = Unknown (0)
[Exif Thumbnail] - X Resolution = 72 dots per inch
[Exif Thumbnail] - Y Resolution = 72 dots per inch
[Exif Thumbnail] - Resolution Unit = Inch
[Exif Thumbnail] - Thumbnail Offset = 1622 bytes
[Exif Thumbnail] - Thumbnail Length = 26099 bytes
[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 = mg.jpg
[File] - File Size = 1771566 bytes
[File] - File Modified Date = 星期五 七月 09 14:30:00 +08:00 2021
获取了常见的属性: 压缩格式、图像宽度、图像高度、拍摄手机、型号、手机系统版本号、gps版本、经度、纬度、高度、UTC时间戳、gps日期、iso速率、曝光时间、曝光模式、光圈值、焦距、图像色彩空间、文件源、场景类型等 效果图如下:
2. 什么是Exif?
EXIF是 Exchangeable Image File的缩写,这是一种专门为数码相机照片设定的格式。这种格式可以用来记录数字照片的属性信息,例如相机的品牌及型号、相片的拍摄时间、拍摄时所设置的光圈大小、快门速度、ISO、照片的宽度、高度等信息。
最简单易用的EXIF信息处理的Java包是Drew Noakes写的metadata-extractor,该项目最新的版本是2.16.0,支持EXIF 2.2版本。
并不是每个JPG图像文件都包含有EXIF信息,可以在Windows资源管理器单击选中图片后,如果该图片包含EXIF信息,则在窗口状态栏会显示出相机的型号,否则exif信息丢失。
- http://www.drewnoakes.com/code/exif/ 可下载该项目的最新版本包括其源码
- github地址:https://github.com/drewnoakes/metadata-extractor/releases?after=2.6.0
3. 源代码
获取图片的压缩格式、图像宽度、图像高度、拍摄手机、型号、手机系统版本号、gps版本、经度、纬度、高度、UTC时间戳、gps日期、iso速率、曝光时间、曝光模式、光圈值、焦距、图像色彩空间、文件源、场景类型等
pom依赖:
<!--获取相机exif信息-->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.16.0</version>
</dependency>
package com.getGps;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.imaging.jpeg.JpegProcessingException;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/*************************************
*Class Name: gpsExifInfo
*Description: <获取相机经纬度并且转换实际位置>
*@author: seminar
*************************************/
public class GpsExifInfo {
public static void main(String[] args) throws ImageProcessingException, IOException {
String imgDir = "E:\\\\imgs";
File[] files = new File(imgDir).listFiles();
for (File file : files) {
if (!file.getName().endsWith(".jpg")) {
continue;
}
System.out.println("----------------------------------------\\n" + file.getName());
// 获取照片信息
Map exifMap = readPicExifInfo(file);
// 打印照片信息
printPicExifInfo(exifMap);
}
}
/**
* 获取图片文件的Exif信息
*
* @param file
* @return
* @throws ImageProcessingException
* @throws IOException
*/
private static Map<String, String> readPicExifInfo(File file) throws ImageProcessingException, IOException {
Map<String, String> map = new HashMap<>();
Metadata metadata = ImageMetadataReader.readMetadata(file);
for (Directory directory : metadata.getDirectories()) {
for (Tag tag : directory.getTags()) {
// 输出所有属性
System.out.format(
"[%s] - %s = %s\\n", directory.getName(), tag.getTagName(), tag.getDescription());
map.put(tag.getTagName(), tag.getDescription());
}
if (directory.hasErrors()) {
for (String error : directory.getErrors()) {
System.err.format("ERROR: %s", error);
}
}
}
return map;
}
/**
* 打印照片Exif信息
*
* @param map
*/
private static void printPicExifInfo(Map<String, String> map) {
String[] strings = new String[]{"Compression", "Image Width", "Image Height", "Make", "Model", "Software",
"GPS Version ID", "GPS Latitude", "GPS Longitude", "GPS Altitude", "GPS Time-Stamp", "GPS Date Stamp",
"ISO Speed Ratings", "Exposure Time", "Exposure Mode", "F-Number", "Focal Length 35", "Color Space", "File Source", "Scene Type"};
String[] names = new String[]{"压缩格式", "图像宽度", "图像高度", "拍摄手机", "型号", "手机系统版本号",
"gps版本", "经度", "纬度", "高度", "UTC时间戳", "gps日期",
"iso速率", "曝光时间", "曝光模式", "光圈值", "焦距", "图像色彩空间", "文件源", "场景类型"};
for (int i = 0; i < strings.length; i++) {
if (map.containsKey(strings[i])) {
if ("GPS Latitude".equals(strings[i]) || "GPS Longitude".endsWith(strings[i])) {
System.out.println(names[i] + " " + strings[i] + " : " + map.get(strings[i]) + ", °转dec: " + latLng2Decimal(map.get(strings[i])));
} else {
System.out.println(names[i] + " " + strings[i] + " : " + map.get(strings[i]));
}
}
}
// 经纬度转location地址信息
if (map.containsKey("GPS Latitude") && map.containsKey("GPS Longitude")) {
convertLatLng2Loaction(latLng2Decimal(map.get("GPS Latitude")), latLng2Decimal(map.get("GPS Longitude")));
}
}
/**
* 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 convertLatLng2Loaction(double gps_latitude, double gps_longitude) throws IOException {
String apiKey = "FxzbLsuDDL4CS2U0M4KezOZZbGUY9iWtRn";
String res = "";
String url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak=" + apiKey + "&output=json&coordtype=wgs84ll&location=" + (gps_latitude + "," + gps_longitude);
System.out.println("【url】" + url);
CloseableHttpClient client = HttpClients.custom().build();
HttpGet httpPost = new HttpGet(url);
httpPost.setHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE);
CloseableHttpResponse resp = client.execute(httpPost);
if (resp != null) {
if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = resp.getEntity();
res = IOUtils.readStreamAsString(entity.getContent());
System.out.println("resJson: " + res);
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.out.println("拍摄地点:" + address.get("country") + " " + address.get("province") + " " + address.get("city") + " " + address.get("district") + " "
+ address.get("street") + " " + result.get("formatted_address") + " " + result.get("business"));
}
}
}
}
}
/***
* 经纬度坐标格式转换(* °转十进制格式)
* @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;
}
}
参考
以上是关于Java获取照片的Exif信息,并解析GPS的主要内容,如果未能解决你的问题,请参考以下文章
web获取照片EXIF信息(例如:拍照方向相机设备型号拍摄时间ISO 感光度GPS 地理位置等数据)
web获取照片EXIF信息(例如:拍照方向相机设备型号拍摄时间ISO 感光度GPS 地理位置等数据)