mirror of https://github.com/apache/nifi.git
NIFI-6686 - Improved exception handling in ResizeImage processor.
This closes #3922. Signed-off-by: Mark Payne <markap14@hotmail.com>
This commit is contained in:
parent
452ca98c29
commit
29e7adb2b4
|
@ -51,7 +51,6 @@ import org.apache.nifi.processor.ProcessContext;
|
|||
import org.apache.nifi.processor.ProcessSession;
|
||||
import org.apache.nifi.processor.Relationship;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.io.StreamCallback;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.util.StopWatch;
|
||||
|
||||
|
@ -150,57 +149,62 @@ public class ResizeImage extends AbstractProcessor {
|
|||
}
|
||||
|
||||
final StopWatch stopWatch = new StopWatch(true);
|
||||
try {
|
||||
flowFile = session.write(flowFile, new StreamCallback() {
|
||||
@Override
|
||||
public void process(final InputStream rawIn, final OutputStream out) throws IOException {
|
||||
try (final BufferedInputStream in = new BufferedInputStream(rawIn)) {
|
||||
final ImageInputStream iis = ImageIO.createImageInputStream(in);
|
||||
if (iis == null) {
|
||||
throw new ProcessException("FlowFile is not in a valid format");
|
||||
}
|
||||
|
||||
final Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
|
||||
if (!readers.hasNext()) {
|
||||
throw new ProcessException("FlowFile is not in a valid format");
|
||||
}
|
||||
final BufferedImage image;
|
||||
final String formatName;
|
||||
|
||||
final ImageReader reader = readers.next();
|
||||
final String formatName = reader.getFormatName();
|
||||
reader.setInput(iis, true);
|
||||
final BufferedImage image = reader.read(0);
|
||||
|
||||
final Image scaledImage = image.getScaledInstance(width, height, hints);
|
||||
final BufferedImage scaledBufferedImg;
|
||||
if (scaledImage instanceof BufferedImage) {
|
||||
scaledBufferedImg = (BufferedImage) scaledImage;
|
||||
} else {
|
||||
// Determine image type, since calling image.getType may return 0
|
||||
int imageType = BufferedImage.TYPE_INT_ARGB;
|
||||
if(image.getTransparency() == Transparency.OPAQUE) {
|
||||
imageType = BufferedImage.TYPE_INT_RGB;
|
||||
}
|
||||
|
||||
scaledBufferedImg = new BufferedImage(scaledImage.getWidth(null), scaledImage.getHeight(null), imageType);
|
||||
final Graphics2D graphics = scaledBufferedImg.createGraphics();
|
||||
try {
|
||||
graphics.drawImage(scaledImage, 0, 0, null);
|
||||
} finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
ImageIO.write(scaledBufferedImg, formatName, out);
|
||||
}
|
||||
try (final InputStream rawIn = session.read(flowFile)) {
|
||||
try (final BufferedInputStream in = new BufferedInputStream(rawIn)) {
|
||||
final ImageInputStream iis = ImageIO.createImageInputStream(in);
|
||||
if (iis == null) {
|
||||
throw new ProcessException("FlowFile is not in a valid format");
|
||||
}
|
||||
});
|
||||
|
||||
session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
|
||||
session.transfer(flowFile, REL_SUCCESS);
|
||||
} catch (final ProcessException pe) {
|
||||
getLogger().error("Failed to resize {} due to {}", new Object[] { flowFile, pe });
|
||||
final Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
|
||||
if (!readers.hasNext()) {
|
||||
throw new ProcessException("FlowFile is not in a valid format");
|
||||
}
|
||||
|
||||
final ImageReader reader = readers.next();
|
||||
formatName = reader.getFormatName();
|
||||
reader.setInput(iis, true);
|
||||
image = reader.read(0);
|
||||
}
|
||||
} catch (final IOException | IllegalArgumentException | ProcessException ex) {
|
||||
getLogger().error("Failed to read {} due to {}", new Object[] { flowFile, ex });
|
||||
session.transfer(flowFile, REL_FAILURE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try (final OutputStream out = session.write(flowFile)) {
|
||||
final Image scaledImage = image.getScaledInstance(width, height, hints);
|
||||
final BufferedImage scaledBufferedImg;
|
||||
if (scaledImage instanceof BufferedImage) {
|
||||
scaledBufferedImg = (BufferedImage) scaledImage;
|
||||
} else {
|
||||
// Determine image type, since calling image.getType may return 0
|
||||
int imageType = BufferedImage.TYPE_INT_ARGB;
|
||||
if(image.getTransparency() == Transparency.OPAQUE) {
|
||||
imageType = BufferedImage.TYPE_INT_RGB;
|
||||
}
|
||||
|
||||
scaledBufferedImg = new BufferedImage(scaledImage.getWidth(null), scaledImage.getHeight(null), imageType);
|
||||
final Graphics2D graphics = scaledBufferedImg.createGraphics();
|
||||
try {
|
||||
graphics.drawImage(scaledImage, 0, 0, null);
|
||||
} finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
ImageIO.write(scaledBufferedImg, formatName, out);
|
||||
} catch (final IOException | NegativeArraySizeException ex) {
|
||||
getLogger().error("Failed to write {} due to {}", new Object[] { flowFile, ex });
|
||||
session.transfer(flowFile, REL_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
session.getProvenanceReporter().modifyContent(flowFile, stopWatch.getElapsed(TimeUnit.MILLISECONDS));
|
||||
session.transfer(flowFile, REL_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.io.IOException;
|
|||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestResizeImage {
|
||||
|
||||
|
@ -71,6 +72,60 @@ public class TestResizeImage {
|
|||
ImageIO.write(img, "JPG", out);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadImageFailure() 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_FAST);
|
||||
|
||||
runner.enqueue(Paths.get("src/test/resources/peppers.jpg"));
|
||||
runner.run();
|
||||
|
||||
// Should return REL_FAILURE and log an IllegalArgumentException
|
||||
runner.assertAllFlowFilesTransferred(ResizeImage.REL_FAILURE, 1);
|
||||
assertEquals(1, runner.getLogger().getErrorMessages().size());
|
||||
assertEquals(4, runner.getLogger().getErrorMessages().get(0).getArgs().length);
|
||||
assertTrue(runner.getLogger().getErrorMessages().get(0).getArgs()[3].toString()
|
||||
.startsWith("java.lang.IllegalArgumentException"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonImageInput() 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_FAST);
|
||||
|
||||
runner.enqueue(Paths.get("src/test/resources/notImage.txt"));
|
||||
runner.run();
|
||||
|
||||
// Should return REL_FAILURE and log a ProcessException
|
||||
runner.assertAllFlowFilesTransferred(ResizeImage.REL_FAILURE, 1);
|
||||
assertEquals(1, runner.getLogger().getErrorMessages().size());
|
||||
assertEquals(4, runner.getLogger().getErrorMessages().get(0).getArgs().length);
|
||||
assertTrue(runner.getLogger().getErrorMessages().get(0).getArgs()[3].toString()
|
||||
.startsWith("org.apache.nifi.processor.exception.ProcessException"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteFailure() throws IOException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(new ResizeImage());
|
||||
runner.setProperty(ResizeImage.IMAGE_HEIGHT, "1000000");
|
||||
runner.setProperty(ResizeImage.IMAGE_WIDTH, "1000000");
|
||||
runner.setProperty(ResizeImage.SCALING_ALGORITHM, ResizeImage.RESIZE_SMOOTH);
|
||||
|
||||
runner.enqueue(Paths.get("src/test/resources/photoshop-8x12-32colors-alpha.gif"));
|
||||
runner.run();
|
||||
|
||||
// Should return REL_FAILURE and log a NegativeArraySizeException
|
||||
runner.assertAllFlowFilesTransferred(ResizeImage.REL_FAILURE, 1);
|
||||
assertEquals(1, runner.getLogger().getErrorMessages().size());
|
||||
assertEquals(4, runner.getLogger().getErrorMessages().get(0).getArgs().length);
|
||||
assertTrue(runner.getLogger().getErrorMessages().get(0).getArgs()[3].toString()
|
||||
.startsWith("java.lang.NegativeArraySizeException"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnlarge() throws IOException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(new ResizeImage());
|
||||
|
@ -92,7 +147,6 @@ public class TestResizeImage {
|
|||
ImageIO.write(img, "PNG", out);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testResizePNG() throws IOException {
|
||||
final TestRunner runner = TestRunners.newTestRunner(new ResizeImage());
|
||||
|
|
|
@ -1 +1 @@
|
|||
This file is not an image and is used for testing the image metadata extractor.
|
||||
This file is not an image and is used for testing the image metadata extractor and resizer.
|
Binary file not shown.
After Width: | Height: | Size: 928 KiB |
Loading…
Reference in New Issue