@radialapps/memories-vips-editor 0.0.0-stage → 0.1.0

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.
Files changed (82) hide show
  1. package/README.md +102 -2
  2. package/dist/index.d.ts +7 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +10 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/math.d.ts +11 -0
  7. package/dist/math.d.ts.map +1 -0
  8. package/dist/math.js +40 -0
  9. package/dist/math.js.map +1 -0
  10. package/dist/pipeline.d.ts +131 -0
  11. package/dist/pipeline.d.ts.map +1 -0
  12. package/dist/pipeline.js +506 -0
  13. package/dist/pipeline.js.map +1 -0
  14. package/dist/shaders.d.ts +8 -0
  15. package/dist/shaders.d.ts.map +1 -0
  16. package/dist/shaders.js +51 -0
  17. package/dist/shaders.js.map +1 -0
  18. package/dist/transforms/blur.d.ts +17 -0
  19. package/dist/transforms/blur.d.ts.map +1 -0
  20. package/dist/transforms/blur.js +35 -0
  21. package/dist/transforms/blur.js.map +1 -0
  22. package/dist/transforms/brightnessContrast.d.ts +19 -0
  23. package/dist/transforms/brightnessContrast.d.ts.map +1 -0
  24. package/dist/transforms/brightnessContrast.js +55 -0
  25. package/dist/transforms/brightnessContrast.js.map +1 -0
  26. package/dist/transforms/crop.d.ts +34 -0
  27. package/dist/transforms/crop.d.ts.map +1 -0
  28. package/dist/transforms/crop.js +103 -0
  29. package/dist/transforms/crop.js.map +1 -0
  30. package/dist/transforms/exposure.d.ts +17 -0
  31. package/dist/transforms/exposure.d.ts.map +1 -0
  32. package/dist/transforms/exposure.js +41 -0
  33. package/dist/transforms/exposure.js.map +1 -0
  34. package/dist/transforms/grayscale.d.ts +15 -0
  35. package/dist/transforms/grayscale.d.ts.map +1 -0
  36. package/dist/transforms/grayscale.js +31 -0
  37. package/dist/transforms/grayscale.js.map +1 -0
  38. package/dist/transforms/hueSaturation.d.ts +19 -0
  39. package/dist/transforms/hueSaturation.d.ts.map +1 -0
  40. package/dist/transforms/hueSaturation.js +66 -0
  41. package/dist/transforms/hueSaturation.js.map +1 -0
  42. package/dist/transforms/index.d.ts +8 -0
  43. package/dist/transforms/index.d.ts.map +1 -0
  44. package/dist/transforms/index.js +44 -0
  45. package/dist/transforms/index.js.map +1 -0
  46. package/dist/transforms/invert.d.ts +15 -0
  47. package/dist/transforms/invert.d.ts.map +1 -0
  48. package/dist/transforms/invert.js +30 -0
  49. package/dist/transforms/invert.js.map +1 -0
  50. package/dist/transforms/rotate.d.ts +45 -0
  51. package/dist/transforms/rotate.d.ts.map +1 -0
  52. package/dist/transforms/rotate.js +194 -0
  53. package/dist/transforms/rotate.js.map +1 -0
  54. package/dist/transforms/sepia.d.ts +17 -0
  55. package/dist/transforms/sepia.d.ts.map +1 -0
  56. package/dist/transforms/sepia.js +45 -0
  57. package/dist/transforms/sepia.js.map +1 -0
  58. package/dist/transforms/sharpen.d.ts +19 -0
  59. package/dist/transforms/sharpen.d.ts.map +1 -0
  60. package/dist/transforms/sharpen.js +61 -0
  61. package/dist/transforms/sharpen.js.map +1 -0
  62. package/dist/transforms/state.d.ts +6 -0
  63. package/dist/transforms/state.d.ts.map +1 -0
  64. package/dist/transforms/state.js +29 -0
  65. package/dist/transforms/state.js.map +1 -0
  66. package/dist/transforms/transform.d.ts +68 -0
  67. package/dist/transforms/transform.d.ts.map +1 -0
  68. package/dist/transforms/transform.js +14 -0
  69. package/dist/transforms/transform.js.map +1 -0
  70. package/dist/transforms/vibrance.d.ts +17 -0
  71. package/dist/transforms/vibrance.d.ts.map +1 -0
  72. package/dist/transforms/vibrance.js +43 -0
  73. package/dist/transforms/vibrance.js.map +1 -0
  74. package/dist/transforms/vignette.d.ts +19 -0
  75. package/dist/transforms/vignette.d.ts.map +1 -0
  76. package/dist/transforms/vignette.js +58 -0
  77. package/dist/transforms/vignette.js.map +1 -0
  78. package/dist/types.d.ts +21 -0
  79. package/dist/types.d.ts.map +1 -0
  80. package/dist/types.js +5 -0
  81. package/dist/types.js.map +1 -0
  82. package/package.json +39 -4
