Merge remote-tracking branch 'origin/master'

This commit is contained in:
Harald Kuhr 2016-11-03 10:57:33 +01:00
commit 88cd76a39c
40 changed files with 302 additions and 79 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.bom</groupId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>common-image</artifactId>
<packaging>jar</packaging>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>common-io</artifactId>
<packaging>jar</packaging>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>common-lang</artifactId>
<packaging>jar</packaging>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.common</groupId>
<artifactId>common</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<groupId>com.twelvemonkeys.contrib</groupId>
<artifactId>contrib</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-batik</artifactId>
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>

View File

@ -120,6 +120,13 @@ public class SVGImageReaderTest extends ImageReaderAbstractTest<SVGImageReader>
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);

View File

@ -86,4 +86,11 @@ public class WMFImageReaderTest extends ImageReaderAbstractTest<WMFImageReader>
public void testReadWithSourceRegionParamEqualImage() throws IOException {
super.testReadWithSourceRegionParamEqualImage();
}
@Test
@Ignore("Known issue: Subsampled reading not supported")
@Override
public void testReadWithSubsampleParamPixels() throws IOException {
super.testReadWithSubsampleParamPixels();
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-bmp</artifactId>
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>

View File

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

View File

@ -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<BMPImageReader>
}
}
@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

View File

@ -119,4 +119,11 @@ public class CURImageReaderTest extends ImageReaderAbstractTest<CURImageReader>
public void testNotBadCaching() throws IOException {
super.testNotBadCaching();
}
@Test
@Ignore("Known issue: Subsampled reading currently not supported")
@Override
public void testReadWithSubsampleParamPixels() throws IOException {
super.testReadWithSubsampleParamPixels();
}
}

View File

@ -76,4 +76,11 @@ public class ICOImageReaderTest extends ImageReaderAbstractTest<ICOImageReader>
public void testNotBadCaching() throws IOException {
super.testNotBadCaching();
}
@Test
@Ignore("Known issue: Subsampled reading currently not supported")
@Override
public void testReadWithSubsampleParamPixels() throws IOException {
super.testReadWithSubsampleParamPixels();
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-clippath</artifactId>
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-core</artifactId>
<name>TwelveMonkeys :: ImageIO :: Core</name>

View File

@ -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<T extends ImageReader> {
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<T extends ImageReader> {
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<T extends ImageReader> {
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) {

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-hdr</artifactId>
<name>TwelveMonkeys :: ImageIO :: HDR plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-icns</artifactId>
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-iff</artifactId>
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-jpeg</artifactId>
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>imageio-metadata</artifactId>

View File

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

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pcx</artifactId>
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pdf</artifactId>
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pict</artifactId>
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>

View File

@ -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<PICTImageReader
return Arrays.asList("image/pict", "image/x-pict");
}
@Ignore("Known issue")
@Test
@Override
public void testReadWithSubsampleParamPixels() throws IOException {
super.testReadWithSubsampleParamPixels();
}
// Regression tests
@Test
@ -142,12 +150,6 @@ public class PICTImageReaderTest extends ImageReaderAbstractTest<PICTImageReader
PICTImageReader reader = createReader();
reader.setInput(new ByteArrayImageInputStream(DATA_V1_COPY_BITS));
reader.read(0);
// BufferedImage image = reader.read(0);
//
// if (!GraphicsEnvironment.isHeadless()) {
// PICTImageReader.showIt(image, "dataV1CopyBits");
// Thread.sleep(10000);
// }
}
private static final byte[] DATA_EXT_V2 = {

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-pnm</artifactId>
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-psd</artifactId>
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-reference</artifactId>
<name>TwelveMonkeys :: ImageIO :: reference test cases</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-sgi</artifactId>
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-tga</artifactId>
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>

View File

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

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-thumbsdb</artifactId>
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<artifactId>imageio-tiff</artifactId>
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>

View File

@ -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);
@ -1001,6 +1002,8 @@ 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.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);

View File

@ -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<TIFFImageReader
assertTrue("no correct guess for PhotometricInterpretation: " + results[i], foundWarning.get());
}
}
@Test
public void testReadWithSubsampleParamPixelsJPEG() throws IOException {
// Tiled "new style" JPEG
ImageReader reader = createReader();
TestData data = new TestData(getClassLoaderResource("/tiff/quad-jpeg.tif"), new Dimension(512, 384));
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
public void testReadWithSubsampleParamPixelsOldJPEG() throws IOException {
ImageReader reader = createReader();
TestData data = new TestData(getClassLoaderResource("/tiff/smallliz.tif"), new Dimension(160, 160));
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
public void testReadWithSubsampleParamPixelsTiled() throws IOException {
ImageReader reader = createReader();
TestData data = new TestData(getClassLoaderResource("/tiff/cramps-tile.tif"), new Dimension(800, 607));
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);
}
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.twelvemonkeys.imageio</groupId>

View File

@ -8,7 +8,7 @@
</parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Twelvemonkeys</name>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>com.twelvemonkeys</groupId>
<artifactId>twelvemonkeys</artifactId>
<version>3.3-SNAPSHOT</version>
<version>3.4-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>