pom.xml
@@ -263,6 +263,13 @@ <artifactId>spring-test</artifactId> <version>5.0.8.RELEASE</version> </dependency> <!-- mp4文件压缩处理 --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-core</artifactId> <version>3.0.0</version> </dependency> </dependencies> src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java
@@ -53,7 +53,7 @@ @Autowired private ITbDkjbxxService tbDkjbxxService; @Autowired private ShpToDataSourceService service; private ShpToDataSourceService shpToDataSourceService; @Autowired private IWaylineFileService waylineFileService; @@ -63,11 +63,11 @@ return ResponseResult.success(list); } /** * 上传文件并保存到数据库 * @param file 需要上传的文件,通过multipart/form-data方式提交 * @return 返回上传结果的ResponseResult对象,其中包含上传成功的消息 */ // /** // * 上传文件并保存到数据库 // * @param file 需要上传的文件,通过multipart/form-data方式提交 // * @return 返回上传结果的ResponseResult对象,其中包含上传成功的消息 // */ // @PostMapping("/upload") // public ResponseResult<String> uploadFile(@RequestParam("file") MultipartFile file) { // tbDkjbxxService.uploadFile(file); @@ -76,6 +76,16 @@ // return tbDkjbxxService.uploadFile(file); // } /** * 将sqlite里的数据入库并生成航线 * @param workspaceId * @param waylineName * @param airportLat * @param airportLon * @param request * @return * @throws Exception */ @PostMapping("/uploadLot") public ResponseResult getGeo(@RequestParam String workspaceId, @RequestParam String waylineName, @@ -83,7 +93,7 @@ @RequestParam double airportLon, HttpServletRequest request) throws Exception { List<TbDkjbxxEntity> list = tbDkjbxxService.list(); service.savaInMysql(list,workspaceId); shpToDataSourceService.savaInMysql(list,workspaceId); MultipartFile multipartFile = tbDkjbxxService.listFile(workspaceId, waylineName, airportLat, airportLon); CustomClaim customClaim = (CustomClaim) request.getAttribute(TOKEN_CLAIM); String creator = customClaim.getUsername(); src/main/java/com/dji/sample/territory/controller/TbFjController.java
@@ -23,15 +23,23 @@ @Autowired private ITbFJService tbFJService; @Autowired private GetPatchesService getPatches; private GetPatchesService getPatchesService; /** * 将地块所保留的照片、视频信息保存到sqlite * * @param dkbh * @param workspaceId * @return * @throws IOException */ @PostMapping("/insertDb") public ResponseResult insertDb(String dkbh, String workspaceId) throws IOException { List<MediaFileEntity> list = getPatches.listPohto(dkbh, workspaceId); List<MediaFileEntity> list = getPatchesService.listPohto(dkbh, workspaceId); if (list.size() == 0) { return ResponseResult.error("未找到该照片、视频信息"); } LotInfo lotInfo = getPatches.getLotinfo(dkbh, workspaceId); LotInfo lotInfo = getPatchesService.getLotinfo(dkbh, workspaceId); if (lotInfo == null) { return ResponseResult.error("未找到该图斑信息"); } src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java
@@ -18,6 +18,7 @@ import org.locationtech.jts.geom.Coordinate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.FileCopyUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.multipart.MultipartFile; @@ -86,6 +87,7 @@ * @return MultipartFile 对象,包含压缩后的航迹文件。 * @throws IOException 如果文件操作失败,则抛出IOException。 */ @Transactional public MultipartFile listFile(String workspaceId, String waylineName, double airportLat, double airportLon) throws IOException { List<TbDkjbxxEntity> list = mapper.selectList(null); List<LotInfo> info = dbConvertToEntity(list); src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java
@@ -4,13 +4,17 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.dji.sample.media.model.MediaFileEntity; import com.dji.sample.patches.config.pojo.PatchesConfigPojo; import com.dji.sample.patches.model.entity.LotInfo; import com.dji.sample.patches.utils.MultipartFileTOFileUtil; import com.dji.sample.territory.dao.ITbFjMapper; import com.dji.sample.territory.model.entity.TbFjEntity; import com.dji.sample.territory.service.ITbFJService; import com.google.gson.JsonObject; import com.dji.sample.territory.utils.VideoZipUtil; import com.dji.sample.territory.utils.WaterMark; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.*; import java.net.HttpURLConnection; @@ -23,7 +27,9 @@ @DS("sqlite-ret") public class TbFjServiceImpl implements ITbFJService { @Autowired private ITbFjMapper mapper; private ITbFjMapper tbFjMapper; @Autowired private PatchesConfigPojo patchesConfigPojo; /** * 按照地块编号所对应的信息和音视频文件存入sqlite数据库 @@ -33,6 +39,7 @@ * @return * @throws IOException */ @Transactional public int insertData(List<MediaFileEntity> mediaFile, LotInfo lotInfo) throws IOException { int count = 0; List<TbFjEntity> list = new ArrayList<>(); @@ -41,7 +48,7 @@ MediaFileEntity file = mediaFile.get(i); tbFj = dbConvertToEntity(file, lotInfo); list.add(tbFj); mapper.insert(tbFj); tbFjMapper.insert(tbFj); count++; } return count; @@ -56,6 +63,8 @@ * @throws IOException */ private TbFjEntity dbConvertToEntity(MediaFileEntity mediaFile, LotInfo lotInfo) throws IOException { File file1 = null; byte[] FJ = null; String jsonString = JSONObject.toJSONString(mediaFile.getMetadata()); JSONObject jsonObject = JSONObject.parseObject(jsonString); Double absoluteAltitude = jsonObject.getDouble("absoluteAltitude"); @@ -64,6 +73,7 @@ JSONObject shootPosition = jsonObject.getJSONObject("shootPosition"); Double lat = shootPosition.getDouble("lat"); Double lng = shootPosition.getDouble("lng"); //本地数据库没有的数据在FJ表非空用0 int psjd = 0; String fjhxz = "0"; int pshgj = 0; @@ -72,15 +82,23 @@ String zsdm = "0"; String dklx = "0"; String xzqdm = "0"; int fjlx = 1; Long pssj = mediaFile.getCreateTime(); String bsm = UUID.randomUUID().toString(); String fjmc = mediaFile.getFileName(); String key = mediaFile.getObjectKey(); String head = "http://dev.jxpskj.com:9000/cloud-bucket"; String url = head + key; File file =downloadFile(url); File file1=WaterMark.addWatermark(file,patchesConfigPojo.getUnzip(),pssj,lat,lng); byte[] FJ = fileToByteArray(file1); File file = downloadFile(url); //对应图片和视频文件进行不同处理 boolean endsWith = key.endsWith(".mp4"); if (!endsWith) { file1 = WaterMark.addWatermark(file, patchesConfigPojo.getUnzip(), pssj, lat, lng); FJ = fileToByteArray(file1); } else { file1 = VideoZipUtil.compressVideo(file, 800000, 128000, 1280, 720); FJ = fileToByteArray(file1); } TbFjEntity.TbFjEntityBuilder builder = TbFjEntity.builder(); if (lotInfo != null) { builder.bsm(bsm) @@ -91,9 +109,9 @@ .jdgd(absoluteAltitude) .Latitude(lat) .longitude(lng) // .fj(FJ) .fj(FJ) .fjmc(fjmc) .fjlx(1) .fjlx(fjlx) .psfyj(gimbalYawDegree) .pssj(String.valueOf(pssj)) .psjd(psjd) @@ -116,28 +134,22 @@ * @param fileUrl * @return */ public File downloadFile(String fileUrl) { public File downloadFile(String fileUrl) { File downloadedFile = null; String localFilePath = patchesConfigPojo.getUnzip()+ "tmp.jpg"; String localFilePath = patchesConfigPojo.getUnzip() + "tmp.jpg"; try { URL url = new URL(fileUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); downloadedFile = new File(localFilePath); InputStream inputStream = connection.getInputStream(); OutputStream outputStream = new FileOutputStream(downloadedFile); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); try (InputStream inputStream = connection.getInputStream(); OutputStream outputStream = new FileOutputStream(downloadedFile)) { byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } } System.out.println("File downloaded and saved at: " + downloadedFile.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } @@ -145,6 +157,13 @@ return downloadedFile; } /** * 将文件转换为字节数组。 * * @param file 需要转换的文件对象。 * @return 文件内容的字节数组。 * @throws IOException 如果读取文件发生错误。 */ public static byte[] fileToByteArray(File file) throws IOException { FileInputStream fis = new FileInputStream(file); byte[] data = new byte[(int) file.length()]; @@ -152,5 +171,4 @@ fis.close(); return data; } } src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java
New file @@ -0,0 +1,42 @@ package com.dji.sample.territory.utils; import javax.imageio.ImageIO; import javax.imageio.ImageWriteParam; import javax.imageio.ImageWriter; import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.MemoryCacheImageOutputStream; import java.awt.image.BufferedImage; import java.io.*; import java.nio.file.Files; import java.nio.file.StandardCopyOption; public class ImgZipUtil { /** * 图片压缩 * * @param originalImageFile * @param compressionQuality 图片压缩质量 0-1 * @return * @throws IOException */ public static File compressImageAndGetFile(File originalImageFile, float compressionQuality) throws IOException { BufferedImage originalImage = ImageIO.read(originalImageFile); try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next(); try (ImageOutputStream ios = new MemoryCacheImageOutputStream(baos)) { writer.setOutput(ios); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(compressionQuality); writer.write(null, new javax.imageio.IIOImage(originalImage, null, null), param); } finally { writer.dispose(); } InputStream in = new ByteArrayInputStream(baos.toByteArray()); File tempFile = File.createTempFile("compressed-", ".jpg"); tempFile.deleteOnExit(); Files.copy(in, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING); return tempFile; } } } src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java
New file @@ -0,0 +1,54 @@ package com.dji.sample.territory.utils; import ws.schild.jave.Encoder; import ws.schild.jave.EncoderException; import ws.schild.jave.MultimediaObject; import ws.schild.jave.encode.AudioAttributes; import ws.schild.jave.encode.EncodingAttributes; import ws.schild.jave.encode.VideoAttributes; import ws.schild.jave.info.VideoSize; import java.io.File; import java.io.IOException; public class VideoZipUtil { /** * 视频压缩 * @param sourceFile 需要压缩的原始视频文件 * @param bitRate 视频的比特率,用于控制视频的质量和文件大小 * @param audioBitRate 音频的比特率,用于控制音频的质量和文件大小 * @param width 压缩后视频的宽度 * @param height 压缩后视频的高度 */ public static File compressVideo(File sourceFile, int bitRate, int audioBitRate, int width, int height) { try { // 创建临时文件来保存压缩后的视频内容 File compressedFile = File.createTempFile("compressed_video", ".mp4"); // 创建音频属性 AudioAttributes audio = new AudioAttributes(); audio.setCodec("aac"); audio.setBitRate(audioBitRate); // 创建视频属性 VideoAttributes video = new VideoAttributes(); video.setCodec("h264"); video.setBitRate(bitRate); video.setSize(new VideoSize(width, height)); // 创建转码属性 EncodingAttributes attrs = new EncodingAttributes(); attrs.setAudioAttributes(audio); attrs.setVideoAttributes(video); // 进行视频转码 Encoder encoder = new Encoder(); encoder.encode(new MultimediaObject(sourceFile), compressedFile, attrs); // 返回压缩后的临时文件 return compressedFile; } catch (IOException | EncoderException e) { e.printStackTrace(); throw new IllegalArgumentException("视频压缩失败"); } } } src/main/java/com/dji/sample/territory/utils/WaterMark.java
New file @@ -0,0 +1,106 @@ package com.dji.sample.territory.utils; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Date; import static com.dji.sample.territory.utils.ImgZipUtil.compressImageAndGetFile; public class WaterMark { /** * 将图片加上水印并压缩 * * @param file * @param path * @param pssj * @param lat * @param lng * @return 添加水印并压缩后的图片文件。 * @throws IOException 如果读取或保存图片失败。 */ public static File addWatermark(File file, String path, Long pssj, Double lat, Double lng) throws IOException { 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)))); File originalImageFile = new File(file.toURI()); BufferedImage originalImage; try { originalImage = ImageIO.read(originalImageFile); } catch (IOException e) { throw new IllegalArgumentException("读取图片失败"+e.getMessage()); } // 创建 Graphics2D 对象以在图像上绘制水印 Graphics2D g2d = originalImage.createGraphics(); // 设置水印文字 "国土调查云" String watermarkText = "国土调查云"; // 设置水印文字样式 g2d.setColor(Color.WHITE); // 设置为白色 float alpha = 0.5f; // 设置透明度为 0.5 AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha); g2d.setComposite(alphaComposite); g2d.setFont(new Font("宋体", Font.BOLD, 200)); // 使用宋体字体 // 设置水印位置(左上角) int x1 = 400; // 左上角水印位置 x 坐标 int y1 = 1200; // 左上角水印位置 y 坐标 // 旋转35度角 double angle = Math.toRadians(35); AffineTransform at = AffineTransform.getRotateInstance(angle, x1, y1); g2d.setTransform(at); // 绘制左上角旋转水印文字 g2d.drawString(watermarkText, x1, y1); // 设置第一个水印完毕,恢复透明度为不透明状态(透明度为 1.0) alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f); g2d.setComposite(alphaComposite); String extraInfo = String.format("时间:%s\nlon:%.9f lat:%.6f", sd, lng, lat); g2d.setFont(new Font("宋体", Font.BOLD, 50)); // 使用宋体字体,更小的字号 g2d.setBackground(Color.black); // 计算文本宽度和高度 FontMetrics fm = g2d.getFontMetrics(); int textWidth = fm.stringWidth(extraInfo); int textHeight = fm.getHeight(); // 恢复坐标系到正常状态(不旋转) g2d.setTransform(new AffineTransform()); // 设置文本位置(右下角) int x2 = originalImage.getWidth() - textWidth - 30; // 右对齐的 x 坐标 int y2 = originalImage.getHeight() - textHeight - 65; // 最底部位置 y 坐标 // 绘制文本信息 String[] lines = extraInfo.split("\n"); for (String line : lines) { // 计算每行文本的宽度 int lineWidth = fm.stringWidth(line); // 将文本的起始位置设置为图像宽度减去文本的宽度 g2d.drawString(line, x2 + textWidth - lineWidth, y2); y2 += g2d.getFontMetrics().getHeight(); // 增加行高 } // 释放 Graphics2D 对象 g2d.dispose(); // 保存添加水印后的图片 File outputFile = new File(path + "mark.jpg"); File originalImageFiles = new File(outputFile.toURI()); float compressionQuality = 0.5f; // 0.0 - 1.0, higher value means better quality File compressedImageFile = compressImageAndGetFile(originalImageFiles, compressionQuality); try { ImageIO.write(originalImage, "jpg", outputFile); } catch (IOException e) { throw new IllegalArgumentException("水印图片保存失败"); } return compressedImageFile; } } src/main/resources/application-dev.yml
@@ -17,12 +17,12 @@ password: jxpskj_2018 sqlite-resource: driver-class-name: org.sqlite.JDBC url: jdbc:sqlite:D:\汇图信息\空天一体检测系统\图斑\resource_db.db url: jdbc:sqlite:DB/resource_db.db username: password: sqlite-ret: driver-class-name: org.sqlite.JDBC url: jdbc:sqlite:D:\汇图信息\空天一体检测系统\图斑\result_db.db url: jdbc:sqlite:DB/result_db.db username: password: # url: jdbc:mysql://192.168.2.104:3306/drone_test?useSSL=false&allowPublicKeyRetrieval=true src/main/resources/tmp/mark.jpg
src/main/resources/tmp/tmp.jpg