pom.xml
@@ -289,6 +289,17 @@ <version>1.70</version> </dependency> <!--图片信息获取--> <dependency> <groupId>com.drewnoakes</groupId> <artifactId>metadata-extractor</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>com.adobe.xmp</groupId> <artifactId>xmpcore</artifactId> <version>5.1.3</version> </dependency> </dependencies> src/main/java/com/dji/sample/media/controller/FileController.java
@@ -66,6 +66,11 @@ } @GetMapping("/getMediaInfo") public ResponseResult mediaInfo(@RequestParam String fileId) { return ResponseResult.success(fileService.mediaInfo(fileId)); } @GetMapping("/{workspace_id}/files/{job_id}") public ResponseResult findFilesList(@PathVariable(name = "workspace_id") String workspaceId, @PathVariable(name = "job_id") String jobId) { return ResponseResult.success(fileService.listMediaFileEntity(workspaceId, jobId)); src/main/java/com/dji/sample/media/model/MediaFileMarkEntity.java
@@ -78,5 +78,8 @@ @TableField("isadd") private Integer isadd; @TableField(value = "drone_data", typeHandler = FastjsonTypeHandler.class) private Object dronedata; } src/main/java/com/dji/sample/media/service/IFileService.java
@@ -5,6 +5,7 @@ import com.dji.sample.media.model.MediaFileDTO; import com.dji.sample.media.model.MediaFileEntity; import com.dji.sample.media.model.MediaFileQueryParam; import com.drew.imaging.ImageProcessingException; import java.awt.*; import java.io.IOException; @@ -36,8 +37,9 @@ */ Integer saveFile(String workspaceId, FileUploadDTO file); Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException; Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException, ImageProcessingException; Object mediaInfo(String fileId); /** * Query information about all files in this workspace based on the workspace id. * src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
@@ -15,9 +15,11 @@ import com.dji.sample.media.dao.IMarkMapper; import com.dji.sample.media.model.*; import com.dji.sample.media.service.IFileService; import com.dji.sample.media.util.ImgUtil; import com.dji.sample.territory.service.impl.TbFjServiceImpl; import com.dji.sample.territory.utils.VideoZipUtil; import com.dji.sample.territory.utils.WaterMarkUtil; import com.drew.imaging.ImageProcessingException; import io.minio.MinioClient; import io.minio.PutObjectArgs; import org.springframework.beans.factory.annotation.Autowired; @@ -82,7 +84,7 @@ return mapper.insert(fileEntity); } public Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException { public Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException, ImageProcessingException { File file2 = null; MediaFileMarkEntity mediaFileMarkEntity = this.fileUploadConvertToMarkEntity(file); String url = "http://dev.jxpskj.com:9000/cloud-bucket" + file.getObjectKey(); @@ -92,9 +94,9 @@ if (!endsWith) { file2 = new File(WaterMarkUtil.addWatermark(file1, timestamp, file.getMetadata().getShootPosition().getLat(), file.getMetadata().getShootPosition().getLng(), file.getMetadata().getGimbalYawDegree()).toURI()); } else { file2 = VideoZipUtil.compressVideo(file1, 1600000, 128000, 1280, 720); } Object data = ImgUtil.getInfo(file1); mediaFileMarkEntity.setDronedata(data); mediaFileMarkEntity.setWorkspaceId(workspaceId); mediaFileMarkEntity.setFileId(UUID.randomUUID().toString()); mediaFileMarkEntity.setObjectKey("/mark" + file.getPath() + "/" + file.getName()); @@ -110,6 +112,13 @@ } @Override public Object mediaInfo(String fileId) { MediaFileMarkEntity entity = markMapper.selectOne(new LambdaQueryWrapper<MediaFileMarkEntity>() .eq(MediaFileMarkEntity::getFileId, fileId)); return entity.getDronedata(); } @Override public List<MediaFileDTO> getAllFilesByWorkspaceId(String workspaceId) { return mapper.selectList(new LambdaQueryWrapper<MediaFileEntity>() .eq(MediaFileEntity::getWorkspaceId, workspaceId)) src/main/java/com/dji/sample/media/util/ImgUtil.java
New file @@ -0,0 +1,120 @@ package com.dji.sample.media.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.dji.sample.territory.service.impl.TbFjServiceImpl; 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 lombok.extern.slf4j.Slf4j; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @Slf4j public class ImgUtil { 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()) { // 将Tag名称和描述添加到Map中 map.put(tag.getTagName(), tag.getDescription()); } if (directory.hasErrors()) { for (String error : directory.getErrors()) { log.error(error); } } } return map; } 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) { log.error(String.valueOf(e)); } 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(); System.out.println(xmpProperties); 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; System.out.println(Arrays.toString(param)); } } return param; } catch (Exception e) { log.error(String.valueOf(e)); return null; } } public static Object getInfo(File file) throws ImageProcessingException, IOException { String str =getXmp(file); // 解析 JSON 字符串为 JSON 对象 JSONObject jsonObject = JSON.parseObject(str); // 获取指定的键值对 String gimbalYawDegree = jsonObject.getString("drone-dji:GimbalYawDegree"); String flightYawDegree = jsonObject.getString("drone-dji:FlightYawDegree"); String flightPitchDegree = jsonObject.getString("drone-dji:FlightPitchDegree"); String gimbalPitchDegree = jsonObject.getString("drone-dji:GimbalPitchDegree"); String mm=readPicExifInfo(file).get("Focal Length 35"); // 构造新的 JSON 对象 JSONObject newJsonObject = new JSONObject(); newJsonObject.put("GimbalYawDegree", gimbalYawDegree); newJsonObject.put("FlightYawDegree", flightYawDegree); newJsonObject.put("FlightPitchDegree", flightPitchDegree); newJsonObject.put("GimbalPitchDegree", gimbalPitchDegree); newJsonObject.put("FocalLength", mm); return newJsonObject; } public static void main(String[] args) throws ImageProcessingException, IOException { File file1 = TbFjServiceImpl.downloadFile("http://dev.jxpskj.com:9000/cloud-bucket/05708dc5-4273-4b12-ad54-e05c89d6c3d4/DJI_202406031131_010_05708dc5-4273-4b12-ad54-e05c89d6c3d4/DJI_20240603113305_0001_W_航点1.jpeg"); System.out.println(getInfo(file1)); } } src/main/java/com/dji/sample/patches/controller/PatchesController.java
@@ -55,7 +55,9 @@ public ResponseResult<PaginationData<LotInfo>> page(@RequestParam Integer page, @RequestParam(name = "page_size", defaultValue = "10") Integer pageSize, @RequestParam String workspaceId, @RequestParam(name = "dkbh", defaultValue = "") String dkbh @RequestParam(name = "dkbh", defaultValue = "") String dkbh, @RequestParam(name = "isPlan", required = false) Integer isPlan, @RequestParam(name = "xzqdm", defaultValue = "") String xzqdm ) { //调用service分页查询 PatchesParam param = PatchesParam.builder() @@ -63,8 +65,9 @@ .workspaceId(workspaceId) .pageSize(pageSize) .dkbh(dkbh) .isPlan(isPlan) .xzqdm(xzqdm) .build(); PaginationData<LotInfo> data = getPatchesService.limitGet(param); return ResponseResult.success(data); } src/main/java/com/dji/sample/patches/model/Param/PatchesParam.java
@@ -19,4 +19,8 @@ private String workspaceId; private String dkbh; private Integer isPlan; private String xzqdm; } src/main/java/com/dji/sample/patches/service/impl/GetPatchesServiceImpl.java
@@ -12,6 +12,8 @@ import com.dji.sample.patches.service.GetPatchesService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -30,14 +32,28 @@ */ @Override public PaginationData<LotInfo> limitGet(PatchesParam param) { if (param.getIsPlan() != null) { Page<LotInfo> page = mapper.selectPage(new Page<LotInfo>(param.getPage(), param.getPageSize()), new LambdaQueryWrapper<LotInfo>() .eq(LotInfo::getWorkspaceId, param.getWorkspaceId()) .like(LotInfo::getDkbh,param.getDkbh())); .like(LotInfo::getDkbh, param.getDkbh()) .like(LotInfo::getXzqdm, param.getXzqdm()) .eq(LotInfo::getIsPlan, param.getIsPlan())); List<LotInfo> records = page.getRecords() .stream() .collect(Collectors.toList()); return new PaginationData<LotInfo>(records, new Pagination(page)); } else { Page<LotInfo> page = mapper.selectPage(new Page<LotInfo>(param.getPage(), param.getPageSize()), new LambdaQueryWrapper<LotInfo>() .eq(LotInfo::getWorkspaceId, param.getWorkspaceId()) .like(LotInfo::getDkbh, param.getDkbh()) .like(LotInfo::getXzqdm, param.getXzqdm())); List<LotInfo> records = page.getRecords() .stream() .collect(Collectors.toList()); return new PaginationData<LotInfo>(records, new Pagination(page)); } } @Override src/main/java/com/dji/sample/patches/xml/mode/share/action/utils/ActionUtils.java
@@ -20,7 +20,8 @@ public static TakePhotoParam setTakePhoto(String dkbh) { TakePhotoParam takePhotoParam = new TakePhotoParam(); takePhotoParam.setFileSuffix("航点" + dkbh); takePhotoParam.setPayloadLensIndex("wide,ir"); // takePhotoParam.setPayloadLensIndex("wide,ir"); takePhotoParam.setPayloadLensIndex("wide"); takePhotoParam.setUseGlobalPayloadLensIndex(1); takePhotoParam.setPayloadPositionIndex(0); return takePhotoParam; src/main/java/com/dji/sample/territory/model/entity/TbFjEntity.java
@@ -62,4 +62,6 @@ private String pstz; private Integer psjj; } src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java
@@ -1,8 +1,10 @@ package com.dji.sample.territory.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.dji.sample.media.model.MediaFileEntity; import com.dji.sample.media.util.ImgUtil; import com.dji.sample.patches.config.pojo.PatchesConfigPojo; import com.dji.sample.patches.model.entity.LotInfo; import com.dji.sample.territory.dao.ITbFjMapper; @@ -106,7 +108,7 @@ // double x = Double.parseDouble(((formatCoordinate(coordinates[1])))); // double y = Double.parseDouble(((formatCoordinate(coordinates[0])))); //本地数据库没有的数据在FJ表非空用0 int psjd = 0; double psjd = WaterMarkUtil.convertAngle(gimbalYawDegree); int pshgj = 0; String psry = "中图智绘无人机"; String zsdm = "23C8CCC61E3042FBA6A658F319337B1A"; @@ -120,6 +122,16 @@ String head = "http://dev.jxpskj.com:9000/cloud-bucket"; String url = head + key; File file = downloadFile(url); // JSONObject jsonObjects = JSONObject.parseObject(ImgUtil.getInfo(file)); JSONObject jsons = (JSONObject) (ImgUtil.getInfo(file)); String str = jsons.toJSONString(); String newstr = str.replace("+", ""); JSONObject json = JSON.parseObject(newstr); Double pitch = json.getDouble("GimbalPitchDegree"); String focal = json.getString("FocalLength"); String numberPart = focal.replaceAll("[^\\d]", ""); int psjj = Integer.parseInt(numberPart); json.getString("GimbalYawDegree"); String fjhxz = HashUtil.SM3Hash(file); BufferedImage image = ImageIO.read(file); int width = image.getWidth(); @@ -151,11 +163,12 @@ .Latitude(truncateToSevenDecimalPlaces(lat)) .longitude(truncateToSevenDecimalPlaces(lng)) .fj(FJ) .psjj(psjj) .fjmc(fjmc) .fjlx(fjlx) .psfyj(gimbalYawDegree) .psfyj(pitch) .pssj(pssj) .psjd(psjd) .psjd((int) psjd) .fjhxz(fjhxz) .pshgj(pshgj) .zsdm(zsdm) @@ -235,6 +248,7 @@ BigDecimal bd = new BigDecimal(value).setScale(2, RoundingMode.DOWN); return bd.doubleValue(); } public static Double truncateToSevenDecimalPlaces(Double value) { if (value == null) { return null; // 处理null值情况 src/main/java/com/dji/sample/territory/utils/WaterMarkUtil.java
@@ -12,6 +12,7 @@ import java.util.Date; import static com.dji.sample.territory.utils.ImgZipUtil.compressImageAndGetFile; @Component public class WaterMarkUtil { /** @@ -25,8 +26,8 @@ * @throws IOException 如果读取或保存图片失败。 */ public static File addWatermark(File file, Long pssj, Double lat, Double lng, Double angles) throws IOException, FontFormatException { String angel=angle(angles); double anglses = convertAngle(angles); String angel = angle(anglses); Long timestamp = pssj; // 例如:Unix 时间戳(以秒为单位) SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String sd = sdf.format(new Date(Long.parseLong(String.valueOf(timestamp)))); @@ -63,7 +64,7 @@ g2d.setComposite(alphaComposite); String extraInfo = String.format("Lon:%.7f Lat:%.7f\n%s %s", lng, lat,angel,sd); File fontFile = new File("/tmp/jave/MiSans-Normal.ttf"); // 替换为你的字体文件路径 File fontFile = new File("src/main/java/com/dji/sample/territory/utils/MiSans-Normal.ttf"); // 替换为你的字体文件路径 Font customFont = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(36.00F); // 注册字体 GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); @@ -128,39 +129,55 @@ if (angle > 0 && angle < 45) { return "北偏东"; } if (angle > 45 && angle < 90) { if (angle >= 45 && angle < 90) { return "东偏北"; } if (angle > 90 && angle < 135) { return "东偏南"; } if (angle > 135 && angle < 180) { if (angle >= 135 && angle < 180) { return "南偏东"; } if (angle > -45 && angle < 0) { if (angle >= 315 && angle < 360) { return "北偏西"; } if (angle > -90 && angle < -45) { if (angle > 270 && angle < 315) { return "西偏北"; } if (angle > -135 && angle < -90) { if (angle >= 225 && angle < 270) { return "西偏南"; } if (angle > -180 && angle < -135) { if (angle > 180 && angle < 225) { return "南偏西"; } if (angle == 0) { if (angle == 0 || angle == 360) { return "正北"; } if (angle == 90) { return "正东"; } if (angle == 180|| angle == -180) { if (angle == 180) { return "正南"; } if (angle == -90) { if (angle == 270) { return "正西"; } return "未知"; } public static double convertAngle(double angle) { // 处理负数角度,将其转换为正数 if (angle < 0) { angle += 360; } return angle; } public static void main(String[] args) { // 测试不同的输入角度 double[] testAngles = {25}; for (double angle : testAngles) { System.out.printf("输入角度: %.1f, 转换后的方位角: %.1f\n", angle, convertAngle(angle)); } } }