在加水印前对文件进行音视频处理,分别执行不同方法。增加图片压缩、视频压缩方法。
6 files modified
5 files added
317 ■■■■ changed files
pom.xml 7 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/controller/TbDkjbxxController.java 24 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/controller/TbFjController.java 14 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/service/impl/TbDkjbxxServiceImpl.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/service/impl/TbFjServiceImpl.java 64 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/utils/ImgZipUtil.java 42 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/utils/VideoZipUtil.java 54 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/utils/WaterMark.java 106 ●●●●● patch | view | raw | blame | history
src/main/resources/application-dev.yml 4 ●●●● patch | view | raw | blame | history
src/main/resources/tmp/mark.jpg patch | view | raw | blame | history
src/main/resources/tmp/tmp.jpg patch | view | raw | blame | history
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