mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 12:05:29 -04:00
Better support for ImageTypeSpecifiers with IndexColorModel.
This commit is contained in:
parent
b55d4e8c1b
commit
4513b0c166
@ -257,18 +257,18 @@ public final class ImageTypeSpecifiers {
|
||||
return createFromIndexColorModel(new IndexColorModel(bits, colors.length, colors, 0, hasAlpha, transIndex, dataType));
|
||||
}
|
||||
|
||||
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel pColorModel) {
|
||||
return new IndexedImageTypeSpecifier(pColorModel);
|
||||
public static ImageTypeSpecifier createFromIndexColorModel(final IndexColorModel colorModel) {
|
||||
return new IndexedImageTypeSpecifier(colorModel);
|
||||
}
|
||||
|
||||
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel pColorModel) {
|
||||
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel);
|
||||
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
|
||||
public static ImageTypeSpecifier createDiscreteAlphaIndexedFromIndexColorModel(final IndexColorModel colorModel) {
|
||||
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel);
|
||||
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
|
||||
}
|
||||
|
||||
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel pColorModel, int extraSamples, boolean hasAlpha) {
|
||||
ColorModel colorModel = new DiscreteAlphaIndexColorModel(pColorModel, extraSamples, hasAlpha);
|
||||
return new ImageTypeSpecifier(colorModel, colorModel.createCompatibleSampleModel(1, 1));
|
||||
public static ImageTypeSpecifier createDiscreteExtraSamplesIndexedFromIndexColorModel(final IndexColorModel colorModel, int extraSamples, boolean hasAlpha) {
|
||||
ColorModel discreteAlphaIndexColorModel = new DiscreteAlphaIndexColorModel(colorModel, extraSamples, hasAlpha);
|
||||
return new ImageTypeSpecifier(discreteAlphaIndexColorModel, discreteAlphaIndexColorModel.createCompatibleSampleModel(1, 1));
|
||||
}
|
||||
|
||||
public static ImageTypeSpecifier createFromRenderedImage(RenderedImage image) {
|
||||
@ -279,7 +279,9 @@ public final class ImageTypeSpecifiers {
|
||||
if (image instanceof BufferedImage) {
|
||||
int bufferedImageType = ((BufferedImage) image).getType();
|
||||
|
||||
if (bufferedImageType != BufferedImage.TYPE_CUSTOM) {
|
||||
if (bufferedImageType != BufferedImage.TYPE_CUSTOM &&
|
||||
// Need to retain the actual palette in the color model for IndexColorModel
|
||||
bufferedImageType != BufferedImage.TYPE_BYTE_BINARY && bufferedImageType != BufferedImage.TYPE_BYTE_INDEXED) {
|
||||
return createFromBufferedImageType(bufferedImageType);
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +52,12 @@ final class IndexedImageTypeSpecifier extends ImageTypeSpecifier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BufferedImage createBufferedImage(final int pWidth, final int pHeight) {
|
||||
public BufferedImage createBufferedImage(final int width, final int height) {
|
||||
try {
|
||||
// This is a fix for the super-method, that first creates a sample model, and then
|
||||
// creates a raster from it, using Raster.createWritableRaster. The problem with
|
||||
// that approach, is that it always creates a TYPE_CUSTOM BufferedImage for indexed images.
|
||||
WritableRaster raster = colorModel.createCompatibleWritableRaster(pWidth, pHeight);
|
||||
WritableRaster raster = colorModel.createCompatibleWritableRaster(width, height);
|
||||
return new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
||||
}
|
||||
catch (NegativeArraySizeException e) {
|
||||
|
@ -39,6 +39,7 @@ import java.awt.color.*;
|
||||
import java.awt.image.*;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
public class ImageTypeSpecifiersTest {
|
||||
|
||||
@ -736,6 +737,7 @@ public class ImageTypeSpecifiersTest {
|
||||
ImageTypeSpecifier fromType = ImageTypeSpecifiers.createFromBufferedImageType(type);
|
||||
|
||||
assertEquals(fromConstructor.getColorModel(), fromType.getColorModel());
|
||||
assertEquals(fromConstructor.getSampleModel(), fromType.getSampleModel());
|
||||
}
|
||||
}
|
||||
|
||||
@ -747,13 +749,43 @@ public class ImageTypeSpecifiersTest {
|
||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
||||
|
||||
assertEquals(fromConstructor.getColorModel(), fromImage.getColorModel());
|
||||
assertEquals(fromConstructor.getSampleModel(), fromImage.getSampleModel());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromRenderedImageIndexedBinaryShouldRetainPalette() {
|
||||
IndexColorModel whiteIsZero = new IndexColorModel(1, 2, new int[]{0xFFFFFFFF, 0xFF000000}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
|
||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY, whiteIsZero);
|
||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
||||
|
||||
assertEquals(whiteIsZero, fromImage.getColorModel());
|
||||
assertSame(whiteIsZero, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
|
||||
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateFromRenderedImageIndexedShouldRetainPalette() {
|
||||
IndexColorModel palette = new IndexColorModel(4, 16, new int[]{
|
||||
0xFFFFFFFF, 0xFF999999, 0xFF666666, 0xFF333333,
|
||||
0xFF000000, 0xFF00202E, 0xFF003F5C, 0xFF2C4875,
|
||||
0xFF8A508F, 0xFFBC5090, 0xFFFF6361, 0xFFFF8531,
|
||||
0xFFFFA600, 0xFFFFD380, 0xFF74A892, 0xFF008585
|
||||
}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
|
||||
BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_INDEXED, palette);
|
||||
ImageTypeSpecifier fromImage = ImageTypeSpecifiers.createFromRenderedImage(image);
|
||||
|
||||
assertEquals(palette, fromImage.getColorModel());
|
||||
assertSame(palette, fromImage.getColorModel()); // Note: This can be relaxed to asserting the LUTs are equal
|
||||
assertEquals(image.getSampleModel(), fromImage.getSampleModel());
|
||||
}
|
||||
|
||||
private static byte[] createByteLut(final int count) {
|
||||
byte[] lut = new byte[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
lut[i] = (byte) count;
|
||||
lut[i] = (byte) (i * 255 / count);
|
||||
}
|
||||
return lut;
|
||||
}
|
||||
@ -762,7 +794,8 @@ public class ImageTypeSpecifiersTest {
|
||||
int[] lut = new int[count];
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lut[i] = 0xff000000 | count << 16 | count << 8 | count;
|
||||
int val = (i * 255 / count);
|
||||
lut[i] = 0xff000000 | val << 16 | val << 8 | val;
|
||||
}
|
||||
|
||||
return lut;
|
||||
|
@ -40,6 +40,7 @@ import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFWriter;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageOutputStream;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers;
|
||||
import com.twelvemonkeys.imageio.util.ProgressListenerBase;
|
||||
import com.twelvemonkeys.io.enc.EncoderStream;
|
||||
import com.twelvemonkeys.io.enc.PackBitsEncoder;
|
||||
@ -149,9 +150,9 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
||||
RenderedImage renderedImage = image.getRenderedImage();
|
||||
SampleModel sampleModel = renderedImage.getSampleModel();
|
||||
|
||||
// Can't use createFromRenderedImage in this case, as it does not consider palette for TYPE_BYTE_BINARY...
|
||||
// TODO: Consider writing workaround in ImageTypeSpecifiers
|
||||
ImageTypeSpecifier spec = new ImageTypeSpecifier(renderedImage);
|
||||
// Need ImageTypeSpecifiers.createFromRenderedImage in this case, as the JDK method does not consider
|
||||
// palette for TYPE_BYTE_BINARY/TYPE_BYTE_INDEXED...
|
||||
ImageTypeSpecifier spec = ImageTypeSpecifiers.createFromRenderedImage(renderedImage);
|
||||
|
||||
// TODO: Handle case where convertImageMetadata returns null, due to unknown metadata format, or reconsider if that's a valid case...
|
||||
TIFFImageMetadata metadata = image.getMetadata() != null
|
||||
|
@ -1304,6 +1304,60 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTest<TIFFImageWriter
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteBinaryWhiteIsZero() throws IOException {
|
||||
IndexColorModel whiteIsZero = new IndexColorModel(1, 2, new int[] {-1, 0}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, whiteIsZero);
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
|
||||
ImageWriter imageWriter = createWriter();
|
||||
imageWriter.setOutput(output);
|
||||
imageWriter.write(image);
|
||||
}
|
||||
|
||||
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
|
||||
|
||||
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
|
||||
assertEquals(TIFFBaseline.PHOTOMETRIC_WHITE_IS_ZERO, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteBinaryBlackIsZero() throws IOException {
|
||||
IndexColorModel blackIsZero = new IndexColorModel(1, 2, new int[] {0, -1}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, blackIsZero);
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
|
||||
ImageWriter imageWriter = createWriter();
|
||||
imageWriter.setOutput(output);
|
||||
imageWriter.write(image);
|
||||
}
|
||||
|
||||
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
|
||||
|
||||
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
|
||||
assertEquals(TIFFBaseline.PHOTOMETRIC_BLACK_IS_ZERO, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteBinaryPalette() throws IOException {
|
||||
IndexColorModel redAndBluePalette = new IndexColorModel(1, 2, new int[] {0xFF00FF00, 0xFF0000FF}, 0, false, -1, DataBuffer.TYPE_BYTE);
|
||||
BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_BYTE_BINARY, redAndBluePalette);
|
||||
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream output = ImageIO.createImageOutputStream(bytes)) {
|
||||
ImageWriter imageWriter = createWriter();
|
||||
imageWriter.setOutput(output);
|
||||
imageWriter.write(image);
|
||||
}
|
||||
|
||||
Directory directory = new TIFFReader().read(new ByteArrayImageInputStream(bytes.toByteArray()));
|
||||
|
||||
assertNotNull(directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION));
|
||||
assertEquals(TIFFBaseline.PHOTOMETRIC_PALETTE, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShortOverflowHuge() throws IOException {
|
||||
int width = 34769;
|
||||
|
Loading…
x
Reference in New Issue
Block a user