diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/HeaderWriter.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/HeaderWriter.java index 1b80a598..d36c3c20 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/HeaderWriter.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/HeaderWriter.java @@ -30,8 +30,6 @@ package com.twelvemonkeys.imageio.plugins.pnm; -import com.twelvemonkeys.imageio.ImageWriterBase; - import org.w3c.dom.NodeList; import javax.imageio.IIOImage; @@ -40,7 +38,7 @@ import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; -import java.awt.image.DataBuffer; +import java.awt.image.*; import java.io.IOException; import java.util.Locale; @@ -53,11 +51,7 @@ abstract class HeaderWriter { this.imageOutput = imageOutput; } - public static void write(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException { - createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider()); - } - - private static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) { + static HeaderWriter createHeaderWriter(final String formatName, final ImageOutputStream imageOutput) { if (formatName.equals("pam")) { return new PAMHeaderWriter(imageOutput); } @@ -83,25 +77,36 @@ abstract class HeaderWriter { return image.hasRaster() ? image.getRaster().getNumBands() : image.getRenderedImage().getSampleModel().getNumBands(); } + protected final SampleModel getSampleModel(final IIOImage image) { + return image.hasRaster() ? image.getRaster().getSampleModel() : image.getRenderedImage().getSampleModel(); + } + protected int getMaxVal(final IIOImage image) { int transferType = getTransferType(image); - if (transferType == DataBuffer.TYPE_BYTE) { - return PNM.MAX_VAL_8BIT; - } - else if (transferType == DataBuffer.TYPE_USHORT) { - return PNM.MAX_VAL_16BIT; - } -// else if (transferType == DataBuffer.TYPE_INT) { - // TODO: Support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB) -// } - else { - throw new IllegalArgumentException("Unsupported data type: " + transferType); + switch (transferType) { + case DataBuffer.TYPE_BYTE: + return PNM.MAX_VAL_8BIT; + + case DataBuffer.TYPE_USHORT: + return PNM.MAX_VAL_16BIT; + + case DataBuffer.TYPE_INT: + // We support TYPE_INT through conversion, if number of channels is 3 or 4 (TYPE_INT_RGB, TYPE_INT_ARGB) + SampleModel sampleModel = getSampleModel(image); + int numBands = sampleModel.getNumBands(); + + if (sampleModel instanceof SinglePixelPackedSampleModel && (numBands == 3 || numBands == 4)) { + return PNM.MAX_VAL_8BIT; + } + // ...else fall through + default: + throw new IllegalArgumentException("Unsupported data type: " + transferType); } } protected final int getTransferType(final IIOImage image) { - return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType(); + return image.hasRaster() ? image.getRaster().getTransferType() : image.getRenderedImage().getSampleModel().getTransferType(); } protected final void writeComments(final IIOMetadata metadata, final ImageWriterSpi provider) throws IOException { @@ -120,5 +125,4 @@ abstract class HeaderWriter { } } } - } diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMHeaderWriter.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMHeaderWriter.java index 6e2fcc0b..0d7a64ea 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMHeaderWriter.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMHeaderWriter.java @@ -30,6 +30,8 @@ package com.twelvemonkeys.imageio.plugins.pnm; +import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; + import javax.imageio.IIOImage; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; @@ -44,6 +46,8 @@ final class PAMHeaderWriter extends HeaderWriter { @Override public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException { + TupleType tupleType = tupleType(image); + // Write PAM magic imageOutput.writeShort(PNM.PAM); imageOutput.write('\n'); @@ -52,12 +56,19 @@ final class PAMHeaderWriter extends HeaderWriter { // Write width/height and number of channels imageOutput.write(String.format("WIDTH %s\nHEIGHT %s\n", getWidth(image), getHeight(image)).getBytes(UTF_8)); imageOutput.write(String.format("DEPTH %s\n", getNumBands(image)).getBytes(UTF_8)); - - // TODO: maxSample (8 or16 bit) imageOutput.write(String.format("MAXVAL %s\n", getMaxVal(image)).getBytes(UTF_8)); - - // TODO: Determine tuple type based on input color model and image data - TupleType tupleType = getNumBands(image) > 3 ? TupleType.RGB_ALPHA : TupleType.RGB; imageOutput.write(String.format("TUPLTYPE %s\nENDHDR\n", tupleType).getBytes(UTF_8)); } + + private static TupleType tupleType(IIOImage image) { + TupleType tupleType = image.hasRaster() + ? TupleType.forPAM(image.getRaster()) + : TupleType.forPAM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage())); + + if (tupleType == null) { + throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage())); + } + + return tupleType; + } } diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpi.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpi.java index e0342b0f..79453287 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpi.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpi.java @@ -45,12 +45,11 @@ public final class PAMImageWriterSpi extends ImageWriterSpiBase { super(new PAMProviderInfo()); } - public boolean canEncodeImage(final ImageTypeSpecifier pType) { - // TODO: FixMe - return true; + public boolean canEncodeImage(final ImageTypeSpecifier type) { + return TupleType.forPAM(type) != null; } - public ImageWriter createWriterInstance(final Object pExtension) { + public ImageWriter createWriterInstance(final Object extension) { return new PNMImageWriter(this); } diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PFMHeaderParser.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PFMHeaderParser.java index c145f90a..33214f68 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PFMHeaderParser.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PFMHeaderParser.java @@ -69,7 +69,7 @@ final class PFMHeaderParser extends HeaderParser { public PNMHeader parse() throws IOException { int width = 0; int height = 0; - float maxSample = tupleType == TupleType.BLACKANDWHITE_WHITE_IS_ZERO ? 1 : 0; // PBM has no maxSample line + float maxSample = 0; List comments = new ArrayList<>(); @@ -77,7 +77,7 @@ final class PFMHeaderParser extends HeaderParser { String line = input.readLine(); if (line == null) { - throw new IIOException("Unexpeced end of stream"); + throw new IIOException("Unexpected end of stream"); } int commentStart = line.indexOf('#'); diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMHeaderWriter.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMHeaderWriter.java index 3b1a60b8..c213dfca 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMHeaderWriter.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMHeaderWriter.java @@ -30,6 +30,8 @@ package com.twelvemonkeys.imageio.plugins.pnm; +import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; + import javax.imageio.IIOImage; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.stream.ImageOutputStream; @@ -45,8 +47,7 @@ final class PNMHeaderWriter extends HeaderWriter { @Override public void writeHeader(final IIOImage image, final ImageWriterSpi provider) throws IOException { // Write P4/P5/P6 magic (Support only RAW formats for now; if we are to support PLAIN formats, pass parameter) - // TODO: Determine PBM, PBM or PPM based on input color model and image data? - short type = PNM.PPM; + short type = type(image); imageOutput.writeShort(type); imageOutput.write('\n'); @@ -61,4 +62,35 @@ final class PNMHeaderWriter extends HeaderWriter { imageOutput.write(String.format("%s\n", getMaxVal(image)).getBytes(UTF_8)); } } + + private short type(IIOImage image) { + TupleType type = tupleType(image); + + if (type != null) { + switch (type) { + case BLACKANDWHITE_WHITE_IS_ZERO: + return PNM.PBM; + case GRAYSCALE: + return PNM.PGM; + case RGB: + return PNM.PPM; + default: + // fall through... + } + } + + throw new IllegalArgumentException("Unsupported tupleType: " + type); + } + + private static TupleType tupleType(IIOImage image) { + TupleType tupleType = image.hasRaster() + ? TupleType.forPNM(image.getRaster()) + : TupleType.forPNM(ImageTypeSpecifiers.createFromRenderedImage(image.getRenderedImage())); + + if (tupleType == null) { + throw new IllegalArgumentException("Unknown TupleType for " + (image.hasRaster() ? image.getRaster() : image.getRenderedImage())); + } + + return tupleType; + } } diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriter.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriter.java index a5388e35..2efa9aee 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriter.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriter.java @@ -31,14 +31,17 @@ package com.twelvemonkeys.imageio.plugins.pnm; import com.twelvemonkeys.imageio.ImageWriterBase; +import com.twelvemonkeys.imageio.util.RasterUtils; -import javax.imageio.*; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; import javax.imageio.metadata.IIOMetadata; import javax.imageio.spi.ImageWriterSpi; -import java.awt.image.BufferedImage; -import java.awt.image.DataBuffer; -import java.awt.image.Raster; -import java.awt.image.SampleModel; +import javax.imageio.stream.ImageOutputStream; +import java.awt.image.*; import java.io.File; import java.io.IOException; @@ -69,7 +72,7 @@ public final class PNMImageWriter extends ImageWriterBase { // TODO: Issue warning if streamMetadata is non-null? // TODO: Issue warning if IIOImage contains thumbnails or other data we can't store? - HeaderWriter.write(image, this, imageOutput); + writeHeader(image, this, imageOutput); // TODO: Sub region // TODO: Subsampling @@ -80,16 +83,20 @@ public final class PNMImageWriter extends ImageWriterBase { processImageComplete(); } + private void writeHeader(final IIOImage image, final ImageWriterBase writer, final ImageOutputStream imageOutput) throws IOException { + HeaderWriter.createHeaderWriter(writer.getFormatName(), imageOutput).writeHeader(image, writer.getOriginatingProvider()); + } + private void writeImageData(final IIOImage image) throws IOException { - // - dump data as is (or convert, if TYPE_INT_xxx) + // - dump data as is (or convert, if TYPE_INT_xxx // Enforce RGB/CMYK order for such data! // TODO: Loop over x/y tiles, using 0,0 is only valid for BufferedImage // TODO: PNM/PAM does not support tiling, we must iterate all tiles along the x-axis for each row we write Raster tile = image.hasRaster() ? image.getRaster() : image.getRenderedImage().getTile(0, 0); + tile = tile.getTransferType() == DataBuffer.TYPE_INT ? RasterUtils.asByteRaster(tile) : tile; SampleModel sampleModel = tile.getSampleModel(); - DataBuffer dataBuffer = tile.getDataBuffer(); int tileWidth = tile.getWidth(); diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpi.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpi.java index 315644d2..13d9075a 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpi.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpi.java @@ -48,12 +48,11 @@ public final class PNMImageWriterSpi extends ImageWriterSpiBase { super(new PNMProviderInfo()); } - public boolean canEncodeImage(final ImageTypeSpecifier pType) { - // TODO: FixMe: Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB - return true; + public boolean canEncodeImage(final ImageTypeSpecifier type) { + return TupleType.forPNM(type) != null; } - public ImageWriter createWriterInstance(final Object pExtension) { + public ImageWriter createWriterInstance(final Object extension) { return new PNMImageWriter(this); } diff --git a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/TupleType.java b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/TupleType.java index 7852b5eb..24c11e23 100755 --- a/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/TupleType.java +++ b/imageio/imageio-pnm/src/main/java/com/twelvemonkeys/imageio/plugins/pnm/TupleType.java @@ -30,7 +30,10 @@ package com.twelvemonkeys.imageio.plugins.pnm; +import javax.imageio.ImageTypeSpecifier; import java.awt.*; +import java.awt.color.*; +import java.awt.image.*; enum TupleType { // Official: @@ -80,4 +83,150 @@ enum TupleType { public boolean isValidMaxSample(int maxSample) { return maxSample >= minMaxSample && maxSample <= maxMaxSample; } + + + static TupleType forPNM(Raster raster) { + return filterPNM(forPAM(raster)); + } + + static TupleType forPNM(ImageTypeSpecifier type) { + return filterPNM(forPAM(type)); + } + + private static TupleType filterPNM(TupleType tupleType) { + if (tupleType == null) { + return null; + } + + switch (tupleType) { + case BLACKANDWHITE: + return BLACKANDWHITE_WHITE_IS_ZERO; + case GRAYSCALE: + case RGB: + return tupleType; + default: + return null; + } + } + + static TupleType forPAM(Raster raster) { + SampleModel sampleModel = raster.getSampleModel(); + switch (sampleModel.getTransferType()) { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_INT: + // B/W, Gray or RGB + int bands = sampleModel.getNumBands(); + + if (bands == 1 && sampleModel.getSampleSize(0) == 1) { + return TupleType.BLACKANDWHITE; + } + else if (bands == 2 && sampleModel.getSampleSize(0) == 1 && sampleModel.getSampleSize(1) == 1) { + return TupleType.BLACKANDWHITE_ALPHA; + } + + // We can only write 8 or 16 bits/band + if (!(sampleModel.getSampleSize(0) == 8 || sampleModel.getSampleSize(0) == 16)) { + return null; + } + for (int i = 1; i < bands; i++) { + if (sampleModel.getSampleSize(0) != sampleModel.getSampleSize(i)) { + return null; + } + } + + if (bands == 1) { + return TupleType.GRAYSCALE; + } + else if (bands == 2) { + return TupleType.GRAYSCALE_ALPHA; + } + else if (bands == 3) { + return TupleType.RGB; + } + else if (bands == 4) { + return TupleType.RGB_ALPHA; + } + // ...else fall through... + } + + return null; + } + + static TupleType forPAM(ImageTypeSpecifier type) { + // Support only 1 bit b/w, 8-16 bit gray and 8-16 bit/sample RGB + switch (type.getBufferedImageType()) { + // 1 bit b/w or b/w + a + case BufferedImage.TYPE_BYTE_BINARY: + switch (type.getNumBands()) { + case 1: + return type.getBitsPerBand(0) == 1 ? TupleType.BLACKANDWHITE : null; + case 2: + return type.getBitsPerBand(0) == 2 || type.getBitsPerBand(0) == 1 && type.getBitsPerBand(1) == 1 ? TupleType.BLACKANDWHITE_ALPHA : null; + default: + return null; + } + // Gray + case BufferedImage.TYPE_BYTE_GRAY: + case BufferedImage.TYPE_USHORT_GRAY: + return TupleType.GRAYSCALE; + // RGB + case BufferedImage.TYPE_3BYTE_BGR: + case BufferedImage.TYPE_INT_RGB: + case BufferedImage.TYPE_INT_BGR: + return TupleType.RGB; + // RGBA + case BufferedImage.TYPE_4BYTE_ABGR: + case BufferedImage.TYPE_4BYTE_ABGR_PRE: + case BufferedImage.TYPE_INT_ARGB: + case BufferedImage.TYPE_INT_ARGB_PRE: + return TupleType.RGB_ALPHA; + default: + // BYTE, USHORT or INT (packed) + switch (type.getSampleModel().getTransferType()) { + case DataBuffer.TYPE_BYTE: + case DataBuffer.TYPE_USHORT: + case DataBuffer.TYPE_INT: + // Gray or RGB + ColorModel colorModel = type.getColorModel(); + + if (!(colorModel instanceof IndexColorModel)) { + ColorSpace cs = colorModel.getColorSpace(); + + // We can only write 8 or 16 bits/band + int bands = type.getNumBands(); + if (!(type.getBitsPerBand(0) == 8 || type.getBitsPerBand(0) == 16)) { + return null; + } + for (int i = 1; i < bands; i++) { + if (type.getBitsPerBand(0) != type.getBitsPerBand(i)) { + return null; + } + } + + if (cs.getType() == ColorSpace.TYPE_GRAY && bands == 1) { + return TupleType.GRAYSCALE; + } + else if (cs.getType() == ColorSpace.TYPE_GRAY && colorModel.hasAlpha() && bands == 2) { + return TupleType.GRAYSCALE_ALPHA; + } + else if (cs.getType() == ColorSpace.TYPE_RGB && bands == 3) { + return TupleType.RGB; + } + else if (cs.getType() == ColorSpace.TYPE_RGB && colorModel.hasAlpha() && bands == 4) { + return TupleType.RGB_ALPHA; + } + else if (cs.getType() == ColorSpace.TYPE_CMYK && bands == 4) { + return TupleType.CMYK; + } + else if (cs.getType() == ColorSpace.TYPE_CMYK && colorModel.hasAlpha() && bands == 5) { + return TupleType.CMYK_ALPHA; + } + // ...else fall through... + } + } + } + + return null; + } } diff --git a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpiTest.java b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpiTest.java index 1befecfb..f833ee84 100644 --- a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpiTest.java +++ b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterSpiTest.java @@ -30,15 +30,23 @@ package com.twelvemonkeys.imageio.plugins.pnm; +import com.twelvemonkeys.imageio.color.ColorSpaces; + import org.junit.Test; +import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageWriterSpi; +import java.awt.*; +import java.awt.color.*; +import java.awt.image.*; import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists; import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * PAMImageWriterSpiTest. @@ -65,4 +73,85 @@ public class PAMImageWriterSpiTest { public void getOutputTypes() { assertNotNull(spi.getOutputTypes()); } + + @Test + public void canEncodeImageBinary() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY))); + } + + @Test + public void canNotEncodeImageIndexed() { + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED))); + } + + @Test + public void canEncodeImageGray() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY))); + } + + @Test + public void canEncodeImageGrayAlpha() { + ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1)))); + } + + @Test + public void canEncodeImageRGB() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR))); + } + + @Test + public void canEncodeImageARGB() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE))); + } + + @Test + public void canEncodeImageCMYK() { + ComponentColorModel cmykByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykByte, cmykByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel cmykUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykUShort, cmykUShort.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel cmykAlphaByte = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaByte, cmykAlphaByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel cmykAlphaUShort = new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT); + assertTrue(spi.canEncodeImage(new ImageTypeSpecifier(cmykAlphaUShort, cmykAlphaUShort.createCompatibleSampleModel(1, 1)))); + } + + @Test + public void canNotEncodeImageNonGrayOrRGB() { + ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1)))); + } } \ No newline at end of file diff --git a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterTest.java b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterTest.java new file mode 100644 index 00000000..1785c971 --- /dev/null +++ b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PAMImageWriterTest.java @@ -0,0 +1,37 @@ +package com.twelvemonkeys.imageio.plugins.pnm; + +import com.twelvemonkeys.imageio.color.ColorSpaces; +import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest; + +import javax.imageio.spi.ImageWriterSpi; +import java.awt.*; +import java.awt.color.*; +import java.awt.image.*; +import java.util.Arrays; +import java.util.List; + +public class PAMImageWriterTest extends ImageWriterAbstractTest { + // NOTE: It's the same writer, however, the different SPI configures PAM mode, and enables extra formats + @Override + protected ImageWriterSpi createProvider() { + return new PAMImageWriterSpi(); + } + + @Override + protected List getTestData() { + return Arrays.asList( + new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_BINARY), + new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR), + new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY), + new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY), + new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR), + new BufferedImage(100, 100, BufferedImage.TYPE_INT_BGR), + new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR), + new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB), + new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB_PRE), + new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 2, null), false, null), + new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE), Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, 10, 10, 4, null), false, null), + new BufferedImage(new ComponentColorModel(ColorSpaces.getColorSpace(ColorSpaces.CS_GENERIC_CMYK), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT), Raster.createInterleavedRaster(DataBuffer.TYPE_USHORT, 10, 10, 5, null), false, null) + ); + } +} \ No newline at end of file diff --git a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpiTest.java b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpiTest.java index d8a7882c..21622b94 100644 --- a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpiTest.java +++ b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterSpiTest.java @@ -32,13 +32,19 @@ package com.twelvemonkeys.imageio.plugins.pnm; import org.junit.Test; +import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.spi.ImageWriterSpi; +import java.awt.*; +import java.awt.color.*; +import java.awt.image.*; import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassExists; import static com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfoTest.assertClassesExist; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; /** * PNMImageWriterSpiTest. @@ -65,4 +71,70 @@ public class PNMImageWriterSpiTest { public void getOutputTypes() { assertNotNull(spi.getOutputTypes()); } + + @Test + public void canEncodeImageBinary() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_BINARY))); + } + + @Test + public void canNotEncodeImageIndexed() { + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_INDEXED))); + } + + @Test + public void canEncodeImageGray() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_USHORT_GRAY))); + } + + @Test + public void canNotEncodeImageGrayAlpha() { + ComponentColorModel grayAlphaByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaByte, grayAlphaByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel grayAlphaUShort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_USHORT); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(grayAlphaUShort, grayAlphaUShort.createCompatibleSampleModel(1, 1)))); + } + + @Test + public void canEncodeImageRGB() { + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB))); + + assertTrue(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_BGR))); + assertTrue(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_BGR))); + } + + @Test + public void canNotEncodeImageARGB() { + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR))); + + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR_PRE))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR_PRE))); + + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB))); + + assertFalse(spi.canEncodeImage(new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB_PRE))); + assertFalse(spi.canEncodeImage(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB_PRE))); + } + + @Test + public void canNotEncodeImageNonGrayOrRGB() { + ComponentColorModel xyzByte = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzByte, xyzByte.createCompatibleSampleModel(1, 1)))); + + ComponentColorModel xyzUshort = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); + assertFalse(spi.canEncodeImage(new ImageTypeSpecifier(xyzUshort, xyzUshort.createCompatibleSampleModel(1, 1)))); + } } \ No newline at end of file diff --git a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterTest.java b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterTest.java index 8560b58f..2792c18b 100644 --- a/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterTest.java +++ b/imageio/imageio-pnm/src/test/java/com/twelvemonkeys/imageio/plugins/pnm/PNMImageWriterTest.java @@ -3,8 +3,7 @@ package com.twelvemonkeys.imageio.plugins.pnm; import com.twelvemonkeys.imageio.util.ImageWriterAbstractTest; import javax.imageio.spi.ImageWriterSpi; -import java.awt.image.BufferedImage; -import java.awt.image.RenderedImage; +import java.awt.image.*; import java.util.Arrays; import java.util.List; @@ -17,10 +16,12 @@ public class PNMImageWriterTest extends ImageWriterAbstractTest @Override protected List getTestData() { return Arrays.asList( + new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_BINARY), new BufferedImage(100, 100, BufferedImage.TYPE_3BYTE_BGR), new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY), new BufferedImage(100, 100, BufferedImage.TYPE_USHORT_GRAY), - new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR) + new BufferedImage(100, 100, BufferedImage.TYPE_INT_BGR), + new BufferedImage(10, 10, BufferedImage.TYPE_INT_BGR) ); } } \ No newline at end of file