/** * Copyright [2015] [Christian Loehnert] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.ks.gallery; import org.apache.sanselan.ImageInfo; import org.apache.sanselan.ImageReadException; import org.apache.sanselan.Sanselan; import org.apache.sanselan.common.IImageMetadata; import org.apache.sanselan.formats.jpeg.JpegImageMetadata; import org.apache.sanselan.formats.tiff.TiffField; import org.apache.sanselan.formats.tiff.constants.ExifTagConstants; import org.imgscalr.Scalr; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.Optional; public class ImageScaler { private static final Logger log = LoggerFactory.getLogger(ImageScaler.class); public Optional<LocalDateTime> getShootingTime(File image) { try { IImageMetadata metadata = Sanselan.getMetadata(image); if (metadata instanceof JpegImageMetadata) { TiffField dateTimeValue = ((JpegImageMetadata) metadata).findEXIFValue(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL); if (dateTimeValue != null) { String stringValue = dateTimeValue.getStringValue().trim(); String dateString = stringValue.split(" ")[0]; String timeString = stringValue.split(" ")[1]; String[] dateParts = dateString.split(":"); String[] timeParts = timeString.split(":"); LocalDate localDate = LocalDate.of(Integer.valueOf(dateParts[0]), Integer.valueOf(dateParts[1]), Integer.valueOf(dateParts[2])); LocalTime localTime = LocalTime.of(Integer.valueOf(timeParts[0]), Integer.valueOf(timeParts[1]), Integer.valueOf(timeParts[2])); return Optional.of(LocalDateTime.of(localDate, localTime)); } } } catch (Exception e) { log.error("Could not get metdata from {}", image, e); } return Optional.empty(); } protected BufferedImage readImage(File src) throws IOException { return ImageIO.read(src); } public BufferedImage rotateAndScale(File src, int width, int height) throws IOException { BufferedImage image = readImage(src); return rotateAndScale(src, width, height, image); } public BufferedImage rotateAndScale(File src, int requestedSize) throws IOException { BufferedImage image = readImage(src); return rotateAndScale(src, requestedSize, image); } public BufferedImage rotate(File src) throws IOException { BufferedImage image = readImage(src); return rotate(src, image); } public void rotateAndWriteImage(File src, File target, int requestedSize) { try { BufferedImage image = readImage(src); ImageInfo imageInfo = Sanselan.getImageInfo(src); image = rotateAndScale(src, requestedSize, image); Files.createDirectories(target.getParentFile().toPath()); String extension = imageInfo.getFormat().extension; ImageIO.write(image, extension, target); } catch (Exception e) { log.error("Rotate and write media {}", src, e); } } protected BufferedImage rotateAndScale(File src, int requestedSize, BufferedImage image) throws IOException { image = Scalr.resize(image, requestedSize); image = rotate(src, image); return image; } protected BufferedImage rotateAndScale(File src, int width, int heigth, BufferedImage image) throws IOException { image = rotate(src, image); image = Scalr.resize(image, Math.min(width, image.getWidth()), Math.min(heigth, image.getHeight())); return image; } protected BufferedImage rotate(File src, BufferedImage image) throws IOException { int orientation = getExifOrientation(src); if (orientation >= 0) { if (orientation == ExifTagConstants.ORIENTATION_VALUE_ROTATE_90_CW) { image = Scalr.rotate(image, Scalr.Rotation.CW_90); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_ROTATE_180) { image = Scalr.rotate(image, Scalr.Rotation.CW_180); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_ROTATE_270_CW) { image = Scalr.rotate(image, Scalr.Rotation.CW_270); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_90_CW) { image = Scalr.rotate(image, Scalr.Rotation.FLIP_HORZ); image = Scalr.rotate(image, Scalr.Rotation.CW_90); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL_AND_ROTATE_270_CW) { image = Scalr.rotate(image, Scalr.Rotation.FLIP_HORZ); image = Scalr.rotate(image, Scalr.Rotation.CW_270); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_MIRROR_HORIZONTAL) { image = Scalr.rotate(image, Scalr.Rotation.FLIP_HORZ); } else if (orientation == ExifTagConstants.ORIENTATION_VALUE_MIRROR_VERTICAL) { image = Scalr.rotate(image, Scalr.Rotation.FLIP_VERT); } } return image; } protected int getExifOrientation(File file) throws IOException { try { IImageMetadata metadata; synchronized (ImageScaler.class) {//fucking sanselan is not thread save at all metadata = Sanselan.getMetadata(file); } if (metadata instanceof JpegImageMetadata) { TiffField orientationField = ((JpegImageMetadata) metadata).findEXIFValue(ExifTagConstants.EXIF_TAG_ORIENTATION); if (orientationField == null) { return -1; } else { int orientation = orientationField.getIntValue(); return orientation; } } } catch (ImageReadException e) { // } return -1; } }