Summary: Pixel JPEG XMP may contain elements (e.g. Camera:Trait, GImage:MicroVideo) without namespace declarations. In Util.readModel(), any RiotException other than the base-URI case is rethrown, aborting merge and losing XMP.
Steps to Reproduce:
Obtain Pixel-generated JPEG.
Extract APP1 XMP segments and call assembleXMP().
readModel() throws RiotException: prefix "... not bound".
Current Behavior: Parsing aborts; extended / standard merge fails; metadata lost.
Expected: Graceful repair of common undeclared Google prefixes (Camera, GImage, GPano) or selective skipping while retaining remaining triples.
Proposed Change: Pre-scan rdfXML and inject missing known namespaces before parsing. Limit catch scope; log repaired cases.
Patch sketch:
edu.illinois.library.cantaloupe.processor.codec.jpeg.Util.java
// ...existing code...
private static Model readModel(String rdfXML) {
Model model = ModelFactory.createDefaultModel();
String base = null;
// Heuristic: inject missing Google Pixel XMP namespaces
if (rdfXML != null) {
if (rdfXML.contains("Camera:") && !rdfXML.contains("xmlns:Camera=")) {
rdfXML = rdfXML.replaceFirst("<rdf:RDF",
"<rdf:RDF xmlns:Camera=\"http://ns.google.com/photos/1.0/camera/\"");
}
}
try (StringReader reader = new StringReader(rdfXML)) {
model.read(reader, base, "RDF/XML");
} catch (RiotException e) {
// ...existing code...