From cd197afc04849b69eead8c89c2937596f9a44d62 Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Thu, 19 Sep 2013 09:52:47 +0200 Subject: [PATCH] TMI-META: Minor improvements in XMP parsing, PSD made public and faster dumping from JPEGSegmentUtil. --- .../imageio/metadata/jpeg/JPEGSegment.java | 2 +- .../metadata/jpeg/JPEGSegmentUtil.java | 71 +++++++++++-------- .../imageio/metadata/psd/PSD.java | 2 +- .../imageio/metadata/xmp/XMPReader.java | 49 ++++++++----- 4 files changed, 73 insertions(+), 51 deletions(-) diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegment.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegment.java index 4de9bd34..d206f438 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegment.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegment.java @@ -87,7 +87,7 @@ public final class JPEGSegment implements Serializable { return data != null ? data.length - offset() : 0; } - private int offset() { + int offset() { String identifier = identifier(); return identifier == null ? 0 : identifier.length() + 1; diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java index 10db0713..99d08d0a 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/jpeg/JPEGSegmentUtil.java @@ -33,6 +33,7 @@ import com.twelvemonkeys.imageio.metadata.exif.EXIFReader; import com.twelvemonkeys.imageio.metadata.psd.PSDReader; import com.twelvemonkeys.imageio.metadata.xmp.XMP; import com.twelvemonkeys.imageio.metadata.xmp.XMPReader; +import com.twelvemonkeys.imageio.stream.ByteArrayImageInputStream; import javax.imageio.IIOException; import javax.imageio.ImageIO; @@ -245,38 +246,48 @@ public final class JPEGSegmentUtil { } public static void main(String[] args) throws IOException { - List segments = readSegments(ImageIO.createImageInputStream(new File(args[0])), ALL_SEGMENTS); - - for (JPEGSegment segment : segments) { - System.err.println("segment: " + segment); - - if ("Exif".equals(segment.identifier())) { - InputStream data = segment.data(); - //noinspection ResultOfMethodCallIgnored - data.read(); // Pad - - ImageInputStream stream = ImageIO.createImageInputStream(data); - - // Root entry is TIFF, that contains the EXIF sub-IFD - Directory tiff = new EXIFReader().read(stream); - System.err.println("EXIF: " + tiff); + for (String arg : args) { + if (args.length > 1) { + System.out.println("File: " + arg); + System.out.println("------"); } - else if (XMP.NS_XAP.equals(segment.identifier())) { - Directory xmp = new XMPReader().read(ImageIO.createImageInputStream(segment.data())); - System.err.println("XMP: " + xmp); + + List segments = readSegments(ImageIO.createImageInputStream(new File(arg)), ALL_SEGMENTS); + + for (JPEGSegment segment : segments) { + System.err.println("segment: " + segment); + + if ("Exif".equals(segment.identifier())) { + ImageInputStream stream = new ByteArrayImageInputStream(segment.data, segment.offset() + 1, segment.length() - 1); + + // Root entry is TIFF, that contains the EXIF sub-IFD + Directory tiff = new EXIFReader().read(stream); + System.err.println("EXIF: " + tiff); + } + else if (XMP.NS_XAP.equals(segment.identifier())) { + Directory xmp = new XMPReader().read(new ByteArrayImageInputStream(segment.data, segment.offset(), segment.length())); + System.err.println("XMP: " + xmp); + System.err.println(EXIFReader.HexDump.dump(segment.data)); + } + else if ("Photoshop 3.0".equals(segment.identifier())) { + // TODO: The "Photoshop 3.0" segment contains several image resources, of which one might contain + // IPTC metadata. Probably duplicated in the XMP though... + ImageInputStream stream = new ByteArrayImageInputStream(segment.data, segment.offset(), segment.length()); + Directory psd = new PSDReader().read(stream); + System.err.println("PSD: " + psd); + System.err.println(EXIFReader.HexDump.dump(segment.data)); + } + else if ("ICC_PROFILE".equals(segment.identifier())) { + // Skip + } + else { + System.err.println(EXIFReader.HexDump.dump(segment.data)); + } } - else if ("Photoshop 3.0".equals(segment.identifier())) { - // TODO: The "Photoshop 3.0" segment contains several image resources, of which one might contain - // IPTC metadata. Probably duplicated in the XMP though... - ImageInputStream stream = ImageIO.createImageInputStream(segment.data()); - Directory psd = new PSDReader().read(stream); - System.err.println("PSD: " + psd); - } - else if ("ICC_PROFILE".equals(segment.identifier())) { - // Skip - } - else { - System.err.println(EXIFReader.HexDump.dump(segment.data)); + + if (args.length > 1) { + System.out.println("------"); + System.out.println(); } } } diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/psd/PSD.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/psd/PSD.java index 4a1b95dc..94e8edac 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/psd/PSD.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/psd/PSD.java @@ -35,7 +35,7 @@ package com.twelvemonkeys.imageio.metadata.psd; * @author last modified by $Author: haraldk$ * @version $Id: PSD.java,v 1.0 24.01.12 16:51 haraldk Exp$ */ -interface PSD { +public interface PSD { static final int RESOURCE_TYPE = ('8' << 24) + ('B' << 16) + ('I' << 8) + 'M'; static final int RES_IPTC_NAA = 0x0404; diff --git a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReader.java b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReader.java index e43d7557..642ecf7f 100644 --- a/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReader.java +++ b/imageio/imageio-metadata/src/main/java/com/twelvemonkeys/imageio/metadata/xmp/XMPReader.java @@ -128,20 +128,8 @@ public final class XMPReader extends MetadataReader { Object value; - Node parseType = node.getAttributes().getNamedItemNS(XMP.NS_RDF, "parseType"); - if (parseType != null && "Resource".equals(parseType.getNodeValue())) { - // See: http://www.w3.org/TR/REC-rdf-syntax/#section-Syntax-parsetype-resource - List entries = new ArrayList(); - - for (Node child : asIterable(node.getChildNodes())) { - if (child.getNodeType() != Node.ELEMENT_NODE) { - continue; - } - - entries.add(new XMPEntry(child.getNamespaceURI() + child.getLocalName(), child.getLocalName(), getChildTextValue(child))); - } - - value = new RDFDescription(entries); + if (isResourceType(node)) { + value = parseAsResource(node); } else { // TODO: This method contains loads of duplication an should be cleaned up... @@ -178,6 +166,27 @@ public final class XMPReader extends MetadataReader { return new XMPDirectory(entries, toolkit); } + private boolean isResourceType(Node node) { + Node parseType = node.getAttributes().getNamedItemNS(XMP.NS_RDF, "parseType"); + + return parseType != null && "Resource".equals(parseType.getNodeValue()); + } + + private RDFDescription parseAsResource(Node node) { + // See: http://www.w3.org/TR/REC-rdf-syntax/#section-Syntax-parsetype-resource + List entries = new ArrayList(); + + for (Node child : asIterable(node.getChildNodes())) { + if (child.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + + entries.add(new XMPEntry(child.getNamespaceURI() + child.getLocalName(), child.getLocalName(), getChildTextValue(child))); + } + + return new RDFDescription(entries); + } + private void parseAttributesForKnownElements(Map> subdirs, Node desc) { // NOTE: NamedNodeMap does not have any particular order... NamedNodeMap attributes = desc.getAttributes(); @@ -201,15 +210,13 @@ public final class XMPReader extends MetadataReader { private Object getChildTextValue(final Node node) { for (Node child : asIterable(node.getChildNodes())) { if (XMP.NS_RDF.equals(child.getNamespaceURI()) && "Alt".equals(child.getLocalName())) { - // Support for -> return a Map (keyed on xml:lang?) + // Support for -> return a Map keyed on xml:lang Map alternatives = new LinkedHashMap(); for (Node alternative : asIterable(child.getChildNodes())) { if (XMP.NS_RDF.equals(alternative.getNamespaceURI()) && "li".equals(alternative.getLocalName())) { - //return getChildTextValue(alternative); NamedNodeMap attributes = alternative.getAttributes(); Node key = attributes.getNamedItem("xml:lang"); - - alternatives.put(key.getTextContent(), getChildTextValue(alternative)); + alternatives.put(key == null ? null : key.getTextContent(), getChildTextValue(alternative)); } } @@ -235,9 +242,13 @@ public final class XMPReader extends MetadataReader { } } + // Need to support rdf:parseType="Resource" here as well... + if (isResourceType(node)) { + return parseAsResource(node); + } + Node child = node.getFirstChild(); String strVal = child != null ? child.getNodeValue() : null; - return strVal != null ? strVal.trim() : ""; }