From 2718db628bfa334298985c0ce6ca737deeb82bff Mon Sep 17 00:00:00 2001 From: guqing Date: Sat, 12 Oct 2024 16:31:26 +0800 Subject: [PATCH] fix: vertical images are rotated to horizontal when generating thumbnails --- 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 8185f2a024..046529c443 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 ad822f05cb..30b2d7455e 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 @@ 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 @@ private void generateThumbnail(Path tempImagePath) throws IOException { } 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 90311f35e7..396df394c7 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" } }