mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 03:55:28 -04:00
This commit is contained in:
parent
762b59674b
commit
6ea1ea8916
@ -198,7 +198,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
int compression;
|
int compression;
|
||||||
if ((param == null || param.getCompressionMode() == TIFFImageWriteParam.MODE_COPY_FROM_METADATA)
|
if ((param == null || param.getCompressionMode() == TIFFImageWriteParam.MODE_COPY_FROM_METADATA)
|
||||||
&& image.getMetadata() != null && metadata.getIFD().getEntryById(TIFF.TAG_COMPRESSION) != null) {
|
&& image.getMetadata() != null && metadata.getIFD().getEntryById(TIFF.TAG_COMPRESSION) != null) {
|
||||||
compression = (int) metadata.getIFD().getEntryById(TIFF.TAG_COMPRESSION).getValue();
|
compression = ((Number) metadata.getIFD().getEntryById(TIFF.TAG_COMPRESSION).getValue()).intValue();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
compression = TIFFImageWriteParam.getCompressionType(param);
|
compression = TIFFImageWriteParam.getCompressionType(param);
|
||||||
@ -243,8 +243,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: We might want to support CMYK in JPEG as well... Pending JPEG CMYK write support.
|
int photometric = getPhotometricInterpretation(colorModel, compression);
|
||||||
int photometric = compression == TIFFExtension.COMPRESSION_JPEG ? TIFFExtension.PHOTOMETRIC_YCBCR : getPhotometricInterpretation(colorModel);
|
|
||||||
entries.put(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, photometric));
|
entries.put(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, photometric));
|
||||||
|
|
||||||
if (photometric == TIFFBaseline.PHOTOMETRIC_PALETTE && colorModel instanceof IndexColorModel) {
|
if (photometric == TIFFBaseline.PHOTOMETRIC_PALETTE && colorModel instanceof IndexColorModel) {
|
||||||
@ -463,7 +462,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
|
|
||||||
// Use predictor by default for LZW and ZLib/Deflate
|
// Use predictor by default for LZW and ZLib/Deflate
|
||||||
// TODO: Unless explicitly disabled in TIFFImageWriteParam
|
// TODO: Unless explicitly disabled in TIFFImageWriteParam
|
||||||
int compression = (int) entries.get(TIFF.TAG_COMPRESSION).getValue();
|
int compression = ((Number) entries.get(TIFF.TAG_COMPRESSION).getValue()).intValue();
|
||||||
OutputStream stream;
|
OutputStream stream;
|
||||||
|
|
||||||
switch (compression) {
|
switch (compression) {
|
||||||
@ -519,7 +518,8 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
long option = 0L;
|
long option = 0L;
|
||||||
|
|
||||||
if (compression != TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE) {
|
if (compression != TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE) {
|
||||||
option = (long) entries.get(compression == TIFFExtension.COMPRESSION_CCITT_T4 ? TIFF.TAG_GROUP3OPTIONS : TIFF.TAG_GROUP4OPTIONS).getValue();
|
Entry optionsEntry = entries.get(compression == TIFFExtension.COMPRESSION_CCITT_T4 ? TIFF.TAG_GROUP3OPTIONS : TIFF.TAG_GROUP4OPTIONS);
|
||||||
|
option = ((Number) optionsEntry.getValue()).longValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry fillOrderEntry = entries.get(TIFF.TAG_FILL_ORDER);
|
Entry fillOrderEntry = entries.get(TIFF.TAG_FILL_ORDER);
|
||||||
@ -533,7 +533,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
throw new IllegalArgumentException(String.format("Unsupported TIFF compression: %d", compression));
|
throw new IllegalArgumentException(String.format("Unsupported TIFF compression: %d", compression));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPhotometricInterpretation(final ColorModel colorModel) {
|
private int getPhotometricInterpretation(final ColorModel colorModel, int compression) {
|
||||||
if (colorModel.getPixelSize() == 1) {
|
if (colorModel.getPixelSize() == 1) {
|
||||||
if (colorModel instanceof IndexColorModel) {
|
if (colorModel instanceof IndexColorModel) {
|
||||||
if (colorModel.getRGB(0) == 0xFFFFFFFF && colorModel.getRGB(1) == 0xFF000000) {
|
if (colorModel.getRGB(0) == 0xFFFFFFFF && colorModel.getRGB(1) == 0xFF000000) {
|
||||||
@ -555,7 +555,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
case ColorSpace.TYPE_GRAY:
|
case ColorSpace.TYPE_GRAY:
|
||||||
return TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO;
|
return TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO;
|
||||||
case ColorSpace.TYPE_RGB:
|
case ColorSpace.TYPE_RGB:
|
||||||
return TIFFBaseline.PHOTOMETRIC_RGB;
|
return compression == TIFFExtension.COMPRESSION_JPEG ? TIFFExtension.PHOTOMETRIC_YCBCR : TIFFBaseline.PHOTOMETRIC_RGB;
|
||||||
case ColorSpace.TYPE_CMYK:
|
case ColorSpace.TYPE_CMYK:
|
||||||
return TIFFExtension.PHOTOMETRIC_SEPARATED;
|
return TIFFExtension.PHOTOMETRIC_SEPARATED;
|
||||||
}
|
}
|
||||||
@ -862,8 +862,17 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Set values from imageType
|
int compression;
|
||||||
entries.put(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, TIFF.TYPE_SHORT, getPhotometricInterpretation(imageType.getColorModel())));
|
if ((param == null || param.getCompressionMode() == TIFFImageWriteParam.MODE_COPY_FROM_METADATA)
|
||||||
|
&& ifd != null && ifd.getEntryById(TIFF.TAG_COMPRESSION) != null) {
|
||||||
|
compression = ((Number) ifd.getEntryById(TIFF.TAG_COMPRESSION).getValue()).intValue();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
compression = TIFFImageWriteParam.getCompressionType(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
int photometricInterpretation = getPhotometricInterpretation(imageType.getColorModel(), compression);
|
||||||
|
entries.put(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, new TIFFEntry(TIFF.TAG_PHOTOMETRIC_INTERPRETATION, TIFF.TYPE_SHORT, photometricInterpretation));
|
||||||
|
|
||||||
// TODO: Set values from param if != null + combined values...
|
// TODO: Set values from param if != null + combined values...
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -921,4 +922,111 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTestCase {
|
|||||||
byte[] bytes = output.toByteArray();
|
byte[] bytes = output.toByteArray();
|
||||||
assertArrayEquals(new byte[] {'I', 'I', 42, 0}, Arrays.copyOf(bytes, 4));
|
assertArrayEquals(new byte[] {'I', 'I', 42, 0}, Arrays.copyOf(bytes, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRewrite() throws IOException {
|
||||||
|
ImageWriter writer = createImageWriter();
|
||||||
|
ImageReader reader = ImageIO.getImageReader(writer);
|
||||||
|
|
||||||
|
List<URL> testData = Arrays.asList(
|
||||||
|
getClassLoaderResource("/tiff/pixtiff/17-tiff-binary-ccitt-group3.tif"),
|
||||||
|
getClassLoaderResource("/tiff/pixtiff/36-tiff-8-bit-gray-jpeg.tif"),
|
||||||
|
getClassLoaderResource("/tiff/pixtiff/51-tiff-24-bit-color-jpeg.tif"),
|
||||||
|
getClassLoaderResource("/tiff/pixtiff/58-plexustiff-binary-ccitt-group4.tif"),
|
||||||
|
getClassLoaderResource("/tiff/balloons.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ColorCheckerCalculator.tif"),
|
||||||
|
getClassLoaderResource("/tiff/quad-jpeg.tif"),
|
||||||
|
getClassLoaderResource("/tiff/quad-lzw.tif"),
|
||||||
|
getClassLoaderResource("/tiff/old-style-jpeg-inconsistent-metadata.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ccitt/group3_1d.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ccitt/group3_2d.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ccitt/group3_1d_fill.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ccitt/group3_2d_fill.tif"),
|
||||||
|
getClassLoaderResource("/tiff/ccitt/group4.tif")
|
||||||
|
);
|
||||||
|
|
||||||
|
for (URL url : testData) {
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
try (ImageInputStream input = ImageIO.createImageInputStream(url);
|
||||||
|
ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||||
|
reader.setInput(input);
|
||||||
|
writer.setOutput(stream);
|
||||||
|
|
||||||
|
List<ImageInfo> infos = new ArrayList<>(20);
|
||||||
|
|
||||||
|
writer.prepareWriteSequence(null);
|
||||||
|
|
||||||
|
for (int i = 0; i < reader.getNumImages(true); i++) {
|
||||||
|
IIOImage image = reader.readAll(i, null);
|
||||||
|
|
||||||
|
// If compression is Old JPEG, rewrite as JPEG
|
||||||
|
// Normally, use the getAsTree method, but we don't care here if we are tied to our impl
|
||||||
|
TIFFImageMetadata metadata = (TIFFImageMetadata) image.getMetadata();
|
||||||
|
Directory ifd = metadata.getIFD();
|
||||||
|
Entry compressionEntry = ifd.getEntryById(TIFF.TAG_COMPRESSION);
|
||||||
|
|
||||||
|
int compression = compressionEntry != null ? ((Number) compressionEntry.getValue()).intValue() : TIFFBaseline.COMPRESSION_NONE;
|
||||||
|
|
||||||
|
infos.add(new ImageInfo(image.getRenderedImage().getWidth(), image.getRenderedImage().getHeight(), compression));
|
||||||
|
|
||||||
|
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||||
|
|
||||||
|
if (compression == TIFFExtension.COMPRESSION_OLD_JPEG) {
|
||||||
|
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); // Override the copy from metadata
|
||||||
|
param.setCompressionType("JPEG");
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.writeToSequence(image, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.endWriteSequence();
|
||||||
|
|
||||||
|
// File tempFile = File.createTempFile("foo-", ".tif");
|
||||||
|
// System.err.println("open " + tempFile.getAbsolutePath());
|
||||||
|
// FileUtil.write(tempFile, output.toByteArray());
|
||||||
|
|
||||||
|
try (ImageInputStream inputAfter = new ByteArrayImageInputStream(output.toByteArray())) {
|
||||||
|
reader.setInput(inputAfter);
|
||||||
|
|
||||||
|
int numImages = reader.getNumImages(true);
|
||||||
|
|
||||||
|
assertEquals("Number of pages differs from original", infos.size(), numImages);
|
||||||
|
|
||||||
|
for (int i = 0; i < numImages; i++) {
|
||||||
|
IIOImage after = reader.readAll(i, null);
|
||||||
|
ImageInfo info = infos.get(i);
|
||||||
|
|
||||||
|
TIFFImageMetadata afterMetadata = (TIFFImageMetadata) after.getMetadata();
|
||||||
|
Directory afterIfd = afterMetadata.getIFD();
|
||||||
|
Entry afterCompressionEntry = afterIfd.getEntryById(TIFF.TAG_COMPRESSION);
|
||||||
|
|
||||||
|
if (info.compression == TIFFExtension.COMPRESSION_OLD_JPEG) {
|
||||||
|
// Should rewrite this from old-style to new style
|
||||||
|
assertEquals("Old JPEG compression not rewritten as JPEG", TIFFExtension.COMPRESSION_JPEG, afterCompressionEntry.getValue());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertEquals("Compression differs from original", info.compression, ((Number) afterCompressionEntry.getValue()).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals("Image width differs from original", info.width, after.getRenderedImage().getWidth());
|
||||||
|
assertEquals("Image height differs from original", info.height, after.getRenderedImage().getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ImageInfo {
|
||||||
|
final int width;
|
||||||
|
final int height;
|
||||||
|
|
||||||
|
final int compression;
|
||||||
|
|
||||||
|
private ImageInfo(int width, int height, int compression) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.compression = compression;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user