mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 03:25:28 -04:00
Clean-up
This commit is contained in:
parent
1292c95040
commit
ee424583c4
@ -26,8 +26,7 @@ class DelegateTileDecoder extends TileDecoder {
|
||||
protected final ImageReader delegate;
|
||||
protected final ImageReadParam param;
|
||||
|
||||
// TODO: Naming... Is this only due to color space conversion? Is it because we need to read raster?
|
||||
private final Predicate<ImageReader> needsConversion;
|
||||
private final Predicate<ImageReader> needsRasterConversion;
|
||||
private final RasterConverter converter;
|
||||
private Boolean readRasterAndConvert;
|
||||
|
||||
@ -35,11 +34,11 @@ class DelegateTileDecoder extends TileDecoder {
|
||||
this(warningListener, createDelegate(format), originalParam, imageReader -> false, null);
|
||||
}
|
||||
|
||||
DelegateTileDecoder(final IIOReadWarningListener warningListener, final String format, final ImageReadParam originalParam, final Predicate<ImageReader> needsConversion, final RasterConverter converter) throws IOException {
|
||||
this(warningListener, createDelegate(format), originalParam, needsConversion, converter);
|
||||
DelegateTileDecoder(final IIOReadWarningListener warningListener, final String format, final ImageReadParam originalParam, final Predicate<ImageReader> needsRasterConversion, final RasterConverter converter) throws IOException {
|
||||
this(warningListener, createDelegate(format), originalParam, needsRasterConversion, converter);
|
||||
}
|
||||
|
||||
private DelegateTileDecoder(final IIOReadWarningListener warningListener, final ImageReader delegate, final ImageReadParam originalParam, final Predicate<ImageReader> needsConversion, final RasterConverter converter) {
|
||||
private DelegateTileDecoder(final IIOReadWarningListener warningListener, final ImageReader delegate, final ImageReadParam originalParam, final Predicate<ImageReader> needsRasterConversion, final RasterConverter converter) {
|
||||
super(warningListener);
|
||||
|
||||
this.delegate = notNull(delegate, "delegate");
|
||||
@ -48,7 +47,7 @@ class DelegateTileDecoder extends TileDecoder {
|
||||
param = delegate.getDefaultReadParam();
|
||||
param.setSourceSubsampling(originalParam.getSourceXSubsampling(), originalParam.getSourceYSubsampling(), 0, 0);
|
||||
|
||||
this.needsConversion = needsConversion;
|
||||
this.needsRasterConversion = needsRasterConversion;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
@ -57,7 +56,7 @@ class DelegateTileDecoder extends TileDecoder {
|
||||
// If it's the TwelveMonkeys one, we will be able to read JPEG Lossless etc.
|
||||
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(format);
|
||||
if (!readers.hasNext()) {
|
||||
throw new IIOException("Could not instantiate " + format + "ImageReader");
|
||||
throw new IIOException("No ImageReader registered for '" + format + "' format");
|
||||
}
|
||||
|
||||
return readers.next();
|
||||
@ -70,7 +69,7 @@ class DelegateTileDecoder extends TileDecoder {
|
||||
|
||||
if (readRasterAndConvert == null) {
|
||||
// All tiles in an image will use the same format, test once and cache result
|
||||
readRasterAndConvert = needsConversion.test(delegate);
|
||||
readRasterAndConvert = needsRasterConversion.test(delegate);
|
||||
}
|
||||
|
||||
if (!readRasterAndConvert) {
|
||||
|
@ -15,8 +15,8 @@ import java.util.function.Predicate;
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: JPEGTileDecoder.java,v 1.0 09/11/2023 haraldk Exp$
|
||||
*/
|
||||
class JPEGTileDecoder extends DelegateTileDecoder {
|
||||
JPEGTileDecoder(final IIOReadWarningListener warningListener, final byte[] jpegTables, final ImageReadParam originalParam, final Predicate<ImageReader> needsConversion, final RasterConverter converter) throws IOException {
|
||||
final class JPEGTileDecoder extends DelegateTileDecoder {
|
||||
JPEGTileDecoder(final IIOReadWarningListener warningListener, final byte[] jpegTables, final int numTiles, final ImageReadParam originalParam, final Predicate<ImageReader> needsConversion, final RasterConverter converter) throws IOException {
|
||||
super(warningListener, "JPEG", originalParam, needsConversion, converter);
|
||||
|
||||
if (jpegTables != null) {
|
||||
@ -29,9 +29,9 @@ class JPEGTileDecoder extends DelegateTileDecoder {
|
||||
// http://docs.oracle.com/javase/6/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html#abbrev
|
||||
delegate.getStreamMetadata();
|
||||
}
|
||||
else {
|
||||
else if (numTiles > 1) {
|
||||
warningListener.warningOccurred(delegate, "Missing JPEGTables for tiled/striped TIFF with compression: 7 (JPEG)");
|
||||
// ...and the JPEG reader will probably choke on missing tables...
|
||||
// ...and the JPEG reader might choke on missing tables...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1172,13 +1172,18 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
|
||||
break;
|
||||
}
|
||||
case TIFFCustom.COMPRESSION_WEBP:
|
||||
case TIFFExtension.COMPRESSION_JPEG:
|
||||
case TIFFCustom.COMPRESSION_WEBP:
|
||||
case TIFFCustom.COMPRESSION_JBIG:
|
||||
case TIFFCustom.COMPRESSION_JPEG2000:
|
||||
readUsingDelegate(imageIndex, compression, interpretation, width, height, tilesAcross, tilesDown, stripTileWidth, stripTileHeight, srcRegion, stripTileOffsets, stripTileByteCounts, param, destination, samplesInTile);
|
||||
break;
|
||||
|
||||
case TIFFExtension.COMPRESSION_OLD_JPEG: {
|
||||
// JPEG ('old-style' JPEG, later overridden in Technote2)
|
||||
// http://www.remotesensing.org/libtiff/TIFFTechNote2.html
|
||||
// TODO: Rewrite to use readUsingDelegate with special case handling inside OldJPEGTileDecoder
|
||||
|
||||
int srcRow = 0;
|
||||
Boolean needsCSConversion = null;
|
||||
|
||||
@ -1497,10 +1502,8 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
case TIFFCustom.COMPRESSION_PIXARFILM:
|
||||
case TIFFCustom.COMPRESSION_PIXARLOG:
|
||||
case TIFFCustom.COMPRESSION_DCS:
|
||||
case TIFFCustom.COMPRESSION_JBIG: // Doable with JBIG plugin?
|
||||
case TIFFCustom.COMPRESSION_SGILOG:
|
||||
case TIFFCustom.COMPRESSION_SGILOG24:
|
||||
case TIFFCustom.COMPRESSION_JPEG2000: // Doable with JPEG2000 plugin?
|
||||
throw new IIOException("Unsupported TIFF Compression value: " + compression);
|
||||
|
||||
default:
|
||||
@ -1521,7 +1524,7 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
// JPEG ('new-style' JPEG)
|
||||
|
||||
// Read data
|
||||
try (TileDecoder tileDecoder = createTileDecoder(param, compression, interpretation, samplesInTile)) {
|
||||
try (TileDecoder tileDecoder = createTileDecoder(param, compression, interpretation, tilesAcross * tilesDown, samplesInTile)) {
|
||||
processImageStarted(imageIndex); // Better yet, would be to delegate read progress here...
|
||||
|
||||
int row = 0;
|
||||
@ -1569,37 +1572,39 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
private DelegateTileDecoder createTileDecoder(ImageReadParam param, int compression, final int interpretation, final int samplesInTile) throws IOException {
|
||||
if (compression == TIFFExtension.COMPRESSION_JPEG) {
|
||||
// JPEG_TABLES should be a full JPEG 'abbreviated table specification', containing:
|
||||
// SOI, DQT, DHT, (optional markers that we ignore)..., EOI
|
||||
Entry tablesEntry = currentIFD.getEntryById(TIFF.TAG_JPEG_TABLES);
|
||||
byte[] tablesValue = tablesEntry != null ? (byte[]) tablesEntry.getValue() : null;
|
||||
private TileDecoder createTileDecoder(ImageReadParam param, int compression, final int interpretation, final int numTiles, final int samplesInTile) throws IOException {
|
||||
try {
|
||||
IIOReadWarningListener warningListener = (source, warning) -> processWarningOccurred(warning);
|
||||
|
||||
Predicate<ImageReader> needsConversion = (reader) -> needsCSConversion(compression, interpretation, readJPEGMetadataSafe(reader));
|
||||
RasterConverter csConverter = (raster) -> {
|
||||
switch (raster.getTransferType()) {
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
normalizeColor(interpretation, samplesInTile, ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||
break;
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
normalizeColor(interpretation, samplesInTile, ((DataBufferUShort) raster.getDataBuffer()).getData());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported transfer type: " + raster.getTransferType());
|
||||
}
|
||||
};
|
||||
if (compression == TIFFExtension.COMPRESSION_JPEG) {
|
||||
// JPEG_TABLES should be a full JPEG 'abbreviated table specification', containing:
|
||||
// SOI, DQT, DHT, (optional markers that we ignore)..., EOI
|
||||
Entry tablesEntry = currentIFD.getEntryById(TIFF.TAG_JPEG_TABLES);
|
||||
byte[] jpegTables = tablesEntry != null ? (byte[]) tablesEntry.getValue() : null;
|
||||
|
||||
return new JPEGTileDecoder((source, warning) -> processWarningOccurred(warning), tablesValue, param, needsConversion, csConverter);
|
||||
Predicate<ImageReader> needsConversion = (reader) -> needsCSConversion(compression, interpretation, readJPEGMetadataSafe(reader));
|
||||
RasterConverter normalize = (raster) -> normalizeColor(interpretation, samplesInTile, raster);
|
||||
|
||||
return new JPEGTileDecoder(warningListener, jpegTables, numTiles, param, needsConversion, normalize);
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_JBIG) {
|
||||
// TODO: Create interop test suite using third party plugin.
|
||||
// LEAD Tools have one sample file: https://leadtools.com/support/forum/resource.ashx?a=545&b=1
|
||||
// Haven't found any plugins. There is however a JBIG2 plugin...
|
||||
return new DelegateTileDecoder(warningListener, "JBIG", param);
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_JPEG2000) {
|
||||
// TODO: Create interop test suite using third party plugin
|
||||
// LEAD Tools have one sample file: https://leadtools.com/support/forum/resource.ashx?a=545&b=1
|
||||
// The open source JAI JP2K reader decodes this as a fully black image...
|
||||
return new DelegateTileDecoder(warningListener, "JPEG2000", param);
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_WEBP) {
|
||||
return new DelegateTileDecoder(warningListener, "WebP", param);
|
||||
}
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_JBIG) {
|
||||
return new DelegateTileDecoder((source, warning) -> processWarningOccurred(warning), "JBIG", param);
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_JPEG2000) {
|
||||
return new DelegateTileDecoder((source, warning) -> processWarningOccurred(warning), "JP2K", param);
|
||||
}
|
||||
else if (compression == TIFFCustom.COMPRESSION_WEBP) {
|
||||
return new DelegateTileDecoder((source, warning) -> processWarningOccurred(warning), "WebP", param);
|
||||
catch (IIOException e) {
|
||||
throw new IIOException("Unsupported TIFF Compression value: " + compression, e);
|
||||
}
|
||||
|
||||
throw new IIOException("Unsupported TIFF Compression value: " + compression);
|
||||
@ -2165,6 +2170,19 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizeColor(int interpretation, int numBands, Raster raster) throws IOException {
|
||||
switch (raster.getTransferType()) {
|
||||
case DataBuffer.TYPE_BYTE:
|
||||
normalizeColor(interpretation, numBands, ((DataBufferByte) raster.getDataBuffer()).getData());
|
||||
break;
|
||||
case DataBuffer.TYPE_USHORT:
|
||||
normalizeColor(interpretation, numBands, ((DataBufferUShort) raster.getDataBuffer()).getData());
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported transfer type: " + raster.getTransferType());
|
||||
}
|
||||
}
|
||||
|
||||
private void normalizeColor(int photometricInterpretation, int numBands, byte[] data) throws IOException {
|
||||
switch (photometricInterpretation) {
|
||||
case TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO:
|
||||
|
@ -6,6 +6,8 @@ import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||
|
||||
/**
|
||||
* TileDecoder.
|
||||
*
|
||||
@ -18,7 +20,7 @@ abstract class TileDecoder implements AutoCloseable {
|
||||
protected final IIOReadWarningListener warningListener;
|
||||
|
||||
public TileDecoder(IIOReadWarningListener warningListener) {
|
||||
this.warningListener = warningListener;
|
||||
this.warningListener = notNull(warningListener, "warningListener");
|
||||
}
|
||||
|
||||
abstract void decodeTile(ImageInputStream input, Rectangle sourceRegion, Point destinationOffset, BufferedImage destination) throws IOException;
|
||||
|
Loading…
x
Reference in New Issue
Block a user