mirror of
https://github.com/apache/nifi.git
synced 2025-02-13 13:35:20 +00:00
NIFI-10392 - This closes #6330. ResizeImage - add option to maintain aspect ratio
Signed-off-by: Joe Witt <joewitt@apache.org>
This commit is contained in:
parent
777238eb32
commit
71ba581fd8
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.nifi.processors.image;
|
package org.apache.nifi.processors.image;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Transparency;
|
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)
|
.allowableValues(RESIZE_DEFAULT, RESIZE_FAST, RESIZE_SMOOTH, RESIZE_REPLICATE, RESIZE_AREA_AVERAGING)
|
||||||
.defaultValue(RESIZE_DEFAULT.getValue())
|
.defaultValue(RESIZE_DEFAULT.getValue())
|
||||||
.build();
|
.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()
|
static final Relationship REL_SUCCESS = new Relationship.Builder()
|
||||||
.name("success")
|
.name("success")
|
||||||
@ -104,6 +114,7 @@ public class ResizeImage extends AbstractProcessor {
|
|||||||
properties.add(IMAGE_WIDTH);
|
properties.add(IMAGE_WIDTH);
|
||||||
properties.add(IMAGE_HEIGHT);
|
properties.add(IMAGE_HEIGHT);
|
||||||
properties.add(SCALING_ALGORITHM);
|
properties.add(SCALING_ALGORITHM);
|
||||||
|
properties.add(KEEP_RATIO);
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,16 +133,6 @@ public class ResizeImage extends AbstractProcessor {
|
|||||||
return;
|
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 String algorithm = context.getProperty(SCALING_ALGORITHM).getValue();
|
||||||
final int hints;
|
final int hints;
|
||||||
if (algorithm.equalsIgnoreCase(RESIZE_DEFAULT.getValue())) {
|
if (algorithm.equalsIgnoreCase(RESIZE_DEFAULT.getValue())) {
|
||||||
@ -176,6 +177,25 @@ public class ResizeImage extends AbstractProcessor {
|
|||||||
return;
|
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)) {
|
try (final OutputStream out = session.write(flowFile)) {
|
||||||
final Image scaledImage = image.getScaledInstance(width, height, hints);
|
final Image scaledImage = image.getScaledInstance(width, height, hints);
|
||||||
final BufferedImage scaledBufferedImg;
|
final BufferedImage scaledBufferedImg;
|
||||||
@ -207,4 +227,12 @@ public class ResizeImage extends AbstractProcessor {
|
|||||||
session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
|
session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
|
||||||
session.transfer(flowFile, REL_SUCCESS);
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -157,4 +157,48 @@ public class TestResizeImage {
|
|||||||
final File out = new File("target/mspaint-8x10resized.png");
|
final File out = new File("target/mspaint-8x10resized.png");
|
||||||
ImageIO.write(img, "PNG", out);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user