diff --git a/web-domain/src/main/java/com/zcloud/edu/domain/utils/FixedPictureUtils.java b/web-domain/src/main/java/com/zcloud/edu/domain/utils/FixedPictureUtils.java index d265f9f..d5440dd 100644 --- a/web-domain/src/main/java/com/zcloud/edu/domain/utils/FixedPictureUtils.java +++ b/web-domain/src/main/java/com/zcloud/edu/domain/utils/FixedPictureUtils.java @@ -2,6 +2,9 @@ package com.zcloud.edu.domain.utils; import com.deepoove.poi.data.PictureRenderData; import com.deepoove.poi.data.Pictures; +import com.drew.imaging.ImageMetadataReader; +import com.drew.metadata.Metadata; +import com.drew.metadata.exif.ExifIFD0Directory; import javax.imageio.ImageIO; import javax.imageio.ImageReader; @@ -27,12 +30,19 @@ public class FixedPictureUtils { * @return 正常显示的PictureRenderData * @throws IOException IO异常 */ - public static PictureRenderData ofNormalUrl(String imgUrl, int width, int height) throws IOException { - byte[] imgBytes = readBytesFromUrl(imgUrl); - byte[] fixedImgBytes = fixImageRotation(imgBytes); - return Pictures.ofBytes(fixedImgBytes) - .size(width, height) - .create(); + public static PictureRenderData ofNormalUrl(String imgUrl, int width, int height) { + try{ + byte[] imgBytes = readBytesFromUrl(imgUrl); + byte[] fixedImgBytes = fixImageRotation(imgBytes); + return Pictures.ofBytes(fixedImgBytes) + .size(width, height) + .create(); + }catch (Exception e){ + return Pictures.ofUrl(imgUrl) + .size(width, height) + .create(); + } + } /** @@ -54,29 +64,65 @@ public class FixedPictureUtils { /** * 核心:修复图片旋转(JDK 8兼容) */ - private static byte[] fixImageRotation(byte[] imageBytes) throws IOException { - // 1. 解析EXIF旋转角度 - int rotation = getExifRotation(imageBytes); + private static byte[] fixImageRotation(byte[] imageBytes) throws Exception { + try (ByteArrayInputStream bais = new ByteArrayInputStream(imageBytes)) { + // 1. 读取 EXIF 元数据 + Metadata metadata = ImageMetadataReader.readMetadata(bais); - // 2. 兜底检测:无EXIF时自动判断 - if (rotation == 0) { - rotation = detectImageOrientation(imageBytes); + // 2. 获取旋转角度 + int rotation = getRotationFromMetadata(metadata); + + // 3. 如果不需要旋转,直接返回原字节 + if (rotation == 0) { + return imageBytes; + } + + // 4. 读取并旋转图片 + bais.reset(); // 重置流到开始位置 + BufferedImage original = ImageIO.read(bais); + BufferedImage rotated = rotateImage(original, rotation); + + // 5. 转为字节数组返回 + try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + String format = getImageFormat(imageBytes); + ImageIO.write(rotated, format, baos); + return baos.toByteArray(); + } } + } + /** + * 从EXIF读取需要旋转的角度 + * 返回:0-不需要旋转,90/180/270-需要旋转的角度 + */ + /** + * 从 Metadata 获取旋转角度 + * @param metadata EXIF 元数据 + * @return 需要旋转的角度(0/90/180/270) + */ + private static int getRotationFromMetadata(Metadata metadata) { + try { + ExifIFD0Directory exifIFD0Directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); - // 3. 无需旋转则返回原字节 - if (rotation == 0) { - return imageBytes; - } + if (exifIFD0Directory == null || !exifIFD0Directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) { + return 0; // 没有 EXIF 或 Orientation 标签,不需要旋转 + } - // 4. 读取并旋转图片 - BufferedImage original = readImage(imageBytes); - BufferedImage rotated = rotateImage(original, rotation); + int orientation = exifIFD0Directory.getInt(ExifIFD0Directory.TAG_ORIENTATION); - // 5. 转为字节返回 - try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - String format = getImageFormat(imageBytes); - ImageIO.write(rotated, format, baos); - return baos.toByteArray(); + // 根据 Orientation 值返回对应的旋转角度 + switch (orientation) { + case 3: // 旋转 180 度 + return 180; + case 6: // 顺时针旋转 90 度 + return 90; + case 8: // 逆时针旋转 90 度(270 度) + return 270; + default: // 1 或其他,不需要旋转 + return 0; + } + } catch (Exception e) { + // 任何异常都返回 0 度 + return 0; } }