Skip to content

Commit 76a2c01

Browse files
committed
feat: sample TIFF validation, with added TAG check
1 parent cbd5e0f commit 76a2c01

File tree

8 files changed

+230
-0
lines changed

8 files changed

+230
-0
lines changed

code-samples-tiff/pom.xml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
5+
<artifactId>code-samples-tiff</artifactId>
6+
7+
<parent>
8+
<groupId>org.fugerit.java</groupId>
9+
<artifactId>code-samples</artifactId>
10+
<version>1.0.0-SNAPSHOT</version>
11+
</parent>
12+
13+
<name>Fugerit Code Samples TIFF</name>
14+
<description>My code samples.</description>
15+
16+
<licenses>
17+
<license>
18+
<name>Apache License, Version 2.0</name>
19+
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
20+
<distribution>repo</distribution>
21+
</license>
22+
</licenses>
23+
24+
<properties>
25+
<imageio-tiff-version>3.10.1</imageio-tiff-version>
26+
</properties>
27+
28+
<scm>
29+
<connection>scm:git:git://github.com/fugerit-org/code-samples.git</connection>
30+
<developerConnection>scm:git:ssh://github.com/fugerit-org/code-samples.git</developerConnection>
31+
<url>https://github.com/fugerit-org/code-samples.git</url>
32+
<tag>HEAD</tag>
33+
</scm>
34+
35+
<dependencies>
36+
37+
<dependency>
38+
<groupId>com.twelvemonkeys.imageio</groupId>
39+
<artifactId>imageio-tiff</artifactId>
40+
<version>${imageio-tiff-version}</version>
41+
</dependency>
42+
43+
</dependencies>
44+
45+
<organization>
46+
<url>https://www.fugerit.org</url>
47+
<name>Fugerit</name>
48+
</organization>
49+
50+
<url>https://www.fugerit.org/</url>
51+
52+
</project>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package org.fugerit.java.code.samples.tiff;
2+
3+
import com.twelvemonkeys.imageio.metadata.tiff.TIFFEntry;
4+
import com.twelvemonkeys.imageio.plugins.tiff.TIFFImageMetadata;
5+
import lombok.extern.slf4j.Slf4j;
6+
7+
import javax.imageio.ImageIO;
8+
import javax.imageio.ImageReader;
9+
import javax.imageio.metadata.IIOMetadata;
10+
import javax.imageio.stream.ImageInputStream;
11+
import java.io.File;
12+
import java.util.Arrays;
13+
import java.util.Iterator;
14+
import java.util.List;
15+
16+
import org.w3c.dom.Node;
17+
import org.w3c.dom.NamedNodeMap;
18+
19+
@Slf4j
20+
public class TiffMetadataValidator {
21+
22+
public static boolean validateTiffAndMetadata(File file, int... idTags) {
23+
ImageReader reader = null;
24+
try (ImageInputStream iis = ImageIO.createImageInputStream(file)) {
25+
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
26+
if (!readers.hasNext()) {
27+
log.warn("No ImageReader available for {}", file);
28+
return Boolean.TRUE;
29+
}
30+
31+
reader = readers.next();
32+
reader.setInput(iis, true);
33+
34+
IIOMetadata meta = reader.getImageMetadata(0);
35+
36+
// TIFF plugin metadata format name
37+
String[] formatNames = meta.getMetadataFormatNames();
38+
for (String format : formatNames) {
39+
log.info("Metadata format: {}", format);
40+
Node root = meta.getAsTree(format);
41+
dumpNode(root, 0);
42+
}
43+
44+
if (meta instanceof TIFFImageMetadata) {
45+
for ( int idTag : idTags ) {
46+
TIFFImageMetadata tiffMeta = (TIFFImageMetadata) meta;
47+
TIFFEntry entry = (TIFFEntry) tiffMeta.getTIFFField(idTag);
48+
if (entry == null) {
49+
return Boolean.FALSE;
50+
}
51+
}
52+
} else {
53+
return Boolean.FALSE;
54+
}
55+
56+
return Boolean.TRUE;
57+
58+
} catch (Exception e) {
59+
log.error("Error reading TIFF metadata from {}: {}", file, e.getMessage(), e);
60+
return Boolean.FALSE;
61+
} finally {
62+
if (reader != null) {
63+
reader.dispose();
64+
}
65+
}
66+
}
67+
68+
private static void dumpNode(Node node, int level) {
69+
StringBuilder sb = new StringBuilder();
70+
for (int i = 0; i < level; i++) {
71+
sb.append(" ");
72+
}
73+
String indent = sb.toString();
74+
log.info("{}Node: {}", indent, node.getNodeName());
75+
76+
NamedNodeMap attributes = node.getAttributes();
77+
if (attributes != null) {
78+
for (int i = 0; i < attributes.getLength(); i++) {
79+
Node attr = attributes.item(i);
80+
log.info("{} @{} = {}", indent, attr.getNodeName(), attr.getNodeValue());
81+
}
82+
}
83+
84+
Node child = node.getFirstChild();
85+
while (child != null) {
86+
dumpNode(child, level + 1);
87+
child = child.getNextSibling();
88+
}
89+
}
90+
91+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.fugerit.java.code.samples.tiff;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
5+
import javax.imageio.ImageIO;
6+
import javax.imageio.ImageReader;
7+
import javax.imageio.stream.ImageInputStream;
8+
import java.io.File;
9+
import java.util.Iterator;
10+
11+
@Slf4j
12+
public class TiffValidator {
13+
14+
private TiffValidator() {}
15+
16+
public static boolean isValidTiff(File file) {
17+
try (ImageInputStream iis = ImageIO.createImageInputStream(file)) {
18+
if (iis == null) {
19+
return false;
20+
}
21+
22+
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
23+
if (!readers.hasNext()) {
24+
return false; // no reader for this format
25+
}
26+
27+
ImageReader reader = readers.next();
28+
reader.setInput(iis, true);
29+
reader.read(0); // try reading first page/frame
30+
reader.dispose();
31+
32+
return Boolean.TRUE;
33+
} catch (Exception e) {
34+
log.error( e.getMessage(), e );
35+
return Boolean.FALSE;
36+
}
37+
}
38+
39+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.fugerit.java.code.samples.tiff;
2+
3+
import com.twelvemonkeys.imageio.metadata.exif.TIFF;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.junit.jupiter.api.Assertions;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.io.File;
9+
10+
@Slf4j
11+
public class TiffMetadataValidatorTest {
12+
13+
@Test
14+
void testValidTiffNotValid() {
15+
File sampleFile = new File("src/test/resources/sample/sample.tiff");
16+
boolean res = TiffMetadataValidator.validateTiffAndMetadata( sampleFile, TIFF.TAG_X_RESOLUTION );
17+
Assertions.assertFalse(res);
18+
}
19+
20+
@Test
21+
void testValidTiffValid() {
22+
File sampleFile = new File("src/test/resources/sample/file_example_TIFF_1MB.tiff");
23+
boolean res = TiffMetadataValidator.validateTiffAndMetadata( sampleFile, TIFF.TAG_X_RESOLUTION );
24+
Assertions.assertTrue(res);
25+
}
26+
27+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.fugerit.java.code.samples.tiff;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.junit.jupiter.api.Assertions;
5+
import org.junit.jupiter.api.Test;
6+
7+
import java.io.File;
8+
9+
@Slf4j
10+
class TiffValidatorTest {
11+
12+
@Test
13+
void testValidTiff() {
14+
File sampleFile = new File("src/test/resources/sample/sample.tiff");
15+
boolean valid = TiffValidator.isValidTiff( sampleFile );
16+
log.info( "validation result : {} -> {}", valid, sampleFile.getAbsolutePath() );
17+
Assertions.assertTrue(valid);
18+
}
19+
20+
}
Binary file not shown.
88 KB
Binary file not shown.

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<module>code-samples-openpdf</module>
3636
<module>code-samples-itext2</module>
3737
<module>code-samples-fop</module>
38+
<module>code-samples-tiff</module>
3839
</modules>
3940

4041
<scm>

0 commit comments

Comments
 (0)