简介
大疆无人机拍摄的JPEG图片中包括了很多扩展信息,比如经纬度、高度、相机名称等,同时如果是视频截取的图片中还包含有metadata信息,这里面存放了飞机和云台姿态信息。
使用com.drewnoakes - metadata-extractor 这个类库可以读取扩展信息和metadata信息。
pom
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.9.1</version>
</dependency>
示例代码
package com.ramble.demo.util;
import com.alibaba.fastjson2.JSON;
import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException;
import com.drew.imaging.jpeg.JpegMetadataReader;
import com.drew.metadata.Directory;
import com.drew.metadata.Metadata;
import com.drew.metadata.Tag;
import com.drew.metadata.exif.ExifIFD0Directory;
import com.drew.metadata.xmp.XmpDirectory;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Project ramble-spring-boot
* Package com.ramble.demo.util
* Class ImgUtil
* date 2024/3/12 9:35
* author cml
* Email liangchen_beijing@163.com
* Description
*/
public class ImgUtil {
/**
* 获取图片扩展信息
* @param file 图片
* @return 扩展信息,示例:
*
* {
* "Compression": "JPEG",
* "Number of Tables": "4 Huffman tables",
* "Exif Version": "2.30",
* "Components Configuration": "YCbCr",
* "Compression Type": "Baseline",
* "Image Description": "default",
* "Number of Components": "3",
* "Component 2": "Cb component: Quantization table 1, Sampling factors 1 horiz/1 vert",
* "Focal Length": "4.5 mm",
* "Component 1": "Y component: Quantization table 0, Sampling factors 2 horiz/2 vert",
* "Samples Per Pixel": "3 samples/pixel",
* "YCbCr Positioning": "Center of pixel array",
* "Date/Time Original": "2022:07:28 15:21:57",
* "X Resolution": "72 dots per inch",
* "Interoperability Version": "1.00",
* "Device Setting Description": "0 0 0 0",
* "Component 3": "Cr component: Quantization table 1, Sampling factors 1 horiz/1 vert",
* "F-Number": "f/2.8",
* "Focal Length 35": "24 mm",
* "Windows XP Keywords": "single",
* "Exposure Program": "Program normal",
* "Digital Zoom Ratio": "1",
* "GPS Version ID": "2.300",
* "GPS Latitude Ref": "N",
* "Detected File Type Long Name": "Joint Photographic Experts Group",
* "File Source": "Digital Still Camera (DSC)",
* "Exposure Time": "1/500 sec",
* "GPS Altitude Ref": "Sea level",
* "Detected MIME Type": "image/jpeg",
* "Expected File Name Extension": "jpg",
* "ISO Speed Ratings": "100",
*
* "GPS Longitude": "121° 41' 41.88\"",
*
* "Make": "DJI",
* "Orientation": "Top, left side (Horizontal / normal)",
* "Metering Mode": "Center weighted average",
* "Contrast": "None",
* "Interoperability Index": "Recommended Exif Interoperability Rules (ExifR98)",
* "GPS Longitude Ref": "E",
* "Thumbnail Offset": "21110 bytes",
* "Gain Control": "None",
* "Lens Specification": "24mm f/2.8",
* "XMP Value Count": "22",
* "Software": "10.00.03.10",
* "Exif Image Height": "6000 pixels",
* "Y Resolution": "72 dots per inch",
* "Scene Type": "Directly photographed image",
*
* "GPS Latitude": "30° 55' 42.86\"",
*
* "FlashPix Version": "1.00",
* "Data Precision": "8 bits",
* "White Balance": "Daylight",
* "Windows XP Comment": "0.9.142",
* "GPS Altitude": "100.92 metres",
* "Thumbnail Length": "30744 bytes",
* "Color Space": "sRGB",
* "File Size": "12503249 bytes",
* "Date/Time Digitized": "2022:07:28 15:21:57",
* "File Name": "DJI_0760_W.JPG",
* "Flash": "Flash did not fire",
* "Makernote": "[19829 values]",
* "File Modified Date": "星期四 七月 28 15:21:56 +08:00 2022",
* "Saturation": "None",
* "Date/Time": "2022:07:28 15:21:57",
* "Exif Image Width": "8000 pixels",
* "Image Height": "128 pixels",
* "Sharpness": "None",
* "Image Width": "160 pixels",
* "Resolution Unit": "Inch",
* "Exposure Bias Value": "0 EV",
* "Detected File Type Name": "JPEG",
* "Max Aperture Value": "f/2.8",
* "Exposure Mode": "Auto exposure",
* "Model": "MAVIC2-ENTERPRISE-ADVANCED",
* "Scene Capture Type": "Standard",
* "White Balance Mode": "Auto white balance",
* "Bits Per Sample": "8 8 8 bits/component/pixel"
* }
*
* @throws ImageProcessingException
* @throws IOException
*/
public 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;
}
/**
* 获取xmp信息
* @param file jpeg图片
* @return xmp信息,示例:
* {
* "drone-dji:GimbalYawDegree": "-81.70",
* "xmp:ModifyDate": "2022-07-28",
* "drone-dji:GpsLongitude": "+121.6950093",
* "drone-dji:SelfData": "",
* "drone-dji:GimbalRollDegree": "+0.00",
* "dc:format": "image/jpg",
* "drone-dji:CamReverse": "0",
* "drone-dji:GpsLatitude": "+30.9285845",
* "tiff:Make": "DJI",
* "drone-dji:FlightRollDegree": "-4.00",
* "drone-dji:AbsoluteAltitude": "+100.92",
* "drone-dji:GimbalPitchDegree": "-45.00",
* "tiff:Model": "MAVIC2-ENTERPRISE-ADVANCED",
* "drone-dji:FlightPitchDegree": "+12.80",
* "crs:HasCrop": "False",
* "crs:Version": "7.0",
* "drone-dji:RelativeAltitude": "+80.03",
* "xmp:CreateDate": "2022-07-28",
* "crs:AlreadyApplied": "False",
* "drone-dji:FlightYawDegree": "-92.40",
* "crs:HasSettings": "False",
* "drone-dji:GimbalReverse": "0"
* }
*/
public static String getXmp(File file) {
try {
Metadata metadata = JpegMetadataReader.readMetadata(file);
for (Directory directory : metadata.getDirectories()) {
if (directory instanceof XmpDirectory) {
XmpDirectory xmpDirectory = (XmpDirectory) directory;
Map<String, String> xmpProperties = xmpDirectory.getXmpProperties();
return JSON.toJSONString(xmpProperties);
}
}
} catch (Exception e) {
System.out.println("error");
}
return null;
}
public static String[] getImageParam(File file) {
try {
String[] param = new String[5];
Metadata metadata = JpegMetadataReader.readMetadata(file);
for (Directory directory : metadata.getDirectories()) {
//获取图片的Exif拍摄时间
if (directory instanceof ExifIFD0Directory) {
ExifIFD0Directory exifIFD0Directory = (ExifIFD0Directory) directory;
exifIFD0Directory.getName();
param[4] = JSON.toJSONString(exifIFD0Directory.getDate(306));
}
if (directory instanceof XmpDirectory) {
XmpDirectory xmpDirectory = (XmpDirectory) directory;
Map<String, String> xmpProperties = xmpDirectory.getXmpProperties();
String degree = xmpProperties.get("drone-dji:GimbalYawDegree");
String lat = xmpProperties.get("drone-dji:GpsLatitude");
String lon = xmpProperties.get("drone-dji:GpsLongtitude");
String relativeAltitude = xmpProperties.get("drone-dji:RelativeAltitude");
param[0] = degree;
param[1] = lat;
param[2] = lon;
param[3] = relativeAltitude;
}
}
return param;
} catch (Exception e) {
return null;
}
}
}