TMI-META: Minor improvements in XMP parsing, PSD made public and faster dumping from JPEGSegmentUtil.

This commit is contained in:
Harald Kuhr 2013-09-19 09:52:47 +02:00
parent 086357694a
commit cd197afc04
4 changed files with 73 additions and 51 deletions

View File

@ -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;

View File

@ -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<JPEGSegment> 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<JPEGSegment> 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();
}
}
}

View File

@ -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;

View File

@ -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<Entry> entries = new ArrayList<Entry>();
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<Entry> entries = new ArrayList<Entry>();
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<String, List<Entry>> 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 <rdf:Alt><rdf:li> -> return a Map<String, Object> (keyed on xml:lang?)
// Support for <rdf:Alt><rdf:li> -> return a Map<String, Object> keyed on xml:lang
Map<String, Object> alternatives = new LinkedHashMap<String, Object>();
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() : "";
}