TMI-73: Now handles TIFF files using only the lower 8 bits of each 16 bit entry in the ColorMap.

This commit is contained in:
Harald Kuhr 2014-10-31 15:38:18 +01:00
parent 706b8a8631
commit ecc896f80d
3 changed files with 66 additions and 11 deletions

View File

@ -340,17 +340,7 @@ public class TIFFImageReader extends ImageReaderBase {
throw new IIOException("Missing ColorMap for Palette TIFF");
}
int[] cmapShort = (int[]) colorMap.getValue();
int[] cmap = new int[colorMap.valueCount() / 3];
// All reds, then greens, and finally blues
for (int i = 0; i < cmap.length; i++) {
cmap[i] = (cmapShort[i ] / 256) << 16
| (cmapShort[i + cmap.length] / 256) << 8
| (cmapShort[i + 2 * cmap.length] / 256);
}
IndexColorModel icm = new IndexColorModel(bitsPerSample, cmap.length, cmap, 0, false, -1, dataType);
IndexColorModel icm = createIndexColorModel(bitsPerSample, dataType, (int[]) colorMap.getValue());
return IndexedImageTypeSpecifier.createFromIndexColorModel(icm);
@ -413,6 +403,43 @@ public class TIFFImageReader extends ImageReaderBase {
}
}
private IndexColorModel createIndexColorModel(final int bitsPerSample, final int dataType, final int[] cmapShort) {
// According to the spec, there should be exactly 3 * bitsPerSample^2 entries in the color map for TIFF.
// Should we enforce this?
int[] cmap = new int[cmapShort.length / 3];
// We'll detect whether the color map data is 8 bit, rather than 16 bit while converting
boolean cmapIs8Bit = true;
// All reds, then greens, and finally blues
for (int i = 0; i < cmap.length; i++) {
cmap[i] = (cmapShort[i ] / 256) << 16
| (cmapShort[i + cmap.length] / 256) << 8
| (cmapShort[i + 2 * cmap.length] / 256);
if (cmapIs8Bit && cmap[i] != 0) {
cmapIs8Bit = false;
}
}
if (cmapIs8Bit) {
// This color map is using only the lower 8 bits, making the image all black.
// We'll create a new color map, based on the non-scaled 8 bit values.
processWarningOccurred("8 bit ColorMap detected.");
// All reds, then greens, and finally blues
for (int i = 0; i < cmap.length; i++) {
cmap[i] = (cmapShort[i ]) << 16
| (cmapShort[i + cmap.length]) << 8
| (cmapShort[i + 2 * cmap.length]);
}
}
return new IndexColorModel(bitsPerSample, cmap.length, cmap, 0, false, -1, dataType);
}
private int getSampleFormat() throws IIOException {
long[] value = getValueAsLongArray(TIFF.TAG_SAMPLE_FORMAT, "SampleFormat", false);

View File

@ -29,6 +29,7 @@ package com.twelvemonkeys.imageio.plugins.tiff;/*
import com.twelvemonkeys.imageio.util.ImageReaderAbstractTestCase;
import org.junit.Test;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.event.IIOReadWarningListener;
import javax.imageio.spi.ImageReaderSpi;
@ -176,4 +177,31 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTestCase<TIFFImageRe
stream.close();
}
}
@Test
public void testColorMap8Bit() throws IOException {
TestData testData = new TestData(getClassLoaderResource("/tiff/scan-lzw-8bit-colormap.tiff"), new Dimension(2550, 3300));
ImageInputStream stream = testData.getInputStream();
try {
TIFFImageReader reader = createReader();
reader.setInput(stream);
IIOReadWarningListener warningListener = mock(IIOReadWarningListener.class);
reader.addIIOReadWarningListener(warningListener);
ImageReadParam param = reader.getDefaultReadParam();
param.setSourceRegion(new Rectangle(8, 8));
BufferedImage image = reader.read(0, param);
assertNotNull(image);
assertEquals(new Dimension(8, 8), new Dimension(image.getWidth(), image.getHeight()));
assertEquals(0xffffffff, image.getRGB(0, 0)); // The pixel at 0, 0 should be white, not black
verify(warningListener, atLeastOnce()).warningOccurred(eq(reader), contains("ColorMap"));
}
finally {
stream.close();
}
}
}