@radialapps/memories-vips-editor 0.0.0-stage → 0.1.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.
Files changed (82) hide show
  1. package/README.md +101 -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 +129 -0
  11. package/dist/pipeline.d.ts.map +1 -0
  12. package/dist/pipeline.js +485 -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,102 @@
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
+ (layout and CSS); the pipeline renders an **ordered list of image edits**
5
+ with fullscreen shader passes (ping-pong, like `glfx.js`), resizing the
6
+ canvas backing store to the rendered output area and presenting 1:1 — the
7
+ image always fills the canvas exactly. The same list serializes
8
+ to JSON that `vips-preview` (`convert`/`thumbnail` `"edits"`) applies
9
+ before saving.
10
+
11
+ ```
12
+ editor/
13
+ src/
14
+ types.ts edit list model + JSON wire format
15
+ math.ts shared pixel-math helpers
16
+ shaders.ts shared GLSL (quad, copy, blit, gaussian)
17
+ pipeline.ts EditPipeline — headless, canvas-taking preview
18
+ transforms/ one Transform class per edit + registry (index.ts)
19
+ + state serialization (state.ts); mirrors src/transforms/*.h
20
+ index.ts public surface (per-transform types import from their file)
21
+ demo/ tests/ playground (schema-driven) · vitest
22
+ demo/parity.html + demo/parity.ts + demo/parity-cases.json
23
+ committed WebGL↔VIPS side-by-side page: static shell, runtime
24
+ cards + live WebGL, cases as typed JSON (`satisfies` import)
25
+ demo/parity/ git-ignored VIPS JPEGs rendered by generate-parity.py
26
+ demo/generate-parity.py dumb renderer: reads parity-cases.json, runs a
27
+ built vips-preview (`npm run parity`)
28
+ UltraHDR source; VIPS side pre-rendered, WebGL side live.
29
+ ```
30
+
31
+ Adding a transform: write its file, add one line to the registry — pipeline,
32
+ validation, serialization, and demo pick it up.
33
+
34
+ ```bash
35
+ cd editor
36
+ npm install
37
+ npm run dev # demo playground
38
+ npm run parity # render VIPS-side parity JPEGs via a built vips-preview
39
+ npm run typecheck && npm test # tsc + vitest
40
+ npm run format # prettier --write
41
+ npm run build # typecheck + demo bundle (index.html + parity.html)
42
+ ```
43
+
44
+ ## Publishing
45
+
46
+ The package ships compiled `dist/` (JS + `.d.ts`, zero runtime deps).
47
+ `npm publish` runs `prepublishOnly` (clean → typecheck → test → `build:lib`).
48
+
49
+ ```bash
50
+ cd editor
51
+ npm run publish:dry # verify tarball contents without uploading
52
+ npm publish # clean + typecheck + test + build:lib, then publish
53
+ ```
54
+
55
+ ## Wire format
56
+
57
+ ```json
58
+ {
59
+ "cmd": "convert",
60
+ "input": "in.jpg",
61
+ "output": "out.jpg",
62
+ "edits": [{ "edit": "brightnessContrast", "brightness": 0.1, "contrast": 0.1 }]
63
+ }
64
+ ```
65
+
66
+ Numerics are optional (missing = no-change, except `sepia.amount` default 1);
67
+ the CLI rejects out-of-range values, so normalize client-side.
68
+
69
+ ## VIPS mapping
70
+
71
+ sRGB 0..1 floats, array order, single uchar clip at the end; alpha is split
72
+ off, normalized to 0..1 float alongside, reattached. Everything agrees to
73
+ float precision (±1 LSB after quantize), including `blur`/`sharpen` (both
74
+ sides convolve the same discrete kernel — `sigma=radius/2`,
75
+ `half=min(15,max(1,ceil(2σ)))`, clamp edges — via two separable passes).
76
+ Thumbnail edits run **after** resize (radii are output pixels). The preview
77
+ downscales sources larger than 2048px and scales `blur`/`sharpen` radii by
78
+ the working/native ratio, so it shows the same *relative* blur as the
79
+ full-res VIPS output. UHDR ICC+gainmap pass through untouched (gainmap is
80
+ not re-derived). `rotate` by
81
+ a non-90 angle appends a transparent alpha band (corners + fringes); 90°
82
+ multiples stay exact with no band change.
83
+
84
+ | edit | params | VIPS |
85
+ | ----------------------- | -------------------------------------- | ------------------------------ |
86
+ | `brightnessContrast` | `brightness`, `contrast` −1..1 | `linear(mult, bias)` |
87
+ | `exposure` | `stops` −5..5 | `linear(2^stops)` |
88
+ | `hueSaturation` | `hue`, `saturation` −1..1 | fused 3×3 (≡ `recomb`) |
89
+ | `sepia` | `amount` 0..1 | same matrix, clipped at cast |
90
+ | `vibrance` / `vignette` | `amount` −1..1 / `size`, `amount` 0..1 | identical CPU loop |
91
+ | `grayscale` / `invert` | — | `(r+g+b)/3` / `linear(-1, +1)` |
92
+ | `blur` / `sharpen` | `radius` 0..100 / +`amount` 0..5 | shared kernel + `convsep` (mix)|
93
+ | `crop` | `x`,`y`,`width`,`height` 0..1 fractions| `extract_area` (rounded+clamped)|
94
+ | `rotate` | `angle` −180..180 (clockwise °) | `rot()` @90s, else `rotate()` |
95
+
96
+ Excluded (no clean VIPS mapping): `denoise`, `noise`, `curves`,
97
+ `lensBlur`/`tiltShift`/`zoomBlur`, halftones, warps.
98
+
99
+ Caveats: no-float GPUs fall back to 8-bit targets (more rounding drift);
100
+ preview caps at 2048px longest side (VIPS renders full-res); WebGL failures
101
+ throw instead of rendering black. Shaders adapted from
102
+ [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,129 @@
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
+ /**
22
+ * Take over the canvas' WebGL context. preserveDrawingBuffer stays true
23
+ * so the demo can read pixels back; premultipliedAlpha stays false
24
+ * so alpha survives the passes unmodified. The canvas backing store is
25
+ * resized to the rendered output on every render — the caller owns layout
26
+ * and CSS only. Throws when WebGL is missing.
27
+ */
28
+ constructor(canvas: HTMLCanvasElement);
29
+ /** Output image size (source size when no geometric edit applies). */
30
+ get width(): number;
31
+ get height(): number;
32
+ /** Ordered edit list (live reference — mutate via setEdits/addEdit/...). */
33
+ getEdits(): Edit[];
34
+ /** Replace the whole edit list (normalizing each edit) and re-render. */
35
+ setEdits(edits: Edit[]): void;
36
+ /** Append one edit (normalized) and re-render. */
37
+ addEdit(edit: Edit): void;
38
+ /** Drop the edit at `index` and re-render. */
39
+ removeEdit(index: number): void;
40
+ /** Reorder one edit and re-render. */
41
+ moveEdit(from: number, to: number): void;
42
+ /** Drop all edits (back to the bare source image) and re-render. */
43
+ clearEdits(): void;
44
+ /** Canonical JSON state for the VIPS side. */
45
+ toJSON(): string;
46
+ /**
47
+ * Longest side of the working image. Camera JPEGs (12-50MP) would need
48
+ * hundreds of MB as float ping-pong targets and exceed
49
+ * MAX_TEXTURE_SIZE on weak GPUs — both failure modes render black with
50
+ * no exception. The preview is resolution-capped (reported via
51
+ * width/height); the VIPS side always renders full-res from the JSON.
52
+ */
53
+ static readonly MAX_DIM = 2048;
54
+ /** Resolve the pixel size of any TexImageSource upload. */
55
+ private sourceDims;
56
+ /** Turn a sticky GL error flag into a thrown message naming the stage. */
57
+ private checkGLError;
58
+ /**
59
+ * Upload a new source image, (re)allocating all targets to it.
60
+ * Oversized sources are downscaled through a 2D canvas first (see
61
+ * MAX_DIM); old GL targets are deleted. Ends with a full render(),
62
+ * which resizes the canvas backing store to the output area.
63
+ * Throws with a message instead of rendering black on failure.
64
+ */
65
+ setImage(source: TexImageSource): void;
66
+ /**
67
+ * Re-run all passes: copy source -> ping, then apply each edit in order,
68
+ * ping-ponging between the two working targets (`cur` holds the latest
69
+ * result, `nxt` is the scratch target; multi-pass edits may bounce
70
+ * between them internally and return either side). Geometric edits
71
+ * (crop/rotate) change dimensions: `nxt` is resized to the edit's
72
+ * outputDims before apply, `extra` is kept at the input size (sharpen
73
+ * scratch). Presents by resizing the canvas to the rendered area and
74
+ * blitting fullscreen 1:1. No-op when no image is loaded yet.
75
+ */
76
+ render(): void;
77
+ /**
78
+ * RenderContext facade for Transform.apply(): exposes the pass/blit/gauss
79
+ * drawing primitives plus the scratch `extra` target, without handing
80
+ * out the raw WebGL context.
81
+ */
82
+ private renderContext;
83
+ /** Resize a working target when geometry changed (returns live target). */
84
+ private ensureSize;
85
+ /**
86
+ * Decide float vs 8-bit ping-pong targets. Float needs both the
87
+ * renderable-float extension and float-linear filtering (every pass
88
+ * samples with LINEAR); either missing falls back to UNSIGNED_BYTE.
89
+ * Also verifies float renderability with a throwaway 4x4 target.
90
+ */
91
+ private probeFloat;
92
+ /**
93
+ * Allocate one offscreen RGBA render target (texture + framebuffer) with
94
+ * linear filtering and clamp-to-edge (NPOT-safe: no mipmaps, no repeat).
95
+ */
96
+ private makeTarget;
97
+ /**
98
+ * Compile one shader stage, throwing the info log on failure (a bad
99
+ * shader would otherwise render black with no indication why).
100
+ */
101
+ private compile;
102
+ /** Compile+link the quad vertex shader with `frag`, cached by source. */
103
+ private program;
104
+ /**
105
+ * Draw one fullscreen pass: render `from` through `frag` into `to`.
106
+ * `from` is bound to unit 0 (`texture` uniform) unless the shader uses
107
+ * other sampler names; `extraTex` optionally binds a second texture
108
+ * (used by the sharpen mix pass). `setUniforms` fills the rest.
109
+ */
110
+ pass(frag: string, from: Target, to: Target, setUniforms?: UniformSetter, extraTex?: ExtraTex): void;
111
+ /** Copy one target to another with the identity shader. */
112
+ blit(from: Target, to: Target): void;
113
+ /**
114
+ * One axis of the separable gaussian: `horizontal` picks the sample
115
+ * direction (offsets are in UV units, hence the 1/width division).
116
+ * The shader loops over a fixed 31-tap array; `kernel.length` tells it
117
+ * how many center taps carry real weight, the rest are zero-padded.
118
+ */
119
+ gauss(from: Target, to: Target, horizontal: boolean, kernel: number[]): void;
120
+ /**
121
+ * Present the final result: resize the canvas backing store to the
122
+ * rendered output area (a no-op assignment when it already matches —
123
+ * setting width/height clears, so this only fires when geometry changed)
124
+ * and blit fullscreen 1:1. (The BLIT_FRAG flip still compensates the
125
+ * unflipped upload.)
126
+ */
127
+ private toCanvas;
128
+ }
129
+ //# sourceMappingURL=pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"AAeA,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;IAEtB;;;;;;OAMG;gBACgB,MAAM,EAAE,iBAAiB;IA2B5C,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;CAsBjB"}