You've already forked FrameTour-BE
feat(printer): 添加图片方向检测与自动旋转功能
- 引入 ImageUtils 工具类处理图片旋转逻辑 - 实现打印前对竖图自动旋转为横图处理 - 完成水印处理后将图片旋转回原始方向-优化临时文件清理逻辑,确保所有中间文件被删除 - 添加图片方向判断方法 isLandscape- 新增图片旋转90度和270度的工具方法
This commit is contained in:
@@ -46,6 +46,7 @@ import com.ycwl.basic.storage.StorageFactory;
|
||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||
import com.ycwl.basic.storage.enums.StorageAcl;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.utils.ImageUtils;
|
||||
import com.ycwl.basic.utils.JacksonUtil;
|
||||
import com.ycwl.basic.utils.SnowFlakeUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -444,7 +445,7 @@ public class PrinterServiceImpl implements PrinterService {
|
||||
ScenicConfigManager scenicConfig = scenicRepository.getScenicConfigManager(item.getScenicId());
|
||||
String printWatermarkType = scenicConfig.getString("print_watermark_type");
|
||||
|
||||
if (printWatermarkType != null && StringUtils.isNotBlank(printWatermarkType)) {
|
||||
if (StringUtils.isNotBlank(printWatermarkType)) {
|
||||
ImageWatermarkOperatorEnum watermarkType = ImageWatermarkOperatorEnum.getByCode(printWatermarkType);
|
||||
if (watermarkType != null) {
|
||||
// 准备存储适配器
|
||||
@@ -466,17 +467,45 @@ public class PrinterServiceImpl implements PrinterService {
|
||||
// 下载原图
|
||||
File originalFile = new File("print_" + item.getId() + ".jpg");
|
||||
File watermarkedFile = new File("print_" + item.getId() + "_" + watermarkType.getType() + "." + watermarkType.getPreferFileType());
|
||||
File rotatedOriginalFile = null;
|
||||
File rotatedWatermarkedFile = null;
|
||||
boolean needRotation = false;
|
||||
|
||||
try {
|
||||
HttpUtil.downloadFile(item.getCropUrl().replace("oss.zhentuai.com", "frametour-assets.oss-cn-shanghai-internal.aliyuncs.com"), originalFile);
|
||||
|
||||
// 判断图片方向并处理旋转
|
||||
boolean isLandscape = ImageUtils.isLandscape(originalFile);
|
||||
log.info("打印照片方向检测,照片ID: {}, 是否为横图: {}", item.getId(), isLandscape);
|
||||
|
||||
if (!isLandscape) {
|
||||
// 竖图需要旋转为横图
|
||||
needRotation = true;
|
||||
rotatedOriginalFile = new File("print_" + item.getId() + "_rotated.jpg");
|
||||
ImageUtils.rotateImage90(originalFile, rotatedOriginalFile);
|
||||
log.info("竖图已旋转为横图,照片ID: {}", item.getId());
|
||||
}
|
||||
|
||||
// 处理水印
|
||||
WatermarkInfo watermarkInfo = new WatermarkInfo();
|
||||
watermarkInfo.setOriginalFile(originalFile);
|
||||
watermarkInfo.setOriginalFile(needRotation ? rotatedOriginalFile : originalFile);
|
||||
watermarkInfo.setWatermarkedFile(watermarkedFile);
|
||||
|
||||
operator.process(watermarkInfo);
|
||||
|
||||
// 如果之前旋转了,需要将水印图片旋转回去
|
||||
if (needRotation) {
|
||||
rotatedWatermarkedFile = new File("print_" + item.getId() + "_final_" + watermarkType.getType() + "." + watermarkType.getPreferFileType());
|
||||
ImageUtils.rotateImage270(watermarkedFile, rotatedWatermarkedFile);
|
||||
log.info("水印图片已旋转回竖图,照片ID: {}", item.getId());
|
||||
// 删除中间的横图水印文件
|
||||
if (watermarkedFile.exists()) {
|
||||
watermarkedFile.delete();
|
||||
}
|
||||
// 将最终的竖图水印文件赋值给watermarkedFile
|
||||
watermarkedFile = rotatedWatermarkedFile;
|
||||
}
|
||||
|
||||
// 上传水印图片
|
||||
String watermarkedUrl = adapter.uploadFile(null, watermarkedFile, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
adapter.setAcl(StorageAcl.PUBLIC_READ, StorageConstant.PHOTO_WATERMARKED_PATH, watermarkedFile.getName());
|
||||
@@ -488,12 +517,18 @@ public class PrinterServiceImpl implements PrinterService {
|
||||
log.error("水印处理失败,使用原始照片进行打印。照片ID: {}", item.getId(), e);
|
||||
} finally {
|
||||
// 清理临时文件
|
||||
if (originalFile.exists()) {
|
||||
if (originalFile != null && originalFile.exists()) {
|
||||
originalFile.delete();
|
||||
}
|
||||
if (watermarkedFile.exists()) {
|
||||
if (rotatedOriginalFile != null && rotatedOriginalFile.exists()) {
|
||||
rotatedOriginalFile.delete();
|
||||
}
|
||||
if (watermarkedFile != null && watermarkedFile.exists()) {
|
||||
watermarkedFile.delete();
|
||||
}
|
||||
if (rotatedWatermarkedFile != null && rotatedWatermarkedFile.exists()) {
|
||||
rotatedWatermarkedFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -77,6 +79,120 @@ public class ImageUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断图片是否为横图(宽度大于高度)
|
||||
*
|
||||
* @param file 图片文件
|
||||
* @return true表示横图,false表示竖图
|
||||
* @throws IOException 读取文件失败
|
||||
*/
|
||||
public static boolean isLandscape(File file) throws IOException {
|
||||
BufferedImage image = null;
|
||||
try {
|
||||
image = ImageIO.read(file);
|
||||
if (image == null) {
|
||||
throw new IOException("无法读取图片文件: " + file.getPath());
|
||||
}
|
||||
return image.getWidth() > image.getHeight();
|
||||
} finally {
|
||||
if (image != null) {
|
||||
image.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转图片90度(顺时针)
|
||||
*
|
||||
* @param sourceFile 源图片文件
|
||||
* @param targetFile 目标图片文件
|
||||
* @throws IOException 读取或写入文件失败
|
||||
*/
|
||||
public static void rotateImage90(File sourceFile, File targetFile) throws IOException {
|
||||
BufferedImage sourceImage = null;
|
||||
BufferedImage rotatedImage = null;
|
||||
try {
|
||||
sourceImage = ImageIO.read(sourceFile);
|
||||
if (sourceImage == null) {
|
||||
throw new IOException("无法读取图片文件: " + sourceFile.getPath());
|
||||
}
|
||||
|
||||
int width = sourceImage.getWidth();
|
||||
int height = sourceImage.getHeight();
|
||||
|
||||
// 创建旋转后的图片(宽高互换)
|
||||
rotatedImage = new BufferedImage(height, width, sourceImage.getType());
|
||||
Graphics2D g2d = rotatedImage.createGraphics();
|
||||
|
||||
// 设置旋转变换
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform.translate(height / 2.0, width / 2.0);
|
||||
transform.rotate(Math.PI / 2);
|
||||
transform.translate(-width / 2.0, -height / 2.0);
|
||||
|
||||
g2d.setTransform(transform);
|
||||
g2d.drawImage(sourceImage, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
// 保存旋转后的图片
|
||||
ImageIO.write(rotatedImage, "jpg", targetFile);
|
||||
log.info("图片旋转成功,原始尺寸: {}x{}, 旋转后尺寸: {}x{}", width, height, height, width);
|
||||
} finally {
|
||||
if (sourceImage != null) {
|
||||
sourceImage.flush();
|
||||
}
|
||||
if (rotatedImage != null) {
|
||||
rotatedImage.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 旋转图片270度(逆时针90度)
|
||||
*
|
||||
* @param sourceFile 源图片文件
|
||||
* @param targetFile 目标图片文件
|
||||
* @throws IOException 读取或写入文件失败
|
||||
*/
|
||||
public static void rotateImage270(File sourceFile, File targetFile) throws IOException {
|
||||
BufferedImage sourceImage = null;
|
||||
BufferedImage rotatedImage = null;
|
||||
try {
|
||||
sourceImage = ImageIO.read(sourceFile);
|
||||
if (sourceImage == null) {
|
||||
throw new IOException("无法读取图片文件: " + sourceFile.getPath());
|
||||
}
|
||||
|
||||
int width = sourceImage.getWidth();
|
||||
int height = sourceImage.getHeight();
|
||||
|
||||
// 创建旋转后的图片(宽高互换)
|
||||
rotatedImage = new BufferedImage(height, width, sourceImage.getType());
|
||||
Graphics2D g2d = rotatedImage.createGraphics();
|
||||
|
||||
// 设置旋转变换
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform.translate(height / 2.0, width / 2.0);
|
||||
transform.rotate(-Math.PI / 2);
|
||||
transform.translate(-width / 2.0, -height / 2.0);
|
||||
|
||||
g2d.setTransform(transform);
|
||||
g2d.drawImage(sourceImage, 0, 0, null);
|
||||
g2d.dispose();
|
||||
|
||||
// 保存旋转后的图片
|
||||
ImageIO.write(rotatedImage, "jpg", targetFile);
|
||||
log.info("图片旋转成功,原始尺寸: {}x{}, 旋转后尺寸: {}x{}", width, height, height, width);
|
||||
} finally {
|
||||
if (sourceImage != null) {
|
||||
sourceImage.flush();
|
||||
}
|
||||
if (rotatedImage != null) {
|
||||
rotatedImage.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Base64DecodedMultipartFile implements MultipartFile {
|
||||
|
||||
private final byte[] imgContent;
|
||||
|
||||
Reference in New Issue
Block a user