From 9ef168a03b75aeca0c2f7dda9ce87d4014c703a9 Mon Sep 17 00:00:00 2001 From: Vitaly Takmazov Date: Fri, 16 Mar 2018 10:46:23 +0300 Subject: merge common projects --- .../java/com/juick/server/util/ImageUtils.java | 168 +++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 juick-common/src/main/java/com/juick/server/util/ImageUtils.java (limited to 'juick-common/src/main/java/com/juick/server/util/ImageUtils.java') diff --git a/juick-common/src/main/java/com/juick/server/util/ImageUtils.java b/juick-common/src/main/java/com/juick/server/util/ImageUtils.java new file mode 100644 index 00000000..94ecf71e --- /dev/null +++ b/juick-common/src/main/java/com/juick/server/util/ImageUtils.java @@ -0,0 +1,168 @@ + +/* + * Copyright (C) 2008-2017, Juick + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package com.juick.server.util; + +import org.apache.commons.imaging.ImageInfo; +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.apache.commons.io.FilenameUtils; +import org.imgscalr.Scalr; +import org.imgscalr.Scalr.Rotation; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +public class ImageUtils { + +/** + * Returns BufferedImage, same as ImageIO.read() does. + * + *

JPEG images with EXIF metadata are rotated according to Orientation tag. + * + * @param imageFile a File 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 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. + */ + public static void saveImageWithPreviews(String tempFilename, String outputFilename, String tmpDir, String imgDir) + throws IOException { + String ext = FilenameUtils.getExtension(outputFilename); + + Path outputImagePath = Paths.get(imgDir, "p", outputFilename); + Files.move(Paths.get(tmpDir, tempFilename), outputImagePath); + BufferedImage originalImage = readImageWithOrientation(outputImagePath.toFile()); + + int width = originalImage.getWidth(); + int height = originalImage.getHeight(); + int maxDimension = (width > height) ? width : height; + BufferedImage image1024 = (maxDimension > 1024) ? Scalr.resize(originalImage, 1024) : originalImage; + BufferedImage image0512 = (maxDimension > 512) ? Scalr.resize(originalImage, 512) : originalImage; + BufferedImage image0160 = (maxDimension > 160) ? Scalr.resize(originalImage, 160) : originalImage; + ImageIO.write(image1024, ext, Paths.get(imgDir, "photos-1024", outputFilename).toFile()); + ImageIO.write(image0512, ext, Paths.get(imgDir, "photos-512", outputFilename).toFile()); + ImageIO.write(image0160, ext, Paths.get(imgDir, "ps", outputFilename).toFile()); + } + + /** + * Save new avatar in all required sizes. + * + * @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. + */ + public static void saveAvatar(String tempFilename, int uid, String tmpDir, String imgDir) + throws IOException { + String ext = FilenameUtils.getExtension(tempFilename); + String originalName = String.format("%s.%s", uid, ext); + Path originalPath = Paths.get(imgDir, "ao", originalName); + Files.move(Paths.get(tmpDir, tempFilename), originalPath, StandardCopyOption.REPLACE_EXISTING); + BufferedImage originalImage = ImageIO.read(originalPath.toFile()); + + String targetExt = "png"; + String targetName = String.format("%s.%s", uid, targetExt); + ImageIO.write(Scalr.resize(originalImage, 96), targetExt, Paths.get(imgDir, "a", targetName).toFile()); + ImageIO.write(Scalr.resize(originalImage, 32), targetExt, Paths.get(imgDir, "as", targetName).toFile()); + } + + public static Integer getImageHeight(File imageFile) throws IOException, ImageReadException { + if (imageFile.exists()) { + ImageInfo info = Imaging.getImageInfo(imageFile); + return info.getHeight(); + } + return 0; + } + public static Integer getImageWidth(File imageFile) throws IOException, ImageReadException { + if (imageFile.exists()) { + ImageInfo info = Imaging.getImageInfo(imageFile); + return info.getWidth(); + } + return 0; + } +} \ No newline at end of file -- cgit v1.2.3