You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jo...@apache.org on 2022/08/25 06:34:40 UTC

[nifi] branch main updated: NIFI-10392 - This closes #6330. ResizeImage - add option to maintain aspect ratio

This is an automated email from the ASF dual-hosted git repository.

joewitt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 71ba581fd8 NIFI-10392 - This closes #6330. ResizeImage - add option to maintain aspect ratio
71ba581fd8 is described below

commit 71ba581fd829b52b7e501ab11cbe0eb3637ba450
Author: Pierre Villard <pi...@gmail.com>
AuthorDate: Wed Aug 24 12:39:43 2022 +0200

    NIFI-10392 - This closes #6330. ResizeImage - add option to maintain aspect ratio
    
    Signed-off-by: Joe Witt <jo...@apache.org>
---
 .../apache/nifi/processors/image/ResizeImage.java  | 48 +++++++++++++++++-----
 .../nifi/processors/image/TestResizeImage.java     | 44 ++++++++++++++++++++
 2 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/main/java/org/apache/nifi/processors/image/ResizeImage.java b/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/main/java/org/apache/nifi/processors/image/ResizeImage.java
index cbe744363b..8b21318266 100644
--- a/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/main/java/org/apache/nifi/processors/image/ResizeImage.java
+++ b/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/main/java/org/apache/nifi/processors/image/ResizeImage.java
@@ -17,6 +17,7 @@
 
 package org.apache.nifi.processors.image;
 
+import java.awt.Dimension;
 import java.awt.Graphics2D;
 import java.awt.Image;
 import java.awt.Transparency;
