From 3bdec9eacf15ff7e7291f9736c6da878f2a4a995 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:47:10 +0800 Subject: [PATCH] fix: vertical images are rotated to horizontal when generating thumbnails (#6842) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind improvement /area core /milestone 2.20.x #### What this PR does / why we need it: 修复竖向图片生成缩略图后会丢失方向信息展示为横向图片的问题 #### Which issue(s) this PR fixes: Fixes #6802 #### Does this PR introduce a user-facing change? ```release-note 修复竖向图片生成缩略图后会丢失方向信息展示为横向图片的问题 ``` --- api/build.gradle | 1 + .../core/attachment/ThumbnailGenerator.java | 33 +++++++++++++++++++ platform/application/build.gradle | 2 ++ 3 files changed, 36 insertions(+) diff --git a/api/build.gradle b/api/build.gradle index 8185f2a02..046529c44 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -68,6 +68,7 @@ dependencies { api "org.thymeleaf.extras:thymeleaf-extras-springsecurity6" api 'org.apache.tika:tika-core' api "org.imgscalr:imgscalr-lib" + api 'com.drewnoakes:metadata-extractor' api "io.github.resilience4j:resilience4j-spring-boot3" api "io.github.resilience4j:resilience4j-reactor" diff --git a/application/src/main/java/run/halo/app/core/attachment/ThumbnailGenerator.java b/application/src/main/java/run/halo/app/core/attachment/ThumbnailGenerator.java index ad822f05c..30b2d7455 100644 --- a/application/src/main/java/run/halo/app/core/attachment/ThumbnailGenerator.java +++ b/application/src/main/java/run/halo/app/core/attachment/ThumbnailGenerator.java @@ -2,6 +2,10 @@ package run.halo.app.core.attachment; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import com.drew.imaging.ImageMetadataReader; +import com.drew.metadata.Directory; +import com.drew.metadata.Metadata; +import com.drew.metadata.exif.ExifIFD0Directory; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -92,9 +96,38 @@ public class ThumbnailGenerator { } var thumbnail = Scalr.resize(img, Scalr.Method.AUTOMATIC, Scalr.Mode.FIT_TO_WIDTH, size.getWidth()); + // Rotate image if needed + var orientation = readExifOrientation(file); + if (orientation != null) { + thumbnail = Scalr.rotate(thumbnail, orientation); + } ImageIO.write(thumbnail, formatName, thumbnailFile); } + private static Scalr.Rotation readExifOrientation(File inputFile) { + try { + Metadata metadata = ImageMetadataReader.readMetadata(inputFile); + Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); + if (directory != null && directory.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) { + return getScalrRotationFromExifOrientation( + directory.getInt(ExifIFD0Directory.TAG_ORIENTATION)); + } + } catch (Exception e) { + log.debug("Failed to read EXIF orientation from file: {}", inputFile, e); + } + return null; + } + + private static Scalr.Rotation getScalrRotationFromExifOrientation(int orientation) { + // https://www.media.mit.edu/pia/Research/deepview/exif.html#:~:text=0x0112-,Orientation,-unsigned%20short + return switch (orientation) { + case 3 -> Scalr.Rotation.CW_180; + case 6 -> Scalr.Rotation.CW_90; + case 8 -> Scalr.Rotation.CW_270; + default -> null; + }; + } + private static boolean isUnsupportedFormat(@NonNull String formatName) { return UNSUPPORTED_FORMATS.contains(formatName.toLowerCase()); } diff --git a/platform/application/build.gradle b/platform/application/build.gradle index 90311f35e..396df394c 100644 --- a/platform/application/build.gradle +++ b/platform/application/build.gradle @@ -24,6 +24,7 @@ ext { twoFactorAuth = "1.3" tika = "2.9.2" imgscalr = '4.2' + exifExtractor = '2.19.0' } javaPlatform { @@ -58,6 +59,7 @@ dependencies { api "com.j256.two-factor-auth:two-factor-auth:$twoFactorAuth" api "org.apache.tika:tika-core:$tika" api "org.imgscalr:imgscalr-lib:$imgscalr" + api "com.drewnoakes:metadata-extractor:$exifExtractor" } }