From 8f942922fdc6274f37a7f25a84fa2cb1ac103097 Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Sun, 28 Jun 2020 11:50:17 +0200 Subject: [PATCH] #547 BMPImageWriterSpi now only claims to write TYPE_4BYTE_ABGR, and registers with low pri. Better exception message for other image types. --- .../plugins/bmp/BMPImageWriterSpi.java | 25 ++++++++++--- .../imageio/plugins/bmp/BMPMetadata.java | 2 +- .../imageio/plugins/bmp/DIBImageWriter.java | 13 ++++--- .../imageio/plugins/bmp/ICOImageWriter.java | 4 +-- .../plugins/bmp/ICOImageWriterSpi.java | 8 +++-- .../plugins/bmp/BMPImageWriterTest.java | 33 +++++++++++++++++ .../plugins/bmp/ICOImageWriterTest.java | 36 +++++++++++++++++++ .../imageio/util/ImageWriterAbstractTest.java | 6 ++-- 8 files changed, 108 insertions(+), 19 deletions(-) create mode 100644 imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterTest.java create mode 100644 imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterTest.java diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterSpi.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterSpi.java index 9f1c1de8..070c75d9 100644 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterSpi.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterSpi.java @@ -33,9 +33,13 @@ package com.twelvemonkeys.imageio.plugins.bmp; import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase; import javax.imageio.ImageTypeSpecifier; -import java.io.IOException; +import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.spi.ServiceRegistry; +import java.awt.image.BufferedImage; import java.util.Locale; +import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName; + /** * BMPImageWriterSpi */ @@ -45,17 +49,28 @@ public final class BMPImageWriterSpi extends ImageWriterSpiBase { } @Override - public boolean canEncodeImage(final ImageTypeSpecifier type) { - return true; + public void onRegistration(ServiceRegistry registry, Class category) { + // Make sure we register BEHIND the built-in BMP writer + ImageWriterSpi sunSpi = lookupProviderByName(registry, "com.sun.imageio.plugins.bmp.BMPImageWriterSpi", ImageWriterSpi.class); + + if (sunSpi != null && sunSpi.getVendorName() != null) { + registry.setOrdering((Class) category, sunSpi, this); + } } @Override - public BMPImageWriter createWriterInstance(final Object extension) throws IOException { + public boolean canEncodeImage(final ImageTypeSpecifier type) { + // TODO: Support more types, as time permits. + return type.getBufferedImageType() == BufferedImage.TYPE_4BYTE_ABGR; + } + + @Override + public BMPImageWriter createWriterInstance(final Object extension) { return new BMPImageWriter(this); } @Override public String getDescription(final Locale locale) { - return "Windows Device Independent Bitmap Format (BMP) Reader"; + return "Windows Device Independent Bitmap Format (BMP) Writer"; } } diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPMetadata.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPMetadata.java index f1cd5cee..8f7bb80a 100755 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPMetadata.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPMetadata.java @@ -40,7 +40,7 @@ import javax.imageio.metadata.IIOMetadataNode; * BMPMetadata. */ final class BMPMetadata extends AbstractMetadata { - /** We return metadata in the exact same form as the JRE built-in, to be compatible with the DIBImageWriter. */ + /** We return metadata in the exact same form as the JRE built-in, to be compatible with the BMPImageWriter. */ public static final String nativeMetadataFormatName = "javax_imageio_bmp_1.0"; private final DIBHeader header; diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/DIBImageWriter.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/DIBImageWriter.java index 8f48be1f..f9a507cb 100644 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/DIBImageWriter.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/DIBImageWriter.java @@ -43,6 +43,7 @@ import java.nio.ByteOrder; * DIBImageWriter */ abstract class DIBImageWriter extends ImageWriterBase { + DIBImageWriter(ImageWriterSpi provider) { super(provider); } @@ -50,7 +51,9 @@ abstract class DIBImageWriter extends ImageWriterBase { @Override public void setOutput(Object output) { super.setOutput(output); - imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN); + if (imageOutput != null) { + imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN); + } } void writeDIBHeader(int infoHeaderSize, int width, int height, boolean isTopDown, int pixelSize, int compression) throws IOException { @@ -82,9 +85,8 @@ abstract class DIBImageWriter extends ImageWriterBase { } void writeUncompressed(boolean isTopDown, BufferedImage img, int height, int width) throws IOException { - // TODO: Fix if (img.getType() != BufferedImage.TYPE_4BYTE_ABGR) { - throw new IIOException("Blows!"); + throw new IIOException("Only TYPE_4BYTE_ABGR supported"); } // Support @@ -93,12 +95,13 @@ abstract class DIBImageWriter extends ImageWriterBase { // - TODO: Packed/DirectColorModel (16 and 32 bit, BI_BITFIELDS, BI_PNG? BI_JPEG?) Raster raster = img.getRaster(); - WritableRaster rowRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, 1, width * 4, 4, new int[]{2, 1, 0, 3}, null); + WritableRaster rowRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, 1, width * 4, 4, new int[] {2, 1, 0, 3}, null); byte[] row = ((DataBufferByte) rowRaster.getDataBuffer()).getData(); + final int[] bandList = {2, 1, 0, 3}; for (int i = 0; i < height; i++) { int line = isTopDown ? i : height - 1 - i; - rowRaster.setDataElements(0, 0, raster.createChild(0, line, width, 1, 0, 0, new int[]{2, 1, 0, 3})); + rowRaster.setDataElements(0, 0, raster.createChild(0, line, width, 1, 0, 0, bandList)); imageOutput.write(row); diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriter.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriter.java index 8a47b90c..1f8709c3 100644 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriter.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriter.java @@ -143,7 +143,7 @@ public final class ICOImageWriter extends DIBImageWriter { } if (image.hasRaster()) { - throw new UnsupportedOperationException("image has a Raster"); + throw new UnsupportedOperationException("Raster not supported"); } if (sequenceIndex >= INITIAL_ENTRY_COUNT) { @@ -155,7 +155,7 @@ public final class ICOImageWriter extends DIBImageWriter { ColorModel colorModel = image.getRenderedImage().getColorModel(); // TODO: The output size may depend on the param (subsampling, source region, etc) - if (width > ICO_MAX_DIMENSION && height > ICO_MAX_DIMENSION) { + if (width > ICO_MAX_DIMENSION || height > ICO_MAX_DIMENSION) { throw new IIOException(String.format("ICO maximum width or height (%d) exceeded", ICO_MAX_DIMENSION)); } diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterSpi.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterSpi.java index 2dbbe4b3..bb216808 100644 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterSpi.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterSpi.java @@ -33,7 +33,7 @@ package com.twelvemonkeys.imageio.plugins.bmp; import com.twelvemonkeys.imageio.spi.ImageWriterSpiBase; import javax.imageio.ImageTypeSpecifier; -import java.io.IOException; +import java.awt.image.BufferedImage; import java.util.Locale; /** @@ -46,11 +46,13 @@ public final class ICOImageWriterSpi extends ImageWriterSpiBase { @Override public boolean canEncodeImage(final ImageTypeSpecifier type) { - return true; + // TODO: Support more types, as time permits. + // NOTE: We do support more types, if writing using PNG compression + return type.getBufferedImageType() == BufferedImage.TYPE_4BYTE_ABGR; } @Override - public ICOImageWriter createWriterInstance(final Object extension) throws IOException { + public ICOImageWriter createWriterInstance(final Object extension) { return new ICOImageWriter(this); } diff --git a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterTest.java b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterTest.java new file mode 100644 index 00000000..2fc97201 --- /dev/null +++ b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageWriterTest.java @@ -0,0 +1,33 @@ +package com.twelvemonkeys.imageio.plugins.bmp; + +import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest; + +import javax.imageio.ImageWriter; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.util.Arrays; +import java.util.List; + +/** + * BMPImageWriterTest. + * + * @author Harald Kuhr + * @author last modified by : harald.kuhr$ + * @version : BMPImageWriterTest.java,v 1.0 25/06/2020 harald.kuhr Exp$ + */ +public class BMPImageWriterTest extends ImageWriterAbstractTest { + + private final BMPImageWriterSpi provider = new BMPImageWriterSpi(); + + @Override + protected ImageWriter createImageWriter() { + return provider.createWriterInstance(null); + } + + @Override + protected List getTestData() { + return Arrays.asList( + new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR) + ); + } +} \ No newline at end of file diff --git a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterTest.java b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterTest.java new file mode 100644 index 00000000..ab6b19e6 --- /dev/null +++ b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageWriterTest.java @@ -0,0 +1,36 @@ +package com.twelvemonkeys.imageio.plugins.bmp; + +import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest; + +import javax.imageio.ImageWriter; +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.util.Arrays; +import java.util.List; + +/** + * ICOImageWriterTest. + * + * @author Harald Kuhr + * @author last modified by : harald.kuhr$ + * @version : ICOImageWriterTest.java,v 1.0 25/06/2020 harald.kuhr Exp$ + */ +public class ICOImageWriterTest extends ImageWriterAbstractTest { + private final ICOImageWriterSpi provider = new ICOImageWriterSpi(); + + @Override + protected ImageWriter createImageWriter() { + return provider.createWriterInstance(null); + } + + @Override + protected List getTestData() { + return Arrays.asList( + new BufferedImage(8, 8, BufferedImage.TYPE_4BYTE_ABGR), + new BufferedImage(16, 16, BufferedImage.TYPE_4BYTE_ABGR), + new BufferedImage(32, 32, BufferedImage.TYPE_4BYTE_ABGR), + new BufferedImage(64, 64, BufferedImage.TYPE_4BYTE_ABGR), + new BufferedImage(128, 128, BufferedImage.TYPE_4BYTE_ABGR) + ); + } +} \ No newline at end of file diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageWriterAbstractTest.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageWriterAbstractTest.java index 729c5cc2..71b30237 100755 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageWriterAbstractTest.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageWriterAbstractTest.java @@ -129,7 +129,7 @@ public abstract class ImageWriterAbstractTest { writer.write(drawSomething((BufferedImage) testData)); } catch (IOException e) { - fail(e.getMessage()); + throw new AssertionError(e.getMessage(), e); } assertTrue("No image data written", buffer.size() > 0); @@ -149,10 +149,10 @@ public abstract class ImageWriterAbstractTest { catch(IllegalArgumentException ignore) { } catch (IOException e) { - fail(e.getMessage()); + throw new AssertionError(e.getMessage(), e); } - assertTrue("Image data written", buffer.size() == 0); + assertEquals("Image data written", 0, buffer.size()); } @Test(expected = IllegalStateException.class)