#547 BMPImageWriterSpi now only claims to write TYPE_4BYTE_ABGR, and registers with low pri.

Better exception message for other image types.
This commit is contained in:
Harald Kuhr 2020-06-28 11:50:17 +02:00
parent db5635e844
commit 8f942922fd
8 changed files with 108 additions and 19 deletions

View File

@ -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<ImageWriterSpi>) 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";
}
}

View File

@ -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;

View File

@ -43,6 +43,7 @@ import java.nio.ByteOrder;
* DIBImageWriter
*/
abstract class DIBImageWriter extends ImageWriterBase {
DIBImageWriter(ImageWriterSpi provider) {
super(provider);
}
@ -50,8 +51,10 @@ abstract class DIBImageWriter extends ImageWriterBase {
@Override
public void setOutput(Object output) {
super.setOutput(output);
if (imageOutput != null) {
imageOutput.setByteOrder(ByteOrder.LITTLE_ENDIAN);
}
}
void writeDIBHeader(int infoHeaderSize, int width, int height, boolean isTopDown, int pixelSize, int compression) throws IOException {
switch (infoHeaderSize) {
@ -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
@ -95,10 +97,11 @@ abstract class DIBImageWriter extends ImageWriterBase {
Raster raster = img.getRaster();
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);

View File

@ -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));
}

View File

@ -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);
}

View File

@ -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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @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<? extends RenderedImage> getTestData() {
return Arrays.asList(
new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR)
);
}
}

View File

@ -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 <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @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<? extends RenderedImage> 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)
);
}
}

View File

@ -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)