diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java index 41fc6e4a8..8ee862cc4 100644 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriter.java @@ -250,7 +250,7 @@ else if (sampleModel instanceof MultiPixelPackedSampleModel) { ListenerDelegate listener = new ListenerDelegate(imageIndex); jpegWriter.addIIOWriteProgressListener(listener); jpegWriter.addIIOWriteWarningListener(listener); - jpegWriter.write(null, image, copyParams(param, jpegWriter)); + jpegWriter.write(null, imageOnly(image), copyParams(param, jpegWriter)); } finally { jpegWriter.dispose(); @@ -285,6 +285,17 @@ else if (sampleModel instanceof MultiPixelPackedSampleModel) { return nextIFDPointerOffset; } + private IIOImage imageOnly(final IIOImage image) { + if (image.getMetadata() == null && image.getNumThumbnails() == 0) { + // Just image data here, no need to copy + return image; + } + + return image.hasRaster() + ? new IIOImage(image.getRaster(), null, null) + : new IIOImage(image.getRenderedImage(), null, null); + } + // TODO: Candidate util method private ImageWriteParam copyParams(final ImageWriteParam param, final ImageWriter writer) { if (param == null) { diff --git a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriterTest.java b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriterTest.java index a74a9e705..f4d1dd4cd 100644 --- a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriterTest.java +++ b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageWriterTest.java @@ -34,6 +34,7 @@ import com.twelvemonkeys.imageio.metadata.Entry; import com.twelvemonkeys.imageio.metadata.tiff.Rational; import com.twelvemonkeys.imageio.metadata.tiff.TIFF; +import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry; import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader; import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream; import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; @@ -73,6 +74,8 @@ import java.util.Arrays; import java.util.List; +import static com.twelvemonkeys.imageio.metadata.tiff.TIFF.TAG_X_RESOLUTION; +import static com.twelvemonkeys.imageio.metadata.tiff.TIFF.TAG_Y_RESOLUTION; import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataFormat.SUN_NATIVE_IMAGE_METADATA_FORMAT_NAME; import static com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadataTest.createTIFFFieldNode; import static com.twelvemonkeys.imageio.util.ImageReaderAbstractTest.assertRGBEquals; @@ -133,8 +136,8 @@ public void testWriteWithCustomResolutionNative() throws IOException { customMeta.appendChild(ifd); createTIFFFieldNode(ifd, TIFF.TAG_RESOLUTION_UNIT, TIFF.TYPE_SHORT, resolutionUnitValue); - createTIFFFieldNode(ifd, TIFF.TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue); - createTIFFFieldNode(ifd, TIFF.TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue); + createTIFFFieldNode(ifd, TAG_X_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue); + createTIFFFieldNode(ifd, TAG_Y_RESOLUTION, TIFF.TYPE_RATIONAL, resolutionValue); metadata.mergeTree(nativeFormat, customMeta); @@ -153,11 +156,11 @@ public void testWriteWithCustomResolutionNative() throws IOException { assertNotNull(resolutionUnit); assertEquals(resolutionUnitValue, ((Number) resolutionUnit.getValue()).intValue()); - Entry xResolution = ifds.getEntryById(TIFF.TAG_X_RESOLUTION); + Entry xResolution = ifds.getEntryById(TAG_X_RESOLUTION); assertNotNull(xResolution); assertEquals(resolutionValue, xResolution.getValue()); - Entry yResolution = ifds.getEntryById(TIFF.TAG_Y_RESOLUTION); + Entry yResolution = ifds.getEntryById(TAG_Y_RESOLUTION); assertNotNull(yResolution); assertEquals(resolutionValue, yResolution.getValue()); } @@ -272,11 +275,11 @@ public void testWriteWithCustomResolutionStandard() throws IOException { assertNotNull(resolutionUnit); assertEquals(resolutionUnitValue, ((Number) resolutionUnit.getValue()).intValue()); - Entry xResolution = ifds.getEntryById(TIFF.TAG_X_RESOLUTION); + Entry xResolution = ifds.getEntryById(TAG_X_RESOLUTION); assertNotNull(xResolution); assertEquals(expectedResolutionValue, xResolution.getValue()); - Entry yResolution = ifds.getEntryById(TIFF.TAG_Y_RESOLUTION); + Entry yResolution = ifds.getEntryById(TAG_Y_RESOLUTION); assertNotNull(yResolution); assertEquals(expectedResolutionValue, yResolution.getValue()); } @@ -1358,6 +1361,25 @@ public void testWriteBinaryPalette() throws IOException { assertEquals(TIFFBaseline.PHOTOMETRIC_PALETTE, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue()); } + @Test + public void testWriteJPEGCompressedShouldNotPassMetadata() throws IOException { + BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_3BYTE_BGR); + + try (ImageOutputStream output = new NullImageOutputStream()) { + ImageWriter imageWriter = createWriter(); + imageWriter.setOutput(output); + + ImageWriteParam param = imageWriter.getDefaultWriteParam(); + param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); + param.setCompressionType("JPEG"); + + // From #815 + // Prior to fix, this would throw IIOException: Metadata components != number of destination bands + // (empty metadata defaults to 1 channel gray, while image data is 3 channel BGR) + imageWriter.write(null, new IIOImage(image, null, new TIFFImageMetadata()), param); + } + } + @Test public void testShortOverflowHuge() throws IOException { int width = 34769;