Pick up Exif "SceneType" for camera detection

This commit is contained in:
N-Pex 2025-11-03 09:17:09 +01:00
parent c66602deb7
commit d26f72baec

View file

@ -148,6 +148,7 @@ const pathsC2PACreationDate = (): FlagValue[] => {
const pathsC2PACamera = (): FlagValue[] => { const pathsC2PACamera = (): FlagValue[] => {
return [ return [
{path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data{exif:SceneType=1|directly photographed image}"},
{path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensMake"}, {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensMake"},
{path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensModel"}, {path: "integrity/c2pa/manifest_info/manifests[]/assertions[label=stds.exif]/data/exif:LensModel"},
]; ];
@ -155,6 +156,7 @@ const pathsC2PACamera = (): FlagValue[] => {
const pathsExifCamera = (): FlagValue[] => { const pathsExifCamera = (): FlagValue[] => {
return [ return [
{path: "integrity/exif{SceneType=1|directly photographed image}"},
{path: "integrity/exif/LensMake"}, {path: "integrity/exif/LensMake"},
{path: "integrity/exif/LensModel"}, {path: "integrity/exif/LensModel"},
]; ];
@ -267,44 +269,62 @@ const extractFlagValues = (flagPath: string, path: FlagMatchRulePathSegment[]):
const o = path[0].object; const o = path[0].object;
let key = keys[0]; let key = keys[0];
const lastBracket = key.lastIndexOf("[");
if (key === "..") { if (key === "..") {
return getValues(keys.slice(1), path.slice(1)); return getValues(keys.slice(1), path.slice(1));
} }
if (key.endsWith("]") && lastBracket > 0) {
const optionalConstraint = key.substring(lastBracket + 1, key.length - 1); const lastBracket = key.lastIndexOf("[");
const hasBracket = key.endsWith("]") && lastBracket > 0;
const lastBrace = key.lastIndexOf("{");
const hasBrace = key.endsWith("}") && lastBrace > 0;
let optionalConstraint: String | undefined = undefined;
if (hasBracket) {
optionalConstraint = key.substring(lastBracket + 1, key.length - 1);
key = key.substring(0, lastBracket); key = key.substring(0, lastBracket);
if (o[key] != undefined) { } else if (hasBrace) {
let opart: any[] = o[key]; optionalConstraint = key.substring(lastBrace + 1, key.length - 1);
if (!Array.isArray(opart)) { key = key.substring(0, lastBrace);
opart = Object.values(opart) ?? [];
} }
let nextObject = o[key];
let omatches: any[] = nextObject ? (Array.isArray(nextObject) ? nextObject : hasBracket ? Object.values(nextObject) : [nextObject]) : [];
// Any constraints controlling what array object(s) to consider? // Any constraints controlling what array object(s) to consider?
if (optionalConstraint) { if (optionalConstraint) {
if (optionalConstraint.startsWith("!!")) { if (optionalConstraint.startsWith("!!")) {
// Ignore this path in the tree if ANY of the values contain the constraint match. // Ignore this path in the tree if ANY of the values contain the constraint match.
const [prop, val] = optionalConstraint.substring(2).split("="); const [prop, val] = optionalConstraint.substring(2).split("=");
if (opart.some((item) => item[prop] === val)) { let valarray = val.split("|");
return undefined; if (omatches.some((item) => valarray.includes(item[prop]))) {
omatches = [];
} }
} else if (optionalConstraint.startsWith("!")) { } else if (optionalConstraint.startsWith("!")) {
const [prop, val] = optionalConstraint.substring(1).split("="); const [prop, val] = optionalConstraint.substring(1).split("=");
opart = opart.filter((item) => item[prop] !== val); let valarray = val.split("|");
omatches = omatches.filter((m) => {
return valarray.includes(m[prop]);
});
} else { } else {
const [prop, val] = optionalConstraint.split("="); const [prop, val] = optionalConstraint.split("=");
let valarray = val.split("|"); let valarray = val.split("|");
opart = opart.filter((item) => valarray.includes(item[prop])); omatches = omatches.filter((m) => {
return valarray.includes(m[prop]);
});
} }
} }
if (omatches.length > 0) {
if (keys.length == 1) { if (keys.length == 1) {
return opart.map((s, i) => { return omatches.map((oin, i) => {
return { value: o, path: [{ object: s, path: key + "[" + i + "]"}, ... path] }; return { value: oin, path: [{ object: oin, path: key + (omatches.length > 1 ? `[${i}]` : "") }, ...path] };
}); });
} else if (omatches.length == 1) {
return getValues(keys.slice(1), [{object: omatches[0], path: key}, ...path]);
} else { } else {
return opart.reduce((res: FlagMatchRuleValue[] | undefined, oin: any, i: number) => { return omatches.reduce((res: FlagMatchRuleValue[] | undefined, oin: any, i: number) => {
let matches = getValues(keys.slice(1), [ { object: oin, path: key + "[" + i + "]"}, ... path]); let matches = getValues(keys.slice(1), [{ object: oin, path: key + "[" + i + "]" }, ...path]);
if (matches) { if (matches) {
const r2 = res || []; const r2 = res || [];
r2.push(...matches); r2.push(...matches);
@ -316,17 +336,6 @@ const extractFlagValues = (flagPath: string, path: FlagMatchRulePathSegment[]):
} else { } else {
return undefined; return undefined;
} }
} else {
if (o[key] != undefined) {
if (keys.length == 1) {
return [{ value: o[key], path: [{object: o[key], path: key}, ...path] }];
} else {
return getValues(keys.slice(1), [{object: o[key], path: key}, ...path]);
}
} else {
return undefined;
}
}
}; };
let result: FlagMatchRuleValue[] = []; let result: FlagMatchRuleValue[] = [];