rain
2024-05-30 c00662a72ca1582c064a2bd76aa92fd22fbfedc6
修改水印部分信息,添加图斑图片审核,大屏图斑图片添加水印
12 files modified
1 files deleted
2791 ■■■■■ changed files
src/main/java/com/dji/sample/media/controller/FileController.java 36 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/controller/MediaController.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/model/MediaFileEntity.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/service/IFileService.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/service/IMediaService.java 5 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java 85 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java 31 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/controller/PatchesController.java 7 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/service/impl/GetPatchesServiceImpl.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/utils/TimerUtil.java 4 ●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/patches/xml/mode/share/action/utils/PayloadParamUtils.java 3 ●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/territory/utils/WaterMarkUtil.java 9 ●●●●● patch | view | raw | blame | history
src/main/resources/template/wpmz/waylines.wpml 2581 ●●●●● patch | view | raw | blame | history
src/main/java/com/dji/sample/media/controller/FileController.java
@@ -3,17 +3,21 @@
import com.dji.sample.common.model.CustomClaim;
import com.dji.sample.common.model.PaginationData;
import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.media.model.FileUploadDTO;
import com.dji.sample.media.model.MediaFileDTO;
import com.dji.sample.media.model.MediaFileEntity;
import com.dji.sample.media.model.MediaFileQueryParam;
import com.dji.sample.media.service.IFileService;
import org.apache.ibatis.annotations.Update;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import static com.dji.sample.component.AuthInterceptor.TOKEN_CLAIM;
@@ -32,6 +36,7 @@
    /**
     * Get information about all the media files in this workspace based on the workspace id.
     * 根据工作空间id获取有关此工作空间中所有媒体文件的信息。
     *
     * @param workspaceId
     * @return
     */
@@ -42,6 +47,23 @@
                                                                      MediaFileQueryParam mediaFileQueryParam) {
        PaginationData<MediaFileEntity> filesList = fileService.getMediaFilesPaginationByWorkspaceId(workspaceId, page, pageSize,mediaFileQueryParam);
        return ResponseResult.success(filesList);
    }
    @GetMapping("/listAdded")
    public ResponseResult listIsadd() {
        List<MediaFileEntity> entityList = fileService.listByIsadd();
        return ResponseResult.success(entityList);
    }
    @PutMapping("/examine")
    public ResponseResult examineData(@RequestParam String fileId) {
        int is = fileService.updateExamByFileId(fileId);
        if (is != 0) {
            return ResponseResult.success();
        } else {
            return ResponseResult.error("更新状态失败");
        }
    }
    @GetMapping("/{workspace_id}/files/{job_id}")