@@ -88,6 +89,15 @@ public class ResizeImage extends AbstractProcessor {
         .allowableValues(RESIZE_DEFAULT, RESIZE_FAST, RESIZE_SMOOTH, RESIZE_REPLICATE, RESIZE_AREA_AVERAGING)
         .defaultValue(RESIZE_DEFAULT.getValue())
         .build();
+    static final PropertyDescriptor KEEP_RATIO = new PropertyDescriptor.Builder()
+        .displayName("Maintain aspect ratio")
+        .name("keep-ratio")
+        .description("Specifies if the ratio of the input image should be maintained")
+        .expressionLanguageSupported(ExpressionLanguageScope.FLOWFILE_ATTRIBUTES)
+        .allowableValues("true", "false")
+        .defaultValue("false")
+        .required(true)
+        .build();
 
     static final Relationship REL_SUCCESS = new Relationship.Builder()
         .name("success")
@@ -104,6 +114,7 @@ public class ResizeImage extends AbstractProcessor {
         properties.add(IMAGE_WIDTH);
         properties.add(IMAGE_HEIGHT);
         properties.add(SCALING_ALGORITHM);
+        properties.add(KEEP_RATIO);
         return properties;
     }
 
@@ -122,16 +133,6 @@ public class ResizeImage extends AbstractProcessor {
             return;
         }
 
-        final int width, height;
-        try {
-            width = context.getProperty(IMAGE_WIDTH).evaluateAttributeExpressions(flowFile).asInteger();
-            height = context.getProperty(IMAGE_HEIGHT).evaluateAttributeExpressions(flowFile).asInteger();
-        } catch (final NumberFormatException nfe) {
-            getLogger().error("Failed to resize {} due to {}", new Object[] { flowFile, nfe });
-            session.transfer(flowFile, REL_FAILURE);
-            return;
-        }
-
         final String algorithm = context.getProperty(SCALING_ALGORITHM).getValue();
         final int hints;
         if (algorithm.equalsIgnoreCase(RESIZE_DEFAULT.getValue())) {
@@ -176,6 +177,25 @@ public class ResizeImage extends AbstractProcessor {
             return;
         }
 
+        final boolean keepRatio = context.getProperty(KEEP_RATIO).evaluateAttributeExpressions(flowFile).asBoolean();
+
+        int width, height;
+        try {
+            width = context.getProperty(IMAGE_WIDTH).evaluateAttributeExpressions(flowFile).asInteger();
+            height = context.getProperty(IMAGE_HEIGHT).evaluateAttributeExpressions(flowFile).asInteger();
+
+            if(keepRatio) {
+                Dimension finalDimension = getScaledDimension(image.getWidth(), image.getHeight(), width, height);
+                width = finalDimension.width;
+                height = finalDimension.height;
+            }
+
+        } catch (final NumberFormatException nfe) {
+            getLogger().error("Failed to resize {} due to {}", new Object[] { flowFile, nfe });
+            session.transfer(flowFile, REL_FAILURE);
+            return;
+        }
+
         try (final OutputStream out = session.write(flowFile)) {
             final Image scaledImage = image.getScaledInstance(width, height, hints);
             final BufferedImage scaledBufferedImg;
@@ -207,4 +227,12 @@ public class ResizeImage extends AbstractProcessor {
         session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
         session.transfer(flowFile, REL_SUCCESS);
     }
+
+    public Dimension getScaledDimension(int originalWidth, int originalHeight, int boundWidth, int boundHeight) {
+        double widthRatio = ((double) boundWidth) / originalWidth;
+        double heightRatio = ((double) boundHeight) / originalHeight;
+        double ratio = Math.min(widthRatio, heightRatio);
+        return new Dimension((int) (originalWidth  * ratio), (int) (originalHeight * ratio));
+    }
+
 }
diff --git a/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/test/java/org/apache/nifi/processors/image/TestResizeImage.java b/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/test/java/org/apache/nifi/processors/image/TestResizeImage.java
index f1c95d8337..1f2025a6f4 100644
--- a/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/test/java/org/apache/nifi/processors/image/TestResizeImage.java
+++ b/nifi-nar-bundles/nifi-media-bundle/nifi-media-processors/src/test/java/org/apache/nifi/processors/image/TestResizeImage.java
@@ -157,4 +157,48 @@ public class TestResizeImage {
         final File out = new File("target/mspaint-8x10resized.png");
         ImageIO.write(img, "PNG", out);
     }
+
+    @Test
+    public void testResizeBiggerPNGWithRatio() throws IOException {
+        final TestRunner runner = TestRunners.newTestRunner(new ResizeImage());
+        runner.setProperty(ResizeImage.IMAGE_HEIGHT, "64");
+        runner.setProperty(ResizeImage.IMAGE_WIDTH, "64");
+        runner.setProperty(ResizeImage.SCALING_ALGORITHM, ResizeImage.RESIZE_SMOOTH);
+        runner.setProperty(ResizeImage.KEEP_RATIO, "true");
+
+        runner.enqueue(Paths.get("src/test/resources/mspaint-8x10.png"));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ResizeImage.REL_SUCCESS, 1);
+        final MockFlowFile mff = runner.getFlowFilesForRelationship(ResizeImage.REL_SUCCESS).get(0);
+        final byte[] data = mff.toByteArray();
+
+        final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
+        assertEquals(42, img.getWidth());
+        assertEquals(64, img.getHeight());
+        final File out = new File("target/mspaint-8x10resized.png");
+        ImageIO.write(img, "PNG", out);
+    }
+
+    @Test
+    public void testResizeSmallerPNGWithRatio() throws IOException {
+        final TestRunner runner = TestRunners.newTestRunner(new ResizeImage());
+        runner.setProperty(ResizeImage.IMAGE_HEIGHT, "5");
+        runner.setProperty(ResizeImage.IMAGE_WIDTH, "5");
+        runner.setProperty(ResizeImage.SCALING_ALGORITHM, ResizeImage.RESIZE_SMOOTH);
+        runner.setProperty(ResizeImage.KEEP_RATIO, "true");
+
+        runner.enqueue(Paths.get("src/test/resources/mspaint-8x10.png"));
+        runner.run();
+
+        runner.assertAllFlowFilesTransferred(ResizeImage.REL_SUCCESS, 1);
+        final MockFlowFile mff = runner.getFlowFilesForRelationship(ResizeImage.REL_SUCCESS).get(0);
+        final byte[] data = mff.toByteArray();
+
+        final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data));
+        assertEquals(3, img.getWidth());
+        assertEquals(5, img.getHeight());
+        final File out = new File("target/mspaint-8x10resized.png");
+        ImageIO.write(img, "PNG", out);
+    }
 }
\ No newline at end of file