From bef972ca0d3ca3eccbd1713d43ae80b838d9bd7f Mon Sep 17 00:00:00 2001 From: zhaokai Date: Wed, 11 Mar 2026 10:57:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=BC=E5=87=BA=E4=B8=80?= =?UTF-8?q?=E4=BA=BA=E4=B8=80=E6=A1=A3=E4=BA=BA=E8=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++ web-domain/pom.xml | 4 ++ .../zcloud/edu/domain/utils/ImageUtil.java | 62 +++++++++++++++---- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/pom.xml b/pom.xml index 98e740b..60c8b26 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,12 @@ thumbnailator 0.4.20 + + com.drewnoakes + metadata-extractor + 2.19.0 + + com.jjb.saas jjb-saas-system-client diff --git a/web-domain/pom.xml b/web-domain/pom.xml index 29907b3..edbf291 100644 --- a/web-domain/pom.xml +++ b/web-domain/pom.xml @@ -22,5 +22,9 @@ com.jjb.saas jjb-saas-base-starter + + com.drewnoakes + metadata-extractor + diff --git a/web-domain/src/main/java/com/zcloud/edu/domain/utils/ImageUtil.java b/web-domain/src/main/java/com/zcloud/edu/domain/utils/ImageUtil.java index e89087f..47d1016 100644 --- a/web-domain/src/main/java/com/zcloud/edu/domain/utils/ImageUtil.java +++ b/web-domain/src/main/java/com/zcloud/edu/domain/utils/ImageUtil.java @@ -9,26 +9,37 @@ import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.net.URL; -import net.coobird.thumbnailator.Thumbnails; -import net.coobird.thumbnailator.geometry.Positions; +import com.drew.imaging.ImageMetadataReader; +import com.drew.metadata.Metadata; +import com.drew.metadata.exif.ExifIFD0Directory; public class ImageUtil { public static PictureRenderData createWithThumbnailator(String imageUrl, int width, int height) { try { // 下载原图 URL url = new URL(imageUrl); - BufferedImage original = ImageIO.read(url); + BufferedImage originalImage = ImageIO.read(url); - // 使用Thumbnailator处理 - 一行代码搞定旋转和缩放 - BufferedImage processed = Thumbnails.of(original) - .size(width, height) - .rotate(270) // 如果需要固定旋转,可以直接指定 - .asBufferedImage(); + // 1. 读取EXIF判断是否需要旋转 + int rotationAngle = getRotationAngleFromExif(url); - // 或者使用EXIF自动旋转(如果Thumbnailator版本支持) - // Thumbnails.of(original).scale(1.0).useExifOrientation().asBufferedImage(); + // 2. 根据判断结果决定是否旋转 + BufferedImage processedImage; + if (rotationAngle != 0) { + // 需要旋转 + processedImage = Thumbnails.of(originalImage) + .size(width, height) + .rotate(rotationAngle) + .asBufferedImage(); + } else { + // 不需要旋转,只缩放 + processedImage = Thumbnails.of(originalImage) + .size(width, height) + .asBufferedImage(); + } + // 3. 转换为byte数组 ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(processed, "jpg", baos); + ImageIO.write(processedImage, "jpg", baos); return Pictures.ofBytes(baos.toByteArray(), PictureType.JPEG) .size(width, height) @@ -40,4 +51,33 @@ public class ImageUtil { .create(); } } + /** + * 从EXIF读取需要旋转的角度 + * 返回:0-不需要旋转,90/180/270-需要旋转的角度 + */ + private static int getRotationAngleFromExif(URL url) { + try { + Metadata metadata = ImageMetadataReader.readMetadata(url.openStream()); + ExifIFD0Directory exifDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); + + if (exifDir != null && exifDir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) { + int orientation = exifDir.getInt(ExifIFD0Directory.TAG_ORIENTATION); + + // 根据Orientation值返回需要的旋转角度 [citation:9] + switch (orientation) { + case 3: // 需要旋转180度 + return 180; + case 6: // 需要顺时针旋转90度(最常见:手机竖拍) + return 90; + case 8: // 需要逆时针旋转90度 + return 270; + default: // 1或其他,不需要旋转 + return 0; + } + } + } catch (Exception e) { + // 忽略EXIF读取错误,返回0表示不旋转 + } + return 0; + } }