diff --git a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiers.java b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiers.java index 372081ea..05cf4468 100644 --- a/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiers.java +++ b/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiers.java @@ -28,12 +28,14 @@ package com.twelvemonkeys.imageio.util; +import com.twelvemonkeys.lang.Validate; + import javax.imageio.ImageTypeSpecifier; import java.awt.color.ColorSpace; -import java.awt.image.ColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DirectColorModel; -import java.awt.image.IndexColorModel; +import java.awt.image.*; + +import static com.twelvemonkeys.lang.Validate.isTrue; +import static com.twelvemonkeys.lang.Validate.notNull; /** * Factory class for creating {@code ImageTypeSpecifier}s. @@ -59,17 +61,9 @@ public final class ImageTypeSpecifiers { final int transferType, boolean isAlphaPremultiplied) { if (transferType == DataBuffer.TYPE_BYTE || transferType == DataBuffer.TYPE_USHORT) { // ImageTypeSpecifier unconditionally uses bits == 32, we'll use a workaround for BYTE/USHORT types - if (colorSpace == null) { - throw new IllegalArgumentException("colorSpace == null!"); - } - - if (colorSpace.getType() != ColorSpace.TYPE_RGB) { - throw new IllegalArgumentException("colorSpace is not of type TYPE_RGB!"); - } - - if (redMask == 0 && greenMask == 0 && blueMask == 0 && alphaMask == 0) { - throw new IllegalArgumentException("No mask has at least 1 bit set!"); - } + notNull(colorSpace, "colorSpace"); + isTrue(colorSpace.getType() == ColorSpace.TYPE_RGB, colorSpace, "ColorSpace must be TYPE_RGB"); + isTrue(redMask != 0 || greenMask != 0 || blueMask != 0 || alphaMask != 0, "No mask has at least 1 bit set"); int bits = transferType == DataBuffer.TYPE_BYTE ? 8 : 16; @@ -131,6 +125,34 @@ public final class ImageTypeSpecifiers { return ImageTypeSpecifier.createGrayscale(bits, dataType, false, isAlphaPremultiplied); } + public static ImageTypeSpecifier createPackedGrayscale(final ColorSpace colorSpace, final int bits, final int dataType) { + notNull(colorSpace, "colorSpace"); + isTrue(colorSpace.getType() == ColorSpace.TYPE_GRAY, colorSpace, "ColorSpace must be TYPE_GRAY"); + isTrue(bits == 1 || bits == 2 || bits == 4, bits, "bits must be 1, 2, or 4: %s"); + isTrue(dataType == DataBuffer.TYPE_BYTE, dataType, "dataType must be TYPE_BYTE: %s"); + + int numEntries = 1 << bits; + + byte[] arr = new byte[numEntries]; + byte[] arg = new byte[numEntries]; + byte[] arb = new byte[numEntries]; + + // Scale array values according to color profile.. + for (int i = 0; i < numEntries; i++) { + float[] gray = new float[]{i / (float) (numEntries - 1)}; + float[] rgb = colorSpace.toRGB(gray); + + arr[i] = (byte) (rgb[0] * 255); + arg[i] = (byte) (rgb[1] * 255); + arb[i] = (byte) (rgb[2]* 255); + } + + ColorModel colorModel = new IndexColorModel(bits, numEntries, arr, arg, arb); + SampleModel sampleModel = new MultiPixelPackedSampleModel(dataType, 1, 1, bits); + + return new ImageTypeSpecifier(colorModel, sampleModel); + } + public static ImageTypeSpecifier createIndexed(final byte[] redLUT, final byte[] greenLUT, final byte[] blueLUT, final byte[] alphaLUT, final int bits, final int dataType) { diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiersTest.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiersTest.java index 9ddfbf9b..9a286bbf 100644 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiersTest.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageTypeSpecifiersTest.java @@ -463,6 +463,30 @@ public class ImageTypeSpecifiersTest { ); } + @Test + public void testCreatePackedGrayscale1() { + assertEquals( + ImageTypeSpecifier.createGrayscale(1, DataBuffer.TYPE_BYTE, false), + ImageTypeSpecifiers.createPackedGrayscale(GRAY, 1, DataBuffer.TYPE_BYTE) + ); + } + + @Test + public void testCreatePackedGrayscale2() { + assertEquals( + ImageTypeSpecifier.createGrayscale(2, DataBuffer.TYPE_BYTE, false), + ImageTypeSpecifiers.createPackedGrayscale(GRAY, 2, DataBuffer.TYPE_BYTE) + ); + } + + @Test + public void testCreatePackedGrayscale4() { + assertEquals( + ImageTypeSpecifier.createGrayscale(4, DataBuffer.TYPE_BYTE, false), + ImageTypeSpecifiers.createPackedGrayscale(GRAY, 4, DataBuffer.TYPE_BYTE) + ); + } + @Test public void testCreateIndexedByteArrays1to8() { for (int bits = 1; bits <= 8; bits <<= 1) { diff --git a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java index 79d5fe35..790b70e5 100755 --- a/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java +++ b/imageio/imageio-tiff/src/main/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReader.java @@ -364,8 +364,11 @@ public class TIFFImageReader extends ImageReaderBase { if (cs == ColorSpace.getInstance(ColorSpace.CS_GRAY) && (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 || bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32)) { return ImageTypeSpecifiers.createGrayscale(bitsPerSample, dataType); } - else if (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 || bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32) { - // TODO: Should use packed format for 1/2/4 + else if (bitsPerSample == 1 || bitsPerSample == 2 || bitsPerSample == 4 ) { + // Use packed format for 1/2/4 bits + return ImageTypeSpecifiers.createPackedGrayscale(cs, bitsPerSample, dataType); + } + else if (bitsPerSample == 8 || bitsPerSample == 16 || bitsPerSample == 32) { return ImageTypeSpecifiers.createInterleaved(cs, new int[] {0}, dataType, false, false); } diff --git a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java index f59def5e..1e224587 100644 --- a/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java +++ b/imageio/imageio-tiff/src/test/java/com/twelvemonkeys/imageio/plugins/tiff/TIFFImageReaderTest.java @@ -90,6 +90,7 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest