diff options
-rw-r--r-- | build.gradle | 3 | ||||
-rw-r--r-- | juick-server-web/build.gradle | 1 | ||||
-rw-r--r-- | juick-server-web/src/main/java/com/juick/server/util/ImageUtils.java | 77 |
3 files changed, 76 insertions, 5 deletions
diff --git a/build.gradle b/build.gradle index 4b1e62bc..a5f37a2b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,9 @@ allprojects { repositories { mavenCentral() - jcenter() + jcenter() maven { url "https://jitpack.io" } + maven { url "https://repository.apache.org/content/repositories/snapshots/" } } apply plugin: 'com.github.ben-manes.versions' dependencyUpdates.resolutionStrategy = { diff --git a/juick-server-web/build.gradle b/juick-server-web/build.gradle index 92f017e4..3ca262bd 100644 --- a/juick-server-web/build.gradle +++ b/juick-server-web/build.gradle @@ -41,6 +41,7 @@ dependencies { compile "rocks.xmpp:xmpp-extensions-client:0.7.4" compile 'org.imgscalr:imgscalr-lib:4.2' + compile "org.apache.commons:commons-imaging:1.0-SNAPSHOT" providedCompile "javax.servlet:javax.servlet-api:3.1.0" diff --git a/juick-server-web/src/main/java/com/juick/server/util/ImageUtils.java b/juick-server-web/src/main/java/com/juick/server/util/ImageUtils.java index 61677750..00fe21ef 100644 --- a/juick-server-web/src/main/java/com/juick/server/util/ImageUtils.java +++ b/juick-server-web/src/main/java/com/juick/server/util/ImageUtils.java @@ -2,11 +2,19 @@ package com.juick.server.util; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.imaging.ImageReadException; +import org.apache.commons.imaging.Imaging; +import org.apache.commons.imaging.common.ImageMetadata; +import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; +import org.apache.commons.imaging.formats.tiff.TiffField; +import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; import org.imgscalr.Scalr; +import org.imgscalr.Scalr.Rotation; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -14,12 +22,73 @@ import java.nio.file.StandardCopyOption; public class ImageUtils { +/** + * Returns <code>BufferedImage</code>, same as <code>ImageIO.read()</code> does. + * + * <p>JPEG images with EXIF metadata are rotated according to Orientation tag. + * + * @param imageFile a <code>File</code> to read from. + */ + private static BufferedImage readImageWithOrientation(File imageFile) + throws IOException { + + BufferedImage image = ImageIO.read(imageFile); + if (!FilenameUtils.getExtension(imageFile.getName()).equals("jpg")) { + return image; + } + + try { + ImageMetadata metadata = Imaging.getMetadata(imageFile); + + if (metadata instanceof JpegImageMetadata) { + JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; + TiffField orientationField = jpegMetadata.findEXIFValue(TiffTagConstants.TIFF_TAG_ORIENTATION); + + if (orientationField != null) { + int orientation = orientationField.getIntValue(); + switch (orientation) { + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_90_CW: + image = Scalr.rotate(image, Rotation.CW_90); + break; + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_180: + image = Scalr.rotate(image, Rotation.CW_180); + break; + case TiffTagConstants.ORIENTATION_VALUE_ROTATE_270_CW: + image = Scalr.rotate(image, Rotation.CW_270); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL: + image = Scalr.rotate(image, Rotation.FLIP_HORZ); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_VERTICAL: + image = Scalr.rotate(image, Rotation.FLIP_VERT); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_90_CW: + image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_90); + break; + case TiffTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_270_CW: + image = Scalr.rotate(Scalr.rotate(image, Rotation.FLIP_HORZ), Rotation.CW_270); + break; + case TiffTagConstants.ORIENTATION_VALUE_HORIZONTAL_NORMAL: + default: + // do nothing + break; + } + } + } + } catch (ImageReadException e) { + // failed to read metadata. + // nothing to do here, return image as is. + } + + return image; + } + /** * Move attached image from temp folder to image folder. * Create preview images in corresponding folders. * - * @param tempFilename Name of the image file in temp folder. - * @param outputFilename Name that will be used in in image folder. + * @param tempFilename Name of the image file in the temp folder. + * @param outputFilename Name that will be used in the image folder. * @param tmpDir Path string for the temp folder. * @param imgDir Path string for the image folder. */ @@ -29,7 +98,7 @@ public class ImageUtils { Path outputImagePath = Paths.get(imgDir, "p", outputFilename); Files.move(Paths.get(tmpDir, tempFilename), outputImagePath); - BufferedImage originalImage = ImageIO.read(outputImagePath.toFile()); + BufferedImage originalImage = readImageWithOrientation(outputImagePath.toFile()); int width = originalImage.getWidth(); int height = originalImage.getHeight(); @@ -45,7 +114,7 @@ public class ImageUtils { /** * Save new avatar in all required sizes. * - * @param tempFilename Name of the image file in temp folder. + * @param tempFilename Name of the image file in the temp folder. * @param uid User id that is used to build image file names. * @param tmpDir Path string for the temp folder. * @param imgDir Path string for the image folder. |