diff --git a/bom/pom.xml b/bom/pom.xml index a684765c..42a7ed3c 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -5,7 +5,7 @@ com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT com.twelvemonkeys.bom diff --git a/common/common-image/pom.xml b/common/common-image/pom.xml index 55cfc26c..cdef6ab4 100644 --- a/common/common-image/pom.xml +++ b/common/common-image/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.common common - 3.3-SNAPSHOT + 3.4-SNAPSHOT common-image jar diff --git a/common/common-io/pom.xml b/common/common-io/pom.xml index b4d3207c..19f61ccc 100644 --- a/common/common-io/pom.xml +++ b/common/common-io/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.common common - 3.3-SNAPSHOT + 3.4-SNAPSHOT common-io jar diff --git a/common/common-lang/pom.xml b/common/common-lang/pom.xml index f3436902..79316441 100644 --- a/common/common-lang/pom.xml +++ b/common/common-lang/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.common common - 3.3-SNAPSHOT + 3.4-SNAPSHOT common-lang jar diff --git a/common/pom.xml b/common/pom.xml index b6b9f6f7..eb530041 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT com.twelvemonkeys.common common diff --git a/contrib/pom.xml b/contrib/pom.xml index 9a73d3c6..f50aac23 100644 --- a/contrib/pom.xml +++ b/contrib/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT com.twelvemonkeys.contrib contrib diff --git a/imageio/imageio-batik/pom.xml b/imageio/imageio-batik/pom.xml index 1f31c074..39ca0cdb 100644 --- a/imageio/imageio-batik/pom.xml +++ b/imageio/imageio-batik/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-batik TwelveMonkeys :: ImageIO :: Batik Plugin diff --git a/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReaderTest.java b/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReaderTest.java index 9f0e8b52..59a06967 100755 --- a/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReaderTest.java +++ b/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/svg/SVGImageReaderTest.java @@ -120,6 +120,13 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest super.testReadWithSourceRegionParamEqualImage(); } + @Test + @Ignore("Known issue: Subsampled reading not supported") + @Override + public void testReadWithSubsampleParamPixels() throws IOException { + super.testReadWithSubsampleParamPixels(); + } + @Test public void testRepeatedRead() throws IOException { Dimension dim = new Dimension(100, 100); diff --git a/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReaderTest.java b/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReaderTest.java index 9220d115..b634b138 100755 --- a/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReaderTest.java +++ b/imageio/imageio-batik/src/test/java/com/twelvemonkeys/imageio/plugins/wmf/WMFImageReaderTest.java @@ -86,4 +86,11 @@ public class WMFImageReaderTest extends ImageReaderAbstractTest public void testReadWithSourceRegionParamEqualImage() throws IOException { super.testReadWithSourceRegionParamEqualImage(); } + + @Test + @Ignore("Known issue: Subsampled reading not supported") + @Override + public void testReadWithSubsampleParamPixels() throws IOException { + super.testReadWithSubsampleParamPixels(); + } } \ No newline at end of file diff --git a/imageio/imageio-bmp/pom.xml b/imageio/imageio-bmp/pom.xml index 8b6aa174..e4a24e22 100644 --- a/imageio/imageio-bmp/pom.xml +++ b/imageio/imageio-bmp/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-bmp TwelveMonkeys :: ImageIO :: BMP plugin diff --git a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReader.java b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReader.java index 6ff96a19..9151dce6 100755 --- a/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReader.java +++ b/imageio/imageio-bmp/src/main/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReader.java @@ -692,12 +692,14 @@ public final class BMPImageReader extends ImageReaderBase { if (imageMetadata != null) { new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName), false); } - } catch (Throwable t) { + } + catch (Throwable t) { if (args.length > 1) { System.err.println("---"); System.err.println("---> " + t.getClass().getSimpleName() + ": " + t.getMessage() + " for " + arg); System.err.println("---"); - } else { + } + else { throwAs(RuntimeException.class, t); } } diff --git a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReaderTest.java b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReaderTest.java index 76a495b3..12646e9a 100755 --- a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReaderTest.java +++ b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/BMPImageReaderTest.java @@ -1,20 +1,19 @@ package com.twelvemonkeys.imageio.plugins.bmp; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; +import org.junit.Ignore; import org.junit.Test; import org.mockito.InOrder; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import javax.imageio.IIOException; -import javax.imageio.ImageIO; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; +import javax.imageio.*; import javax.imageio.event.IIOReadProgressListener; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataNode; import javax.imageio.spi.ImageReaderSpi; import java.awt.*; +import java.awt.image.BufferedImage; import java.io.IOException; import java.lang.reflect.Constructor; import java.net.URISyntaxException; @@ -174,6 +173,58 @@ public class BMPImageReaderTest extends ImageReaderAbstractTest } } + @Ignore("Known issue: Subsampled reading is currently broken") + @Test + public void testReadWithSubsampleParamPixelsIndexed8() throws IOException { + ImageReader reader = createReader(); + TestData data = getTestData().get(0); + reader.setInput(data.getInputStream()); + + ImageReadParam param = reader.getDefaultReadParam(); + + BufferedImage image = null; + BufferedImage subsampled = null; + try { + image = reader.read(0, param); + + param.setSourceSubsampling(2, 2, 0, 0); + subsampled = reader.read(0, param); + } + catch (IOException e) { + failBecause("Image could not be read", e); + } + + assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param); + } + + // TODO: 1. Subsampling is currently broken, should fix it. + // 2. BMPs are (normally) stored bottom/up, meaning y subsampling offsets will differ from normal + // subsampling of the same data with an offset... Should we deal with this in the reader? Yes? + @Ignore("Known issue: Subsampled reading is currently broken") + @Test + @Override + public void testReadWithSubsampleParamPixels() throws IOException { + ImageReader reader = createReader(); + TestData data = getTestData().get(19); // RGB 24 + reader.setInput(data.getInputStream()); + + ImageReadParam param = reader.getDefaultReadParam(); + + BufferedImage image = null; + BufferedImage subsampled = null; + try { + image = reader.read(0, param); + + param.setSourceSubsampling(2, 2, 0, 0); + subsampled = reader.read(0, param); + } + catch (IOException e) { + failBecause("Image could not be read", e); + } + + assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param); + } + @Test(expected = IIOException.class) public void testReadCorruptCausesIIOException() throws IOException { // See https://bugs.openjdk.java.net/browse/JDK-8066904 diff --git a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/CURImageReaderTest.java b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/CURImageReaderTest.java index fe885d86..a40ba06d 100755 --- a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/CURImageReaderTest.java +++ b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/CURImageReaderTest.java @@ -119,4 +119,11 @@ public class CURImageReaderTest extends ImageReaderAbstractTest public void testNotBadCaching() throws IOException { super.testNotBadCaching(); } + + @Test + @Ignore("Known issue: Subsampled reading currently not supported") + @Override + public void testReadWithSubsampleParamPixels() throws IOException { + super.testReadWithSubsampleParamPixels(); + } } \ No newline at end of file diff --git a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageReaderTest.java b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageReaderTest.java index ed5a2adc..9c121287 100755 --- a/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageReaderTest.java +++ b/imageio/imageio-bmp/src/test/java/com/twelvemonkeys/imageio/plugins/bmp/ICOImageReaderTest.java @@ -76,4 +76,11 @@ public class ICOImageReaderTest extends ImageReaderAbstractTest public void testNotBadCaching() throws IOException { super.testNotBadCaching(); } + + @Test + @Ignore("Known issue: Subsampled reading currently not supported") + @Override + public void testReadWithSubsampleParamPixels() throws IOException { + super.testReadWithSubsampleParamPixels(); + } } \ No newline at end of file diff --git a/imageio/imageio-clippath/pom.xml b/imageio/imageio-clippath/pom.xml index 85d4852a..45ba89f4 100755 --- a/imageio/imageio-clippath/pom.xml +++ b/imageio/imageio-clippath/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-clippath TwelveMonkeys :: ImageIO :: Photoshop Path Support diff --git a/imageio/imageio-core/pom.xml b/imageio/imageio-core/pom.xml index 3c295d76..34e815db 100644 --- a/imageio/imageio-core/pom.xml +++ b/imageio/imageio-core/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-core TwelveMonkeys :: ImageIO :: Core diff --git a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java index 2864f844..f002a0fb 100644 --- a/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java +++ b/imageio/imageio-core/src/test/java/com/twelvemonkeys/imageio/util/ImageReaderAbstractTest.java @@ -28,7 +28,6 @@ package com.twelvemonkeys.imageio.util; -import com.twelvemonkeys.image.ImageUtil; import com.twelvemonkeys.imageio.stream.URLImageInputStreamSpi; import org.junit.Ignore; import org.junit.Test; @@ -46,6 +45,7 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.awt.image.RenderedImage; import java.awt.image.SampleModel; +import java.io.File; import java.io.IOException; import java.net.URL; import java.util.ArrayList; @@ -98,7 +98,7 @@ public abstract class ImageReaderAbstractTest { return false; } - private static void failBecause(String message, Throwable exception) { + protected static void failBecause(String message, Throwable exception) { AssertionError error = new AssertionError(message); error.initCause(exception); throw error; @@ -471,7 +471,6 @@ public abstract class ImageReaderAbstractTest { assertEquals("Read image has wrong height: ", (data.getDimension(0).height + 4) / 5, image.getHeight()); } - @Ignore @Test public void testReadWithSubsampleParamPixels() throws IOException { ImageReader reader = createReader(); @@ -479,28 +478,66 @@ public abstract class ImageReaderAbstractTest { reader.setInput(data.getInputStream()); ImageReadParam param = reader.getDefaultReadParam(); - param.setSourceRegion(new Rectangle(Math.min(100, reader.getWidth(0)), Math.min(100, reader.getHeight(0)))); BufferedImage image = null; BufferedImage subsampled = null; try { image = reader.read(0, param); - param.setSourceSubsampling(2, 2, 1, 1); // Hmm.. Seems to be the offset the fake version (ReplicateScaleFilter) uses + param.setSourceSubsampling(2, 2, 0, 0); subsampled = reader.read(0, param); } catch (IOException e) { failBecause("Image could not be read", e); } - BufferedImage expected = ImageUtil.toBuffered(IIOUtil.fakeSubsampling(image, param)); + assertSubsampledImageDataEquals("Subsampled image data does not match expected", image, subsampled, param); + } -// JPanel panel = new JPanel(); -// panel.add(new JLabel("Expected", new BufferedImageIcon(expected, 300, 300), JLabel.CENTER)); -// panel.add(new JLabel("Actual", new BufferedImageIcon(subsampled, 300, 300), JLabel.CENTER)); -// JOptionPane.showConfirmDialog(null, panel); + // TODO: Subsample all test data + // TODO: Subsample with varying ratios and offsets - assertImageDataEquals("Subsampled image data does not match expected", expected, subsampled); + protected final void assertSubsampledImageDataEquals(String message, BufferedImage expected, BufferedImage actual, ImageReadParam param) throws IOException { + assertNotNull("Expected image was null", expected); + assertNotNull("Actual image was null!", actual); + + if (expected == actual) { + return; + } + + int xOff = param.getSubsamplingXOffset(); + int yOff = param.getSubsamplingYOffset(); + int xSub = param.getSourceXSubsampling(); + int ySub = param.getSourceYSubsampling(); + + assertEquals("Subsampled image has wrong width: ", (expected.getWidth() - xOff + xSub - 1) / xSub, actual.getWidth()); + assertEquals("Subsampled image has wrong height: ", (expected.getHeight() - yOff + ySub - 1) / ySub, actual.getHeight()); + assertEquals("Subsampled has different type", expected.getType(), actual.getType()); + + for (int y = 0; y < actual.getHeight(); y++) { + for (int x = 0; x < actual.getWidth(); x++) { + int expectedRGB = expected.getRGB(xOff + x * xSub, yOff + y * ySub); + int actualRGB = actual.getRGB(x, y); + + try { + assertEquals(String.format("%s alpha at (%d, %d)", message, x, y), (expectedRGB >>> 24) & 0xff, (actualRGB >>> 24) & 0xff, 5); + assertEquals(String.format("%s red at (%d, %d)", message, x, y), (expectedRGB >> 16) & 0xff, (actualRGB >> 16) & 0xff, 5); + assertEquals(String.format("%s green at (%d, %d)", message, x, y), (expectedRGB >> 8) & 0xff, (actualRGB >> 8) & 0xff, 5); + assertEquals(String.format("%s blue at (%d, %d)", message, x, y), expectedRGB & 0xff, actualRGB & 0xff, 5); + } + catch (AssertionError e) { + File tempExpected = File.createTempFile("junit-expected-", ".png"); + System.err.println("tempExpected.getAbsolutePath(): " + tempExpected.getAbsolutePath()); + ImageIO.write(expected, "PNG", tempExpected); + File tempActual = File.createTempFile("junit-actual-", ".png"); + System.err.println("tempActual.getAbsolutePath(): " + tempActual.getAbsolutePath()); + ImageIO.write(actual, "PNG", tempActual); + + + assertEquals(String.format("%s ARGB at (%d, %d)", message, x, y), String.format("#%08x", expectedRGB), String.format("#%08x", actualRGB)); + } + } + } } protected final void assertImageDataEquals(String message, BufferedImage expected, BufferedImage actual) { diff --git a/imageio/imageio-hdr/pom.xml b/imageio/imageio-hdr/pom.xml index 20efae92..985c48f7 100644 --- a/imageio/imageio-hdr/pom.xml +++ b/imageio/imageio-hdr/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-hdr TwelveMonkeys :: ImageIO :: HDR plugin diff --git a/imageio/imageio-icns/pom.xml b/imageio/imageio-icns/pom.xml index 37937b29..9a76609e 100644 --- a/imageio/imageio-icns/pom.xml +++ b/imageio/imageio-icns/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-icns TwelveMonkeys :: ImageIO :: ICNS plugin diff --git a/imageio/imageio-iff/pom.xml b/imageio/imageio-iff/pom.xml index 1bac81f2..0c5176f1 100644 --- a/imageio/imageio-iff/pom.xml +++ b/imageio/imageio-iff/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-iff TwelveMonkeys :: ImageIO :: IFF plugin diff --git a/imageio/imageio-jpeg/pom.xml b/imageio/imageio-jpeg/pom.xml index 1a2c62e0..913c4426 100644 --- a/imageio/imageio-jpeg/pom.xml +++ b/imageio/imageio-jpeg/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-jpeg TwelveMonkeys :: ImageIO :: JPEG plugin diff --git a/imageio/imageio-metadata/pom.xml b/imageio/imageio-metadata/pom.xml index 40993b3f..659f5428 100644 --- a/imageio/imageio-metadata/pom.xml +++ b/imageio/imageio-metadata/pom.xml @@ -3,7 +3,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT 4.0.0 imageio-metadata diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java index 0c6f5403..9d88ef24 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/exif/EXIFEntry.java @@ -102,7 +102,7 @@ final class EXIFEntry extends AbstractEntry { case TIFF.TAG_ORIENTATION: return "Orientation"; case TIFF.TAG_SAMPLES_PER_PIXEL: - return "SamplesPerPixels"; + return "SamplesPerPixel"; case TIFF.TAG_ROWS_PER_STRIP: return "RowsPerStrip"; case TIFF.TAG_STRIP_BYTE_COUNTS: diff --git a/imageio/imageio-pcx/pom.xml b/imageio/imageio-pcx/pom.xml index 0f49aa20..f775b43d 100755 --- a/imageio/imageio-pcx/pom.xml +++ b/imageio/imageio-pcx/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-pcx TwelveMonkeys :: ImageIO :: PCX plugin diff --git a/imageio/imageio-pdf/pom.xml b/imageio/imageio-pdf/pom.xml index 9f19c32e..1ccf8f17 100644 --- a/imageio/imageio-pdf/pom.xml +++ b/imageio/imageio-pdf/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-pdf TwelveMonkeys :: ImageIO :: PDF plugin diff --git a/imageio/imageio-pict/pom.xml b/imageio/imageio-pict/pom.xml index 1b9afc34..758bff49 100644 --- a/imageio/imageio-pict/pom.xml +++ b/imageio/imageio-pict/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-pict TwelveMonkeys :: ImageIO :: PICT plugin diff --git a/imageio/imageio-pict/src/test/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReaderTest.java b/imageio/imageio-pict/src/test/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReaderTest.java index 9c46904c..15078df2 100644 --- a/imageio/imageio-pict/src/test/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReaderTest.java +++ b/imageio/imageio-pict/src/test/java/com/twelvemonkeys/imageio/plugins/pict/PICTImageReaderTest.java @@ -3,6 +3,7 @@ package com.twelvemonkeys.imageio.plugins.pict; import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream; import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStreamSpi; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; +import org.junit.Ignore; import org.junit.Test; import javax.imageio.spi.IIORegistry; @@ -83,6 +84,13 @@ public class PICTImageReaderTest extends ImageReaderAbstractTest com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-pnm TwelveMonkeys :: ImageIO :: PNM plugin diff --git a/imageio/imageio-psd/pom.xml b/imageio/imageio-psd/pom.xml index c58d19b4..9eb4a91d 100644 --- a/imageio/imageio-psd/pom.xml +++ b/imageio/imageio-psd/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-psd TwelveMonkeys :: ImageIO :: PSD plugin diff --git a/imageio/imageio-reference/pom.xml b/imageio/imageio-reference/pom.xml index 00899b72..94ad0bf7 100644 --- a/imageio/imageio-reference/pom.xml +++ b/imageio/imageio-reference/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-reference TwelveMonkeys :: ImageIO :: reference test cases diff --git a/imageio/imageio-sgi/pom.xml b/imageio/imageio-sgi/pom.xml index 0296d502..4fe7bb94 100755 --- a/imageio/imageio-sgi/pom.xml +++ b/imageio/imageio-sgi/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-sgi TwelveMonkeys :: ImageIO :: SGI plugin diff --git a/imageio/imageio-tga/pom.xml b/imageio/imageio-tga/pom.xml index 2683485a..9e1ead30 100755 --- a/imageio/imageio-tga/pom.xml +++ b/imageio/imageio-tga/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-tga TwelveMonkeys :: ImageIO :: TGA plugin diff --git a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java index bceccb8b..b6340926 100755 --- a/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java +++ b/imageio/imageio-tga/src/main/java/com/twelvemonkeys/imageio/plugins/tga/TGAImageReader.java @@ -229,15 +229,16 @@ public final class TGAImageReader extends ImageReaderBase { input.readFully(rowDataByte, 0, rowDataByte.length); - if (srcChannel.getNumBands() == 4 && (header.getAttributeBits() == 0 || extensions != null && !extensions.hasAlpha())) { + int numBands = srcChannel.getNumBands(); + if (numBands == 4 && (header.getAttributeBits() == 0 || extensions != null && !extensions.hasAlpha())) { // Remove the alpha channel (make pixels opaque) if there are no "attribute bits" (alpha bits) removeAlpha32(rowDataByte); } // Subsample horizontal if (xSub != 1) { - for (int x = 0; x < srcRegion.width / xSub; x++) { - rowDataByte[srcRegion.x + x] = rowDataByte[srcRegion.x + x * xSub]; + for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + srcRegion.width) / xSub) * numBands; x += numBands) { + System.arraycopy(rowDataByte, x * xSub, rowDataByte, x, numBands); } } diff --git a/imageio/imageio-thumbsdb/pom.xml b/imageio/imageio-thumbsdb/pom.xml index 7ade94f8..1a60813d 100644 --- a/imageio/imageio-thumbsdb/pom.xml +++ b/imageio/imageio-thumbsdb/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-thumbsdb TwelveMonkeys :: ImageIO :: Thumbs.db plugin diff --git a/imageio/imageio-tiff/pom.xml b/imageio/imageio-tiff/pom.xml index 11f66f34..7fc02cce 100644 --- a/imageio/imageio-tiff/pom.xml +++ b/imageio/imageio-tiff/pom.xml @@ -4,7 +4,7 @@ com.twelvemonkeys.imageio imageio - 3.3-SNAPSHOT + 3.4-SNAPSHOT imageio-tiff TwelveMonkeys :: ImageIO :: TIFF plugin 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 8c80285e..5961f6e5 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 @@ -52,6 +52,7 @@ import com.twelvemonkeys.io.FastByteArrayOutputStream; import com.twelvemonkeys.io.LittleEndianDataInputStream; import com.twelvemonkeys.io.enc.DecoderStream; import com.twelvemonkeys.io.enc.PackBitsDecoder; +import com.twelvemonkeys.xml.XMLSerializer; import org.w3c.dom.NodeList; import javax.imageio.*; @@ -454,7 +455,7 @@ public class TIFFImageReader extends ImageReaderBase { return ImageTypeSpecifiers.createPacked(cs, 0xF000, 0xF00, 0xF0, 0xF, DataBuffer.TYPE_USHORT, isAlphaPremultiplied); } default: - throw new IIOException(String.format("Unsupported SamplesPerPixels/BitsPerSample combination for RGB TIFF (expected 3/8, 4/8, 3/16 or 4/16): %d/%d", samplesPerPixel, bitsPerSample)); + throw new IIOException(String.format("Unsupported SamplesPerPixel/BitsPerSample combination for RGB TIFF (expected 3/8, 4/8, 3/16 or 4/16): %d/%d", samplesPerPixel, bitsPerSample)); } case TIFFBaseline.PHOTOMETRIC_PALETTE: // Palette @@ -517,7 +518,7 @@ public class TIFFImageReader extends ImageReaderBase { default: throw new IIOException( - String.format("Unsupported SamplesPerPixels/BitsPerSample combination for Separated TIFF (expected 4/8, 4/16, 5/8 or 5/16): %d/%s", samplesPerPixel, bitsPerSample) + String.format("Unsupported SamplesPerPixel/BitsPerSample combination for Separated TIFF (expected 4/8, 4/16, 5/8 or 5/16): %d/%s", samplesPerPixel, bitsPerSample) ); } case TIFFExtension.PHOTOMETRIC_CIELAB: @@ -777,7 +778,7 @@ public class TIFFImageReader extends ImageReaderBase { // NOTE: We handle strips as tiles of tileWidth == width by tileHeight == rowsPerStrip // Strips are top/down, tiles are left/right, top/down int stripTileWidth = width; - long rowsPerStrip = getValueAsLongWithDefault(TIFF.TAG_ROWS_PER_STRIP, (1L << 32) - 1); + long rowsPerStrip = getValueAsLongWithDefault(TIFF.TAG_ROWS_PER_STRIP, (long) Integer.MAX_VALUE); int stripTileHeight = rowsPerStrip < height ? (int) rowsPerStrip : height; long[] stripTileOffsets = getValueAsLongArray(TIFF.TAG_TILE_OFFSETS, "TileOffsets", false); @@ -924,7 +925,7 @@ public class TIFFImageReader extends ImageReaderBase { } // Clip the stripTile rowRaster to not exceed the srcRegion - clip.width = Math.min((colsInTile + xSub - 1) / xSub, srcRegion.width); + clip.width = Math.min(colsInTile, srcRegion.width); Raster clippedRow = clipRowToRect(rowRaster, clip, param != null ? param.getSourceBands() : null, param != null ? param.getSourceXSubsampling() : 1); @@ -992,7 +993,7 @@ public class TIFFImageReader extends ImageReaderBase { // Read only tiles that lies within region Rectangle tileRect = new Rectangle(col, row, colsInTile, rowsInTile); - Rectangle intersection = tileRect.intersection( srcRegion ); + Rectangle intersection = tileRect.intersection(srcRegion); if (!intersection.isEmpty()) { imageInput.seek(stripTileOffsets[i]); @@ -1000,7 +1001,9 @@ public class TIFFImageReader extends ImageReaderBase { try (ImageInputStream subStream = new SubImageInputStream(imageInput, length)) { jpegReader.setInput(subStream); - jpegParam.setSourceRegion(new Rectangle( intersection.x - col, intersection.y - row, intersection.width, intersection.height)); + jpegParam.setSourceRegion(new Rectangle(intersection.x - col, intersection.y - row, intersection.width, intersection.height)); + jpegParam.setSourceSubsampling(xSub, ySub, 0, 0); + Point offset = new Point((intersection.x - srcRegion.x) / xSub, (intersection.y - srcRegion.y) / ySub); // TODO: If we have non-standard reference B/W or yCbCr coefficients, // we might still have to do extra color space conversion... @@ -1009,7 +1012,7 @@ public class TIFFImageReader extends ImageReaderBase { } if (!needsCSConversion) { - jpegParam.setDestinationOffset(new Point(intersection.x - srcRegion.x, intersection.y - srcRegion.y)); + jpegParam.setDestinationOffset(offset); jpegParam.setDestination(destination); jpegReader.read(0, jpegParam); } @@ -1018,7 +1021,7 @@ public class TIFFImageReader extends ImageReaderBase { // We'll have to use readAsRaster and later apply color space conversion ourselves Raster raster = jpegReader.readRaster(0, jpegParam); normalizeColor(interpretation, ((DataBufferByte) raster.getDataBuffer()).getData()); - destination.getRaster().setDataElements(intersection.x - srcRegion.x, intersection.y - srcRegion.y, raster); + destination.getRaster().setDataElements(offset.x, offset.y, raster); } } } @@ -1140,12 +1143,14 @@ public class TIFFImageReader extends ImageReaderBase { try (ImageInputStream stream = new SubImageInputStream(imageInput, length)) { jpegReader.setInput(stream); jpegParam.setSourceRegion(srcRegion); + jpegParam.setSourceSubsampling(xSub, ySub, 0, 0); if (needsCSConversion == null) { needsCSConversion = needsCSConversion(interpretation, jpegReader.getImageMetadata(0)); } if (!needsCSConversion) { + // Single tile, no dest offset needed jpegParam.setDestination(destination); jpegReader.read(0, jpegParam); } @@ -1242,14 +1247,15 @@ public class TIFFImageReader extends ImageReaderBase { )))) { jpegReader.setInput(stream); jpegParam.setSourceRegion(new Rectangle(0, 0, colsInTile, rowsInTile)); - jpegParam.setDestinationOffset(new Point(col - srcRegion.x, row - srcRegion.y)); - jpegParam.setDestination(destination); + jpegParam.setSourceSubsampling(xSub, ySub, 0, 0); + Point offset = new Point(col - srcRegion.x, row - srcRegion.y); if (needsCSConversion == null) { needsCSConversion = needsCSConversion(interpretation, jpegReader.getImageMetadata(0)); } if (!needsCSConversion) { + jpegParam.setDestinationOffset(offset); jpegParam.setDestination(destination); jpegReader.read(0, jpegParam); } @@ -1258,7 +1264,7 @@ public class TIFFImageReader extends ImageReaderBase { // We'll have to use readAsRaster and later apply color space conversion ourselves Raster raster = jpegReader.readRaster(0, jpegParam); normalizeColor(interpretation, ((DataBufferByte) raster.getDataBuffer()).getData()); - destination.getRaster().setDataElements(0, 0, raster); + destination.getRaster().setDataElements(offset.x, offset.y, raster); } } } @@ -1385,7 +1391,7 @@ public class TIFFImageReader extends ImageReaderBase { out.writeShort(JPEG.SOI); out.writeShort(JPEG.SOF0); out.writeShort(2 + 6 + 3 * bands); // SOF0 len - out.writeByte(8); // bits TODO: Consult bands/transfer type or BitsPerSample for 12/16 bits support + out.writeByte(8); // bits TODO: Consult raster/transfer type or BitsPerSample for 12/16 bits support out.writeShort(stripTileHeight); // height out.writeShort(stripTileWidth); // width out.writeByte(bands); // Number of components @@ -1447,7 +1453,7 @@ public class TIFFImageReader extends ImageReaderBase { return raster; } - return raster.createChild(rect.x / xSub, 0, rect.width / xSub, 1, 0, 0, bands); + return raster.createChild((rect.x + xSub - 1) / xSub, 0, (rect.width + xSub - 1) / xSub, 1, 0, 0, bands); } private WritableRaster clipToRect(final WritableRaster raster, final Rectangle rect, final int[] bands) { @@ -1497,12 +1503,12 @@ public class TIFFImageReader extends ImageReaderBase { // Subsample horizontal if (xSub != 1) { - for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + srcRegion.width) / xSub) * numBands; x += numBands) { + for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) { System.arraycopy(rowDataByte, x * xSub, rowDataByte, x, numBands); } } - destChannel.setDataElements(startCol, (row - srcRegion.y) / ySub, srcChannel); + destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel); } // Else skip data } @@ -1540,12 +1546,12 @@ public class TIFFImageReader extends ImageReaderBase { // Subsample horizontal if (xSub != 1) { - for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + srcRegion.width) / xSub) * numBands; x += numBands) { + for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) { System.arraycopy(rowDataShort, x * xSub, rowDataShort, x, numBands); } } - destChannel.setDataElements(startCol, row - srcRegion.y, srcChannel); + destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel); // TODO: Possible speedup ~30%!: // raster.setDataElements(startCol, row - srcRegion.y, colsInTile, 1, rowDataShort); } @@ -1577,12 +1583,12 @@ public class TIFFImageReader extends ImageReaderBase { // Subsample horizontal if (xSub != 1) { - for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + srcRegion.width) / xSub) * numBands; x += numBands) { + for (int x = srcRegion.x / xSub * numBands; x < ((srcRegion.x + colsInTile) / xSub) * numBands; x += numBands) { System.arraycopy(rowDataInt, x * xSub, rowDataInt, x, numBands); } } - destChannel.setDataElements(startCol, row - srcRegion.y, srcChannel); + destChannel.setDataElements(startCol / xSub, (row - srcRegion.y) / ySub, srcChannel); } // Else skip data } @@ -1907,22 +1913,34 @@ public class TIFFImageReader extends ImageReaderBase { case TIFFBaseline.COMPRESSION_PACKBITS: return new DecoderStream(stream, new PackBitsDecoder(), 1024); case TIFFExtension.COMPRESSION_LZW: + // NOTE: Needs large buffer for compatibility with certain encoders return new DecoderStream(stream, LZWDecoder.create(LZWDecoder.isOldBitReversedStream(stream)), Math.max(width * bands, 4096)); case TIFFExtension.COMPRESSION_ZLIB: - // TIFFphotoshop.pdf (aka TIFF specification, supplement 2) says ZLIB (8) and DEFLATE (32946) algorithms are identical case TIFFExtension.COMPRESSION_DEFLATE: + // TIFF specification, supplement 2 says ZLIB (8) and DEFLATE (32946) algorithms are identical return new InflaterInputStream(stream, new Inflater(), 1024); case TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE: - return new CCITTFaxDecoderStream(stream, width, compression, getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1),0L); case TIFFExtension.COMPRESSION_CCITT_T4: - return new CCITTFaxDecoderStream(stream, width, compression, getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1),getValueAsLongWithDefault(TIFF.TAG_GROUP3OPTIONS, 0L)); case TIFFExtension.COMPRESSION_CCITT_T6: - return new CCITTFaxDecoderStream(stream, width, compression, getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1),getValueAsLongWithDefault(TIFF.TAG_GROUP4OPTIONS, 0L)); + return new CCITTFaxDecoderStream(stream, width, compression, getValueAsIntWithDefault(TIFF.TAG_FILL_ORDER, 1), getCCITTOptions(compression)); default: throw new IllegalArgumentException("Unsupported TIFF compression: " + compression); } } + private long getCCITTOptions(final int compression) throws IIOException { + switch (compression) { + case TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE: + return 0L; + case TIFFExtension.COMPRESSION_CCITT_T4: + return getValueAsLongWithDefault(TIFF.TAG_GROUP3OPTIONS, 0L); + case TIFFExtension.COMPRESSION_CCITT_T6: + return getValueAsLongWithDefault(TIFF.TAG_GROUP4OPTIONS, 0L); + default: + throw new IllegalArgumentException("No CCITT options for compression: " + compression); + } + } + private InputStream createUnpredictorStream(final int predictor, final int width, final int samplesPerPixel, final int bitsPerSample, final InputStream stream, final ByteOrder byteOrder) throws IOException { switch (predictor) { case TIFFBaseline.PREDICTOR_NONE: @@ -2155,6 +2173,7 @@ public class TIFFImageReader extends ImageReaderBase { // param.setSourceRegion(new Rectangle(3, 3, 9, 9)); // param.setDestinationOffset(new Point(50, 150)); // param.setSourceSubsampling(2, 2, 0, 0); +// param.setSourceSubsampling(3, 3, 0, 0); BufferedImage image = reader.read(imageNo, param); System.err.println("Read time: " + (System.currentTimeMillis() - start) + " ms"); @@ -2171,6 +2190,20 @@ public class TIFFImageReader extends ImageReaderBase { System.err.println("image: " + image); +// int w = image.getWidth(); +// int h = image.getHeight(); +// +// int newW = h; +// int newH = w; +// +// AffineTransform xform = AffineTransform.getTranslateInstance((newW - w) / 2.0, (newH - h) / 2.0); +// xform.concatenate(AffineTransform.getQuadrantRotateInstance(3, w / 2.0, h / 2.0)); +// AffineTransformOp op = new AffineTransformOp(xform, null); +// +// image = op.filter(image, null); +// +// System.err.println("image: " + image); +// // File tempFile = File.createTempFile("lzw-", ".bin"); // byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); // FileOutputStream stream = new FileOutputStream(tempFile); 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 35e7c171..08bbf63d 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 @@ -27,7 +27,6 @@ package com.twelvemonkeys.imageio.plugins.tiff;/* */ import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; -import org.junit.Ignore; import org.junit.Test; import javax.imageio.ImageIO; @@ -442,4 +441,74 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT 4.0.0 com.twelvemonkeys.imageio diff --git a/pom.xml b/pom.xml index cb1d24ad..db48b399 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT pom Twelvemonkeys diff --git a/servlet/pom.xml b/servlet/pom.xml index 2f2fc663..fdf7a8ff 100644 --- a/servlet/pom.xml +++ b/servlet/pom.xml @@ -3,7 +3,7 @@ com.twelvemonkeys twelvemonkeys - 3.3-SNAPSHOT + 3.4-SNAPSHOT 4.0.0