mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-04 20:15:28 -04:00
#290 TIFF Stream Medata support
This commit is contained in:
parent
18705be7f6
commit
0b030dde52
@ -75,7 +75,7 @@ import java.util.*;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import static com.twelvemonkeys.imageio.util.IIOUtil.*;
|
||||
import static com.twelvemonkeys.imageio.util.IIOUtil.createStreamAdapter;
|
||||
import static com.twelvemonkeys.imageio.util.IIOUtil.lookupProviderByName;
|
||||
|
||||
/**
|
||||
@ -2113,8 +2113,9 @@ public final class TIFFImageReader extends ImageReaderBase {
|
||||
|
||||
@Override
|
||||
public IIOMetadata getStreamMetadata() throws IOException {
|
||||
// TODO:
|
||||
return super.getStreamMetadata();
|
||||
readMetadata();
|
||||
|
||||
return new TIFFStreamMetadata(imageInput.getByteOrder());
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws IOException {
|
||||
|
@ -60,6 +60,8 @@ import java.util.*;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFStreamMetadata.configureStreamByteOrder;
|
||||
|
||||
/**
|
||||
* TIFFImageWriter
|
||||
*
|
||||
@ -195,9 +197,8 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
||||
|
||||
@Override
|
||||
public void write(final IIOMetadata streamMetadata, final IIOImage image, final ImageWriteParam param) throws IOException {
|
||||
// TODO: Validate input
|
||||
assertOutput();
|
||||
// TODO: streamMetadata?
|
||||
configureStreamByteOrder(streamMetadata, imageOutput);
|
||||
|
||||
// TODO: Make TIFFEntry and possibly TIFFDirectory? public
|
||||
EXIFWriter exifWriter = new EXIFWriter();
|
||||
|
@ -35,8 +35,10 @@ import org.w3c.dom.Node;
|
||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||
|
||||
/**
|
||||
@ -56,6 +58,10 @@ public final class TIFFStreamMetadata extends IIOMetadata {
|
||||
super(false, SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, null, null, null);
|
||||
}
|
||||
|
||||
TIFFStreamMetadata(final ByteOrder byteOrder) {
|
||||
this();
|
||||
this.byteOrder = byteOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
@ -78,7 +84,7 @@ public final class TIFFStreamMetadata extends IIOMetadata {
|
||||
@Override
|
||||
public void mergeTree(final String formatName, final Node root) throws IIOInvalidTreeException {
|
||||
Validate.isTrue(nativeMetadataFormatName.equals(formatName), formatName, "Unsupported metadata format: %s");
|
||||
Validate.notNull(root, "root");
|
||||
notNull(root, "root");
|
||||
|
||||
if (!nativeMetadataFormatName.equals(root.getNodeName())) {
|
||||
throw new IIOInvalidTreeException("Root must be " + nativeMetadataFormatName, root);
|
||||
@ -90,8 +96,8 @@ public final class TIFFStreamMetadata extends IIOMetadata {
|
||||
}
|
||||
|
||||
NamedNodeMap attributes = node.getAttributes();
|
||||
String value = attributes.getNamedItem("value").getNodeValue();
|
||||
|
||||
String value = attributes.getNamedItem("value").getNodeValue();
|
||||
if (value == null) {
|
||||
throw new IIOInvalidTreeException("Missing \"value\" attribute in \"ByteOrder\" node", node);
|
||||
}
|
||||
@ -121,4 +127,19 @@ public final class TIFFStreamMetadata extends IIOMetadata {
|
||||
// Big endian is always the default
|
||||
byteOrder = BIG_ENDIAN;
|
||||
}
|
||||
|
||||
static void configureStreamByteOrder(final IIOMetadata streamMetadata, final ImageOutputStream imageOutput) throws IIOInvalidTreeException {
|
||||
notNull(imageOutput, "imageOutput");
|
||||
|
||||
if (streamMetadata instanceof TIFFStreamMetadata) {
|
||||
imageOutput.setByteOrder(((TIFFStreamMetadata) streamMetadata).byteOrder);
|
||||
}
|
||||
else if (streamMetadata != null) {
|
||||
TIFFStreamMetadata metadata = new TIFFStreamMetadata();
|
||||
// Will throw exception if stream format differs from native
|
||||
metadata.mergeTree(metadata.nativeMetadataFormatName, streamMetadata.getAsTree(metadata.nativeMetadataFormatName));
|
||||
imageOutput.setByteOrder(metadata.byteOrder);
|
||||
}
|
||||
// else, leave as-is
|
||||
}
|
||||
}
|
||||
|
@ -34,16 +34,19 @@ import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageReadParam;
|
||||
import javax.imageio.ImageReader;
|
||||
import javax.imageio.event.IIOReadWarningListener;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.spi.ImageReaderSpi;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.internal.matchers.StringContains.containsString;
|
||||
import static org.mockito.Matchers.contains;
|
||||
@ -560,4 +563,44 @@ public class TIFFImageReaderTest extends ImageReaderAbstractTest<TIFFImageReader
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStreamMetadataNonNull() {
|
||||
ImageReader reader = createReader();
|
||||
|
||||
for (TestData data : getTestData()) {
|
||||
reader.setInput(data.getInputStream());
|
||||
|
||||
try {
|
||||
IIOMetadata streamMetadata = reader.getStreamMetadata();
|
||||
assertNotNull(streamMetadata);
|
||||
assertThat(streamMetadata, is(TIFFStreamMetadata.class));
|
||||
}
|
||||
catch (Exception e) {
|
||||
failBecause(String.format("Image %s could not be read: %s", data.getInput(), e), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStreamMetadataII() throws IOException {
|
||||
ImageReader reader = createReader();
|
||||
|
||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/tiff/ccitt_tolessrows.tif"))) {
|
||||
reader.setInput(stream);
|
||||
TIFFStreamMetadata streamMetadata = (TIFFStreamMetadata) reader.getStreamMetadata();
|
||||
assertEquals(ByteOrder.LITTLE_ENDIAN, streamMetadata.byteOrder);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStreamMetadataMM() throws IOException {
|
||||
ImageReader reader = createReader();
|
||||
|
||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getClassLoaderResource("/tiff/sm_colors_pb.tif"))) {
|
||||
reader.setInput(stream);
|
||||
TIFFStreamMetadata streamMetadata = (TIFFStreamMetadata) reader.getStreamMetadata();
|
||||
assertEquals(ByteOrder.BIG_ENDIAN, streamMetadata.byteOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +48,11 @@ import javax.imageio.stream.ImageOutputStream;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@ -789,4 +790,68 @@ public class TIFFImageWriterTest extends ImageWriterAbstractTestCase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteStreamMetadataDefaultMM() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN); // Should pass through
|
||||
writer.setOutput(stream);
|
||||
|
||||
writer.write(null, new IIOImage(getTestData(0), null, null), null);
|
||||
}
|
||||
|
||||
byte[] bytes = output.toByteArray();
|
||||
assertArrayEquals(new byte[] {'M', 'M', 0, 42}, Arrays.copyOf(bytes, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteStreamMetadataDefaultII() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); // Should pass through
|
||||
writer.setOutput(stream);
|
||||
|
||||
writer.write(null, new IIOImage(getTestData(0), null, null), null);
|
||||
}
|
||||
|
||||
byte[] bytes = output.toByteArray();
|
||||
assertArrayEquals(new byte[] {'I', 'I', 42, 0}, Arrays.copyOf(bytes, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteStreamMetadataMM() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||
stream.setByteOrder(ByteOrder.LITTLE_ENDIAN); // Should be overridden by stream metadata
|
||||
writer.setOutput(stream);
|
||||
|
||||
writer.write(new TIFFStreamMetadata(ByteOrder.BIG_ENDIAN), new IIOImage(getTestData(0), null, null), null);
|
||||
}
|
||||
|
||||
byte[] bytes = output.toByteArray();
|
||||
assertArrayEquals(new byte[] {'M', 'M', 0, 42}, Arrays.copyOf(bytes, 4));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteStreamMetadataII() throws IOException {
|
||||
ImageWriter writer = createImageWriter();
|
||||
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
try (ImageOutputStream stream = ImageIO.createImageOutputStream(output)) {
|
||||
stream.setByteOrder(ByteOrder.BIG_ENDIAN); // Should be overridden by stream metadata
|
||||
writer.setOutput(stream);
|
||||
|
||||
writer.write(new TIFFStreamMetadata(ByteOrder.LITTLE_ENDIAN), new IIOImage(getTestData(0), null, null), null);
|
||||
}
|
||||
|
||||
byte[] bytes = output.toByteArray();
|
||||
assertArrayEquals(new byte[] {'I', 'I', 42, 0}, Arrays.copyOf(bytes, 4));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,139 @@
|
||||
package com.twelvemonkeys.imageio.plugins.tiff;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.imageio.metadata.IIOInvalidTreeException;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static com.twelvemonkeys.imageio.plugins.tiff.TIFFStreamMetadata.SUN_NATIVE_STREAM_METADATA_FORMAT_NAME;
|
||||
import static java.nio.ByteOrder.BIG_ENDIAN;
|
||||
import static java.nio.ByteOrder.LITTLE_ENDIAN;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* TIFFStreamMetadataTest
|
||||
*/
|
||||
public class TIFFStreamMetadataTest {
|
||||
// Test that we configure byte order of stream correctly (MM + II)
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testConfigureStreamNullStream() throws IIOInvalidTreeException {
|
||||
TIFFStreamMetadata.configureStreamByteOrder(new TIFFStreamMetadata(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureStreamNullMetadata() throws IIOInvalidTreeException {
|
||||
ImageOutputStream stream = mock(ImageOutputStream.class);
|
||||
TIFFStreamMetadata.configureStreamByteOrder(null, stream);
|
||||
|
||||
verify(stream, never()).setByteOrder(any(ByteOrder.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureStreamMM() throws IIOInvalidTreeException {
|
||||
ImageOutputStream stream = mock(ImageOutputStream.class);
|
||||
TIFFStreamMetadata.configureStreamByteOrder(new TIFFStreamMetadata(BIG_ENDIAN), stream);
|
||||
|
||||
verify(stream, only()).setByteOrder(BIG_ENDIAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureStreamII() throws IIOInvalidTreeException {
|
||||
ImageOutputStream stream = mock(ImageOutputStream.class);
|
||||
TIFFStreamMetadata.configureStreamByteOrder(new TIFFStreamMetadata(LITTLE_ENDIAN), stream);
|
||||
|
||||
verify(stream, only()).setByteOrder(LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigureStreamForegin() throws IIOInvalidTreeException {
|
||||
ImageOutputStream stream = mock(ImageOutputStream.class);
|
||||
IIOMetadata metadata = mock(IIOMetadata.class);
|
||||
when(metadata.getAsTree(eq(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME))).thenReturn(createForeignTree(LITTLE_ENDIAN));
|
||||
|
||||
TIFFStreamMetadata.configureStreamByteOrder(metadata, stream);
|
||||
|
||||
verify(stream, only()).setByteOrder(LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
private IIOMetadataNode createForeignTree(ByteOrder order) {
|
||||
IIOMetadataNode root = new IIOMetadataNode(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME);
|
||||
IIOMetadataNode byteOrder = new IIOMetadataNode("ByteOrder");
|
||||
byteOrder.setAttribute("value", order == LITTLE_ENDIAN ? "LITTLE_ENDIAN" : "BIG_ENDIAN");
|
||||
root.appendChild(byteOrder);
|
||||
return root;
|
||||
}
|
||||
|
||||
// Test that we merge correctly with "forreign" metadata class, as long as format names are the same (MM + II)
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMergeNull() throws IIOInvalidTreeException {
|
||||
new TIFFStreamMetadata().mergeTree(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testMergeIllegal() throws IIOInvalidTreeException {
|
||||
new TIFFStreamMetadata().mergeTree("com.foo.bar", createForeignTree(BIG_ENDIAN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeII() throws IIOInvalidTreeException {
|
||||
TIFFStreamMetadata metadata = new TIFFStreamMetadata();
|
||||
metadata.mergeTree(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, createForeignTree(LITTLE_ENDIAN));
|
||||
assertEquals(LITTLE_ENDIAN, metadata.byteOrder);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMergeMM() throws IIOInvalidTreeException {
|
||||
TIFFStreamMetadata metadata = new TIFFStreamMetadata();
|
||||
metadata.byteOrder = LITTLE_ENDIAN;
|
||||
metadata.mergeTree(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, createForeignTree(BIG_ENDIAN));
|
||||
assertEquals(BIG_ENDIAN, metadata.byteOrder);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetAsTreeNull() {
|
||||
new TIFFStreamMetadata().getAsTree(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetAsTreeIllegal() {
|
||||
new TIFFStreamMetadata().getAsTree("com.foo.bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAsTreeNative() {
|
||||
Node root = new TIFFStreamMetadata().getAsTree(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME);
|
||||
assertNotNull(root);
|
||||
assertThat(root, is(IIOMetadataNode.class));
|
||||
assertEquals(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, root.getNodeName());
|
||||
NodeList childNodes = root.getChildNodes();
|
||||
assertEquals(1, childNodes.getLength());
|
||||
assertThat(childNodes.item(0), is(IIOMetadataNode.class));
|
||||
IIOMetadataNode byteOrder = (IIOMetadataNode) childNodes.item(0);
|
||||
assertEquals("ByteOrder", byteOrder.getNodeName());
|
||||
assertEquals("BIG_ENDIAN", byteOrder.getAttribute("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAsTreeNativeII() {
|
||||
Node root = new TIFFStreamMetadata(LITTLE_ENDIAN).getAsTree(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME);
|
||||
assertNotNull(root);
|
||||
assertThat(root, is(IIOMetadataNode.class));
|
||||
assertEquals(SUN_NATIVE_STREAM_METADATA_FORMAT_NAME, root.getNodeName());
|
||||
NodeList childNodes = root.getChildNodes();
|
||||
assertEquals(1, childNodes.getLength());
|
||||
assertThat(childNodes.item(0), is(IIOMetadataNode.class));
|
||||
IIOMetadataNode byteOrder = (IIOMetadataNode) childNodes.item(0);
|
||||
assertEquals("ByteOrder", byteOrder.getNodeName());
|
||||
assertEquals("LITTLE_ENDIAN", byteOrder.getAttribute("value"));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user