diff --git a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java index 259ff3f5..627efc2b 100644 --- a/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java +++ b/src/main/java/com/ycwl/basic/service/printer/impl/PrinterServiceImpl.java @@ -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(); + } } } } diff --git a/src/main/java/com/ycwl/basic/utils/ImageUtils.java b/src/main/java/com/ycwl/basic/utils/ImageUtils.java index 96103caf..d4f4ad5c 100644 --- a/src/main/java/com/ycwl/basic/utils/ImageUtils.java +++ b/src/main/java/com/ycwl/basic/utils/ImageUtils.java @@ -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;