@@ -55,6 +77,7 @@
        mediaFileEntity.setUserId(claims.getId());
        return ResponseResult.success(fileService.updateMediaFile(workspaceId, mediaFileEntity));
    }
    @DeleteMapping("/{workspace_id}/deleteFile")
    public ResponseResult deleteFile(@PathVariable(name = "workspace_id") String workspaceId, @RequestParam String fileId) {
@@ -69,6 +92,7 @@
    /**
     * Query the download address of the file according to the media file id,
     * and redirect to this address directly for download.
     *
     * @param workspaceId
     * @param fileId
     * @param response
@@ -84,16 +108,4 @@
            e.printStackTrace();
        }
    }
//    @PostMapping("/{workspace_id}/files/download")
//    public ResponseResult<String> waterMarkFile(){
//        //获取media实体信息
//
//        //对mediaUrl进行下载
//
//        //对图片进行水印
//
//        //将带有水印的图片存入本地
//
//        //将链接返回
//    }
}
src/main/java/com/dji/sample/media/controller/MediaController.java
@@ -35,6 +35,7 @@
    /**
     * Check if the file has been uploaded by the fingerprint.
     * 检查文件是否已通过指纹上传。
     *
     * @param workspaceId
     * @param file
     * @return
@@ -50,6 +51,7 @@
    /**
     * When the file is uploaded to the storage server by pilot,
     * the basic information of the file is reported through this interface.
     *
     * @param workspaceId
     * @param file
     * @return
@@ -57,12 +59,12 @@
    @PostMapping("/{workspace_id}/upload-callback")
    public ResponseResult<String> uploadCallback(@PathVariable(name = "workspace_id") String workspaceId, @RequestBody FileUploadDTO file) throws IOException, FontFormatException {
        mediaService.saveMediaFile(workspaceId, file);
        mediaService.saveMediaMarkFile(workspaceId, file);
        return ResponseResult.success(file.getObjectKey());
    }
    /**
     * Query the files that already exist in this workspace based on the workspace id and the collection of tiny fingerprints.
     *
     * @param workspaceId
     * @param tinyFingerprints  There is only one tiny_fingerprint parameter in the body.
     *                          But it is not recommended to use Map to receive the parameter.
src/main/java/com/dji/sample/media/model/MediaFileEntity.java
@@ -78,6 +78,9 @@
    @TableField("isadd")
    private Integer isadd;
    @TableField("examine")
    private Integer examine;
}
src/main/java/com/dji/sample/media/service/IFileService.java
@@ -20,6 +20,7 @@
    /**
     * Query if the file already exists based on the workspace id and the fingerprint of the file.
     *
     * @param workspaceId
     * @param fingerprint
     * @return
@@ -28,23 +29,32 @@
    /**
     * Save the basic information of the file to the database.
     *
     * @param workspaceId
     * @param file
     * @return
     */
    Integer saveFile(String workspaceId, FileUploadDTO file);
    Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException;
    /**
     * Query information about all files in this workspace based on the workspace id.
     *
     * @param workspaceId
     * @return
     */
    List<MediaFileDTO> getAllFilesByWorkspaceId(String workspaceId);
    List<MediaFileEntity> listByIsadd();
    int updateExamByFileId(String fileId);
    List<MediaFileEntity> listMediaFileEntity(String workspaceId, String jobId);
    /**
     * Paginate through all media files in this workspace.
     *
     * @param workspaceId
     * @param page
     * @param pageSize
@@ -54,6 +64,7 @@
    /**
     * Get the download address of the file.
     *
     * @param workspaceId
     * @param fileId
     * @return
@@ -62,6 +73,7 @@
    /**
     * Query all media files of a job.
     *
     * @param workspaceId
     * @param jobId
     * @return
@@ -70,6 +82,7 @@
    /**
     * 更新文件
     *
     * @param workspaceId 项目id
     * @param mediaFileEntity
     * @return
src/main/java/com/dji/sample/media/service/IMediaService.java
@@ -20,6 +20,7 @@
    /**
     * Check if the file has been uploaded by the fingerprint.
     *
     * @param workspaceId
     * @param fingerprint
     * @return
@@ -28,16 +29,17 @@
    /**
     * Save the basic information of the file to the database.
     *
     * @param workspaceId
     * @param file
     * @return
     */
    Integer saveMediaFile(String workspaceId, FileUploadDTO file);
    Integer saveMediaMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException;
    /**
     * Query tiny fingerprints about all files in this workspace based on the workspace id.
     *
     * @param workspaceId
     * @return
     */
@@ -45,6 +47,7 @@
    /**
     * Query the fingerprints that already exist in it based on the incoming tiny fingerprints data.
     *
     * @param workspaceId
     * @param tinyFingerprints
     * @return
src/main/java/com/dji/sample/media/service/impl/FileServiceImpl.java
@@ -1,9 +1,5 @@
package com.dji.sample.media.service.impl;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
@@ -20,22 +16,24 @@
import com.dji.sample.media.model.*;
import com.dji.sample.media.service.IFileService;
import com.dji.sample.territory.service.impl.TbFjServiceImpl;
import com.dji.sample.territory.utils.VideoZipUtil;
import com.dji.sample.territory.utils.WaterMarkUtil;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.awt.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.*;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
/**
@@ -83,21 +81,34 @@
        fileEntity.setFileId(UUID.randomUUID().toString());
        return mapper.insert(fileEntity);
    }
        public Integer saveMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException {
        File file2 = null;
            MediaFileMarkEntity mediaFileMarkEntity =this.fileUploadConvertToMarkEntity(file);
            String url =  "http://dev.jxpskj.com:9000/cloud-bucket" + file.getObjectKey();
            File file1=TbFjServiceImpl.downloadFile(url);
            File file2= new File(WaterMarkUtil.addWatermark(file1, Long.valueOf(file.getMetadata().getCreatedTime().toString()),file.getMetadata().getPhotoedPosition().getLat(),
                    file.getMetadata().getPhotoedPosition().getLng(),file.getMetadata().getGimbalYawDegree()).toURI());
            mediaFileMarkEntity.setObjectKey(file.getPath());
        long timestamp = convertToTimestamp(file.getMetadata().getCreatedTime());
        boolean endsWith = file.getObjectKey().endsWith(".mp4");
        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);
        }
            mediaFileMarkEntity.setWorkspaceId(workspaceId);
            mediaFileMarkEntity.setFileId(UUID.randomUUID().toString());
            mediaFileMarkEntity.setObjectKey("/mark"+file.getPath()+"/"+file.getName());
            mediaFileMarkEntity.setFileName("mark"+file.getName());
            mediaFileMarkEntity.setFilePath("mark"+file.getPath());
            uploadFile(String.valueOf(file2), mediaFileMarkEntity.getObjectKey());
        String endpoint = "http://dev.jxpskj.com:9000";
        String accessKey = "pskj";
        String secretKey = "pskj@2021";
        String bucketName = "cloud-bucket";
        String objectName = mediaFileMarkEntity.getObjectKey(); // 例如 "folder/file.txt"
        uploadFile(endpoint, accessKey, secretKey, bucketName, objectName, file2);
            return markMapper.insert(mediaFileMarkEntity);
        }
    @Override
    public List<MediaFileDTO> getAllFilesByWorkspaceId(String workspaceId) {
        return mapper.selectList(new LambdaQueryWrapper<MediaFileEntity>()
@@ -111,6 +122,20 @@
    public List<MediaFileEntity> listMediaFileEntity(String workspaceId, String jobId) {
        return mapper.selectList(new LambdaQueryWrapper<MediaFileEntity>()
                .eq(MediaFileEntity::getWorkspaceId, workspaceId).eq(MediaFileEntity::getJobId,jobId));
    }
    public List<MediaFileEntity> listByIsadd() {
        return mapper.selectList(new LambdaQueryWrapper<MediaFileEntity>().eq(MediaFileEntity::getIsadd, 0)
                .like(MediaFileEntity::getFileName, "~"));
    }
    public int updateExamByFileId(String fileId) {
        // 创建并配置 LambdaUpdateWrapper
        LambdaUpdateWrapper<MediaFileEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(MediaFileEntity::getFileId, fileId)
                .set(MediaFileEntity::getExamine, 0);
        // 执行更新操作并返回更新的行数
        return mapper.update(null, updateWrapper);
    }
    @Override
@@ -135,6 +160,7 @@
                .eq(MediaFileEntity::getWorkspaceId, workspaceId));
    return count;
    }
    @Override
    public URL getObjectUrl(String workspaceId, String fileId) {
        Optional<MediaFileEntity> mediaFileOpt = getMediaByFileId(workspaceId, fileId);
@@ -171,6 +197,7 @@
    /**
     * Convert the received file object into a database entity object.
     *
     * @param file
     * @return
     */
@@ -181,6 +208,7 @@
            builder.fileName(file.getName())
                    .filePath(file.getPath())
                    .isadd(0)
                    .examine(1)
                    .fingerprint(file.getFingerprint())
                    .objectKey(file.getObjectKey())
                    .subFileType(file.getSubFileType())
@@ -200,6 +228,7 @@
        }
        return builder.build();
    }
    private MediaFileMarkEntity fileUploadConvertToMarkEntity(FileUploadDTO file) {
        MediaFileMarkEntity.MediaFileMarkEntityBuilder builder = MediaFileMarkEntity.builder();
@@ -230,6 +259,7 @@
    /**
     * Convert database entity objects into file data transfer object.
     *
     * @param entity
     * @return
     */
@@ -255,16 +285,33 @@
        return builder.build();
    }
    public void uploadFile(String filePath, String key) {
        OSS ossClient = new OSSClientBuilder().build(OssConfiguration.endpoint, OssConfiguration.accessKey, OssConfiguration.secretKey);
    public static void uploadFile(String endpoint, String accessKey, String secretKey, String bucketName, String objectName, File file) {
        try {
            File file = new File(filePath);
            PutObjectRequest putObjectRequest = new PutObjectRequest(OssConfiguration.bucket, key, file);
            PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);
            // 创建MinIO客户端实例
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(endpoint)
                    .credentials(accessKey, secretKey)
                    .build();
            // 上传文件
            FileInputStream fileInputStream = new FileInputStream(file);
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(fileInputStream, file.length(), -1)
                            .build()
            );
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ossClient.shutdown();
            throw new RuntimeException("上传文件至服务器失败" + e);
        }
    }
    public static long convertToTimestamp(Date date) {
        // 获取时间戳(毫秒级别)
        return date.getTime();
}
}
src/main/java/com/dji/sample/media/service/impl/MediaServiceImpl.java
@@ -15,6 +15,7 @@
import com.dji.sample.component.websocket.service.ISendMessageService;
import com.dji.sample.manage.model.dto.DeviceDTO;
import com.dji.sample.manage.model.enums.UserTypeEnum;
import com.dji.sample.manage.model.receiver.OsdSubDeviceReceiver;
import com.dji.sample.manage.service.IDeviceRedisService;
import com.dji.sample.manage.service.IDeviceService;
import com.dji.sample.media.dao.IFileMapper;
@@ -39,6 +40,8 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
/**
@@ -78,6 +81,7 @@
    private String fileAddress;
    @Value("${oss.bucket}")
    private String bucket;
    @Override
    public Boolean fastUpload(String workspaceId, String fingerprint) {
        return fileService.checkExist(workspaceId, fingerprint);
@@ -86,9 +90,6 @@
    @Override
    public Integer saveMediaFile(String workspaceId, FileUploadDTO file) {
        return fileService.saveFile(workspaceId, file);
    }
    public Integer saveMediaMarkFile(String workspaceId, FileUploadDTO file) throws IOException, FontFormatException {
        return fileService.saveMarkFile(workspaceId, file);
    }
    @Override
@@ -125,13 +126,13 @@
    /**
     * Handle media files messages reported by dock.
     * 处理由dock报告的媒体文件消息。
     *
     * @param receiver
     * @return
     */
    @ServiceActivator(inputChannel = ChannelName.INBOUND_EVENTS_FILE_UPLOAD_CALLBACK, outputChannel = ChannelName.OUTBOUND_EVENTS)
    public CommonTopicReceiver handleFileUploadCallBack(CommonTopicReceiver receiver) {
    public CommonTopicReceiver handleFileUploadCallBack(CommonTopicReceiver receiver) throws IOException, FontFormatException {
        FileUploadCallback callback = objectMapper.convertValue(receiver.getData(), FileUploadCallback.class);
        if (callback.getResult() != ResponseResult.CODE_SUCCESS) {
            log.error("媒体文件上传失败;Media file upload failed!");
            return null;
@@ -175,6 +176,7 @@
    /**
     * update the uploaded count and notify web side
     * 更新上传的计数并通知web端
     *
     * @param mediaFileCount
     * @param receiver
     * @param jobId
@@ -215,7 +217,7 @@
                        BizCodeEnum.FILE_UPLOAD_CALLBACK.getCode(), mediaFileCount);
    }
    private Boolean parseMediaFile(FileUploadCallback callback, WaylineJobDTO job) {
    private Boolean parseMediaFile(FileUploadCallback callback, WaylineJobDTO job) throws IOException, FontFormatException {
        // Set the drone sn that shoots the media
        Optional<DeviceDTO> dockDTO = deviceService.getDeviceBySn(job.getDockSn());
        dockDTO.ifPresent(dock -> callback.getFile().getExt().setSn(dock.getChildDeviceSn()));
@@ -223,12 +225,29 @@
        // set path
        String objectKey = callback.getFile().getObjectKey();
        callback.getFile().setPath(objectKey.substring(objectKey.indexOf("/") + 1, objectKey.lastIndexOf("/")));
        try {
            System.out.println(callback.getFile().toString());
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(() -> {
                try {
                    fileService.saveMarkFile(job.getWorkspaceId(), callback.getFile());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
            executor.shutdown();
        } catch (Exception e) {
            log.error("方法执行有误==============: ", e);
            throw e;
        }
        return fileService.saveFile(job.getWorkspaceId(), callback.getFile()) > 0;
    }
    /**
     * Handles the highest priority message about media uploads.
     *
     * @param receiver
     * @param headers
     * @return
src/main/java/com/dji/sample/patches/controller/PatchesController.java
@@ -41,6 +41,7 @@
    private TbDkjbxxServiceImpl tbDkjbxxService;
    @Autowired
    private TimerUtil timerUtil;
    /**
     * 根据workspaceId获取图斑列表信息
     *
@@ -74,16 +75,18 @@
        getPatchesService.delPatches();
        return ResponseResult.success();
    }
    @GetMapping("/useMyTask")
    public ResponseResult useMyTask() throws Exception {
        try {
            timerUtil.myTask();
//            timerUtil.myTask2();
//            timerUtil.myTask();
            timerUtil.myTask2();
            return ResponseResult.success();
        }catch (Exception e){
            throw new RuntimeException("db存储发送出现异常");
        }
    }
    /**
     * 根据图斑的地块编号获取相对应音视频
     *
src/main/java/com/dji/sample/patches/service/impl/GetPatchesServiceImpl.java
@@ -14,6 +14,7 @@
import com.dji.sample.wayline.model.entity.WaylineFileEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@@ -26,6 +27,7 @@
    /**
     * 分页获取数据的接口实现。
     *
     * @param param 包含分页信息和查询条件的工作空间ID。
     * @return 返回一个包含查询结果和分页信息的PaginationData对象。
     */
@@ -44,6 +46,7 @@
    public void delPatches() {
        mapper.delete(null);
    }
    /**
     * 根据条件获取照片的分页数据
     *
@@ -54,12 +57,13 @@
    @Override
    public PaginationData<MediaFileEntity> getPhoto(PatchesParam param,String dkbh) {
        Page<MediaFileEntity> page=fileMapper.selectPage(new Page<MediaFileEntity>(param.getPage(), param.getPageSize()),
                new LambdaQueryWrapper<MediaFileEntity>().like(MediaFileEntity::getFileName, "%" + dkbh + "%") );
                new LambdaQueryWrapper<MediaFileEntity>().like(MediaFileEntity::getFileName, "%" + dkbh + "~" + "%"));
        List<MediaFileEntity> records = page.getRecords()
                .stream()
                .collect(Collectors.toList());
        return new PaginationData<MediaFileEntity>(records, new Pagination(page));
    }
    /**
     * 根据条件获取照片的分页数据
     *
@@ -71,8 +75,10 @@
       return fileMapper.selectList(new LambdaQueryWrapper<MediaFileEntity>().like(MediaFileEntity::getFileName, "%" + dkbh + "%")
               .eq(MediaFileEntity::getWorkspaceId,workspaceId));
    }
    /**
     * 根据地块编号和工作空间ID获取地块信息。
     *
     * @param dkbh 地块编号,用于查询特定定单的地块信息。
     * @param workspaceId 工作空间ID,用于查询属于特定工作空间的地块信息。
     * @return 返回匹配给定地块编号和工作空间ID的地块信息对象。如果找不到匹配的记录,则返回null。
@@ -81,9 +87,11 @@
       return mapper.selectOne(new LambdaQueryWrapper<LotInfo>().eq(LotInfo::getDkbh, dkbh)
                .eq(LotInfo::getWorkspaceId, workspaceId));
    }
    public LotInfo getLotinfoToDb(String dkbh) {
        return mapper.selectOne(new LambdaQueryWrapper<LotInfo>().eq(LotInfo::getDkbh, dkbh));
    }
    public List<LotInfo>listLotinfo(){
        return mapper.selectList(null);
    }
src/main/java/com/dji/sample/patches/utils/TimerUtil.java
@@ -225,7 +225,9 @@
    public List<List<MediaFileEntity>> getNoadd() {
        List<MediaFileEntity> list = fileMapper.selectList(new LambdaQueryWrapper<MediaFileEntity>()
                .eq(MediaFileEntity::getIsadd, 0).like(MediaFileEntity::getFileName, "~"));
                .eq(MediaFileEntity::getIsadd, 0)
                .eq(MediaFileEntity::getExamine, 1)
                .like(MediaFileEntity::getFileName, "~"));
        List<List<MediaFileEntity>> groupedFilenames = groupTasks(list);
        return groupedFilenames;
    }
src/main/java/com/dji/sample/patches/xml/mode/share/action/utils/PayloadParamUtils.java
@@ -18,7 +18,8 @@
                .samplingRate("240000")
                .scanningMode("repetitive")
                .payloadPositionIndex(0)
                .imageFormat("wide,ir")
//                .imageFormat("wide,ir")
                .imageFormat("wide")
                .build();
        return pp;
    }
src/main/java/com/dji/sample/territory/utils/WaterMarkUtil.java
@@ -61,7 +61,7 @@
        g2d.drawString(watermarkText, x1, y1);
        alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f);
        g2d.setComposite(alphaComposite);
        String extraInfo = String.format("Lon:%.9f Lat:%.6f\n%s 时间:%s", lng, lat,angel,sd);
        String extraInfo = String.format("Lon:%.7f Lat:%.7f\n%s %s", lng, lat,angel,sd);
        File fontFile = new File("/tmp/jave/MiSans-Normal.ttf"); // 替换为你的字体文件路径
        Font customFont = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(36.00F);
@@ -81,14 +81,14 @@
        int y2 = originalImage.getHeight() - textHeight - 30; // 最底部位置 y 坐标
        int rectX = originalImage.getWidth() - textWidth  +530;
        int rectX = originalImage.getWidth() - textWidth  +490;
        int rectY = originalImage.getHeight() - textHeight -15;
        // 绘制半透明黑色背景矩形
        Color semiTransparentColor = new Color(0, 0, 0, 156); // 0-255 的 alpha 值,0 表示完全透明,255 表示完全不透明
        g2d.setColor(semiTransparentColor);
        g2d.fillRect(rectX, rectY, textWidth, textHeight-6);
        int rectXs = originalImage.getWidth() - textWidth +450 ;
        int rectXs = originalImage.getWidth() - textWidth +420 ;
        int rectYs = originalImage.getHeight() - textHeight  -62;
        // 绘制半透明黑色背景矩形
        g2d.setColor(semiTransparentColor);
@@ -113,7 +113,8 @@
        // 释放 Graphics2D 对象
        g2d.dispose();
        // 保存添加水印后的图片
        File outputFile = new File("src/main/copy.jpeg");
        File outputFile = File.createTempFile("mark", ".jpg");
        try {
            ImageIO.write(originalImage, "jpg", outputFile); // 将图像写入临时文件
        } catch (IOException e) {
src/main/resources/template/wpmz/waylines.wpml
File was deleted