package/README.md CHANGED
@@ -1,3 +1,103 @@
1
- # Temporary Holding Version
1
+ # @radialapps/memories-vips-editor — headless WebGL preview + VIPS-mappable edit list
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Pure-TypeScript, zero-dependency library. The caller provides a `<canvas>`
4
+ **and owns its size** (backing store `width`/`height` plus CSS); the
5
+ pipeline renders an **ordered list of image edits** with fullscreen
6
+ shader passes (ping-pong, like `glfx.js`), presenting contain-fit —
7
+ centered on opaque black, never resizing the canvas. A ResizeObserver
8
+ re-presents when the host resizes the canvas box. The same list serializes
9
+ to JSON that `vips-preview` (`convert`/`thumbnail` `"edits"`) applies
10
+ before saving.
11
+
12
+ ```
13
+ editor/
14
+ src/
15
+ types.ts edit list model + JSON wire format
16
+ math.ts shared pixel-math helpers
17
+ shaders.ts shared GLSL (quad, copy, blit, gaussian)
18
+ pipeline.ts EditPipeline — headless, canvas-taking preview
19
+ transforms/ one Transform class per edit + registry (index.ts)
20
+ + state serialization (state.ts); mirrors src/transforms/*.h
21
+ index.ts public surface (per-transform types import from their file)
22
+ demo/ tests/ playground (schema-driven) · vitest
23
+ demo/parity.html + demo/parity.ts + demo/parity-cases.json
24
+ committed WebGL↔VIPS side-by-side page: static shell, runtime
25
+ cards + live WebGL, cases as typed JSON (`satisfies` import)
26
+ demo/parity/ git-ignored VIPS JPEGs rendered by generate-parity.py
27
+ demo/generate-parity.py dumb renderer: reads parity-cases.json, runs a
28
+ built vips-preview (`npm run parity`)
29
+ UltraHDR source; VIPS side pre-rendered, WebGL side live.
30
+ ```
31
+
32
+ Adding a transform: write its file, add one line to the registry — pipeline,
33
+ validation, serialization, and demo pick it up.
34
+
35
+ ```bash
36
+ cd editor
37
+ npm install
38
+ npm run dev # demo playground
39
+ npm run parity # render VIPS-side parity JPEGs via a built vips-preview
40
+ npm run typecheck && npm test # tsc + vitest
41
+ npm run format # prettier --write
42
+ npm run build # typecheck + demo bundle (index.html + parity.html)
43
+ ```
44
+
45
+ ## Publishing
46
+
47
+ The package ships compiled `dist/` (JS + `.d.ts`, zero runtime deps).
48
+ `npm publish` runs `prepublishOnly` (clean → typecheck → test → `build:lib`).
49
+
50
+ ```bash
51
+ cd editor
52
+ npm run publish:dry # verify tarball contents without uploading
53
+ npm publish # clean + typecheck + test + build:lib, then publish
54
+ ```
55
+
56
+ ## Wire format
57
+
58
+ ```json
59
+ {
60
+ "cmd": "convert",
61
+ "input": "in.jpg",
62
+ "output": "out.jpg",
63
+ "edits": [{ "edit": "brightnessContrast", "brightness": 0.1, "contrast": 0.1 }]
64
+ }
65
+ ```
66
+
67
+ Numerics are optional (missing = no-change, except `sepia.amount` default 1);
68
+ the CLI rejects out-of-range values, so normalize client-side.
69
+
70
+ ## VIPS mapping
71
+
72
+ sRGB 0..1 floats, array order, single uchar clip at the end; alpha is split
73
+ off, normalized to 0..1 float alongside, reattached. Everything agrees to
74
+ float precision (±1 LSB after quantize), including `blur`/`sharpen` (both
75
+ sides convolve the same discrete kernel — `sigma=radius/2`,
76
+ `half=min(15,max(1,ceil(2σ)))`, clamp edges — via two separable passes).
77
+ Thumbnail edits run **after** resize (radii are output pixels). The preview
78
+ downscales sources larger than 2048px and scales `blur`/`sharpen` radii by
79
+ the working/native ratio, so it shows the same *relative* blur as the
80
+ full-res VIPS output. UHDR ICC+gainmap pass through untouched (gainmap is
81
+ not re-derived). `rotate` by
82
+ a non-90 angle appends a transparent alpha band (corners + fringes); 90°
83
+ multiples stay exact with no band change.
84
+
85
+ | edit | params | VIPS |
86
+ | ----------------------- | -------------------------------------- | ------------------------------ |
87
+ | `brightnessContrast` | `brightness`, `contrast` −1..1 | `linear(mult, bias)` |
88
+ | `exposure` | `stops` −5..5 | `linear(2^stops)` |
89
+ | `hueSaturation` | `hue`, `saturation` −1..1 | fused 3×3 (≡ `recomb`) |
90
+ | `sepia` | `amount` 0..1 | same matrix, clipped at cast |
91
+ | `vibrance` / `vignette` | `amount` −1..1 / `size`, `amount` 0..1 | identical CPU loop |
92
+ | `grayscale` / `invert` | — | `(r+g+b)/3` / `linear(-1, +1)` |
93
+ | `blur` / `sharpen` | `radius` 0..100 / +`amount` 0..5 | shared kernel + `convsep` (mix)|
94
+ | `crop` | `x`,`y`,`width`,`height` 0..1 fractions| `extract_area` (rounded+clamped)|
95
+ | `rotate` | `angle` −180..180 (clockwise °) | `rot()` @90s, else `rotate()` |
96
+
97
+ Excluded (no clean VIPS mapping): `denoise`, `noise`, `curves`,
98
+ `lensBlur`/`tiltShift`/`zoomBlur`, halftones, warps.
99
+
100
+ Caveats: no-float GPUs fall back to 8-bit targets (more rounding drift);
101
+ preview caps at 2048px longest side (VIPS renders full-res); WebGL failures
102
+ throw instead of rendering black. Shaders adapted from
103
+ [evanw/glfx.js](https://github.com/evanw/glfx.js) (BSD).
@@ -0,0 +1,7 @@
1
+ export { EditPipeline } from './pipeline.js';
2
+ export { TRANSFORMS, validateEdit, normalizeEdit } from './transforms/index.js';
3
+ export { validateState, stateToJSON, stateFromJSON } from './transforms/state.js';
4
+ export type { Transform, ParamControl, RenderContext, Target } from './transforms/transform.js';
5
+ export { emptyState, EDIT_STATE_VERSION } from './types.js';
6
+ export type { Edit, EditName, EditState } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAClF,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC5D,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ // index.ts — minimal public surface: the pipeline, the registry, state
2
+ // helpers, and the types needed to consume them (including writing a
3
+ // custom Transform). Internal helpers (lookup, isNumInRange,
4
+ // setFloatUniform, math utils, per-transform types) live in their own
5
+ // modules — import those directly.
6
+ export { EditPipeline } from './pipeline.js';
7
+ export { TRANSFORMS, validateEdit, normalizeEdit } from './transforms/index.js';
8
+ export { validateState, stateToJSON, stateFromJSON } from './transforms/state.js';
9
+ export { emptyState, EDIT_STATE_VERSION } from './types.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,qEAAqE;AACrE,6DAA6D;AAC7D,sEAAsE;AACtE,mCAAmC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAElF,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC"}
package/dist/math.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ export declare function clampf(lo: number, v: number, hi: number): number;
2
+ /** Exposure gain for a stop shift. */
3
+ export declare function exposureMult(stops: number): number;
4
+ /** 1D gaussian kernel for a blur radius (sigma = radius/2). Preview + docs.
5
+ *
6
+ * Single source of truth, ported term-for-term to src/transforms/gaussian.h:
7
+ * both sides convolve these exact weights (separable, clamp edges), so
8
+ * preview and VIPS agree to ±1 LSB at every radius.
9
+ */
10
+ export declare function gaussianKernel(radius: number): number[];
11
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAYA,wBAAgB,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAavD"}
package/dist/math.js ADDED
@@ -0,0 +1,40 @@
1
+ // math.ts — CPU reference for every edit's pixel math.
2
+ //
3
+ // These functions are the single source of truth shared (by port, not by
4
+ // import) with the GLSL in shaders.ts and the libvips code in src/edit.h:
5
+ // preview (WebGL) == math.ts == VIPS applier
6
+ // all operate on sRGB-encoded 0..1 floats and apply in array order.
7
+ //
8
+ // glfx.js inspiration: brightnessContrast / hueSaturation / sepia / vibrance /
9
+ // vignette shaders are direct ports of evanw/glfx.js adjust filters (see
10
+ // shaders.ts); the matrix derivations below match those shaders term for term
11
+ // so a VIPS `recomb`/`linear` does exactly what the canvas showed.
12
+ export function clampf(lo, v, hi) {
13
+ return Math.min(hi, Math.max(lo, v));
14
+ }
15
+ /** Exposure gain for a stop shift. */
16
+ export function exposureMult(stops) {
17
+ return Math.pow(2, clampf(-5, stops, 5));
18
+ }
19
+ /** 1D gaussian kernel for a blur radius (sigma = radius/2). Preview + docs.
20
+ *
21
+ * Single source of truth, ported term-for-term to src/transforms/gaussian.h:
22
+ * both sides convolve these exact weights (separable, clamp edges), so
23
+ * preview and VIPS agree to ±1 LSB at every radius.
24
+ */
25
+ export function gaussianKernel(radius) {
26
+ const r = clampf(0, radius, 100);
27
+ if (r <= 0)
28
+ return [1];
29
+ const sigma = r / 2;
30
+ const half = Math.min(15, Math.max(1, Math.ceil(sigma * 2)));
31
+ const w = [];
32
+ let sum = 0;
33
+ for (let i = -half; i <= half; i++) {
34
+ const v = Math.exp(-0.5 * (i / sigma) * (i / sigma));
35
+ w.push(v);
36
+ sum += v;
37
+ }
38
+ return w.map((v) => v / sum);
39
+ }
40
+ //# sourceMappingURL=math.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.js","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,EAAE;AACF,yEAAyE;AACzE,0EAA0E;AAC1E,mDAAmD;AACnD,oEAAoE;AACpE,EAAE;AACF,+EAA+E;AAC/E,yEAAyE;AACzE,8EAA8E;AAC9E,mEAAmE;AAEnE,MAAM,UAAU,MAAM,CAAC,EAAU,EAAE,CAAS,EAAE,EAAU;IACtD,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,CAAC,GAAa,EAAE,CAAC;IACvB,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACV,GAAG,IAAI,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,131 @@
1
+ import type { Target, UniformSetter, ExtraTex } from './transforms/transform.js';
2
+ import { type Edit } from './types.js';
3
+ export declare class EditPipeline {
4
+ private gl;
5
+ private canvas;
6
+ private programs;
7
+ private quad;
8
+ private src;
9
+ private ping;
10
+ private pong;
11
+ private extra;
12
+ private imgW;
13
+ private imgH;
14
+ private outW;
15
+ private outH;
16
+ /** Working/native resolution ratio backing RenderContext.resolutionScale. */
17
+ private resScale;
18
+ private state;
19
+ private floatOK;
20
+ private highp;
21
+ private resizeObserver;
22
+ /**
23
+ * Take over the canvas' WebGL context. preserveDrawingBuffer stays true
24
+ * so the demo can read pixels back; premultipliedAlpha stays false
25
+ * so alpha survives the passes unmodified. The canvas backing store is
26
+ * never touched — size it externally; the pipeline contain-fits the
27
+ * output into it (centered, black surround) and re-renders on resize.
28
+ * Throws when WebGL is missing.
29
+ */
30
+ constructor(canvas: HTMLCanvasElement);
31
+ /** Output image size (source size when no geometric edit applies). */
32
+ get width(): number;
33
+ get height(): number;
34
+ /** Ordered edit list (live reference — mutate via setEdits/addEdit/...). */
35
+ getEdits(): Edit[];
36
+ /** Replace the whole edit list (normalizing each edit) and re-render. */
37
+ setEdits(edits: Edit[]): void;
38
+ /** Append one edit (normalized) and re-render. */
39
+ addEdit(edit: Edit): void;
40
+ /** Drop the edit at `index` and re-render. */
41
+ removeEdit(index: number): void;
42
+ /** Reorder one edit and re-render. */
43
+ moveEdit(from: number, to: number): void;
44
+ /** Drop all edits (back to the bare source image) and re-render. */
45
+ clearEdits(): void;
46
+ /** Canonical JSON state for the VIPS side. */
47
+ toJSON(): string;
48
+ /**
49
+ * Longest side of the working image. Camera JPEGs (12-50MP) would need
50
+ * hundreds of MB as float ping-pong targets and exceed
51
+ * MAX_TEXTURE_SIZE on weak GPUs — both failure modes render black with
52
+ * no exception. The preview is resolution-capped (reported via
53
+ * width/height); the VIPS side always renders full-res from the JSON.
54
+ */
55
+ static readonly MAX_DIM = 2048;
56
+ /** Resolve the pixel size of any TexImageSource upload. */
57
+ private sourceDims;
58
+ /** Turn a sticky GL error flag into a thrown message naming the stage. */
59
+ private checkGLError;
60
+ /**
61
+ * Upload a new source image, (re)allocating all targets to it.
62
+ * Oversized sources are downscaled through a 2D canvas first (see
63
+ * MAX_DIM); old GL targets are deleted. The canvas backing store is
64
+ * left alone (externally owned). Ends with a full render().
65
+ * Throws with a message instead of rendering black on failure.
66
+ */
67
+ setImage(source: TexImageSource): void;
68
+ /**
69
+ * Re-run all passes: copy source -> ping, then apply each edit in order,
70
+ * ping-ponging between the two working targets (`cur` holds the latest
71
+ * result, `nxt` is the scratch target; multi-pass edits may bounce
72
+ * between them internally and return either side). Geometric edits
73
+ * (crop/rotate) change dimensions: `nxt` is resized to the edit's
74
+ * outputDims before apply, `extra` is kept at the input size (sharpen
75
+ * scratch). Presents contain-fit into the externally-sized canvas.
76
+ * No-op when no image is loaded yet.
77
+ */
78
+ render(): void;
79
+ /**
80
+ * RenderContext facade for Transform.apply(): exposes the pass/blit/gauss
81
+ * drawing primitives plus the scratch `extra` target, without handing
82
+ * out the raw WebGL context.
83
+ */
84
+ private renderContext;
85
+ /** Resize a working target when geometry changed (returns live target). */
86
+ private ensureSize;
87
+ /**
88
+ * Decide float vs 8-bit ping-pong targets. Float needs both the
89
+ * renderable-float extension and float-linear filtering (every pass
90
+ * samples with LINEAR); either missing falls back to UNSIGNED_BYTE.
91
+ * Also verifies float renderability with a throwaway 4x4 target.
92
+ */
93
+ private probeFloat;
94
+ /**
95
+ * Allocate one offscreen RGBA render target (texture + framebuffer) with
96
+ * linear filtering and clamp-to-edge (NPOT-safe: no mipmaps, no repeat).
97
+ */
98
+ private makeTarget;
99
+ /**
100
+ * Compile one shader stage, throwing the info log on failure (a bad
101
+ * shader would otherwise render black with no indication why).
102
+ */
103
+ private compile;
104
+ /** Compile+link the quad vertex shader with `frag`, cached by source. */
105
+ private program;
106
+ /**
107
+ * Draw one fullscreen pass: render `from` through `frag` into `to`.
108
+ * `from` is bound to unit 0 (`texture` uniform) unless the shader uses
109
+ * other sampler names; `extraTex` optionally binds a second texture
110
+ * (used by the sharpen mix pass). `setUniforms` fills the rest.
111
+ */
112
+ pass(frag: string, from: Target, to: Target, setUniforms?: UniformSetter, extraTex?: ExtraTex): void;
113
+ /** Copy one target to another with the identity shader. */
114
+ blit(from: Target, to: Target): void;
115
+ /**
116
+ * One axis of the separable gaussian: `horizontal` picks the sample
117
+ * direction (offsets are in UV units, hence the 1/width division).
118
+ * The shader loops over a fixed 31-tap array; `kernel.length` tells it
119
+ * how many center taps carry real weight, the rest are zero-padded.
120
+ */
121
+ gauss(from: Target, to: Target, horizontal: boolean, kernel: number[]): void;
122
+ /**
123
+ * Present the final result contain-fit into the externally-sized canvas:
124
+ * the whole backing store is cleared to opaque black, then the image is
125
+ * drawn into the largest centered rect preserving aspect ratio (the
126
+ * BLIT_FRAG flip still compensates the unflipped upload). The canvas
127
+ * backing store is only ever read here, never resized.
128
+ */
129
+ private toCanvas;
130
+ }
131
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAiB,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAChG,OAAO,EAAc,KAAK,IAAI,EAAkB,MAAM,YAAY,CAAC;AAEnE,qBAAa,YAAY;IACvB,OAAO,CAAC,EAAE,CAAwB;IAClC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,QAAQ,CAAmC;IAEnD,OAAO,CAAC,IAAI,CAA4B;IAIxC,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAK;IACjB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IAItB,OAAO,CAAC,cAAc,CAA+B;IAErD;;;;;;;OAOG;gBACgB,MAAM,EAAE,iBAAiB;IAqC5C,sEAAsE;IACtE,IAAW,KAAK,IAAI,MAAM,CAEzB;IACD,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED,4EAA4E;IACrE,QAAQ,IAAI,IAAI,EAAE;IAIzB,yEAAyE;IAClE,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IAKpC,kDAAkD;IAC3C,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAKhC,8CAA8C;IACvC,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAKtC,sCAAsC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAM/C,oEAAoE;IAC7D,UAAU,IAAI,IAAI;IAKzB,8CAA8C;IACvC,MAAM,IAAI,MAAM;IAIvB;;;;;;OAMG;IACH,gBAAuB,OAAO,QAAQ;IAEtC,2DAA2D;IAC3D,OAAO,CAAC,UAAU;IAelB,0EAA0E;IAC1E,OAAO,CAAC,YAAY;IAQpB;;;;;;OAMG;IACI,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAuD7C;;;;;;;;;OASG;IACI,MAAM,IAAI,IAAI;IAqCrB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAoBrB,2EAA2E;IAC3E,OAAO,CAAC,UAAU;IAelB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAqBlB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAiBlB;;;OAGG;IACH,OAAO,CAAC,OAAO;IAcf,yEAAyE;IACzE,OAAO,CAAC,OAAO;IAoBf;;;;;OAKG;IACI,IAAI,CACT,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,WAAW,CAAC,EAAE,aAAa,EAC3B,QAAQ,CAAC,EAAE,QAAQ,GAClB,IAAI;IA2BP,2DAA2D;IACpD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAI3C;;;;;OAKG;IACI,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAenF;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ;CA0BjB"}