mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-01 00:00:02 -04:00
#204 TIFF metadata refactor
This commit is contained in:
+1
-15
@@ -30,8 +30,8 @@ package com.twelvemonkeys.imageio.metadata.exif;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.MetadataReaderAbstractTest;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -149,20 +149,6 @@ public class EXIFReaderTest extends MetadataReaderAbstractTest {
|
||||
assertEquals("", directory.getEntryById(TIFF.TAG_IMAGE_DESCRIPTION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBadDataRationalZeroDenominator() throws IOException {
|
||||
// This image seems to contain bad Exif. But as other tools are able to read, so should we..
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-rgb-thumbnail-bad-exif-kodak-dc210.jpg"));
|
||||
stream.seek(12);
|
||||
Directory directory = createReader().read(new SubImageInputStream(stream, 21674));
|
||||
|
||||
// Special case: Rational with zero-denominator inside EXIF data
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
Entry entry = exif.getEntryById(EXIF.TAG_COMPRESSED_BITS_PER_PIXEL);
|
||||
assertNotNull(entry);
|
||||
assertEquals(Rational.NaN, entry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBadDirectoryCount() throws IOException {
|
||||
// This image seems to contain bad Exif. But as other tools are able to read, so should we..
|
||||
|
||||
+27
-76
@@ -29,6 +29,10 @@
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.*;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFWriter;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||
import org.junit.Test;
|
||||
@@ -41,18 +45,16 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* EXIFWriterTest
|
||||
* TIFFWriterTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: EXIFWriterTest.java,v 1.0 18.07.13 09:53 haraldk Exp$
|
||||
* @version $Id: TIFFWriterTest.java,v 1.0 18.07.13 09:53 haraldk Exp$
|
||||
*/
|
||||
public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
|
||||
@@ -61,28 +63,28 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
return getResource("/exif/exif-jpeg-segment.bin").openStream();
|
||||
}
|
||||
|
||||
protected EXIFReader createReader() {
|
||||
return new EXIFReader();
|
||||
protected TIFFReader createReader() {
|
||||
return new TIFFReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EXIFWriter createWriter() {
|
||||
return new EXIFWriter();
|
||||
protected TIFFWriter createWriter() {
|
||||
return new TIFFWriter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteReadSimple() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new EXIFEntry(TIFF.TAG_ORIENTATION, 1, TIFF.TYPE_SHORT));
|
||||
entries.add(new EXIFEntry(TIFF.TAG_IMAGE_WIDTH, 1600, TIFF.TYPE_SHORT));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ORIENTATION, TIFF.TYPE_SHORT, 1));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_SHORT, 1600));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_IMAGE_HEIGHT, 900) {});
|
||||
entries.add(new EXIFEntry(TIFF.TAG_ARTIST, "Harald K.", TIFF.TYPE_ASCII));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ARTIST, TIFF.TYPE_ASCII, "Harald K."));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
new EXIFWriter().write(directory, imageStream);
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
@@ -95,13 +97,11 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
assertEquals(0, data[2]);
|
||||
assertEquals(42, data[3]);
|
||||
|
||||
Directory read = new EXIFReader().read(new ByteArrayImageInputStream(data));
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(5, read.size());
|
||||
|
||||
// TODO: Assert that the tags are written in ascending order (don't test the read directory, but the file structure)!
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertEquals("TwelveMonkeys ImageIO", read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
|
||||
@@ -122,7 +122,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
public void testWriteMotorola() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
entries.add(new EXIFEntry(TIFF.TAG_IMAGE_WIDTH, Integer.MAX_VALUE, TIFF.TYPE_LONG));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_LONG, Integer.MAX_VALUE));
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
@@ -130,7 +130,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
|
||||
imageStream.setByteOrder(ByteOrder.BIG_ENDIAN); // BE = Motorola
|
||||
|
||||
new EXIFWriter().write(directory, imageStream);
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
@@ -143,7 +143,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
assertEquals(0, data[2]);
|
||||
assertEquals(42, data[3]);
|
||||
|
||||
Directory read = new EXIFReader().read(new ByteArrayImageInputStream(data));
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(2, read.size());
|
||||
@@ -157,7 +157,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
public void testWriteIntel() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
entries.add(new EXIFEntry(TIFF.TAG_IMAGE_WIDTH, Integer.MAX_VALUE, TIFF.TYPE_LONG));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_LONG, Integer.MAX_VALUE));
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
@@ -165,7 +165,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
|
||||
imageStream.setByteOrder(ByteOrder.LITTLE_ENDIAN); // LE = Intel
|
||||
|
||||
new EXIFWriter().write(directory, imageStream);
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
@@ -178,7 +178,7 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
assertEquals(42, data[2]);
|
||||
assertEquals(0, data[3]);
|
||||
|
||||
Directory read = new EXIFReader().read(new ByteArrayImageInputStream(data));
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(2, read.size());
|
||||
@@ -188,45 +188,15 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
assertEquals((long) Integer.MAX_VALUE, read.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNesting() throws IOException {
|
||||
EXIFEntry artist = new EXIFEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO", TIFF.TYPE_ASCII);
|
||||
|
||||
EXIFEntry subSubSubSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(artist)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subSubSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubSubSubIFD)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubSubIFD)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubIFD)), TIFF.TYPE_LONG);
|
||||
|
||||
Directory directory = new IFD(Collections.<Entry>singletonList(subIFD));
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
|
||||
new EXIFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
|
||||
Directory read = new EXIFReader().read(new ByteArrayImageInputStream(output.toByteArray()));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(1, read.size());
|
||||
assertEquals(subIFD, read.getEntryById(TIFF.TAG_SUB_IFD)); // Recursively tests content!
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWriteRead() throws IOException {
|
||||
Directory original = createReader().read(getDataAsIIS());
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(256);
|
||||
ImageOutputStream imageOutput = ImageIO.createImageOutputStream(output);
|
||||
|
||||
try {
|
||||
try (ImageOutputStream imageOutput = ImageIO.createImageOutputStream(output)) {
|
||||
createWriter().write(original, imageOutput);
|
||||
}
|
||||
finally {
|
||||
imageOutput.close();
|
||||
}
|
||||
|
||||
Directory read = createReader().read(new ByteArrayImageInputStream(output.toByteArray()));
|
||||
|
||||
@@ -236,35 +206,16 @@ public class EXIFWriterTest extends MetadataWriterAbstractTest {
|
||||
@Test
|
||||
public void testComputeIFDSize() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new EXIFEntry(TIFF.TAG_ORIENTATION, 1, TIFF.TYPE_SHORT));
|
||||
entries.add(new EXIFEntry(TIFF.TAG_IMAGE_WIDTH, 1600, TIFF.TYPE_SHORT));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ORIENTATION, TIFF.TYPE_SHORT, 1));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_SHORT, 1600));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_IMAGE_HEIGHT, 900) {});
|
||||
entries.add(new EXIFEntry(TIFF.TAG_ARTIST, "Harald K.", TIFF.TYPE_ASCII));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ARTIST, TIFF.TYPE_ASCII, "Harald K."));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
|
||||
EXIFWriter writer = createWriter();
|
||||
TIFFWriter writer = createWriter();
|
||||
|
||||
ImageOutputStream stream = new NullImageOutputStream();
|
||||
writer.write(new IFD(entries), stream);
|
||||
|
||||
assertEquals(stream.getStreamPosition(), writer.computeIFDSize(entries) + 12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeIFDSizeNested() throws IOException {
|
||||
EXIFEntry artist = new EXIFEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO", TIFF.TYPE_ASCII);
|
||||
|
||||
EXIFEntry subSubSubSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(artist)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subSubSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubSubSubIFD)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subSubIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubSubIFD)), TIFF.TYPE_LONG);
|
||||
EXIFEntry subIFD = new EXIFEntry(TIFF.TAG_SUB_IFD, new IFD(Collections.singletonList(subSubIFD)), TIFF.TYPE_LONG);
|
||||
|
||||
List<Entry> entries = Collections.<Entry>singletonList(subIFD);
|
||||
|
||||
EXIFWriter writer = createWriter();
|
||||
|
||||
ImageOutputStream stream = new NullImageOutputStream();
|
||||
writer.write(new IFD(entries), stream);
|
||||
writer.write(entries, stream);
|
||||
|
||||
assertEquals(stream.getStreamPosition(), writer.computeIFDSize(entries) + 12);
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* RationalTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: RationalTest.java,v 1.0 Nov 18, 2009 3:23:17 PM haraldk Exp$
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class RationalTest {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testZeroDenominator() {
|
||||
new Rational(1, 0);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testLongMinValueNumerator() {
|
||||
new Rational(Long.MIN_VALUE, 1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testLongMinValueDenominator() {
|
||||
new Rational(1, Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(new Rational(0, 1), new Rational(0, 999));
|
||||
assertEquals(new Rational(0, 1), new Rational(0, -1));
|
||||
assertEquals(new Rational(1, 2), new Rational(1000000, 2000000));
|
||||
assertEquals(new Rational(1, -2), new Rational(-1, 2));
|
||||
|
||||
Rational x = new Rational(1, -2);
|
||||
Rational y = new Rational(-1000000, 2000000);
|
||||
assertEquals(x, y);
|
||||
assertEquals(x.numerator(), y.numerator());
|
||||
assertEquals(x.denominator(), y.denominator());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsBoundaries() {
|
||||
assertEquals(new Rational(Long.MAX_VALUE, Long.MAX_VALUE), new Rational(1, 1));
|
||||
|
||||
// NOTE: Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE... :-P
|
||||
assertEquals(new Rational(Long.MIN_VALUE + 1, Long.MIN_VALUE + 1), new Rational(1, 1));
|
||||
assertEquals(new Rational(Long.MIN_VALUE + 1, Long.MAX_VALUE), new Rational(-1, 1));
|
||||
assertEquals(new Rational(Long.MAX_VALUE, Long.MIN_VALUE + 1), new Rational(-1, 1));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.DirectoryAbstractTest;
|
||||
+27
-31
@@ -1,41 +1,34 @@
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* RationalTestCase
|
||||
* RationalTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: RationalTestCase.java,v 1.0 Nov 18, 2009 3:23:17 PM haraldk Exp$
|
||||
* @version $Id: RationalTest.java,v 1.0 Nov 18, 2009 3:23:17 PM haraldk Exp$
|
||||
*/
|
||||
public class RationalTestCase extends TestCase {
|
||||
public class RationalTest {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testZeroDenominator() {
|
||||
try {
|
||||
new Rational(1, 0);
|
||||
fail("IllegalArgumentException expected");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
new Rational(1, 0);
|
||||
}
|
||||
|
||||
// TODO: Find a solution to this problem, as we should be able to work with it...
|
||||
public void testLongMinValue() {
|
||||
try {
|
||||
new Rational(Long.MIN_VALUE, 1);
|
||||
fail("IllegalArgumentException expected");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
|
||||
try {
|
||||
new Rational(1, Long.MIN_VALUE);
|
||||
fail("IllegalArgumentException expected");
|
||||
}
|
||||
catch (IllegalArgumentException expected) {
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testLongMinValueNumerator() {
|
||||
new Rational(Long.MIN_VALUE, 1);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testLongMinValueDenominator() {
|
||||
new Rational(1, Long.MIN_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(new Rational(0, 1), new Rational(0, 999));
|
||||
assertEquals(new Rational(0, 1), new Rational(0, -1));
|
||||
@@ -47,9 +40,9 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(x, y);
|
||||
assertEquals(x.numerator(), y.numerator());
|
||||
assertEquals(x.denominator(), y.denominator());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsBoundaries() {
|
||||
assertEquals(new Rational(Long.MAX_VALUE, Long.MAX_VALUE), new Rational(1, 1));
|
||||
|
||||
@@ -59,16 +52,19 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(new Rational(Long.MAX_VALUE, Long.MIN_VALUE + 1), new Rational(-1, 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReciprocal() {
|
||||
assertEquals(new Rational(1, 99), new Rational(99, 1).reciprocal());
|
||||
assertEquals(new Rational(-1, 1234567), new Rational(-1234567, 1).reciprocal());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegate() {
|
||||
assertEquals(new Rational(-1, 99), new Rational(1, 99).negate());
|
||||
assertEquals(new Rational(1, 1234567), new Rational(1, -1234567).negate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlus() {
|
||||
Rational x, y;
|
||||
|
||||
@@ -96,6 +92,7 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(x, x.plus(Rational.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTimes() {
|
||||
Rational x, y;
|
||||
|
||||
@@ -113,6 +110,7 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(Rational.ZERO, x.times(Rational.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinus() {
|
||||
// 1/6 - -4/-8 = -1/3
|
||||
Rational x = new Rational(1, 6);
|
||||
@@ -123,6 +121,7 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(x, x.minus(Rational.ZERO));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDivides() {
|
||||
// 3037141/3247033 / 3246599/3037547 = 841/961
|
||||
Rational x = new Rational(3037141, 3247033);
|
||||
@@ -133,11 +132,8 @@ public class RationalTestCase extends TestCase {
|
||||
assertEquals(Rational.ZERO, new Rational(0, 386).divides(x));
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void testDivideZero() {
|
||||
try {
|
||||
new Rational(3037141, 3247033).divides(new Rational(0, 1));
|
||||
}
|
||||
catch (ArithmeticException expected) {
|
||||
}
|
||||
new Rational(3037141, 3247033).divides(new Rational(0, 1));
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectoryAbstractTest;
|
||||
@@ -35,15 +35,15 @@ import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* EXIFDirectoryTest
|
||||
* TIFFDirectoryTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: EXIFDirectoryTest.java,v 1.0 02.01.12 16:41 haraldk Exp$
|
||||
* @version $Id: TIFFDirectoryTest.java,v 1.0 02.01.12 16:41 haraldk Exp$
|
||||
*/
|
||||
public class EXIFDirectoryTest extends CompoundDirectoryAbstractTest {
|
||||
public class TIFFDirectoryTest extends CompoundDirectoryAbstractTest {
|
||||
@Override
|
||||
protected CompoundDirectory createCompoundDirectory(Collection<Directory> directories) {
|
||||
return new EXIFDirectory(directories);
|
||||
return new TIFFDirectory(directories);
|
||||
}
|
||||
}
|
||||
+6
-6
@@ -26,27 +26,27 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.EntryAbstractTest;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* EXIFEntryTest
|
||||
* TIFFEntryTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: EXIFEntryTest.java,v 1.0 02.01.12 17:35 haraldk Exp$
|
||||
* @version $Id: TIFFEntryTest.java,v 1.0 02.01.12 17:35 haraldk Exp$
|
||||
*/
|
||||
public class EXIFEntryTest extends EntryAbstractTest {
|
||||
public class TIFFEntryTest extends EntryAbstractTest {
|
||||
@Override
|
||||
protected Entry createEntry(final Object value) {
|
||||
return createEXIFEntry(TIFF.TAG_COPYRIGHT, value, (short) 2);
|
||||
}
|
||||
|
||||
private EXIFEntry createEXIFEntry(final int identifier, final Object value, final int type) {
|
||||
return new EXIFEntry(identifier, value, (short) type);
|
||||
private TIFFEntry createEXIFEntry(final int identifier, final Object value, final int type) {
|
||||
return new TIFFEntry(identifier, (short) type, value);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
import com.twelvemonkeys.imageio.metadata.Directory;
|
||||
import com.twelvemonkeys.imageio.metadata.Entry;
|
||||
import com.twelvemonkeys.imageio.metadata.MetadataReaderAbstractTest;
|
||||
import com.twelvemonkeys.imageio.metadata.exif.EXIF;
|
||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* TIFFReaderTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: TIFFReaderTest.java,v 1.0 23.12.11 13:50 haraldk Exp$
|
||||
*/
|
||||
public class TIFFReaderTest extends MetadataReaderAbstractTest {
|
||||
@Override
|
||||
protected InputStream getData() throws IOException {
|
||||
return getResource("/exif/exif-jpeg-segment.bin").openStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TIFFReader createReader() {
|
||||
return new TIFFReader();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsCompoundDirectory() throws IOException {
|
||||
Directory exif = createReader().read(getDataAsIIS());
|
||||
assertThat(exif, instanceOf(CompoundDirectory.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDirectory() throws IOException {
|
||||
CompoundDirectory exif = (CompoundDirectory) createReader().read(getDataAsIIS());
|
||||
|
||||
assertEquals(2, exif.directoryCount());
|
||||
assertNotNull(exif.getDirectory(0));
|
||||
assertNotNull(exif.getDirectory(1));
|
||||
assertEquals(exif.size(), exif.getDirectory(0).size() + exif.getDirectory(1).size());
|
||||
}
|
||||
|
||||
@Test(expected = IndexOutOfBoundsException.class)
|
||||
public void testDirectoryOutOfBounds() throws IOException {
|
||||
InputStream data = getData();
|
||||
|
||||
CompoundDirectory exif = (CompoundDirectory) createReader().read(ImageIO.createImageInputStream(data));
|
||||
|
||||
assertEquals(2, exif.directoryCount());
|
||||
assertNotNull(exif.getDirectory(exif.directoryCount()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntries() throws IOException {
|
||||
CompoundDirectory exif = (CompoundDirectory) createReader().read(getDataAsIIS());
|
||||
|
||||
// From IFD0
|
||||
assertNotNull(exif.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertEquals("Adobe Photoshop CS2 Macintosh", exif.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
assertEquals(exif.getEntryById(TIFF.TAG_SOFTWARE), exif.getEntryByFieldName("Software"));
|
||||
|
||||
// From IFD1
|
||||
assertNotNull(exif.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT));
|
||||
assertEquals((long) 418, exif.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT).getValue());
|
||||
assertEquals(exif.getEntryById(TIFF.TAG_JPEG_INTERCHANGE_FORMAT), exif.getEntryByFieldName("JPEGInterchangeFormat"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIFD0() throws IOException {
|
||||
CompoundDirectory exif = (CompoundDirectory) createReader().read(getDataAsIIS());
|
||||
|
||||
Directory ifd0 = exif.getDirectory(0);
|
||||
assertNotNull(ifd0);
|
||||
|
||||
assertNotNull(ifd0.getEntryById(TIFF.TAG_IMAGE_WIDTH));
|
||||
assertEquals(3601, ifd0.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
|
||||
assertNotNull(ifd0.getEntryById(TIFF.TAG_IMAGE_HEIGHT));
|
||||
assertEquals(4176, ifd0.getEntryById(TIFF.TAG_IMAGE_HEIGHT).getValue());
|
||||
|
||||
// Assert 'uncompressed' (there's no TIFF image here, really)
|
||||
assertNotNull(ifd0.getEntryById(TIFF.TAG_COMPRESSION));
|
||||
assertEquals(1, ifd0.getEntryById(TIFF.TAG_COMPRESSION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIFD1() throws IOException {
|
||||
CompoundDirectory exif = (CompoundDirectory) createReader().read(getDataAsIIS());
|
||||
|
||||
Directory ifd1 = exif.getDirectory(1);
|
||||
assertNotNull(ifd1);
|
||||
|
||||
// Assert 'JPEG compression' (thumbnail only)
|
||||
assertNotNull(ifd1.getEntryById(TIFF.TAG_COMPRESSION));
|
||||
assertEquals(6, ifd1.getEntryById(TIFF.TAG_COMPRESSION).getValue());
|
||||
|
||||
assertNull(ifd1.getEntryById(TIFF.TAG_IMAGE_WIDTH));
|
||||
assertNull(ifd1.getEntryById(TIFF.TAG_IMAGE_HEIGHT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBadDataZeroCount() throws IOException {
|
||||
// This image seems to contain bad Exif. But as other tools are able to read, so should we..
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-rgb-thumbnail-bad-exif-kodak-dc210.jpg"));
|
||||
stream.seek(12);
|
||||
Directory directory = createReader().read(new SubImageInputStream(stream, 21674));
|
||||
|
||||
assertEquals(22, directory.size());
|
||||
|
||||
// Special case: Ascii string with count == 0, not ok according to spec (?), but we'll let it pass
|
||||
assertEquals("", directory.getEntryById(TIFF.TAG_IMAGE_DESCRIPTION).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBadDataRationalZeroDenominator() throws IOException {
|
||||
// This image seems to contain bad Exif. But as other tools are able to read, so should we..
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-rgb-thumbnail-bad-exif-kodak-dc210.jpg"));
|
||||
stream.seek(12);
|
||||
Directory directory = createReader().read(new SubImageInputStream(stream, 21674));
|
||||
|
||||
// Special case: Rational with zero-denominator inside EXIF data
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
Entry entry = exif.getEntryById(EXIF.TAG_COMPRESSED_BITS_PER_PIXEL);
|
||||
assertNotNull(entry);
|
||||
assertEquals(Rational.NaN, entry.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadBadDirectoryCount() throws IOException {
|
||||
// This image seems to contain bad Exif. But as other tools are able to read, so should we..
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-bad-directory-entry-count.jpg"));
|
||||
stream.seek(4424 + 10);
|
||||
|
||||
Directory directory = createReader().read(new SubImageInputStream(stream, 214 - 6));
|
||||
assertEquals(7, directory.size()); // TIFF structure says 8, but the last entry isn't there
|
||||
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(3, exif.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTIFFWithBadExifIFD() throws IOException {
|
||||
// This image seems to contain bad TIFF data. But as other tools are able to read, so should we..
|
||||
// It seems that the EXIF data (at offset 494196 or 0x78a74) overlaps with a custom
|
||||
// Microsoft 'OLE Property Set' entry at 0x78a70 (UNDEFINED, count 5632)...
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/tiff/chifley_logo.tif"));
|
||||
Directory directory = createReader().read(stream);
|
||||
assertEquals(22, directory.size());
|
||||
|
||||
// Some (all?) of the EXIF data is duplicated in the XMP, meaning PhotoShop can probably re-create it
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(0, exif.size()); // EXIFTool reports "Warning: Bad ExifIFD directory"
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifJPEGWithInteropSubDirR98() throws IOException {
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-with-interop-subdir-R98.jpg"));
|
||||
stream.seek(30);
|
||||
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(new SubImageInputStream(stream, 1360));
|
||||
assertEquals(17, directory.size());
|
||||
assertEquals(2, directory.directoryCount());
|
||||
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(23, exif.size());
|
||||
|
||||
// The interop IFD is empty (entry count is 0)
|
||||
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
|
||||
assertNotNull(interop);
|
||||
assertEquals(2, interop.size());
|
||||
|
||||
assertNotNull(interop.getEntryById(1)); // InteropIndex
|
||||
assertEquals("ASCII", interop.getEntryById(1).getTypeName());
|
||||
assertEquals("R98", interop.getEntryById(1).getValue()); // Known values: R98, THM or R03
|
||||
|
||||
assertNotNull(interop.getEntryById(2)); // InteropVersion
|
||||
assertEquals("UNDEFINED", interop.getEntryById(2).getTypeName());
|
||||
assertArrayEquals(new byte[] {'0', '1', '0', '0'}, (byte[]) interop.getEntryById(2).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifJPEGWithInteropSubDirEmpty() throws IOException {
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-with-interop-subdir-empty.jpg"));
|
||||
stream.seek(30);
|
||||
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(new SubImageInputStream(stream, 1360));
|
||||
assertEquals(11, directory.size());
|
||||
assertEquals(1, directory.directoryCount());
|
||||
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(24, exif.size());
|
||||
|
||||
// The interop IFD is empty (entry count is 0)
|
||||
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
|
||||
assertNotNull(interop);
|
||||
assertEquals(0, interop.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifJPEGWithInteropSubDirEOF() throws IOException {
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-with-interop-subdir-eof.jpg"));
|
||||
stream.seek(30);
|
||||
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(new SubImageInputStream(stream, 236));
|
||||
assertEquals(8, directory.size());
|
||||
assertEquals(1, directory.directoryCount());
|
||||
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(5, exif.size());
|
||||
|
||||
// The interop IFD isn't there (offset points to outside the TIFF structure)...
|
||||
// Have double-checked using ExifTool, which says "Warning : Bad InteropOffset SubDirectory start"
|
||||
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
|
||||
assertNotNull(interop);
|
||||
assertEquals(0, interop.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifJPEGWithInteropSubDirBad() throws IOException {
|
||||
ImageInputStream stream = ImageIO.createImageInputStream(getResource("/jpeg/exif-with-interop-subdir-bad.jpg"));
|
||||
stream.seek(30);
|
||||
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(new SubImageInputStream(stream, 12185));
|
||||
assertEquals(16, directory.size());
|
||||
assertEquals(2, directory.directoryCount());
|
||||
|
||||
Directory exif = (Directory) directory.getEntryById(TIFF.TAG_EXIF_IFD).getValue();
|
||||
assertNotNull(exif);
|
||||
assertEquals(26, exif.size());
|
||||
|
||||
// JPEG starts at offset 1666 and length 10519, interop IFD points to offset 1900...
|
||||
// Have double-checked using ExifTool, which says "Warning : Bad InteropIFD directory"
|
||||
Directory interop = (Directory) exif.getEntryById(TIFF.TAG_INTEROP_IFD).getValue();
|
||||
assertNotNull(interop);
|
||||
assertEquals(0, interop.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifWithMissingEOFMarker() throws IOException {
|
||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getResource("/exif/noeof.tif"))) {
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(stream);
|
||||
assertEquals(15, directory.size());
|
||||
assertEquals(1, directory.directoryCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadExifWithEmptyTag() throws IOException {
|
||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getResource("/exif/emptyexiftag.tif"))) {
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(stream);
|
||||
assertEquals(3, directory.directoryCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadValueBeyondEOF() throws IOException {
|
||||
try (ImageInputStream stream = ImageIO.createImageInputStream(getResource("/exif/value-beyond-eof.tif"))) {
|
||||
CompoundDirectory directory = (CompoundDirectory) createReader().read(stream);
|
||||
assertEquals(1, directory.directoryCount());
|
||||
assertEquals(5, directory.size());
|
||||
|
||||
assertEquals(1, directory.getEntryById(TIFF.TAG_PHOTOMETRIC_INTERPRETATION).getValue());
|
||||
assertEquals(10, directory.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
assertEquals(10, directory.getEntryById(TIFF.TAG_IMAGE_HEIGHT).getValue());
|
||||
assertEquals(42L, directory.getEntryById(32935).getValue());
|
||||
// NOTE: Assumes current implementation, could possibly change in the future.
|
||||
assertTrue(directory.getEntryById(32934).getValue() instanceof EOFException);
|
||||
}
|
||||
}
|
||||
}
|
||||
+293
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.imageio.metadata.*;
|
||||
import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream;
|
||||
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import javax.imageio.stream.ImageOutputStreamImpl;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* TIFFWriterTest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: TIFFWriterTest.java,v 1.0 18.07.13 09:53 haraldk Exp$
|
||||
*/
|
||||
public class TIFFWriterTest extends MetadataWriterAbstractTest {
|
||||
|
||||
@Override
|
||||
protected InputStream getData() throws IOException {
|
||||
return getResource("/exif/exif-jpeg-segment.bin").openStream();
|
||||
}
|
||||
|
||||
protected TIFFReader createReader() {
|
||||
return new TIFFReader();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TIFFWriter createWriter() {
|
||||
return new TIFFWriter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteReadSimple() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ORIENTATION, TIFF.TYPE_SHORT, 1));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_SHORT, 1600));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_IMAGE_HEIGHT, 900) {});
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ARTIST, TIFF.TYPE_ASCII, "Harald K."));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
|
||||
byte[] data = output.toByteArray();
|
||||
|
||||
assertEquals(106, data.length);
|
||||
assertEquals('M', data[0]);
|
||||
assertEquals('M', data[1]);
|
||||
assertEquals(0, data[2]);
|
||||
assertEquals(42, data[3]);
|
||||
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(5, read.size());
|
||||
|
||||
// TODO: Assert that the tags are written in ascending order (don't test the read directory, but the file structure)!
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertEquals("TwelveMonkeys ImageIO", read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_IMAGE_WIDTH));
|
||||
assertEquals(1600, read.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_IMAGE_HEIGHT));
|
||||
assertEquals(900, read.getEntryById(TIFF.TAG_IMAGE_HEIGHT).getValue());
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_ORIENTATION));
|
||||
assertEquals(1, read.getEntryById(TIFF.TAG_ORIENTATION).getValue());
|
||||
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_ARTIST));
|
||||
assertEquals("Harald K.", read.getEntryById(TIFF.TAG_ARTIST).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteMotorola() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_LONG, Integer.MAX_VALUE));
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
|
||||
imageStream.setByteOrder(ByteOrder.BIG_ENDIAN); // BE = Motorola
|
||||
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
|
||||
byte[] data = output.toByteArray();
|
||||
|
||||
assertEquals(60, data.length);
|
||||
assertEquals('M', data[0]);
|
||||
assertEquals('M', data[1]);
|
||||
assertEquals(0, data[2]);
|
||||
assertEquals(42, data[3]);
|
||||
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(2, read.size());
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertEquals("TwelveMonkeys ImageIO", read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_IMAGE_WIDTH));
|
||||
assertEquals((long) Integer.MAX_VALUE, read.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteIntel() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_LONG, Integer.MAX_VALUE));
|
||||
Directory directory = new AbstractDirectory(entries) {};
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
|
||||
imageStream.setByteOrder(ByteOrder.LITTLE_ENDIAN); // LE = Intel
|
||||
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
|
||||
byte[] data = output.toByteArray();
|
||||
|
||||
assertEquals(60, data.length);
|
||||
assertEquals('I', data[0]);
|
||||
assertEquals('I', data[1]);
|
||||
assertEquals(42, data[2]);
|
||||
assertEquals(0, data[3]);
|
||||
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(data));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(2, read.size());
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_SOFTWARE));
|
||||
assertEquals("TwelveMonkeys ImageIO", read.getEntryById(TIFF.TAG_SOFTWARE).getValue());
|
||||
assertNotNull(read.getEntryById(TIFF.TAG_IMAGE_WIDTH));
|
||||
assertEquals((long) Integer.MAX_VALUE, read.getEntryById(TIFF.TAG_IMAGE_WIDTH).getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNesting() throws IOException {
|
||||
TIFFEntry artist = new TIFFEntry(TIFF.TAG_SOFTWARE, TIFF.TYPE_ASCII, "TwelveMonkeys ImageIO");
|
||||
|
||||
TIFFEntry subSubSubSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(artist)));
|
||||
TIFFEntry subSubSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubSubIFD)));
|
||||
TIFFEntry subSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubIFD)));
|
||||
TIFFEntry subIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubIFD)));
|
||||
|
||||
Directory directory = new IFD(Collections.<Entry>singletonList(subIFD));
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(1024);
|
||||
ImageOutputStream imageStream = ImageIO.createImageOutputStream(output);
|
||||
|
||||
new TIFFWriter().write(directory, imageStream);
|
||||
imageStream.flush();
|
||||
|
||||
assertEquals(output.size(), imageStream.getStreamPosition());
|
||||
|
||||
Directory read = new TIFFReader().read(new ByteArrayImageInputStream(output.toByteArray()));
|
||||
|
||||
assertNotNull(read);
|
||||
assertEquals(1, read.size());
|
||||
assertEquals(subIFD, read.getEntryById(TIFF.TAG_SUB_IFD)); // Recursively tests content!
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWriteRead() throws IOException {
|
||||
Directory original = createReader().read(getDataAsIIS());
|
||||
|
||||
ByteArrayOutputStream output = new FastByteArrayOutputStream(256);
|
||||
ImageOutputStream imageOutput = ImageIO.createImageOutputStream(output);
|
||||
|
||||
try {
|
||||
createWriter().write(original, imageOutput);
|
||||
}
|
||||
finally {
|
||||
imageOutput.close();
|
||||
}
|
||||
|
||||
Directory read = createReader().read(new ByteArrayImageInputStream(output.toByteArray()));
|
||||
|
||||
assertEquals(original, read);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeIFDSize() throws IOException {
|
||||
ArrayList<Entry> entries = new ArrayList<>();
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ORIENTATION, TIFF.TYPE_SHORT, 1));
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_WIDTH, TIFF.TYPE_SHORT, 1600));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_IMAGE_HEIGHT, 900) {});
|
||||
entries.add(new TIFFEntry(TIFF.TAG_ARTIST, TIFF.TYPE_ASCII, "Harald K."));
|
||||
entries.add(new AbstractEntry(TIFF.TAG_SOFTWARE, "TwelveMonkeys ImageIO") {});
|
||||
|
||||
TIFFWriter writer = createWriter();
|
||||
|
||||
ImageOutputStream stream = new NullImageOutputStream();
|
||||
writer.write(new IFD(entries), stream);
|
||||
|
||||
assertEquals(stream.getStreamPosition(), writer.computeIFDSize(entries) + 12);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComputeIFDSizeNested() throws IOException {
|
||||
TIFFEntry artist = new TIFFEntry(TIFF.TAG_SOFTWARE, TIFF.TYPE_ASCII, "TwelveMonkeys ImageIO");
|
||||
|
||||
TIFFEntry subSubSubSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(artist)));
|
||||
TIFFEntry subSubSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubSubIFD)));
|
||||
TIFFEntry subSubIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubSubIFD)));
|
||||
TIFFEntry subIFD = new TIFFEntry(TIFF.TAG_SUB_IFD, TIFF.TYPE_LONG, new IFD(Collections.singletonList(subSubIFD)));
|
||||
|
||||
List<Entry> entries = Collections.<Entry>singletonList(subIFD);
|
||||
|
||||
TIFFWriter writer = createWriter();
|
||||
|
||||
ImageOutputStream stream = new NullImageOutputStream();
|
||||
writer.write(new IFD(entries), stream);
|
||||
|
||||
assertEquals(stream.getStreamPosition(), writer.computeIFDSize(entries) + 12);
|
||||
}
|
||||
|
||||
private static class NullImageOutputStream extends ImageOutputStreamImpl {
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
streamPos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
streamPos += len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
throw new UnsupportedOperationException("Method read not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
throw new UnsupportedOperationException("Method read not implemented");
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.imageio.metadata.exif;
|
||||
package com.twelvemonkeys.imageio.metadata.tiff;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
|
||||
|
||||
Reference in New Issue
Block a user