From 465623d5ae9481fea31b55191c61c659a7ba5787 Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Sun, 18 Oct 2020 02:51:16 +0200 Subject: [PATCH] Factor out ImageData.resize into ImageResizer (FINERACT-1201) --- .../api/ImagesApiResource.java | 9 +- .../documentmanagement/data/ImageData.java | 55 +----------- .../documentmanagement/data/ImageResizer.java | 85 +++++++++++++++++++ 3 files changed, 92 insertions(+), 57 deletions(-) create mode 100644 fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageResizer.java diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/api/ImagesApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/api/ImagesApiResource.java index 1bf5c12e6..851af090a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/api/ImagesApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/api/ImagesApiResource.java @@ -44,6 +44,7 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils; import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils.ImageFileExtension; import org.apache.fineract.infrastructure.documentmanagement.data.ImageData; +import org.apache.fineract.infrastructure.documentmanagement.data.ImageResizer; import org.apache.fineract.infrastructure.documentmanagement.exception.ContentManagementException; import org.apache.fineract.infrastructure.documentmanagement.exception.InvalidEntityTypeForImageManagementException; import org.apache.fineract.infrastructure.documentmanagement.service.ImageReadPlatformService; @@ -64,16 +65,18 @@ public class ImagesApiResource { private final ImageWritePlatformService imageWritePlatformService; private final DefaultToApiJsonSerializer toApiJsonSerializer; private final FileUploadValidator fileUploadValidator; + private final ImageResizer imageResizer; @Autowired public ImagesApiResource(final PlatformSecurityContext context, final ImageReadPlatformService readPlatformService, final ImageWritePlatformService imageWritePlatformService, final DefaultToApiJsonSerializer toApiJsonSerializer, - final FileUploadValidator fileUploadValidator) { + final FileUploadValidator fileUploadValidator, final ImageResizer imageResizer) { this.context = context; this.imageReadPlatformService = readPlatformService; this.imageWritePlatformService = imageWritePlatformService; this.toApiJsonSerializer = toApiJsonSerializer; this.fileUploadValidator = fileUploadValidator; + this.imageResizer = imageResizer; } /** @@ -146,7 +149,7 @@ public class ImagesApiResource { imageDataURISuffix = ContentRepositoryUtils.ImageDataURIsuffix.PNG.getValue(); } - ImageData resizedImage = imageData.resize(imageData, maxWidth, maxHeight); + ImageData resizedImage = imageResizer.resize(imageData, maxWidth, maxHeight); try { byte[] resizedImageBytes = resizedImage.getInputStream().readAllBytes(); final String clientImageAsBase64Text = imageDataURISuffix + Base64.getMimeEncoder().encodeToString(resizedImageBytes); @@ -170,7 +173,7 @@ public class ImagesApiResource { } final ImageData imageData = this.imageReadPlatformService.retrieveImage(entityName, entityId); - final ImageData resizedImage = imageData.resize(imageData, maxWidth, maxHeight); + final ImageData resizedImage = imageResizer.resize(imageData, maxWidth, maxHeight); final ResponseBuilder response = Response.ok(resizedImage.getInputStream()); final String dispositionType = "inline_octet".equals(output) ? "inline" : "attachment"; response.header("Content-Disposition", diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageData.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageData.java index e0509b58f..3f7df51b1 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageData.java @@ -18,20 +18,12 @@ */ package org.apache.fineract.infrastructure.documentmanagement.data; -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.image.BufferedImage; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.IOException; +import java.io.FileNotFoundException; import java.io.InputStream; -import javax.imageio.ImageIO; import org.apache.commons.lang3.StringUtils; import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils; -import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils.ImageFileExtension; import org.apache.fineract.infrastructure.documentmanagement.domain.StorageType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -54,51 +46,6 @@ public class ImageData { this.entityDisplayName = entityDisplayName; } - public ImageData resize(ImageData image, Integer maxWidth, Integer maxHeight) { - if (maxWidth == null && maxHeight != null) { - return image; - } - try (InputStream is = image.getInputStream()) { - InputStream resizedIS = resizeImage(image.getFileExtension(), is, maxWidth != null ? maxWidth : Integer.MAX_VALUE, - maxHeight != null ? maxHeight : Integer.MAX_VALUE); - - ImageData resizedImage = new ImageData(image.location(), image.storageType(), image.getEntityDisplayName()); - resizedImage.updateContent(resizedIS); - return resizedImage; - } catch (IOException e) { - LOG.warn("resize() failed, returning original image: {}", e.getMessage(), e); - return image; - } - } - - private InputStream resizeImage(ImageFileExtension fileExtension, InputStream in, int maxWidth, int maxHeight) throws IOException { - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - BufferedImage src = ImageIO.read(in); - if (src.getWidth() <= maxWidth && src.getHeight() <= maxHeight) { - in.reset(); - return in; - } - float widthRatio = (float) src.getWidth() / maxWidth; - float heightRatio = (float) src.getHeight() / maxHeight; - float scaleRatio = widthRatio > heightRatio ? widthRatio : heightRatio; - - // TODO(lindahl): Improve compressed image quality (perhaps quality ratio) - - int newWidth = (int) (src.getWidth() / scaleRatio); - int newHeight = (int) (src.getHeight() / scaleRatio); - int colorModel = fileExtension == ContentRepositoryUtils.ImageFileExtension.JPEG ? BufferedImage.TYPE_INT_RGB - : BufferedImage.TYPE_INT_ARGB; - BufferedImage target = new BufferedImage(newWidth, newHeight, colorModel); - Graphics2D g = target.createGraphics(); - g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); - g.drawImage(src, 0, 0, newWidth, newHeight, Color.BLACK, null); - g.dispose(); - ImageIO.write(target, fileExtension != null ? fileExtension.getValueWithoutDot() : "jpeg", os); - - return new ByteArrayInputStream(os.toByteArray()); - } - private void setImageFileExtension(String filename) { fileExtension = ContentRepositoryUtils.ImageFileExtension.JPEG; diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageResizer.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageResizer.java new file mode 100644 index 000000000..9241ea6ab --- /dev/null +++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/documentmanagement/data/ImageResizer.java @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.fineract.infrastructure.documentmanagement.data; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import javax.imageio.ImageIO; +import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils; +import org.apache.fineract.infrastructure.documentmanagement.contentrepository.ContentRepositoryUtils.ImageFileExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; + +@Service +public class ImageResizer { + + private static final Logger LOG = LoggerFactory.getLogger(ImageResizer.class); + + public ImageData resize(ImageData image, Integer maxWidth, Integer maxHeight) { + if (maxWidth == null && maxHeight != null) { + return image; + } + try (InputStream is = image.getInputStream()) { + InputStream resizedIS = resizeImage(image.getFileExtension(), is, maxWidth != null ? maxWidth : Integer.MAX_VALUE, + maxHeight != null ? maxHeight : Integer.MAX_VALUE); + + ImageData resizedImage = new ImageData(image.location(), image.storageType(), image.getEntityDisplayName()); + resizedImage.updateContent(resizedIS); + return resizedImage; + } catch (IOException e) { + LOG.warn("resize() failed, returning original image: {}", e.getMessage(), e); + return image; + } + } + + private InputStream resizeImage(ImageFileExtension fileExtension, InputStream in, int maxWidth, int maxHeight) throws IOException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + BufferedImage src = ImageIO.read(in); + if (src.getWidth() <= maxWidth && src.getHeight() <= maxHeight) { + in.reset(); + return in; + } + float widthRatio = (float) src.getWidth() / maxWidth; + float heightRatio = (float) src.getHeight() / maxHeight; + float scaleRatio = widthRatio > heightRatio ? widthRatio : heightRatio; + + // TODO(lindahl): Improve compressed image quality (perhaps quality ratio) + + int newWidth = (int) (src.getWidth() / scaleRatio); + int newHeight = (int) (src.getHeight() / scaleRatio); + int colorModel = fileExtension == ContentRepositoryUtils.ImageFileExtension.JPEG ? BufferedImage.TYPE_INT_RGB + : BufferedImage.TYPE_INT_ARGB; + BufferedImage target = new BufferedImage(newWidth, newHeight, colorModel); + Graphics2D g = target.createGraphics(); + g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); + g.drawImage(src, 0, 0, newWidth, newHeight, Color.BLACK, null); + g.dispose(); + ImageIO.write(target, fileExtension != null ? fileExtension.getValueWithoutDot() : "jpeg", os); + + return new ByteArrayInputStream(os.toByteArray()); + } +}