From fa89f5c4b746a41efee0362bd3a42ea2c97e2cff Mon Sep 17 00:00:00 2001
From: rain <167982779@qq.com>
Date: Mon, 22 Apr 2024 18:13:46 +0800
Subject: [PATCH] 在加水印前对文件进行音视频处理,分别执行不同方法。增加图片压缩、视频压缩方法。
---
src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java | 64 ++++++---
src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java | 54 +++++++++
src/main/java/com/dji/sample/territory/controller/TbFjController.java | 14 +
src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java | 2
src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java | 42 +++++++
src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java | 24 ++-
src/main/resources/application-dev.yml | 4
src/main/java/com/dji/sample/territory/utils/WaterMark.java | 106 +++++++++++++++++
src/main/resources/tmp/tmp.jpg | 0
pom.xml | 7 +
src/main/resources/tmp/mark.jpg | 0
11 files changed, 282 insertions(+), 35 deletions(-)
diff --git a/pom.xml b/pom.xml
index 7ceceb8..9e252ad 100644
--- a/pom.xml
+++ b/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>
diff --git a/src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java b/src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java
index 14fdec2..44e4415 100644
--- a/src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java
+++ b/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();
diff --git a/src/main/java/com/dji/sample/territory/controller/TbFjController.java b/src/main/java/com/dji/sample/territory/controller/TbFjController.java
index c65dbed..3ad1e49 100644
--- a/src/main/java/com/dji/sample/territory/controller/TbFjController.java
+++ b/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("未找到该图斑信息");
}
diff --git a/src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java b/src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java
index bb4cd4f..82ec6a2 100644
--- a/src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java
+++ b/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);
diff --git a/src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java b/src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java
index 27724eb..0f534bd 100644
--- a/src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java
+++ b/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;
}
-
}
\ No newline at end of file
diff --git a/src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java b/src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java
new file mode 100644
index 0000000..39a842b
--- /dev/null
+++ b/src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java
@@ -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;
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java b/src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java
new file mode 100644
index 0000000..34e3765
--- /dev/null
+++ b/src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java
@@ -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("视频压缩失败");
+ }
+ }
+}
diff --git a/src/main/java/com/dji/sample/territory/utils/WaterMark.java b/src/main/java/com/dji/sample/territory/utils/WaterMark.java
new file mode 100644
index 0000000..3fb012a
--- /dev/null
+++ b/src/main/java/com/dji/sample/territory/utils/WaterMark.java
@@ -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;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index e467728..80e4a08 100644
--- a/src/main/resources/application-dev.yml
+++ b/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
diff --git a/src/main/resources/tmp/mark.jpg b/src/main/resources/tmp/mark.jpg
new file mode 100644
index 0000000..024c101
--- /dev/null
+++ b/src/main/resources/tmp/mark.jpg
Binary files differ
diff --git a/src/main/resources/tmp/tmp.jpg b/src/main/resources/tmp/tmp.jpg
new file mode 100644
index 0000000..3df14e6
--- /dev/null
+++ b/src/main/resources/tmp/tmp.jpg
Binary files differ
--
Gitblit v1.9.3