editmamei 0.22.4 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/dist/api/extendscript/_helpers.js +97 -13
- package/dist/api/photoshop-api.js +4 -3
- package/dist/api/snippet-client.js +38 -2
- package/dist/bin/editmamei-core-darwin-arm64 +0 -0
- package/dist/bin/editmamei-core-darwin-x64 +0 -0
- package/dist/bin/editmamei-core-win-x64.exe +0 -0
- package/dist/core/server.js +56 -180
- package/dist/delivery/client.js +50 -1
- package/dist/delivery/provision.js +18 -1
- package/dist/delivery/signing.js +38 -1
- package/dist/delivery/store.js +149 -16
- package/dist/detection/detect-active-doc.js +41 -10
- package/dist/detection/detection-client.js +3 -3
- package/dist/detection/face-detector.js +2 -2
- package/dist/detection/geometry.js +14 -0
- package/dist/detection/landmark-detection-client.js +3 -3
- package/dist/detection/mesh-face.js +2 -3
- package/dist/detection/object-detector.js +2 -2
- package/dist/detection/runtime.js +14 -3
- package/dist/detection/sam-segmenter.js +69 -26
- package/dist/kernel/kernel.js +5 -9
- package/dist/kernel/module-lifecycle.js +181 -0
- package/dist/license/entitlement.js +13 -3
- package/dist/license/store.js +8 -1
- package/dist/modules/ce/index.js +1 -1
- package/dist/perception/facets.js +19 -1
- package/dist/perception/grounding-anchors.js +2 -12
- package/dist/perception/grounding-locate.js +1 -9
- package/dist/perception/grounding-review-crop.js +4 -29
- package/dist/perception/overlay.js +62 -0
- package/dist/perception/pixel-identity.js +41 -0
- package/dist/perception/region-precompute.js +85 -17
- package/dist/perception/scene-model.js +93 -50
- package/dist/perception/select-recipes.js +107 -66
- package/dist/perception/sky-ground-flood.js +0 -5
- package/dist/perception/sky-mask-transfer.js +72 -13
- package/dist/platform/connection.js +42 -11
- package/dist/platform/executor-queue.js +68 -0
- package/dist/platform/macos-detector.js +2 -1
- package/dist/platform/macos-executor.js +18 -67
- package/dist/platform/run-child.js +6 -3
- package/dist/platform/windows-detector.js +14 -7
- package/dist/platform/windows-executor.js +9 -64
- package/dist/skills/editmamei-skill.zip +0 -0
- package/dist/tools/adjustment-tools.js +78 -130
- package/dist/tools/brush-tools.js +3 -14
- package/dist/tools/channel-compose-tools.js +4 -23
- package/dist/tools/detection-tools.js +59 -47
- package/dist/tools/document-tools.js +121 -131
- package/dist/tools/filter-tools.js +489 -730
- package/dist/tools/group-tools.js +90 -156
- package/dist/tools/guide-tools.js +52 -83
- package/dist/tools/history-tools.js +29 -63
- package/dist/tools/image-placement-tools.js +18 -37
- package/dist/tools/image-tools.js +23 -51
- package/dist/tools/layer-ordering-tools.js +2 -9
- package/dist/tools/layer-properties-tools.js +245 -384
- package/dist/tools/layer-tools.js +115 -181
- package/dist/tools/layer-transform-tools.js +41 -106
- package/dist/tools/metadata-tools.js +2 -9
- package/dist/tools/path-tools.js +3 -14
- package/dist/tools/portrait-tools.js +2 -5
- package/dist/tools/preview-tools.js +53 -65
- package/dist/tools/retouch-tools.js +32 -70
- package/dist/tools/scene-tools.js +94 -73
- package/dist/tools/selection-tools.js +306 -563
- package/dist/tools/shape-tools.js +18 -10
- package/dist/tools/text-tools.js +24 -57
- package/dist/tools/transform-canvas-tools.js +21 -54
- package/dist/tools/vector-mask-tools.js +2 -9
- package/dist/utils/jpeg-quality.js +1 -0
- package/dist/utils/logger.js +3 -0
- package/dist/utils/operation-timeouts.js +7 -0
- package/dist/utils/run-script.js +7 -2
- package/dist/utils/session-log.js +134 -12
- package/dist/utils/template-storage.js +5 -6
- package/dist/utils/tool-helpers.js +37 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { runScript } from '../utils/run-script.js';
|
|
2
|
+
import { SCENE_CHANNEL_TIMEOUT_MS } from '../utils/operation-timeouts.js';
|
|
2
3
|
import { jsLit } from '../utils/jsx.js';
|
|
3
|
-
import { restoreCompositeChannel } from '../api/extendscript/_helpers.js';
|
|
4
|
+
import { restoreCompositeChannel, getSelectionInfo } from '../api/extendscript/_helpers.js';
|
|
5
|
+
import { Logger } from '../utils/logger.js';
|
|
4
6
|
import { resolveSelection, } from './select-recipes.js';
|
|
7
|
+
const logger = new Logger('region-precompute');
|
|
5
8
|
let lastPrecomputedKey = null;
|
|
6
9
|
let cachedMenu = [];
|
|
7
10
|
export function __resetPrecompute() {
|
|
@@ -10,7 +13,7 @@ export function __resetPrecompute() {
|
|
|
10
13
|
}
|
|
11
14
|
export const CHANNEL_PREFIX = 'scene:';
|
|
12
15
|
export async function saveSelectionAsSceneChannel(connection, target) {
|
|
13
|
-
await runScript(connection, saveSelectionToNamedChannelScript(`${CHANNEL_PREFIX}${target}`));
|
|
16
|
+
await runScript(connection, saveSelectionToNamedChannelScript(`${CHANNEL_PREFIX}${target}`), SCENE_CHANNEL_TIMEOUT_MS);
|
|
14
17
|
}
|
|
15
18
|
const PRECOMPUTE_TARGETS = [
|
|
16
19
|
'sky',
|
|
@@ -36,6 +39,12 @@ function deleteSceneChannelsScript() {
|
|
|
36
39
|
return { removed: removed };
|
|
37
40
|
`;
|
|
38
41
|
}
|
|
42
|
+
export async function purgeSceneChannels(connection) {
|
|
43
|
+
const r = (await runScript(connection, deleteSceneChannelsScript(), SCENE_CHANNEL_TIMEOUT_MS));
|
|
44
|
+
lastPrecomputedKey = null;
|
|
45
|
+
cachedMenu = [];
|
|
46
|
+
return r.removed ?? 0;
|
|
47
|
+
}
|
|
39
48
|
function saveSelectionToNamedChannelScript(name) {
|
|
40
49
|
return `
|
|
41
50
|
var doc = app.activeDocument;
|
|
@@ -50,6 +59,37 @@ function saveSelectionToNamedChannelScript(name) {
|
|
|
50
59
|
return { saved: true, name: ${jsLit(name)} };
|
|
51
60
|
`;
|
|
52
61
|
}
|
|
62
|
+
function channelsExistScript(names) {
|
|
63
|
+
const namesLit = `[${names.map((n) => jsLit(n)).join(', ')}]`;
|
|
64
|
+
return `
|
|
65
|
+
// __mcp_scene_chk__ cheap existence check for previously-saved scene:* channels
|
|
66
|
+
if (app.documents.length === 0) { throw new Error('No active document'); }
|
|
67
|
+
var doc = app.activeDocument;
|
|
68
|
+
var have = {};
|
|
69
|
+
for (var i = 0; i < doc.channels.length; i++) {
|
|
70
|
+
have[String(doc.channels[i].name)] = true;
|
|
71
|
+
}
|
|
72
|
+
var names = ${namesLit};
|
|
73
|
+
var allPresent = true;
|
|
74
|
+
for (var j = 0; j < names.length; j++) {
|
|
75
|
+
if (!have[names[j]]) { allPresent = false; break; }
|
|
76
|
+
}
|
|
77
|
+
return { all_present: allPresent };
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
async function channelsExist(connection, names) {
|
|
81
|
+
if (names.length === 0)
|
|
82
|
+
return true;
|
|
83
|
+
try {
|
|
84
|
+
const r = (await runScript(connection, channelsExistScript(names)));
|
|
85
|
+
return r.all_present === true;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
logger.debug(`region-precompute: channelsExist check failed (${msg}) — treating as stale, rebuilding`);
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
53
93
|
function loadNamedChannelScript(name) {
|
|
54
94
|
return `
|
|
55
95
|
if (app.documents.length === 0) { throw new Error('No active document'); }
|
|
@@ -62,27 +102,52 @@ function loadNamedChannelScript(name) {
|
|
|
62
102
|
doc.selection.load(ch, SelectionType.REPLACE);
|
|
63
103
|
${restoreCompositeChannel}
|
|
64
104
|
restoreCompositeChannel(doc);
|
|
65
|
-
|
|
105
|
+
// Measure in the SAME round trip. The fast path used to return
|
|
106
|
+
// selection_info:null, which forced any caller that wanted to verify the mask
|
|
107
|
+
// into a second PS call — the one thing this path exists to avoid.
|
|
108
|
+
${getSelectionInfo}
|
|
109
|
+
return {
|
|
110
|
+
loaded: true,
|
|
111
|
+
width: doc.width.as('px'),
|
|
112
|
+
height: doc.height.as('px'),
|
|
113
|
+
selection_info: getSelectionInfo()
|
|
114
|
+
};
|
|
66
115
|
`;
|
|
67
116
|
}
|
|
117
|
+
function countingConnection(connection, tally) {
|
|
118
|
+
return new Proxy(connection, {
|
|
119
|
+
get(target, prop, receiver) {
|
|
120
|
+
if (prop === 'executeScript') {
|
|
121
|
+
return (script, timeoutMs) => {
|
|
122
|
+
tally.scripts++;
|
|
123
|
+
return target.executeScript(script, timeoutMs);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return Reflect.get(target, prop, receiver);
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
}
|
|
68
130
|
export async function precomputeRegions(connection, snippet, model, composition, opts = {}) {
|
|
69
131
|
if (!opts.force &&
|
|
70
132
|
lastPrecomputedKey !== null &&
|
|
71
|
-
lastPrecomputedKey === model.provenance.cache_key
|
|
133
|
+
lastPrecomputedKey === model.provenance.cache_key &&
|
|
134
|
+
(await channelsExist(connection, cachedMenu.filter((m) => !m.on_demand).map((m) => m.key)))) {
|
|
72
135
|
return cachedMenu;
|
|
73
136
|
}
|
|
74
|
-
|
|
137
|
+
const tally = { scripts: 0 };
|
|
138
|
+
const countedConnection = countingConnection(connection, tally);
|
|
139
|
+
await runScript(countedConnection, deleteSceneChannelsScript(), SCENE_CHANNEL_TIMEOUT_MS);
|
|
75
140
|
const menu = [];
|
|
76
141
|
for (const target of PRECOMPUTE_TARGETS) {
|
|
77
142
|
try {
|
|
78
|
-
const res = await resolveSelection(
|
|
143
|
+
const res = await resolveSelection(countedConnection, snippet, model, target, {
|
|
79
144
|
composition,
|
|
80
145
|
proRefine: opts.proRefine,
|
|
81
146
|
skyCtx: opts.skyCtx,
|
|
82
147
|
});
|
|
83
148
|
if (res.passed) {
|
|
84
149
|
const key = `${CHANNEL_PREFIX}${target}`;
|
|
85
|
-
await runScript(
|
|
150
|
+
await runScript(countedConnection, saveSelectionToNamedChannelScript(key), SCENE_CHANNEL_TIMEOUT_MS);
|
|
86
151
|
menu.push({
|
|
87
152
|
key,
|
|
88
153
|
target,
|
|
@@ -97,26 +162,29 @@ export async function precomputeRegions(connection, snippet, model, composition,
|
|
|
97
162
|
continue;
|
|
98
163
|
}
|
|
99
164
|
}
|
|
100
|
-
if (opts.
|
|
101
|
-
|
|
102
|
-
const faceItems = await opts.precomputeFace();
|
|
103
|
-
menu.push(...faceItems);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
}
|
|
165
|
+
if (opts.faceMenu?.length) {
|
|
166
|
+
menu.push(...opts.faceMenu);
|
|
107
167
|
}
|
|
108
168
|
try {
|
|
109
|
-
await runScript(
|
|
169
|
+
await runScript(countedConnection, await snippet.build('deselect'));
|
|
110
170
|
}
|
|
111
171
|
catch {
|
|
112
172
|
}
|
|
173
|
+
logger.debug(`precompute: ${PRECOMPUTE_TARGETS.length} targets, ${tally.scripts} scripts` +
|
|
174
|
+
` (7 CE targets ≈ 21 scripts before the 2026-07-29 derive+measure merge → 15 after, ` +
|
|
175
|
+
` then 14 once skin short-circuits with no person/face (2026-08-01), ` +
|
|
176
|
+
`on the all-fail path; production pass-paths differ)`);
|
|
113
177
|
lastPrecomputedKey = model.provenance.cache_key;
|
|
114
178
|
cachedMenu = menu;
|
|
115
179
|
return menu;
|
|
116
180
|
}
|
|
117
181
|
export async function loadPrecomputedRegion(connection, target) {
|
|
118
|
-
const r = (await runScript(connection, loadNamedChannelScript(`${CHANNEL_PREFIX}${target}`)));
|
|
182
|
+
const r = (await runScript(connection, loadNamedChannelScript(`${CHANNEL_PREFIX}${target}`), SCENE_CHANNEL_TIMEOUT_MS));
|
|
119
183
|
if (r.loaded !== true)
|
|
120
184
|
return null;
|
|
121
|
-
return {
|
|
185
|
+
return {
|
|
186
|
+
width: r.width ?? 0,
|
|
187
|
+
height: r.height ?? 0,
|
|
188
|
+
selection_info: r.selection_info ?? null,
|
|
189
|
+
};
|
|
122
190
|
}
|
|
@@ -1,36 +1,24 @@
|
|
|
1
|
-
import { decode } from 'jpeg-js';
|
|
2
1
|
import { runScript } from '../utils/run-script.js';
|
|
3
2
|
import { getContextInfo } from '../api/extendscript/_helpers.js';
|
|
4
3
|
import { detectActiveDoc } from '../detection/detect-active-doc.js';
|
|
4
|
+
import { computePixelIdentity, docKeyFrom, identityKeyString, samePixelIdentity, } from './pixel-identity.js';
|
|
5
|
+
import { Logger } from '../utils/logger.js';
|
|
5
6
|
import { computeComposition, computeTonalZones, estimateHorizon, pickThresholdLevel, boxArea, toLumaHistogram, } from './facets.js';
|
|
7
|
+
const logger = new Logger('scene-model');
|
|
6
8
|
let cache = null;
|
|
9
|
+
const NO_PIXEL_IDENTITY_COUNTER_WRAP = 1_000_000_000;
|
|
10
|
+
let noPixelIdentityCounter = 0;
|
|
11
|
+
function nextNoPixelIdentityId() {
|
|
12
|
+
noPixelIdentityCounter = (noPixelIdentityCounter + 1) % NO_PIXEL_IDENTITY_COUNTER_WRAP;
|
|
13
|
+
return noPixelIdentityCounter;
|
|
14
|
+
}
|
|
7
15
|
export function __clearSceneCache() {
|
|
8
16
|
cache = null;
|
|
9
17
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (app.documents.length === 0) { throw new Error('No active document'); }
|
|
13
|
-
var doc = app.activeDocument;
|
|
14
|
-
var id = -1;
|
|
15
|
-
try { id = doc.id; } catch (eId) {}
|
|
16
|
-
var hs = -1;
|
|
17
|
-
try { hs = doc.historyStates.length; } catch (eHs) {}
|
|
18
|
-
return { doc_id: id, history_states: hs };
|
|
19
|
-
`;
|
|
20
|
-
const r = (await runScript(connection, script));
|
|
21
|
-
return `${r.doc_id ?? -1}:${r.history_states ?? -1}`;
|
|
22
|
-
}
|
|
23
|
-
export function rowBrightnessProfile(exportBytes, strips = 64) {
|
|
24
|
-
if (!exportBytes || exportBytes.length === 0)
|
|
25
|
-
return undefined;
|
|
26
|
-
let img;
|
|
27
|
-
try {
|
|
28
|
-
img = decode(exportBytes, { useTArray: true, formatAsRGBA: true });
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
18
|
+
export function rowBrightnessProfile(decoded, strips = 64) {
|
|
19
|
+
if (!decoded)
|
|
31
20
|
return undefined;
|
|
32
|
-
}
|
|
33
|
-
const { width: w, height: h, data } = img;
|
|
21
|
+
const { width: w, height: h, data } = decoded;
|
|
34
22
|
if (w <= 0 || h <= 0)
|
|
35
23
|
return undefined;
|
|
36
24
|
const R = Math.max(1, Math.min(strips, h));
|
|
@@ -50,24 +38,55 @@ export function rowBrightnessProfile(exportBytes, strips = 64) {
|
|
|
50
38
|
}
|
|
51
39
|
export async function buildSceneModel(connection, snippet, client, opts = {}) {
|
|
52
40
|
const useCache = opts.useCache ?? true;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const cached = cache.result;
|
|
56
|
-
return {
|
|
57
|
-
...cached,
|
|
58
|
-
model: {
|
|
59
|
-
...cached.model,
|
|
60
|
-
provenance: { ...cached.model.provenance, cached: true },
|
|
61
|
-
},
|
|
62
|
-
};
|
|
63
|
-
}
|
|
41
|
+
let hit = null;
|
|
42
|
+
let freshIdentity = null;
|
|
64
43
|
const det = await detectActiveDoc(connection, client, {
|
|
65
44
|
faces: true,
|
|
66
45
|
objects: true,
|
|
67
46
|
maxDimension: opts.maxDimension,
|
|
68
47
|
objectThreshold: opts.objectThreshold,
|
|
69
48
|
faceThreshold: opts.faceThreshold,
|
|
70
|
-
|
|
49
|
+
shouldDetect: ({ decoded, context, docWidth, docHeight }) => {
|
|
50
|
+
if (!decoded)
|
|
51
|
+
return true;
|
|
52
|
+
const identity = computePixelIdentity(decoded, docKeyFrom(context, docWidth, docHeight));
|
|
53
|
+
freshIdentity = identity;
|
|
54
|
+
if (useCache && cache && samePixelIdentity(cache.identity, identity)) {
|
|
55
|
+
hit = cache;
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
},
|
|
60
|
+
}, opts.detectDeps);
|
|
61
|
+
if (hit) {
|
|
62
|
+
const cached = hit;
|
|
63
|
+
logger.debug(`scene-model: pixel-identity cache HIT (${cached.cacheKey}) — reusing detection + ` +
|
|
64
|
+
`facets, skipping ONNX + histogram + facet rebuild`);
|
|
65
|
+
const model = {
|
|
66
|
+
doc: { width: det.docWidth, height: det.docHeight },
|
|
67
|
+
subjects: cached.subjects,
|
|
68
|
+
faces: cached.faces,
|
|
69
|
+
regions: cached.regions,
|
|
70
|
+
horizon: cached.horizon,
|
|
71
|
+
tonal_zones: cached.tonalZones,
|
|
72
|
+
composition: cached.composition,
|
|
73
|
+
provenance: {
|
|
74
|
+
backends: cached.backends,
|
|
75
|
+
edition: 'ce',
|
|
76
|
+
cache_key: cached.cacheKey,
|
|
77
|
+
cached: true,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
model,
|
|
82
|
+
exportBytes: det.exportBytes,
|
|
83
|
+
decoded: det.decoded,
|
|
84
|
+
context: det.context,
|
|
85
|
+
rawFaces: cached.rawFaces,
|
|
86
|
+
rawObjects: cached.rawObjects,
|
|
87
|
+
exportImage: cached.exportImage,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
71
90
|
const docW = det.docWidth;
|
|
72
91
|
const docH = det.docHeight;
|
|
73
92
|
const objects = det.result.objects ?? [];
|
|
@@ -105,8 +124,11 @@ export async function buildSceneModel(connection, snippet, client, opts = {}) {
|
|
|
105
124
|
const hist = toLumaHistogram(histRaw);
|
|
106
125
|
const pick = pickThresholdLevel(hist);
|
|
107
126
|
const tonalZones = computeTonalZones(hist);
|
|
108
|
-
const
|
|
109
|
-
const
|
|
127
|
+
const allBoxes = objects.map((o) => o.bbox);
|
|
128
|
+
const mainBox = mainIdx >= 0 ? objects[mainIdx].bbox : null;
|
|
129
|
+
const primaryFaceBox = faces.find((f) => f.is_primary)?.bbox ?? faces[0]?.bbox ?? null;
|
|
130
|
+
const rowMeans = rowBrightnessProfile(det.decoded);
|
|
131
|
+
const horizon = estimateHorizon(rowMeans, docH, pick, mainBox, primaryFaceBox);
|
|
110
132
|
const skyCoverage = pick.bright_fraction;
|
|
111
133
|
const regions = [
|
|
112
134
|
{
|
|
@@ -120,9 +142,18 @@ export async function buildSceneModel(connection, snippet, client, opts = {}) {
|
|
|
120
142
|
recipe: { kind: 'posterize_region', levels: 3, sample: 'below_horizon' },
|
|
121
143
|
},
|
|
122
144
|
];
|
|
123
|
-
const allBoxes = objects.map((o) => o.bbox);
|
|
124
|
-
const mainBox = mainIdx >= 0 ? objects[mainIdx].bbox : null;
|
|
125
145
|
const composition = computeComposition(mainBox, allBoxes, docW, docH, horizon.placement);
|
|
146
|
+
const backends = {
|
|
147
|
+
faces: det.result.backends.faces,
|
|
148
|
+
objects: det.result.backends.objects,
|
|
149
|
+
regions: 'heuristic',
|
|
150
|
+
};
|
|
151
|
+
const rawFaces = (det.raw.faces ?? []).map((f) => f.bbox);
|
|
152
|
+
const rawObjects = (det.raw.objects ?? []).map((o) => ({ label: o.label, bbox: o.bbox }));
|
|
153
|
+
const exportImage = det.raw.image;
|
|
154
|
+
const cacheKey = freshIdentity
|
|
155
|
+
? identityKeyString(freshIdentity)
|
|
156
|
+
: `nopixel-${nextNoPixelIdentityId()}`;
|
|
126
157
|
const model = {
|
|
127
158
|
doc: { width: docW, height: docH },
|
|
128
159
|
subjects,
|
|
@@ -132,25 +163,37 @@ export async function buildSceneModel(connection, snippet, client, opts = {}) {
|
|
|
132
163
|
tonal_zones: tonalZones,
|
|
133
164
|
composition,
|
|
134
165
|
provenance: {
|
|
135
|
-
backends
|
|
136
|
-
faces: det.result.backends.faces,
|
|
137
|
-
objects: det.result.backends.objects,
|
|
138
|
-
regions: 'heuristic',
|
|
139
|
-
},
|
|
166
|
+
backends,
|
|
140
167
|
edition: 'ce',
|
|
141
|
-
cache_key:
|
|
168
|
+
cache_key: cacheKey,
|
|
142
169
|
cached: false,
|
|
143
170
|
},
|
|
144
171
|
};
|
|
145
172
|
const result = {
|
|
146
173
|
model,
|
|
147
174
|
exportBytes: det.exportBytes,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
175
|
+
decoded: det.decoded,
|
|
176
|
+
rawFaces,
|
|
177
|
+
rawObjects,
|
|
178
|
+
exportImage,
|
|
151
179
|
context: det.context,
|
|
152
180
|
};
|
|
153
|
-
|
|
181
|
+
if (freshIdentity) {
|
|
182
|
+
cache = {
|
|
183
|
+
identity: freshIdentity,
|
|
184
|
+
cacheKey,
|
|
185
|
+
subjects,
|
|
186
|
+
faces,
|
|
187
|
+
regions,
|
|
188
|
+
horizon,
|
|
189
|
+
tonalZones,
|
|
190
|
+
composition,
|
|
191
|
+
backends,
|
|
192
|
+
rawFaces,
|
|
193
|
+
rawObjects,
|
|
194
|
+
exportImage,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
154
197
|
return result;
|
|
155
198
|
}
|
|
156
199
|
export { getContextInfo };
|