Globals
Instance Methods
exportMakeup(): Promise.<void>
Coordinates the Copy Makeup button workflow. It gathers the current Ghostmaxxing export source, renders the diagnostic header/footer around it, converts the result to PNG, and then tries Clipboard first with Web Share as a fallback. This is the only function in the module that reads the live application globals and writes user-visible status messages through setLog; the exported helper functions stay small so the rendering and delivery decisions can be unit-tested independently.
Returns
Promise.<void>— Resolves after the image is copied, shared, skipped, or an error is logged.
- See:
- main - Registered as the `copyMakeupBtn` click handler.
- collectExportInput - Builds the export model from app state and DOM handles.
- renderExportCanvas - Produces the PNG source canvas with report chrome.
- copyBlobToClipboard - First delivery path attempted by this workflow.
- shareImageFile - Fallback delivery path when clipboard write fails.
collectExportInput(appState: object, domEls: object): Object
Builds the data model for a makeup export from the current app state and DOM. It prefers the last efficacy composite when available, otherwise it creates a live composite from the webcam and overlay layers so the Copy button still returns a useful image when no active Ghostyle result has been produced.
Parameters
appState(object) — Current Ghostmaxxing state object.appState.lastCompositedCanvas(HTMLCanvasElement | null, optional) — Most recent efficacy composite, if one exists.appState.isMirrored(boolean) — Whether the exported source should be mirrored.appState.loadedGhostyles(Map.<string, object>) — Loaded Ghostyle records keyed by id.appState.activeEffect(string | null) — Currently active Ghostyle id.
domEls(object) — DOM handles collected bydom.js.domEls.logBox(HTMLElement, optional) — Log container whose last child becomes footer text.
Returns
Object— Export input for rendering.
- See:
- exportMakeup - Calls this before rendering or delivery.
- buildLiveComposite - Provides the fallback source canvas when no efficacy composite exists.
buildLiveComposite(domEls: object): HTMLCanvasElement | null
Composites the visible lab layers into a single source canvas in overlay pixel space: webcam frame, 2D effect overlay, 3D mesh overlay, then bbox/label overlay. Mirroring is intentionally left for drawSourceImage, matching the efficacy export path and preserving readable bbox labels.
Parameters
domEls(object) — DOM handles collected bydom.js.domEls.overlay(HTMLCanvasElement) — Main 2D effect overlay canvas.domEls.video(HTMLVideoElement, optional) — Webcam video element.
Returns
HTMLCanvasElement | null— Composite canvas, or null when the overlay is unavailable.
- See:
- collectExportInput - Uses this as the copy source when `lastCompositedCanvas` is empty.
- drawSourceImage - Applies the global mirror transform after this raw composite is built.
getLatestLogText(logBox: HTMLElement): string
Reads the newest diagnostic line from the app log for use as the export footer, preserving the same concise status text the user saw in the lab UI.
Parameters
logBox(HTMLElement) — Log container rendered by the application.
Returns
string— Text from the latest log entry, or an empty string.
- See:
- collectExportInput - Stores the value as `logText` for footer rendering.
renderExportCanvas(
input: object,
layout: object,
): HTMLCanvasElement
Allocates and paints the final export image: opaque background, source image, diagnostic header, and latest-log footer. The output canvas is taller than the source canvas because it includes the report chrome used by shared PNGs.
Parameters
input(object) — Export input collected from app state and DOM.input.sourceCanvas(HTMLCanvasElement) — Source image to place between header and footer.input.isMirrored(boolean) — Whether the source image should be horizontally flipped.input.pluginName(string) — Active Ghostyle name for the header.input.logText(string) — Latest diagnostic log line for the footer.
layout(object) — Export layout and color settings.
Returns
HTMLCanvasElement— Rendered export canvas ready for PNG conversion.
Throws
Error— When a 2D canvas context cannot be created.
- See:
- exportMakeup - Converts this canvas to a blob for delivery.
- drawSourceImage - Draws the captured makeup image.
- drawHeader - Draws the Ghostyle/report header.
- drawFooter - Draws the diagnostic footer.
drawSourceImage(
ctx: CanvasRenderingContext2D,
data: object,
): void
Places the captured makeup image into the final export canvas, flipping the whole source when the webcam is mirrored so the shared PNG matches the user's current lab view.
Parameters
ctx(CanvasRenderingContext2D) — Export canvas rendering context.data(object) — Rendering bundle for the current export.data.canvas(HTMLCanvasElement) — Final export canvas.data.input(object) — Export input collected from the app.data.layout(object) — Header/footer layout settings.
Returns
void
- See:
- renderExportCanvas - Calls this before drawing report text.
drawHeader(ctx: CanvasRenderingContext2D, data: object): void
Draws the top report line containing the project URL, active Ghostyle module, and report URL. This makes exported makeup images self-identifying when they are copied or shared outside the lab UI.
Parameters
ctx(CanvasRenderingContext2D) — Export canvas rendering context.data(object) — Rendering bundle for the current export.data.canvas(HTMLCanvasElement) — Final export canvas.data.input(object) — Export input collected from the app.data.layout(object) — Header/footer layout settings.
Returns
void
- See:
- renderExportCanvas - Calls this after the source image is drawn.
- buildHeaderText - Builds the actual header string.
buildHeaderText(pluginName: string): string
Builds the export header copy shown above the makeup image, binding the active Ghostyle name to the Ghostmaxxing source and report links.
Parameters
pluginName(string) — Human-readable active Ghostyle name.
Returns
string— Header text for the exported PNG.
- See:
- drawHeader - Renders this text onto the export canvas.
drawFooter(ctx: CanvasRenderingContext2D, data: object): void
Draws the latest diagnostic log line below the exported image. The footer color reflects whether the last known effect result had a detection, keeping successful and failed diagnostic outcomes visually distinct in the shared PNG.
Parameters
ctx(CanvasRenderingContext2D) — Export canvas rendering context.data(object) — Rendering bundle for the current export.data.canvas(HTMLCanvasElement) — Final export canvas.data.input(object) — Export input collected from the app.data.layout(object) — Header/footer layout settings.
Returns
void
- See:
- renderExportCanvas - Calls this as the final drawing step.
canvasToBlob(canvas: HTMLCanvasElement): Promise.<Blob>
Converts the rendered export canvas into the PNG blob delivered to Clipboard or Web Share, treating a null browser callback as an export failure.
Parameters
canvas(HTMLCanvasElement) — Final export canvas.
Returns
Promise.<Blob>— PNG blob generated from the canvas.
- See:
- exportMakeup - Awaits this before clipboard/share delivery.
makeImageFile(blob: Blob, copy: object): File
Wraps the exported PNG blob in a browser File with the configured filename and MIME type so the Web Share API can receive it.
Parameters
blob(Blob) — PNG blob generated from the export canvas.copy(object) — Export copy and file metadata.copy.filename(string) — Filename for the shared image.copy.mimeType(string) — MIME type for the image file.
Returns
File— Shareable image file.
- See:
- exportMakeup - Creates this file before invoking the Share API fallback.
- shareImageFile - Delivers the returned file when sharing is supported.
copyBlobToClipboard(blob: Blob): Promise.<void>
Writes the exported PNG blob to the browser clipboard using ClipboardItem. This is the primary delivery path for the Copy Makeup action.
Parameters
blob(Blob) — PNG blob generated from the export canvas.
Returns
Promise.<void>— Resolves when the browser accepts the clipboard write.
- See:
- exportMakeup - Attempts this before falling back to Web Share.
- canUseClipboard - Guards Clipboard API support before writing.
canUseClipboard(browserNavigator: Navigator | object): boolean
Checks whether the current browser navigator exposes the image clipboard pieces needed by the Copy Makeup workflow.
Parameters
browserNavigator(Navigator | object) — Browser navigator or test double.
Returns
boolean— True whenclipboard.writeandClipboardItemare available.
- See:
- copyBlobToClipboard - Uses this before constructing a clipboard item.
shareImageFile(file: File, copy: object): Promise.<void>
Shares the exported makeup PNG through the Web Share API when clipboard delivery fails, preserving the same project title and explanatory share text.
Parameters
file(File) — Exported makeup PNG file.copy(object) — Share title, text, and file metadata.copy.shareTitle(string) — Title passed to the Web Share API.copy.shareText(string) — Text passed to the Web Share API.
Returns
Promise.<void>— Resolves when the browser accepts the share request.
- See:
- exportMakeup - Calls this as the fallback after clipboard failure.
- canShareFile - Guards Web Share support before invoking `navigator.share`.
canShareFile(file: File): boolean
Checks whether the browser can share the generated makeup PNG. Browsers with navigator.share but no navigator.canShare are treated as share-capable, matching the fallback behavior expected by the lab UI.
Parameters
file(File) — Exported makeup PNG file.
Returns
boolean— True when the Share API can be attempted for this file.
- See:
- shareImageFile - Uses this before calling `navigator.share`.
setLoaderStatus(kind: string, key: string): void
Updates the loader status label from a translation key and remembers the active status so it can be refreshed after a locale change.
Parameters
kind(string) — Status class hint passed to the shared status widget.key(string) — Translation key for the status text.
Returns
void
formatVideoTime(seconds: number): string
Formats a floating-point video timestamp as mm:ss.mmm.
Parameters
seconds(number) — Video time in seconds.
Returns
string— Zero-padded display time.
currentPosition(): Object
Reads the current video playhead, duration, percentage, and display label.
Returns
Object— Current timeline position.
setActionButtonsEnabled(enabled: boolean): void
Enables or disables face actions based on model, video, and lock state.
Parameters
enabled(boolean) — Whether the caller wants actions to be available.
Returns
void
updateTimelineFromVideo(): void
Synchronizes timeline labels and the seek input with the video element.
Returns
void
syncCanvasSize(): void
Resizes all diagnostic overlay canvases to match the active video surface.
Returns
void
snapshotCanvas(): HTMLCanvasElement
Captures the current video frame plus diagnostic overlays into a canvas.
Returns
HTMLCanvasElement— Snapshot canvas used in activity-log entries.
saveFacePreview(id: number, result: *): Promise.<boolean>
Captures and persists the same saved-face preview used by lab.html's history drawer. The loader already has the successful face-api result, so reuse its box instead of running a second detection pass.
Parameters
id(number) — Saved face id shared by the 2D and 3D stores.result(*) — face-api detection result returned by saveFace().
Returns
Promise.<boolean>— Whether a thumbnail was saved.
appendChip(parent: HTMLElement, label: string, value: *): void
Appends a compact metadata chip to an activity-log container.
Parameters
parent(HTMLElement) — Element that receives the chip.label(string) — Chip label.value(*) — Chip value rendered as text.
Returns
void
appendEntry(
kind: string,
snapshot: HTMLCanvasElement,
summary: Object,
details: *,
): void
Prepends a diagnostic activity entry with snapshot, summary chips, and JSON details.
Parameters
kind(string) — Human-readable action name.snapshot(HTMLCanvasElement) — Canvas snapshot for the entry.summary(Object) — Position and headline metrics.details(*) — Structured details rendered in the entry body.
Returns
void
summarizeFace(result: *): object
Extracts stable 2D and 3D face-detection details for logging.
Parameters
result(*) — face-api detection result.
Returns
object— Serializable face summary.
get2dDistances(result: *): Array.<object>
Computes sorted descriptor distances between a live 2D result and saved faces.
Parameters
result(*) — face-api detection result containing a descriptor.
Returns
Array.<object>— Distances sorted from nearest to farthest.
get3dDistances(
embedding: Float32Array | Array.<number> | null,
): Array.<object>
Computes sorted cosine-similarity matches for a live 3D embedding.
Parameters
embedding(Float32Array | Array.<number> | null) — Live MediaPipe embedding.
Returns
Array.<object>— Matches sorted from highest to lowest similarity.
buildOverall(
faceapiSection: object,
mediapipeSection: object,
): string
Collapses 2D and 3D detection states into the shared overall match state.
Parameters
faceapiSection(object) — 2D match section.mediapipeSection(object) — 3D match section.
Returns
string— Overall state used by the readout event bus.
withActionLock(fn: function): Promise.<void>
Runs a face action while preventing concurrent Record/Seek operations.
Parameters
fn(function) — Action callback to execute under the lock.
Returns
Promise.<void>
recordFace(): Promise.<void>
Saves the face visible at the current video frame into the 2D and 3D archives.
Returns
Promise.<void>
seekFace(): Promise.<void>
Searches the saved 2D and 3D face archives for the face in the current frame.
Returns
Promise.<void>
loadModels(): Promise.<void>
Loads face-api model weights and the MediaPipe 3D embedder required by the loader.
Returns
Promise.<void>
bindVideo(): void
Wires file input, video timeline, seek, playback, and resize event handlers.
Returns
void
init(): Promise.<void>
Initializes localization, local databases, video bindings, models, and actions.
Returns
Promise.<void>
getGraphPalette(): Object
Reads graph colors from shared style tokens with sane fallbacks.
Returns
Object— Graph color palette.
setStatus(message: string): void
Updates the floating status message shown over the video feed.
Parameters
message(string) — Message visible in the status pill.
Returns
void
setTrackingState(state: string): void
Updates the right-panel state label between CALIBRATING and TRACKING.
Parameters
state(string) — Current app state value.
Returns
void
setDistanceValue(value: number): void
Updates the numeric distance readout with a fixed 3-decimal value.
Parameters
value(number) — Euclidean distance value to display.
Returns
void
initEqualizer(): void
Builds the 128x10 descriptor equalizer grid and caches each row.
Returns
void
drawGraphCanvas(): void
Draws the smoothed distance history with time on the vertical axis. Old samples are at the top and newest samples at the bottom.
Returns
void
updateEqualizer(
baseline: Float32Array | Array.<number>,
current: Float32Array | Array.<number>,
): void
Updates every descriptor row based on per-index absolute baseline deltas.
Parameters
baseline(Float32Array | Array.<number>) — Baseline descriptor captured during calibration.current(Float32Array | Array.<number>) — Current live descriptor.
Returns
void
resetEqualizer(): void
Resets the equalizer UI to its neutral unlit state.
Returns
void
resizeGraphCanvas(): void
Resizes the graph canvas to match CSS pixels and device pixel ratio.
Returns
void
armSafeBaselineCapture(): void
Captures a baseline descriptor after the countdown by waiting for the first valid face.
Returns
void
startCalibration(): void
Runs the 3-2-1 countdown then enables safe baseline capture mode.
Returns
void
setBaseline(descriptor: Float32Array | Array.<number>): void
Updates app state after a valid baseline descriptor is captured.
Parameters
descriptor(Float32Array | Array.<number>) — Descriptor captured from the live frame.
Returns
void
processDetection(detection: *): void
Handles one detected face based on the current runtime state.
Parameters
detection(*) — face-api detection result containing a descriptor.
Returns
void
processNoFace(): void
Handles "no face detected" situations depending on calibrating/tracking state.
Returns
void
onFrame(): Promise.<void>
Executes one face-api detection pass and schedules the next animation frame.
Returns
Promise.<void>
flushDistanceBuffer(): void
Pulls buffered distance samples, computes an average, and updates graph history.
Returns
void
startGraphLoop(): void
Starts the low-frequency graph smoothing loop at 3 updates per second.
Returns
void
initWebcam(): Promise.<void>
Requests camera stream and binds it to the realtime video element.
Returns
Promise.<void>
loadModels(): Promise.<void>
Loads the face-api models required for descriptor extraction.
Returns
Promise.<void>
bindListeners(): void
Binds interaction and resize listeners needed during runtime.
Returns
void
initRealtime(): Promise.<void>
Initializes realtime visualizer components and starts analysis loops.
Returns
Promise.<void>
boot(): void
Bootstraps realtime visualizer and reports startup errors in the status pill.
Returns
void
onDraw()
Questo effetto non e' adversarial: serve come riferimento didattico per l'uso combinato di drawCheekSweep, drawClosedPath e drawLabel.
eyeFrame()
Build a similarity frame (origin-less): eye centres, unit axes, scale.
toLocal()
Screen point -> face-relative sample {i,a,b}.
toScreen()
Face-relative sample -> screen point, using the CURRENT landmarks.
isMirrored()
True if the canvas carries a horizontal-flip CSS transform (front camera).
eventToCanvas()
Pointer event -> overlay internal coordinates (mirror-aware).
bakeGhostyle()
Turn the current painted state into a standalone, dependency-free Ghostyle file and download it. This is the honest "author a Ghostyle" path the roadmap describes: paint live, keep what works, bake it into a reusable static plugin. The generated file replays the same eye-frame re-projection.
onDraw()
Called every render tick on the visible overlay, and also on the offscreen composite that gets re-detected. We (a) cache the latest live landmarks so pointer samples can be anchored between ticks, (b) lazily wire up input + the control panel the first time we see the real (connected) overlay, and (c) redraw every stroke from the current landmarks.
onClear()
Called when the effect is switched off. Tear down input + panel; keep strokes.
onDraw()
Applica una composizione ispirata al lavoro CV-Dazzle di Adam Harvey (2010).
Strategia adversarial usata qui:
- Rottura della simmetria bilaterale con diagonali e sbordi extra-volto.
- Copertura di feature biometriche stabili (ponte nasale, zigomo, contorni occhio).
- Contrasto alto e alternanza chiaro/scuro per destabilizzare i descrittori locali.
- Sovrapposizioni opache su regioni semantiche forti che i modelli pesano molto.
- Etichette e forme "non anatomiche" per indebolire i cue faciali classici.
onDraw()
Meta' sinistra: landmark face-api, disegno diretto in pixel-space. Il clip evita sovrapposizioni con la controparte UV della meta' destra.
paintUV()
Meta' destra: la mesh MediaPipe viene dipinta in UV-space. Questa texture viene poi warpata sui triangoli del volto dal renderer UV.
onDraw()
Meta' sinistra in pixel-space: usa i 68 landmark face-api e i helper contour.
paintUV()
Meta' destra in UV-space: dipinge bande morbide sulla texture MediaPipe. E' lo stesso intento visivo del contour 2D, ma con pipeline mesh UV.
Instance Fields
Template
Canonical template for Ghostmaxxing plugins: minimal example with 2D + UV callbacks. ==/Ghostyle==
- Version: 2.0.0
- Author: vecna
Beauty Demo 2D
Demo beauty non-adversarial per mostrare helper composti 2D. ==/Ghostyle==
- Version: 1.0.0
- Author: NINA
Face Brush
Hold-to-paint brush anchored to face landmarks. Marks track the face and are scored live by the recognition pipeline; bake a promising state into a static Ghostyle.
- Version: 0.1.0
- License: AGPL-3.0-only
- Author: vecna
strokes
Committed strokes. Each: { color, alpha, nWidth, samples: [{i,a,b}] }.
current
Stroke currently being drawn, or null.
painting
Whether a pointer is held down and painting.
latest
Last landmark snapshot seen on the visible overlay, used to anchor pointer samples between render ticks. { positions:[{x,y}], frame, t }.
boundCanvas
The connected overlay canvas we attached listeners to (guards re-attach).
handlers
Saved handlers so onClear can detach cleanly.
panel
The injected floating control panel element.
CV-Dazzle example 1
Pattern ad alto contrasto ispirato al CV-Dazzle per rottura simmetrica del volto. ==/Ghostyle==
- Version: 1.0.0
- Author: vecna, but actually a dump of random points
Maximalism
Pattern massimalista ispirato a trucchi club/drag contemporanei. Spezza la simmetria, ridisegna la bocca, copre lo zigomo, estende l'occhio verso l'alto. ==/Ghostyle==
- Version: 1.0.0
- Author: vecna
Smokey Eyes
Demo split: pixel-space su meta' sinistra, UV-space su meta' destra. ==/Ghostyle==
- Version: 2.0.0
- Author: vecna, but actually inspired by a paper.
Soft Contour
Demo split contour: face-api a sinistra, UV-space a destra. ==/Ghostyle==
- Version: 2.0.0
- Author: NINA
UV Stripes
Strisce/chevron oblique disegnate sul volto in spazio UV canonico. ==/Ghostyle==
- Version: 0.3.0
- Author: edne
Other
DEFAULT_LOCALE
Centralized translation strings. Runtime: i18n(key, locale) returns localized string or English fallback.
Baseline notes:
- English is the source baseline and default locale.
- Existing Italian copy is preserved exactly where it already appeared in code.
G
Public API object. Uses the target window.gstmxx; falls back defensively.
brush
Current brush settings (snapshotted per stroke at pointerdown).