diff --git a/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java b/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java index 9d6ccd80..699848ac 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/core/PhotoProcessContext.java @@ -91,7 +91,7 @@ public class PhotoProcessContext { private File originalFile; private File processedFile; private boolean isLandscape = true; - private boolean needRotation = false; + private boolean rotationApplied = false; /** * 图像需要旋转的角度(用于后续Stage使用) diff --git a/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java b/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java index 78aa2d9d..e48de004 100644 --- a/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java +++ b/src/main/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStage.java @@ -30,7 +30,8 @@ public class ConditionalRotateStage extends AbstractPipelineStage {}", currentFile.getName(), finalFile.getName()); - ImageUtils.rotateImage270(currentFile, finalFile); + log.debug("恢复图片方向(旋转{}度): {} -> {}", restoreAngle, currentFile.getName(), finalFile.getName()); + rotateByAngle(currentFile, finalFile, restoreAngle); if (!finalFile.exists()) { return StageResult.failed("旋转后的文件未生成"); } context.updateProcessedFile(finalFile); - log.info("竖图方向已恢复(旋转270度)"); + log.info("图片方向已恢复(旋转{}度)", restoreAngle); - return StageResult.success("已恢复竖图方向"); + return StageResult.success("已恢复原方向"); } catch (Exception e) { log.error("图片旋转失败", e); @@ -63,6 +73,37 @@ public class RestoreOrientationStage extends AbstractPipelineStage { } // 根据旋转状态自己处理 offsetLeft - if (context.isNeedRotation()) { + if (context.isRotationApplied()) { if (context.getImageRotation() == 90) { info.setOffsetLeft(OFFSET_FOR_PRINTER); } else if (context.getImageRotation() == 270) { diff --git a/src/test/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStageTest.java b/src/test/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStageTest.java index 04f3f0d3..fd3eec79 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStageTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/stages/ConditionalRotateStageTest.java @@ -36,6 +36,7 @@ class ConditionalRotateStageTest { .build(); context.setLandscape(false); // 竖图 + context.setImageRotation(90); // 需要旋转 assertTrue(stage.shouldExecute(context)); } @@ -112,7 +113,7 @@ class ConditionalRotateStageTest { assertTrue(result.isSuccess()); assertEquals("已旋转90度", result.getMessage()); - assertTrue(context.isNeedRotation()); + assertTrue(context.isRotationApplied()); assertNotNull(context.getCurrentFile()); } @@ -140,7 +141,7 @@ class ConditionalRotateStageTest { assertTrue(result.isSuccess()); assertEquals("已旋转180度", result.getMessage()); - assertTrue(context.isNeedRotation()); + assertTrue(context.isRotationApplied()); } /** @@ -167,7 +168,7 @@ class ConditionalRotateStageTest { assertTrue(result.isSuccess()); assertEquals("已旋转270度", result.getMessage()); - assertTrue(context.isNeedRotation()); + assertTrue(context.isRotationApplied()); } /** diff --git a/src/test/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStageTest.java b/src/test/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStageTest.java index 98d68b1b..92031037 100644 --- a/src/test/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStageTest.java +++ b/src/test/java/com/ycwl/basic/image/pipeline/stages/RestoreOrientationStageTest.java @@ -4,6 +4,12 @@ import com.ycwl.basic.image.pipeline.core.PhotoProcessContext; import com.ycwl.basic.image.pipeline.core.StageResult; import com.ycwl.basic.image.pipeline.enums.ImageType; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.nio.file.Path; import static org.junit.jupiter.api.Assertions.*; @@ -20,7 +26,7 @@ class RestoreOrientationStageTest { } @Test - void testShouldExecute_NormalPhotoAndNeedRotation() { + void testShouldExecute_NormalPhotoAndRotationApplied() { RestoreOrientationStage stage = new RestoreOrientationStage(); PhotoProcessContext context = PhotoProcessContext.builder() @@ -29,13 +35,13 @@ class RestoreOrientationStageTest { .imageType(ImageType.NORMAL_PHOTO) .build(); - context.setNeedRotation(true); + context.setRotationApplied(true); assertTrue(stage.shouldExecute(context)); } @Test - void testShouldExecute_NormalPhotoButNoNeedRotation_ShouldSkip() { + void testShouldExecute_NormalPhotoButNoRotationApplied_ShouldSkip() { RestoreOrientationStage stage = new RestoreOrientationStage(); PhotoProcessContext context = PhotoProcessContext.builder() @@ -44,7 +50,7 @@ class RestoreOrientationStageTest { .imageType(ImageType.NORMAL_PHOTO) .build(); - context.setNeedRotation(false); + context.setRotationApplied(false); assertFalse(stage.shouldExecute(context)); } @@ -59,7 +65,7 @@ class RestoreOrientationStageTest { .imageType(ImageType.PUZZLE) .build(); - context.setNeedRotation(true); + context.setRotationApplied(true); assertFalse(stage.shouldExecute(context)); } @@ -74,11 +80,113 @@ class RestoreOrientationStageTest { .imageType(ImageType.NORMAL_PHOTO) .build(); - context.setNeedRotation(true); + context.setRotationApplied(true); StageResult result = stage.execute(context); assertTrue(result.isFailed()); assertEquals("当前文件不存在", result.getMessage()); } + + @Test + void testExecute_Restore90Rotation(@TempDir Path tempDir) throws Exception { + RestoreOrientationStage stage = new RestoreOrientationStage(); + + File testFile = createTestImage(tempDir, "test.jpg", 1920, 1080); + + PhotoProcessContext context = PhotoProcessContext.builder() + .processId("test-restore-90") + .originalUrl("https://example.com/test.jpg") + .scenicId(123L) + .imageType(ImageType.NORMAL_PHOTO) + .build(); + + context.setOriginalFile(testFile); + context.setRotationApplied(true); + context.setImageRotation(90); // 原始旋转了90度,恢复需要旋转270度 + + StageResult result = stage.execute(context); + + assertTrue(result.isSuccess()); + assertEquals("已恢复原方向", result.getMessage()); + } + + @Test + void testExecute_Restore270Rotation(@TempDir Path tempDir) throws Exception { + RestoreOrientationStage stage = new RestoreOrientationStage(); + + File testFile = createTestImage(tempDir, "test.jpg", 1920, 1080); + + PhotoProcessContext context = PhotoProcessContext.builder() + .processId("test-restore-270") + .originalUrl("https://example.com/test.jpg") + .scenicId(123L) + .imageType(ImageType.NORMAL_PHOTO) + .build(); + + context.setOriginalFile(testFile); + context.setRotationApplied(true); + context.setImageRotation(270); // 原始旋转了270度,恢复需要旋转90度 + + StageResult result = stage.execute(context); + + assertTrue(result.isSuccess()); + assertEquals("已恢复原方向", result.getMessage()); + } + + @Test + void testExecute_Restore180Rotation(@TempDir Path tempDir) throws Exception { + RestoreOrientationStage stage = new RestoreOrientationStage(); + + File testFile = createTestImage(tempDir, "test.jpg", 1920, 1080); + + PhotoProcessContext context = PhotoProcessContext.builder() + .processId("test-restore-180") + .originalUrl("https://example.com/test.jpg") + .scenicId(123L) + .imageType(ImageType.NORMAL_PHOTO) + .build(); + + context.setOriginalFile(testFile); + context.setRotationApplied(true); + context.setImageRotation(180); // 原始旋转了180度,恢复需要旋转180度 + + StageResult result = stage.execute(context); + + assertTrue(result.isSuccess()); + assertEquals("已恢复原方向", result.getMessage()); + } + + @Test + void testExecute_NoRotationInfo_ShouldSkip(@TempDir Path tempDir) throws Exception { + RestoreOrientationStage stage = new RestoreOrientationStage(); + + File testFile = createTestImage(tempDir, "test.jpg", 1920, 1080); + + PhotoProcessContext context = PhotoProcessContext.builder() + .processId("test-no-rotation-info") + .originalUrl("https://example.com/test.jpg") + .scenicId(123L) + .imageType(ImageType.NORMAL_PHOTO) + .build(); + + context.setOriginalFile(testFile); + context.setRotationApplied(true); + context.setImageRotation(null); // 无旋转信息 + + StageResult result = stage.execute(context); + + assertTrue(result.isSkipped()); + assertEquals("无旋转信息", result.getMessage()); + } + + /** + * 创建测试用的图片文件 + */ + private File createTestImage(Path tempDir, String filename, int width, int height) throws Exception { + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + File file = tempDir.resolve(filename).toFile(); + ImageIO.write(image, "jpg", file); + return file; + } }