Skip to content

Commit

Permalink
Retry failed XMP parse with combined standard+extended chunks
Browse files Browse the repository at this point in the history
  • Loading branch information
mattiasw committed Jul 6, 2023
1 parent 88f602a commit b4c1dbc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 6 deletions.
2 changes: 1 addition & 1 deletion dist/exif-reader.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/exif-reader.js.map

Large diffs are not rendered by default.

30 changes: 26 additions & 4 deletions src/xmp-tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,31 @@ export default {
};

function read(dataView, chunks) {
const tags = {};

if (typeof dataView === 'string') {
return readTags({}, dataView);
readTags(tags, dataView);
return tags;
}

const [standardXmp, extendedXmp] = extractCompleteChunks(dataView, chunks);

const hasStandardTags = readTags(tags, standardXmp);

if (extendedXmp) {
const hasExtendedTags = readTags(tags, extendedXmp);

if (!hasStandardTags && !hasExtendedTags) {
// Some writers are not spec-compliant in that they split an XMP
// metadata tree over both the standard XMP block and the extended
// XMP block. If we failed parsing both of the XMPs in the regular
// way, we try to combine them to see if that works better.
delete tags._raw;
readTags(tags, combineChunks(dataView, chunks));
}
}
return extractCompleteChunks(dataView, chunks).reduce(readTags, {});

return tags;
}

// The first chunk is always the regular XMP document. Then there is something
Expand Down Expand Up @@ -54,9 +75,10 @@ function readTags(tags, chunkDataView) {
tags._raw = (tags._raw || '') + raw;
const rdf = getRDF(doc);

return objectAssign(tags, parseXMPObject(convertToObject(rdf, true)));
objectAssign(tags, parseXMPObject(convertToObject(rdf, true)));
return true;
} catch (error) {
return tags;
return false;
}
}

Expand Down
25 changes: 25 additions & 0 deletions test/unit/xmp-tags-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,31 @@ describe('xmp-tags', function () {
});
});

// This is non-spec but there are files in the wild using this format.
it('should be able to handle multiple chunks where they are all part of a single XMP metadata tree', function () {
const xmlString = getXmlString(`
<rdf:Description xmlns:xmp="http://ns.example.com/xmp" xmp:MyXMPTag="4711">
</rdf:Description>
`);
const xmlString0 = xmlString.substr(0, 40);
const xmlString1 = xmlString.substr(40);
const dataView = getDataView(xmlString0 + xmlString1);

const tags = XmpTags.read(dataView, [
{dataOffset: 0, length: xmlString0.length},
{dataOffset: xmlString0.length, length: xmlString1.length},
]);

expect(tags).to.deep.equal({
_raw: xmlString0 + xmlString1,
MyXMPTag: {
value: '4711',
attributes: {},
description: '4711'
}
});
});

it('should handle when input is a regular string', () => {
const xmlString = getXmlString(`
<rdf:Description xmlns:xmp="http://ns.example.com/xmp" xmp:MyXMPTag0="4711">
Expand Down

0 comments on commit b4c1dbc

Please sign in to comment.