@pixerate/editor 0.111.0 → 0.113.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 (38) hide show
  1. package/THIRD_PARTY_NOTICES.md +6 -0
  2. package/dist/chunk-4KLT7ZYS.cjs +781 -0
  3. package/dist/chunk-4KLT7ZYS.cjs.map +1 -0
  4. package/dist/{chunk-HHZ6ZJTW.js → chunk-CZOXTEMN.js} +1772 -456
  5. package/dist/chunk-CZOXTEMN.js.map +1 -0
  6. package/dist/chunk-LPYOIVLA.js +781 -0
  7. package/dist/chunk-LPYOIVLA.js.map +1 -0
  8. package/dist/{chunk-PHUMLSCW.cjs → chunk-YGIMK4NX.cjs} +1810 -494
  9. package/dist/chunk-YGIMK4NX.cjs.map +1 -0
  10. package/dist/{export-DoDhCszr.d.cts → export-CEXEzqBf.d.cts} +150 -18
  11. package/dist/{export-DBNVwb6h.d.ts → export-DIkoK8-r.d.ts} +150 -18
  12. package/dist/image-editor/index.cjs +1922 -788
  13. package/dist/image-editor/index.cjs.map +1 -1
  14. package/dist/image-editor/index.d.cts +233 -9
  15. package/dist/image-editor/index.d.ts +233 -9
  16. package/dist/image-editor/index.js +1208 -74
  17. package/dist/image-editor/index.js.map +1 -1
  18. package/dist/paint/index.cjs +61 -2
  19. package/dist/paint/index.cjs.map +1 -1
  20. package/dist/paint/index.d.cts +29 -2
  21. package/dist/paint/index.d.ts +29 -2
  22. package/dist/paint/index.js +60 -1
  23. package/dist/paint-editor/index.cjs +6 -6
  24. package/dist/paint-editor/index.d.cts +3 -3
  25. package/dist/paint-editor/index.d.ts +3 -3
  26. package/dist/paint-editor/index.js +1 -1
  27. package/dist/{blending-DXl06NSx.d.ts → retouch-BXmeSCaB.d.ts} +218 -1
  28. package/dist/{blending-aOE6Y3UE.d.cts → retouch-CEIKR22W.d.cts} +218 -1
  29. package/package.json +1 -1
  30. package/skills/pixerate-image-editor/SKILL.md +30 -6
  31. package/skills/pixerate-image-editor/references/retouching.md +36 -0
  32. package/skills/pixerate-vector/SKILL.md +102 -5
  33. package/dist/chunk-FTBZPI77.cjs +0 -1
  34. package/dist/chunk-FTBZPI77.cjs.map +0 -1
  35. package/dist/chunk-HHZ6ZJTW.js.map +0 -1
  36. package/dist/chunk-PHUMLSCW.cjs.map +0 -1
  37. package/dist/chunk-VKK5VS2T.js +0 -1
  38. package/dist/chunk-VKK5VS2T.js.map +0 -1
@@ -1,4 +1,34 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});require('../chunk-FTBZPI77.cjs');
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+ var _chunk4KLT7ZYScjs = require('../chunk-4KLT7ZYS.cjs');
2
32
 
3
33
 
4
34
 
@@ -102,5 +132,34 @@ var _chunkXIOMMGPDcjs = require('../chunk-XIOMMGPD.cjs');
102
132
 
103
133
 
104
134
 
105
- exports.CoverageMap = _chunk7VOHOPLWcjs.CoverageMap; exports.DEFAULT_BLENDER = _chunk7VOHOPLWcjs.DEFAULT_BLENDER; exports.DEFAULT_BRUSH = _chunk7VOHOPLWcjs.DEFAULT_BRUSH; exports.DEFAULT_MIXER = _chunk7VOHOPLWcjs.DEFAULT_MIXER; exports.DEFAULT_SMUDGE = _chunk7VOHOPLWcjs.DEFAULT_SMUDGE; exports.DabWalker = _chunk7VOHOPLWcjs.DabWalker; exports.EMPTY_MIXER_LOAD = _chunk7VOHOPLWcjs.EMPTY_MIXER_LOAD; exports.MAX_BRUSH_SIZE = _chunk7VOHOPLWcjs.MAX_BRUSH_SIZE; exports.MIXER_DRAIN = _chunk7VOHOPLWcjs.MIXER_DRAIN; exports.MIXER_PICKUP_RATE = _chunk7VOHOPLWcjs.MIXER_PICKUP_RATE; exports.MIXING_MODELS = _chunk7VOHOPLWcjs.MIXING_MODELS; exports.MixerStroke = _chunk7VOHOPLWcjs.MixerStroke; exports.PIGMENT_BANDS = _chunkXIOMMGPDcjs.PIGMENT_BANDS; exports.PIGMENT_LAMBDA_MIN = _chunkXIOMMGPDcjs.PIGMENT_LAMBDA_MIN; exports.PIGMENT_LAMBDA_STEP = _chunkXIOMMGPDcjs.PIGMENT_LAMBDA_STEP; exports.PIGMENT_WAVELENGTHS = _chunkXIOMMGPDcjs.PIGMENT_WAVELENGTHS; exports.PaintExchange = _chunk7VOHOPLWcjs.PaintExchange; exports.SmudgeTip = _chunk7VOHOPLWcjs.SmudgeTip; exports.StrokeCoverage = _chunk7VOHOPLWcjs.StrokeCoverage; exports.TileMedium = _chunk7VOHOPLWcjs.TileMedium; exports.applyStrokeToTile = _chunk7VOHOPLWcjs.applyStrokeToTile; exports.blendRadius = _chunk7VOHOPLWcjs.blendRadius; exports.blenderDab = _chunk7VOHOPLWcjs.blenderDab; exports.cleanMixer = _chunk7VOHOPLWcjs.cleanMixer; exports.coverageTileCoord = _chunk7VOHOPLWcjs.coverageTileCoord; exports.createBlenderScratch = _chunk7VOHOPLWcjs.createBlenderScratch; exports.createPigment = _chunkXIOMMGPDcjs.createPigment; exports.createPigmentTools = _chunk7VOHOPLWcjs.createPigmentTools; exports.dabCoverage = _chunk7VOHOPLWcjs.dabCoverage; exports.dabRect = _chunk7VOHOPLWcjs.dabRect; exports.exchangeRates = _chunk7VOHOPLWcjs.exchangeRates; exports.lerpPigment = _chunkXIOMMGPDcjs.lerpPigment; exports.lerpPigmentInto = _chunkXIOMMGPDcjs.lerpPigmentInto; exports.loadMixer = _chunk7VOHOPLWcjs.loadMixer; exports.mixPigments = _chunkXIOMMGPDcjs.mixPigments; exports.mixerRates = _chunk7VOHOPLWcjs.mixerRates; exports.normalizeBlender = _chunk7VOHOPLWcjs.normalizeBlender; exports.normalizeBrush = _chunk7VOHOPLWcjs.normalizeBrush; exports.normalizeMixer = _chunk7VOHOPLWcjs.normalizeMixer; exports.normalizeSmudge = _chunk7VOHOPLWcjs.normalizeSmudge; exports.rasterizeDab = _chunk7VOHOPLWcjs.rasterizeDab; exports.reflectanceToRgb = _chunkXIOMMGPDcjs.reflectanceToRgb; exports.rgbToReflectance = _chunkXIOMMGPDcjs.rgbToReflectance; exports.setPigmentColor = _chunkXIOMMGPDcjs.setPigmentColor; exports.smoothPoints = _chunk7VOHOPLWcjs.smoothPoints; exports.tipFalloff = _chunk7VOHOPLWcjs.tipFalloff; exports.tipReach = _chunk7VOHOPLWcjs.tipReach; exports.tipShape = _chunk7VOHOPLWcjs.tipShape; exports.walkDabs = _chunk7VOHOPLWcjs.walkDabs;
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+ exports.CoverageMap = _chunk7VOHOPLWcjs.CoverageMap; exports.DEFAULT_BLENDER = _chunk7VOHOPLWcjs.DEFAULT_BLENDER; exports.DEFAULT_BRUSH = _chunk7VOHOPLWcjs.DEFAULT_BRUSH; exports.DEFAULT_MIXER = _chunk7VOHOPLWcjs.DEFAULT_MIXER; exports.DEFAULT_RETOUCH = _chunk4KLT7ZYScjs.DEFAULT_RETOUCH; exports.DEFAULT_SMUDGE = _chunk7VOHOPLWcjs.DEFAULT_SMUDGE; exports.DabWalker = _chunk7VOHOPLWcjs.DabWalker; exports.EMPTY_MIXER_LOAD = _chunk7VOHOPLWcjs.EMPTY_MIXER_LOAD; exports.MAX_BRUSH_SIZE = _chunk7VOHOPLWcjs.MAX_BRUSH_SIZE; exports.MIXER_DRAIN = _chunk7VOHOPLWcjs.MIXER_DRAIN; exports.MIXER_PICKUP_RATE = _chunk7VOHOPLWcjs.MIXER_PICKUP_RATE; exports.MIXING_MODELS = _chunk7VOHOPLWcjs.MIXING_MODELS; exports.MixerStroke = _chunk7VOHOPLWcjs.MixerStroke; exports.PIGMENT_BANDS = _chunkXIOMMGPDcjs.PIGMENT_BANDS; exports.PIGMENT_LAMBDA_MIN = _chunkXIOMMGPDcjs.PIGMENT_LAMBDA_MIN; exports.PIGMENT_LAMBDA_STEP = _chunkXIOMMGPDcjs.PIGMENT_LAMBDA_STEP; exports.PIGMENT_WAVELENGTHS = _chunkXIOMMGPDcjs.PIGMENT_WAVELENGTHS; exports.PaintExchange = _chunk7VOHOPLWcjs.PaintExchange; exports.RETOUCH_SAMPLES = _chunk4KLT7ZYScjs.RETOUCH_SAMPLES; exports.RegionPixelSource = _chunk4KLT7ZYScjs.RegionPixelSource; exports.RetouchDabStroke = _chunk4KLT7ZYScjs.RetouchDabStroke; exports.SPOT_HEAL_TYPES = _chunk4KLT7ZYScjs.SPOT_HEAL_TYPES; exports.SmudgeTip = _chunk7VOHOPLWcjs.SmudgeTip; exports.StrokeCoverage = _chunk7VOHOPLWcjs.StrokeCoverage; exports.TONE_RANGES = _chunk4KLT7ZYScjs.TONE_RANGES; exports.TileMedium = _chunk7VOHOPLWcjs.TileMedium; exports.TilePixelSource = _chunk4KLT7ZYScjs.TilePixelSource; exports.applyRetouchToTile = _chunk4KLT7ZYScjs.applyRetouchToTile; exports.applyStrokeToTile = _chunk7VOHOPLWcjs.applyStrokeToTile; exports.bestOffset = _chunk4KLT7ZYScjs.bestOffset; exports.blendRadius = _chunk7VOHOPLWcjs.blendRadius; exports.blenderDab = _chunk7VOHOPLWcjs.blenderDab; exports.cleanMixer = _chunk7VOHOPLWcjs.cleanMixer; exports.coverageTileCoord = _chunk7VOHOPLWcjs.coverageTileCoord; exports.createBlenderScratch = _chunk7VOHOPLWcjs.createBlenderScratch; exports.createPigment = _chunkXIOMMGPDcjs.createPigment; exports.createPigmentTools = _chunk7VOHOPLWcjs.createPigmentTools; exports.dabCoverage = _chunk7VOHOPLWcjs.dabCoverage; exports.dabRect = _chunk7VOHOPLWcjs.dabRect; exports.dilateMask = _chunk4KLT7ZYScjs.dilateMask; exports.dodgeBurn = _chunk4KLT7ZYScjs.dodgeBurn; exports.dodgeBurnCurve = _chunk4KLT7ZYScjs.dodgeBurnCurve; exports.exchangeRates = _chunk7VOHOPLWcjs.exchangeRates; exports.healPixels = _chunk4KLT7ZYScjs.healPixels; exports.lerpPigment = _chunkXIOMMGPDcjs.lerpPigment; exports.lerpPigmentInto = _chunkXIOMMGPDcjs.lerpPigmentInto; exports.loadMixer = _chunk7VOHOPLWcjs.loadMixer; exports.luma = _chunk4KLT7ZYScjs.luma; exports.maskBounds = _chunk4KLT7ZYScjs.maskBounds; exports.membraneFill = _chunk4KLT7ZYScjs.membraneFill; exports.mixPigments = _chunkXIOMMGPDcjs.mixPigments; exports.mixerRates = _chunk7VOHOPLWcjs.mixerRates; exports.normalizeBlender = _chunk7VOHOPLWcjs.normalizeBlender; exports.normalizeBrush = _chunk7VOHOPLWcjs.normalizeBrush; exports.normalizeMixer = _chunk7VOHOPLWcjs.normalizeMixer; exports.normalizeRetouch = _chunk4KLT7ZYScjs.normalizeRetouch; exports.normalizeSmudge = _chunk7VOHOPLWcjs.normalizeSmudge; exports.perDabStrength = _chunk4KLT7ZYScjs.perDabStrength; exports.rasterizeDab = _chunk7VOHOPLWcjs.rasterizeDab; exports.readSourceRegion = _chunk4KLT7ZYScjs.readSourceRegion; exports.reflectanceToRgb = _chunkXIOMMGPDcjs.reflectanceToRgb; exports.rgbToReflectance = _chunkXIOMMGPDcjs.rgbToReflectance; exports.rgbaViewOfGrey = _chunk4KLT7ZYScjs.rgbaViewOfGrey; exports.saturationOf = _chunk4KLT7ZYScjs.saturationOf; exports.seamlessClone = _chunk4KLT7ZYScjs.seamlessClone; exports.setPigmentColor = _chunkXIOMMGPDcjs.setPigmentColor; exports.smoothPoints = _chunk7VOHOPLWcjs.smoothPoints; exports.smudgeEffect = _chunk4KLT7ZYScjs.smudgeEffect; exports.solveMembrane = _chunk4KLT7ZYScjs.solveMembrane; exports.sponge = _chunk4KLT7ZYScjs.sponge; exports.spongeEffect = _chunk4KLT7ZYScjs.spongeEffect; exports.spotHealPixels = _chunk4KLT7ZYScjs.spotHealPixels; exports.spotHealWindow = _chunk4KLT7ZYScjs.spotHealWindow; exports.tipFalloff = _chunk7VOHOPLWcjs.tipFalloff; exports.tipReach = _chunk7VOHOPLWcjs.tipReach; exports.tipShape = _chunk7VOHOPLWcjs.tipShape; exports.toneOf = _chunk4KLT7ZYScjs.toneOf; exports.walkDabs = _chunk7VOHOPLWcjs.walkDabs;
106
165
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/paint/index.cjs"],"names":[],"mappings":"AAAA,0GAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,4uFAAC","file":"/home/runner/work/editor/editor/packages/core/dist/paint/index.cjs"}
1
+ {"version":3,"sources":["/home/runner/work/editor/editor/packages/core/dist/paint/index.cjs"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,yDAA8B;AAC9B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,q0IAAC","file":"/home/runner/work/editor/editor/packages/core/dist/paint/index.cjs"}
@@ -1,4 +1,4 @@
1
- export { j as BlenderScratch, b as BlenderSettings, B as BrushSettings, C as CoverageMap, k as DEFAULT_BLENDER, l as DEFAULT_BRUSH, m as DEFAULT_MIXER, n as DEFAULT_SMUDGE, D as Dab, o as DabWalker, E as EMPTY_MIXER_LOAD, p as ExchangeRates, e as MAX_BRUSH_SIZE, q as MIXER_DRAIN, r as MIXER_PICKUP_RATE, s as MIXING_MODELS, d as MixerLoad, M as MixerSettings, h as MixerStroke, g as MixerTarget, a as MixingModel, t as PaintExchange, u as PaintMedium, v as PaintSample, P as PaintTileTarget, R as RgbTriple, w as SmudgeDab, S as SmudgeSettings, x as SmudgeTip, i as StrokeApply, f as StrokeCoverage, c as StrokePoint, T as TileMedium, y as TileMediumOptions, z as applyStrokeToTile, A as blendRadius, F as blenderDab, G as cleanMixer, H as coverageTileCoord, I as createBlenderScratch, J as dabCoverage, K as dabRect, L as exchangeRates, N as loadMixer, O as mixerRates, Q as normalizeBlender, U as normalizeBrush, V as normalizeMixer, W as normalizeSmudge, X as rasterizeDab, Y as smoothPoints, Z as tipFalloff, _ as tipReach, $ as tipShape, a0 as walkDabs } from '../blending-aOE6Y3UE.cjs';
1
+ export { m as BlenderScratch, b as BlenderSettings, B as BrushSettings, C as CoverageMap, n as DEFAULT_BLENDER, o as DEFAULT_BRUSH, p as DEFAULT_MIXER, q as DEFAULT_RETOUCH, r as DEFAULT_SMUDGE, D as Dab, s as DabWalker, E as EMPTY_MIXER_LOAD, t as ExchangeRates, e as MAX_BRUSH_SIZE, u as MIXER_DRAIN, v as MIXER_PICKUP_RATE, w as MIXING_MODELS, d as MixerLoad, M as MixerSettings, i as MixerStroke, h as MixerTarget, a as MixingModel, x as PaintExchange, y as PaintMedium, z as PaintSample, P as PaintTileTarget, A as PixelSource, F as RETOUCH_SAMPLES, G as RegionPixelSource, j as RetouchApply, H as RetouchDabEffect, I as RetouchDabStroke, k as RetouchPaint, J as RetouchSample, f as RetouchSettings, R as RgbTriple, K as SPOT_HEAL_TYPES, L as SmudgeDab, S as SmudgeSettings, N as SmudgeTip, O as SpotHealType, l as StrokeApply, g as StrokeCoverage, c as StrokePoint, T as TONE_RANGES, Q as TileMedium, U as TileMediumOptions, V as TilePixelSource, W as ToneRange, X as applyRetouchToTile, Y as applyStrokeToTile, Z as blendRadius, _ as blenderDab, $ as cleanMixer, a0 as coverageTileCoord, a1 as createBlenderScratch, a2 as dabCoverage, a3 as dabRect, a4 as dodgeBurn, a5 as dodgeBurnCurve, a6 as exchangeRates, a7 as healPixels, a8 as loadMixer, a9 as luma, aa as mixerRates, ab as normalizeBlender, ac as normalizeBrush, ad as normalizeMixer, ae as normalizeRetouch, af as normalizeSmudge, ag as perDabStrength, ah as rasterizeDab, ai as readSourceRegion, aj as rgbaViewOfGrey, ak as saturationOf, al as smoothPoints, am as smudgeEffect, an as sponge, ao as spongeEffect, ap as spotHealPixels, aq as spotHealWindow, ar as tipFalloff, as as tipReach, at as tipShape, au as toneOf, av as walkDabs } from '../retouch-CEIKR22W.cjs';
2
2
  export { h as PIGMENT_BANDS, j as PIGMENT_LAMBDA_MIN, k as PIGMENT_LAMBDA_STEP, l as PIGMENT_WAVELENGTHS, P as Pigment, m as PigmentOptions, n as PigmentRgb, D as createPigment, I as lerpPigment, J as lerpPigmentInto, N as mixPigments, X as reflectanceToRgb, Y as rgbToReflectance, _ as setPigmentColor } from '../surface-C8RRg_Bh.cjs';
3
3
  import { A as AgentTool } from '../registry-BqA1AZt0.cjs';
4
4
  import '../schema-Di0CS6Pe.cjs';
@@ -9,4 +9,31 @@ import '../schema-Di0CS6Pe.cjs';
9
9
  */
10
10
  declare function createPigmentTools(): AgentTool[];
11
11
 
12
- export { createPigmentTools };
12
+ /**
13
+ * Solves `Δv = 0` on the `unknown` pixels, with the known pixels of `v` as Dirichlet values
14
+ * (neighbours off the grid are ignored: a free boundary). `v` holds the known values on entry and
15
+ * the solution on exit.
16
+ */
17
+ declare function solveMembrane(w: number, h: number, unknown: ArrayLike<boolean | number>, v: Float32Array): void;
18
+ /**
19
+ * Seamless cloning: `dst` outside `mask`; inside, `src` plus the membrane that removes the
20
+ * mismatch at the mask's edge. So the result keeps the source's texture and takes the
21
+ * destination's colour and light. `src` and `dst` are interleaved `w × h × ch`; leave a one-pixel
22
+ * unmasked margin for a fully fixed boundary.
23
+ */
24
+ declare function seamlessClone(w: number, h: number, ch: number, src: ArrayLike<number>, dst: ArrayLike<number>, mask: ArrayLike<boolean | number>): Float32Array;
25
+ /** Membrane fill (no source texture): the known pixels interpolated smoothly into `hole`. */
26
+ declare function membraneFill(w: number, h: number, ch: number, img: ArrayLike<number>, hole: ArrayLike<boolean | number>): Float32Array;
27
+ /** A mask grown by `r` pixels (square structuring element). */
28
+ declare function dilateMask(w: number, h: number, mask: ArrayLike<boolean | number>, r: number): Uint8Array;
29
+ /** Bounding box [x0, y0, x1, y1) of the set cells, or null. */
30
+ declare function maskBounds(w: number, h: number, mask: ArrayLike<boolean | number>): [number, number, number, number] | null;
31
+ /**
32
+ * Proximity match: the translation `(dx, dy)` (within `maxRadius`) whose pixels best match the
33
+ * ring of `ring` pixels around the hole (sum of squared differences), so `img[p + (dx, dy)]` can
34
+ * fill `p` in the hole. The source window must lie on the grid and hold no hole pixels. Nearer
35
+ * sources win ties. Returns null when no translation fits.
36
+ */
37
+ declare function bestOffset(w: number, h: number, ch: number, img: ArrayLike<number>, hole: ArrayLike<boolean | number>, ring: number, maxRadius: number): [number, number] | null;
38
+
39
+ export { bestOffset, createPigmentTools, dilateMask, maskBounds, membraneFill, seamlessClone, solveMembrane };
@@ -1,4 +1,4 @@
1
- export { j as BlenderScratch, b as BlenderSettings, B as BrushSettings, C as CoverageMap, k as DEFAULT_BLENDER, l as DEFAULT_BRUSH, m as DEFAULT_MIXER, n as DEFAULT_SMUDGE, D as Dab, o as DabWalker, E as EMPTY_MIXER_LOAD, p as ExchangeRates, e as MAX_BRUSH_SIZE, q as MIXER_DRAIN, r as MIXER_PICKUP_RATE, s as MIXING_MODELS, d as MixerLoad, M as MixerSettings, h as MixerStroke, g as MixerTarget, a as MixingModel, t as PaintExchange, u as PaintMedium, v as PaintSample, P as PaintTileTarget, R as RgbTriple, w as SmudgeDab, S as SmudgeSettings, x as SmudgeTip, i as StrokeApply, f as StrokeCoverage, c as StrokePoint, T as TileMedium, y as TileMediumOptions, z as applyStrokeToTile, A as blendRadius, F as blenderDab, G as cleanMixer, H as coverageTileCoord, I as createBlenderScratch, J as dabCoverage, K as dabRect, L as exchangeRates, N as loadMixer, O as mixerRates, Q as normalizeBlender, U as normalizeBrush, V as normalizeMixer, W as normalizeSmudge, X as rasterizeDab, Y as smoothPoints, Z as tipFalloff, _ as tipReach, $ as tipShape, a0 as walkDabs } from '../blending-DXl06NSx.js';
1
+ export { m as BlenderScratch, b as BlenderSettings, B as BrushSettings, C as CoverageMap, n as DEFAULT_BLENDER, o as DEFAULT_BRUSH, p as DEFAULT_MIXER, q as DEFAULT_RETOUCH, r as DEFAULT_SMUDGE, D as Dab, s as DabWalker, E as EMPTY_MIXER_LOAD, t as ExchangeRates, e as MAX_BRUSH_SIZE, u as MIXER_DRAIN, v as MIXER_PICKUP_RATE, w as MIXING_MODELS, d as MixerLoad, M as MixerSettings, i as MixerStroke, h as MixerTarget, a as MixingModel, x as PaintExchange, y as PaintMedium, z as PaintSample, P as PaintTileTarget, A as PixelSource, F as RETOUCH_SAMPLES, G as RegionPixelSource, j as RetouchApply, H as RetouchDabEffect, I as RetouchDabStroke, k as RetouchPaint, J as RetouchSample, f as RetouchSettings, R as RgbTriple, K as SPOT_HEAL_TYPES, L as SmudgeDab, S as SmudgeSettings, N as SmudgeTip, O as SpotHealType, l as StrokeApply, g as StrokeCoverage, c as StrokePoint, T as TONE_RANGES, Q as TileMedium, U as TileMediumOptions, V as TilePixelSource, W as ToneRange, X as applyRetouchToTile, Y as applyStrokeToTile, Z as blendRadius, _ as blenderDab, $ as cleanMixer, a0 as coverageTileCoord, a1 as createBlenderScratch, a2 as dabCoverage, a3 as dabRect, a4 as dodgeBurn, a5 as dodgeBurnCurve, a6 as exchangeRates, a7 as healPixels, a8 as loadMixer, a9 as luma, aa as mixerRates, ab as normalizeBlender, ac as normalizeBrush, ad as normalizeMixer, ae as normalizeRetouch, af as normalizeSmudge, ag as perDabStrength, ah as rasterizeDab, ai as readSourceRegion, aj as rgbaViewOfGrey, ak as saturationOf, al as smoothPoints, am as smudgeEffect, an as sponge, ao as spongeEffect, ap as spotHealPixels, aq as spotHealWindow, ar as tipFalloff, as as tipReach, at as tipShape, au as toneOf, av as walkDabs } from '../retouch-BXmeSCaB.js';
2
2
  export { h as PIGMENT_BANDS, j as PIGMENT_LAMBDA_MIN, k as PIGMENT_LAMBDA_STEP, l as PIGMENT_WAVELENGTHS, P as Pigment, m as PigmentOptions, n as PigmentRgb, D as createPigment, I as lerpPigment, J as lerpPigmentInto, N as mixPigments, X as reflectanceToRgb, Y as rgbToReflectance, _ as setPigmentColor } from '../surface-C8RRg_Bh.js';
3
3
  import { A as AgentTool } from '../registry-D-4fit9C.js';
4
4
  import '../schema-Di0CS6Pe.js';
@@ -9,4 +9,31 @@ import '../schema-Di0CS6Pe.js';
9
9
  */
10
10
  declare function createPigmentTools(): AgentTool[];
11
11
 
12
- export { createPigmentTools };
12
+ /**
13
+ * Solves `Δv = 0` on the `unknown` pixels, with the known pixels of `v` as Dirichlet values
14
+ * (neighbours off the grid are ignored: a free boundary). `v` holds the known values on entry and
15
+ * the solution on exit.
16
+ */
17
+ declare function solveMembrane(w: number, h: number, unknown: ArrayLike<boolean | number>, v: Float32Array): void;
18
+ /**
19
+ * Seamless cloning: `dst` outside `mask`; inside, `src` plus the membrane that removes the
20
+ * mismatch at the mask's edge. So the result keeps the source's texture and takes the
21
+ * destination's colour and light. `src` and `dst` are interleaved `w × h × ch`; leave a one-pixel
22
+ * unmasked margin for a fully fixed boundary.
23
+ */
24
+ declare function seamlessClone(w: number, h: number, ch: number, src: ArrayLike<number>, dst: ArrayLike<number>, mask: ArrayLike<boolean | number>): Float32Array;
25
+ /** Membrane fill (no source texture): the known pixels interpolated smoothly into `hole`. */
26
+ declare function membraneFill(w: number, h: number, ch: number, img: ArrayLike<number>, hole: ArrayLike<boolean | number>): Float32Array;
27
+ /** A mask grown by `r` pixels (square structuring element). */
28
+ declare function dilateMask(w: number, h: number, mask: ArrayLike<boolean | number>, r: number): Uint8Array;
29
+ /** Bounding box [x0, y0, x1, y1) of the set cells, or null. */
30
+ declare function maskBounds(w: number, h: number, mask: ArrayLike<boolean | number>): [number, number, number, number] | null;
31
+ /**
32
+ * Proximity match: the translation `(dx, dy)` (within `maxRadius`) whose pixels best match the
33
+ * ring of `ring` pixels around the hole (sum of squared differences), so `img[p + (dx, dy)]` can
34
+ * fill `p` in the hole. The source window must lie on the grid and hold no hole pixels. Nearer
35
+ * sources win ties. Returns null when no translation fits.
36
+ */
37
+ declare function bestOffset(w: number, h: number, ch: number, img: ArrayLike<number>, hole: ArrayLike<boolean | number>, ring: number, maxRadius: number): [number, number] | null;
38
+
39
+ export { bestOffset, createPigmentTools, dilateMask, maskBounds, membraneFill, seamlessClone, solveMembrane };
@@ -1,4 +1,34 @@
1
- import "../chunk-VKK5VS2T.js";
1
+ import {
2
+ DEFAULT_RETOUCH,
3
+ RETOUCH_SAMPLES,
4
+ RegionPixelSource,
5
+ RetouchDabStroke,
6
+ SPOT_HEAL_TYPES,
7
+ TONE_RANGES,
8
+ TilePixelSource,
9
+ applyRetouchToTile,
10
+ bestOffset,
11
+ dilateMask,
12
+ dodgeBurn,
13
+ dodgeBurnCurve,
14
+ healPixels,
15
+ luma,
16
+ maskBounds,
17
+ membraneFill,
18
+ normalizeRetouch,
19
+ perDabStrength,
20
+ readSourceRegion,
21
+ rgbaViewOfGrey,
22
+ saturationOf,
23
+ seamlessClone,
24
+ smudgeEffect,
25
+ solveMembrane,
26
+ sponge,
27
+ spongeEffect,
28
+ spotHealPixels,
29
+ spotHealWindow,
30
+ toneOf
31
+ } from "../chunk-LPYOIVLA.js";
2
32
  import {
3
33
  CoverageMap,
4
34
  DEFAULT_BLENDER,
@@ -57,6 +87,7 @@ export {
57
87
  DEFAULT_BLENDER,
58
88
  DEFAULT_BRUSH,
59
89
  DEFAULT_MIXER,
90
+ DEFAULT_RETOUCH,
60
91
  DEFAULT_SMUDGE,
61
92
  DabWalker,
62
93
  EMPTY_MIXER_LOAD,
@@ -70,10 +101,18 @@ export {
70
101
  PIGMENT_LAMBDA_STEP,
71
102
  PIGMENT_WAVELENGTHS,
72
103
  PaintExchange,
104
+ RETOUCH_SAMPLES,
105
+ RegionPixelSource,
106
+ RetouchDabStroke,
107
+ SPOT_HEAL_TYPES,
73
108
  SmudgeTip,
74
109
  StrokeCoverage,
110
+ TONE_RANGES,
75
111
  TileMedium,
112
+ TilePixelSource,
113
+ applyRetouchToTile,
76
114
  applyStrokeToTile,
115
+ bestOffset,
77
116
  blendRadius,
78
117
  blenderDab,
79
118
  cleanMixer,
@@ -83,24 +122,44 @@ export {
83
122
  createPigmentTools,
84
123
  dabCoverage,
85
124
  dabRect,
125
+ dilateMask,
126
+ dodgeBurn,
127
+ dodgeBurnCurve,
86
128
  exchangeRates,
129
+ healPixels,
87
130
  lerpPigment,
88
131
  lerpPigmentInto,
89
132
  loadMixer,
133
+ luma,
134
+ maskBounds,
135
+ membraneFill,
90
136
  mixPigments,
91
137
  mixerRates,
92
138
  normalizeBlender,
93
139
  normalizeBrush,
94
140
  normalizeMixer,
141
+ normalizeRetouch,
95
142
  normalizeSmudge,
143
+ perDabStrength,
96
144
  rasterizeDab,
145
+ readSourceRegion,
97
146
  reflectanceToRgb,
98
147
  rgbToReflectance,
148
+ rgbaViewOfGrey,
149
+ saturationOf,
150
+ seamlessClone,
99
151
  setPigmentColor,
100
152
  smoothPoints,
153
+ smudgeEffect,
154
+ solveMembrane,
155
+ sponge,
156
+ spongeEffect,
157
+ spotHealPixels,
158
+ spotHealWindow,
101
159
  tipFalloff,
102
160
  tipReach,
103
161
  tipShape,
162
+ toneOf,
104
163
  walkDabs
105
164
  };
106
165
  //# sourceMappingURL=index.js.map
@@ -4,7 +4,7 @@
4
4
 
5
5
 
6
6
 
7
- var _chunkPHUMLSCWcjs = require('../chunk-PHUMLSCW.cjs');
7
+ var _chunkYGIMK4NXcjs = require('../chunk-YGIMK4NX.cjs');
8
8
 
9
9
 
10
10
 
@@ -1697,11 +1697,11 @@ function header(state, options) {
1697
1697
  return out;
1698
1698
  }
1699
1699
  function serializePaintDocument(state, options = {}) {
1700
- const { layers, assets } = _chunkPHUMLSCWcjs.serializeLayers.call(void 0, state.layers);
1700
+ const { layers, assets } = _chunkYGIMK4NXcjs.serializeLayers.call(void 0, state.layers);
1701
1701
  return { ...header(state, options), layers, assets };
1702
1702
  }
1703
1703
  async function serializePaintDocumentExternal(state, store, options = {}) {
1704
- const { layers, assets } = await _chunkPHUMLSCWcjs.serializeLayersExternal.call(void 0, state.layers, store);
1704
+ const { layers, assets } = await _chunkYGIMK4NXcjs.serializeLayersExternal.call(void 0, state.layers, store);
1705
1705
  return { ...header(state, options), layers, assets };
1706
1706
  }
1707
1707
  function paintLayersOnly(layers, problems) {
@@ -1738,7 +1738,7 @@ function deserializePaintDocument(raw) {
1738
1738
  const canvas = normalizeCanvas({ width: r.width, height: r.height, dpi: _nullishCoalesce(r.dpi, () => ( void 0)) });
1739
1739
  const paper = normalizePaper(_nullishCoalesce(r.paper, () => ( {})));
1740
1740
  const assets = r.assets && typeof r.assets === "object" ? r.assets : {};
1741
- const layers = paintLayersOnly(_chunkPHUMLSCWcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1741
+ const layers = paintLayersOnly(_chunkYGIMK4NXcjs.deserializeLayers.call(void 0, r.layers, { assets, problems }), problems);
1742
1742
  const wanted = typeof r.activeLayerId === "string" ? r.activeLayerId : null;
1743
1743
  const activeLayerId = wanted && _chunkPOGBUYWEcjs.findLayer.call(void 0, layers, wanted) ? wanted : _nullishCoalesce(_optionalChain([_chunkPOGBUYWEcjs.flattenLayers.call(void 0, layers), 'access', _33 => _33.filter, 'call', _34 => _34((l) => l.type === "pixel"), 'access', _35 => _35.pop, 'call', _36 => _36(), 'optionalAccess', _37 => _37.id]), () => ( null));
1744
1744
  return { state: { canvas, paper, layers, activeLayerId, strokes: readStrokes(r.strokes, problems) }, extensions: documentExtensions(r), guides: r.guides, swatches: r.swatches, mixingPad: r.mixingPad, problems };
@@ -1747,7 +1747,7 @@ async function deserializePaintDocumentAsync(raw, store) {
1747
1747
  if (!raw || typeof raw !== "object") throw new Error("Not a paint document: expected a JSON object.");
1748
1748
  const r = raw;
1749
1749
  const problems = [];
1750
- const assets = await _chunkPHUMLSCWcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1750
+ const assets = await _chunkYGIMK4NXcjs.resolveExternalAssets.call(void 0, _nullishCoalesce(r.assets, () => ( {})), store, problems);
1751
1751
  const loaded = deserializePaintDocument({ ...r, assets });
1752
1752
  return { ...loaded, problems: [...problems, ...loaded.problems] };
1753
1753
  }
@@ -3420,7 +3420,7 @@ var PaintEditorController = (_class10 = class {
3420
3420
  return next.type === "group" ? { ...next, children: toStandard(next.children) } : next;
3421
3421
  });
3422
3422
  const layers = toStandard(this.doc.layers);
3423
- const result = _chunkPHUMLSCWcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
3423
+ const result = _chunkYGIMK4NXcjs.exportPsd.call(void 0, { width, height, layers: [paperLayer, ...layers], merged, resolution: dpi });
3424
3424
  for (const [mode, names] of changed) {
3425
3425
  const label = _nullishCoalesce(_optionalChain([_chunkXIOMMGPDcjs.BLEND_MODES, 'access', _81 => _81.find, 'call', _82 => _82((m) => m.id === mode), 'optionalAccess', _83 => _83.label]), () => ( mode));
3426
3426
  const std = _nullishCoalesce(_optionalChain([_chunkXIOMMGPDcjs.BLEND_MODES, 'access', _84 => _84.find, 'call', _85 => _85((m) => m.id === _chunkXIOMMGPDcjs.standardBlendMode.call(void 0, mode)), 'optionalAccess', _86 => _86.label]), () => ( _chunkXIOMMGPDcjs.standardBlendMode.call(void 0, mode)));
@@ -1,9 +1,9 @@
1
1
  import { R as RasterLayer, a as RasterGroupLayer, b as RasterPixelLayer, C as CompositorLayer, c as RasterCompositor, d as RasterSources, L as LayerLocks } from '../render-BEriFuqK.cjs';
2
- import { B as BrushSettings, M as MixerSettings, a as MixingModel, b as BlenderSettings, S as SmudgeSettings, C as CoverageMap, D as Dab, c as StrokePoint, d as MixerLoad, P as PaintTileTarget, R as RgbTriple } from '../blending-aOE6Y3UE.cjs';
3
- export { e as MAX_BRUSH_SIZE } from '../blending-aOE6Y3UE.cjs';
2
+ import { B as BrushSettings, M as MixerSettings, a as MixingModel, b as BlenderSettings, S as SmudgeSettings, C as CoverageMap, D as Dab, c as StrokePoint, d as MixerLoad, P as PaintTileTarget, R as RgbTriple } from '../retouch-CEIKR22W.cjs';
3
+ export { e as MAX_BRUSH_SIZE } from '../retouch-CEIKR22W.cjs';
4
4
  import { R as RasterRect, a as TiledSurface, B as BlendMode, c as BlendModeInfo } from '../surface-C8RRg_Bh.cjs';
5
5
  export { d as BLEND_MODES, e as PAINTERLY_BLEND_MODES, f as Tile, i as isBlendMode, g as isPainterlyBlendMode, s as standardBlendMode } from '../surface-C8RRg_Bh.cjs';
6
- import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-DoDhCszr.cjs';
6
+ import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-CEXEzqBf.cjs';
7
7
  import { g as PresenceStore, e as PresenceClock, d as PresenceActorInfo, c as PresenceActor, f as PresenceState } from '../presence-Cb6WhcrQ.cjs';
8
8
  import { a as AgentToolProvider } from '../registry-BqA1AZt0.cjs';
9
9
  import '../types-CwMPoRMU.cjs';
@@ -1,9 +1,9 @@
1
1
  import { R as RasterLayer, a as RasterGroupLayer, b as RasterPixelLayer, C as CompositorLayer, c as RasterCompositor, d as RasterSources, L as LayerLocks } from '../render-tjzKaik-.js';
2
- import { B as BrushSettings, M as MixerSettings, a as MixingModel, b as BlenderSettings, S as SmudgeSettings, C as CoverageMap, D as Dab, c as StrokePoint, d as MixerLoad, P as PaintTileTarget, R as RgbTriple } from '../blending-DXl06NSx.js';
3
- export { e as MAX_BRUSH_SIZE } from '../blending-DXl06NSx.js';
2
+ import { B as BrushSettings, M as MixerSettings, a as MixingModel, b as BlenderSettings, S as SmudgeSettings, C as CoverageMap, D as Dab, c as StrokePoint, d as MixerLoad, P as PaintTileTarget, R as RgbTriple } from '../retouch-BXmeSCaB.js';
3
+ export { e as MAX_BRUSH_SIZE } from '../retouch-BXmeSCaB.js';
4
4
  import { R as RasterRect, a as TiledSurface, B as BlendMode, c as BlendModeInfo } from '../surface-C8RRg_Bh.js';
5
5
  export { d as BLEND_MODES, e as PAINTERLY_BLEND_MODES, f as Tile, i as isBlendMode, g as isPainterlyBlendMode, s as standardBlendMode } from '../surface-C8RRg_Bh.js';
6
- import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-DBNVwb6h.js';
6
+ import { I as ImageEditorAssetStore, S as SerializedLayer, P as PsdExportResult } from '../export-DIkoK8-r.js';
7
7
  import { g as PresenceStore, e as PresenceClock, d as PresenceActorInfo, c as PresenceActor, f as PresenceState } from '../presence-Cb6WhcrQ.js';
8
8
  import { a as AgentToolProvider } from '../registry-D-4fit9C.js';
9
9
  import '../types-CwMPoRMU.js';
@@ -4,7 +4,7 @@ import {
4
4
  resolveExternalAssets,
5
5
  serializeLayers,
6
6
  serializeLayersExternal
7
- } from "../chunk-HHZ6ZJTW.js";
7
+ } from "../chunk-CZOXTEMN.js";
8
8
  import {
9
9
  RasterCompositor,
10
10
  base64ToBytes,
@@ -483,4 +483,221 @@ declare class SmudgeTip {
483
483
  dab(medium: TileMedium, d: SmudgeDab, rect: RasterRect, cov: ArrayLike<number>): void;
484
484
  }
485
485
 
486
- export { tipShape as $, blendRadius as A, type BrushSettings as B, CoverageMap as C, type Dab as D, EMPTY_MIXER_LOAD as E, blenderDab as F, cleanMixer as G, coverageTileCoord as H, createBlenderScratch as I, dabCoverage as J, dabRect as K, exchangeRates as L, type MixerSettings as M, loadMixer as N, mixerRates as O, type PaintTileTarget as P, normalizeBlender as Q, type RgbTriple as R, type SmudgeSettings as S, TileMedium as T, normalizeBrush as U, normalizeMixer as V, normalizeSmudge as W, rasterizeDab as X, smoothPoints as Y, tipFalloff as Z, tipReach as _, type MixingModel as a, walkDabs as a0, type BlenderSettings as b, type StrokePoint as c, type MixerLoad as d, MAX_BRUSH_SIZE as e, StrokeCoverage as f, type MixerTarget as g, MixerStroke as h, type StrokeApply as i, type BlenderScratch as j, DEFAULT_BLENDER as k, DEFAULT_BRUSH as l, DEFAULT_MIXER as m, DEFAULT_SMUDGE as n, DabWalker as o, type ExchangeRates as p, MIXER_DRAIN as q, MIXER_PICKUP_RATE as r, MIXING_MODELS as s, PaintExchange as t, type PaintMedium as u, type PaintSample as v, type SmudgeDab as w, SmudgeTip as x, type TileMediumOptions as y, applyStrokeToTile as z };
486
+ /**
487
+ * The retouching tools on the shared brush engine: Clone Stamp, Healing Brush, Spot Healing
488
+ * Brush, Smudge, Dodge, Burn and Sponge. Two stroke shapes cover them all:
489
+ *
490
+ * - **Accumulate, then composite** (Clone Stamp, Dodge, Burn; the Healing tools' result): the
491
+ * stroke's dabs build up one `CoverageMap` (flow builds towards the dab's opacity ceiling), and
492
+ * per-pixel paint taken from the pre-stroke state (a cloned source, a toned copy of the pixel,
493
+ * a healed patch) is composited through it with `applyRetouchToTile`. Pixels painted earlier in
494
+ * the stroke are never sampled again, and overlapping dabs never exceed the stroke's opacity.
495
+ * - **Sequential dabs** (Smudge, Sponge): `RetouchDabStroke` runs each dab in order over live
496
+ * tiles, so dab n sees what dab n − 1 did.
497
+ *
498
+ * The Healing Brush clones while it is drawn and, when the stroke ends, replaces the clone with a
499
+ * seamless clone (`healPixels`, Poisson blending): the source's texture with the colour and light
500
+ * of the pixels around the stroke. The Spot Healing Brush finds its own source (`spotHealPixels`).
501
+ *
502
+ * Tone curves (`dodgeBurnCurve`, `dodgeBurn`, `sponge`) are photocraft's, made to behave like
503
+ * Photoshop's tools: the chosen range moves most, black and white stay put for midtones, and
504
+ * Protect Tones works on luma so hue and saturation are kept. Data in, pixels out; no DOM.
505
+ */
506
+
507
+ /** The tonal range Dodge and Burn work on most. */
508
+ type ToneRange = 'shadows' | 'midtones' | 'highlights';
509
+ declare const TONE_RANGES: readonly ToneRange[];
510
+ /** Rec. 601 luma of straight RGB (0..1). */
511
+ declare function luma(r: number, g: number, b: number): number;
512
+ /** The dodge (or burn) transfer of one value `v` (0..1) at exposure `e` (0..1). */
513
+ declare function dodgeBurnCurve(v: number, e: number, range: ToneRange, burn: boolean): number;
514
+ /**
515
+ * Dodge (or burn) straight RGB `c` (0..1, written in place) at exposure `e`. With `protectTones`
516
+ * the curve moves luma and the colour is scaled to it (hue and saturation kept); otherwise each
517
+ * channel goes through the curve.
518
+ */
519
+ declare function dodgeBurn(c: number[], e: number, range: ToneRange, burn: boolean, protectTones: boolean): number[];
520
+ /** HSV saturation (chroma / max) of straight RGB. */
521
+ declare function saturationOf(r: number, g: number, b: number): number;
522
+ /**
523
+ * Sponge: moves straight RGB `c` (written in place) away from (`saturate`) or towards its luma
524
+ * grey by `amount` (0..1). `vibrance` damps it where it would clip: saturating touches already
525
+ * saturated colours less, desaturating touches near-greys less. Gamut-compressed, never clipped.
526
+ */
527
+ declare function sponge(c: number[], amount: number, saturate: boolean, vibrance: boolean): number[];
528
+ /** Per-dab strength so that one pass over a point totals about `e`, whatever the spacing. */
529
+ declare function perDabStrength(e: number, spacing: number): number;
530
+ /** Which pixels the Clone Stamp and the Healing tools sample. */
531
+ type RetouchSample = 'current' | 'current-below' | 'all';
532
+ declare const RETOUCH_SAMPLES: readonly RetouchSample[];
533
+ /** How the Spot Healing Brush finds its source. */
534
+ type SpotHealType = 'proximity-match' | 'smooth';
535
+ declare const SPOT_HEAL_TYPES: readonly SpotHealType[];
536
+ /** The retouching tools' options. */
537
+ interface RetouchSettings {
538
+ /** Clone / heal: keep the source offset from stroke to stroke (default true); off, every stroke starts at the source point. */
539
+ aligned: boolean;
540
+ /** Clone / heal / spot heal: what is sampled (default `current`: the target layer). */
541
+ sample: RetouchSample;
542
+ /** Spot heal: `proximity-match` (default: the best matching patch nearby) or `smooth` (a smooth fill from the edges). */
543
+ spotType: SpotHealType;
544
+ /** Dodge / burn: the tonal range (default `midtones`). */
545
+ range: ToneRange;
546
+ /** Dodge / burn: exposure 0..1 (default 0.5). */
547
+ exposure: number;
548
+ /** Dodge / burn: tone luma only, keeping hue and saturation (default true). */
549
+ protectTones: boolean;
550
+ /** Sponge: `desaturate` (default) or `saturate`. */
551
+ spongeMode: 'desaturate' | 'saturate';
552
+ /** Sponge: damp the change where colours would clip (default true). */
553
+ vibrance: boolean;
554
+ /** Smudge: how strongly the finger carries and lays paint, 0..1 (default 0.5). */
555
+ strength: number;
556
+ }
557
+ declare const DEFAULT_RETOUCH: Readonly<RetouchSettings>;
558
+ /** Retouch settings with every field valid (missing or invalid fields from `base`). */
559
+ declare function normalizeRetouch(raw?: Partial<RetouchSettings>, base?: RetouchSettings): RetouchSettings;
560
+ /** Pixels a retouching stroke samples, by document pixel. */
561
+ interface PixelSource {
562
+ /** Straight RGBA 0..255 of document pixel (x, y) into `out`; false (and `out` zeroed) where there is nothing. */
563
+ sample(x: number, y: number, out: number[]): boolean;
564
+ }
565
+ /**
566
+ * A source over raster tiles (layer pixels, a mask, or composite tiles): `readTile` gives tile
567
+ * (tx, ty) in source space or `null` when it is empty; source pixel = document pixel − `offset`.
568
+ * One-channel tiles read as grey (alpha 255). Tiles are cached, so make one per stroke.
569
+ */
570
+ declare class TilePixelSource implements PixelSource {
571
+ private readonly readTile;
572
+ readonly channels: 1 | 4;
573
+ readonly offset: {
574
+ x: number;
575
+ y: number;
576
+ };
577
+ private readonly cache;
578
+ private lastKey;
579
+ private last;
580
+ constructor(readTile: (tx: number, ty: number) => Uint8ClampedArray | null, channels: 1 | 4, offset?: {
581
+ x: number;
582
+ y: number;
583
+ });
584
+ sample(x: number, y: number, out: number[]): boolean;
585
+ }
586
+ /** A source over a region of float RGBA pixels (0..255), e.g. a healed patch. */
587
+ declare class RegionPixelSource implements PixelSource {
588
+ readonly rect: RasterRect;
589
+ readonly data: Float32Array;
590
+ constructor(rect: RasterRect, data: Float32Array);
591
+ sample(x: number, y: number, out: number[]): boolean;
592
+ }
593
+ /** `rect` of a source, shifted by (dx, dy), as float RGBA 0..255 (`rect.width × rect.height × 4`). */
594
+ declare function readSourceRegion(source: PixelSource, rect: RasterRect, dx?: number, dy?: number): Float32Array;
595
+ /** What a coverage-based retouching stroke lays through its coverage. */
596
+ type RetouchPaint =
597
+ /** Source pixels at document pixel + (dx, dy) (Clone Stamp, a healed patch). */
598
+ {
599
+ kind: 'source';
600
+ source: PixelSource;
601
+ dx: number;
602
+ dy: number;
603
+ }
604
+ /** The target pixel itself, toned (Dodge, Burn): `tone` edits straight RGB 0..1 in place. */
605
+ | {
606
+ kind: 'tone';
607
+ tone: (rgb: number[]) => void;
608
+ }
609
+ /** A flat colour (the Spot Healing Brush's trail while it is drawn), RGBA 0..255. */
610
+ | {
611
+ kind: 'color';
612
+ color: readonly [number, number, number, number];
613
+ };
614
+ /** How a coverage-based retouching stroke composites. */
615
+ interface RetouchApply {
616
+ /** Stroke opacity 0..1. */
617
+ opacity: number;
618
+ /** Blend mode for source paint (default normal). */
619
+ blend?: BlendMode;
620
+ lockTransparency: boolean;
621
+ /** Selection coverage (document space, canvas-sized), or `null`. */
622
+ selection: {
623
+ width: number;
624
+ height: number;
625
+ data: ArrayLike<number>;
626
+ } | null;
627
+ /** Layer offset (target pixels are in layer space). */
628
+ offset: {
629
+ x: number;
630
+ y: number;
631
+ };
632
+ }
633
+ /**
634
+ * Composites `paint` through the stroke's coverage over `tileData` (target tile (tx, ty) as it was
635
+ * before the stroke, layer space; RGBA, or one byte per pixel for masks) and returns the new tile.
636
+ * With `into` (the previous result) and `region` (document space), only `region` is recomputed.
637
+ * Tone paint keeps alpha; source and colour paint composite with `blend` (source-over by
638
+ * default), keeping alpha on a locked layer.
639
+ */
640
+ declare function applyRetouchToTile(coverage: CoverageMap, tileData: Uint8ClampedArray, channels: 1 | 4, tx: number, ty: number, paint: RetouchPaint, s: RetouchApply, options?: {
641
+ into?: Uint8ClampedArray;
642
+ region?: RasterRect;
643
+ }): Uint8ClampedArray;
644
+ /** The tone function of a Dodge or Burn stroke. */
645
+ declare function toneOf(tool: 'dodge' | 'burn', settings: Pick<RetouchSettings, 'exposure' | 'range' | 'protectTones'>): (rgb: number[]) => void;
646
+ /**
647
+ * Heals `src` into `dst` over `mask` (all `w × h`, RGBA floats 0..255): a seamless clone solved
648
+ * only over the mask's bounds plus a one-pixel fixed ring; elsewhere the result is `dst`.
649
+ */
650
+ declare function healPixels(w: number, h: number, src: Float32Array, dst: Float32Array, mask: ArrayLike<boolean | number>): Float32Array;
651
+ /**
652
+ * Spot healing: fills `hole` (`w × h`) of `img` (RGBA floats 0..255) with no given source, then
653
+ * heals the fill into its surroundings. `proximity-match` copies the best matching nearby patch
654
+ * (falling back to `smooth` when none fits); `smooth` interpolates the edges inwards. `size` is
655
+ * the brush diameter in pixels. Returns the healed pixels over the whole grid.
656
+ */
657
+ declare function spotHealPixels(w: number, h: number, img: Float32Array, hole: ArrayLike<boolean | number>, size: number, type: SpotHealType,
658
+ /** Told the patch offset it copied (`null`: a smooth fill). */
659
+ onOffset?: (offset: [number, number] | null) => void): Float32Array;
660
+ /** The window a Spot Healing stroke over `bounds` looks for texture in: the bounds grown by their size, on the canvas. */
661
+ declare function spotHealWindow(bounds: RasterRect, canvas: {
662
+ width: number;
663
+ height: number;
664
+ }): RasterRect;
665
+ /**
666
+ * One dab of a sequential retouching stroke: `cov` is the tip's pure coverage over `rect`
667
+ * (document space, 0..1); `d.alpha` is the flow and `d.opacity` the pressure opacity.
668
+ */
669
+ type RetouchDabEffect = (medium: TileMedium, d: Dab, rect: RasterRect, cov: Float32Array) => void;
670
+ /**
671
+ * A stroke whose dabs edit live tiles in order (Smudge, Sponge). Feed points with `push` (any
672
+ * chunks give the same dabs), end with `finish`; each returns the document rectangles it touched.
673
+ */
674
+ declare class RetouchDabStroke {
675
+ readonly brush: BrushSettings;
676
+ private readonly effect;
677
+ dabCount: number;
678
+ bounds: RasterRect | null;
679
+ private readonly walker;
680
+ private readonly medium;
681
+ private smoothPos;
682
+ private buf;
683
+ constructor(brush: BrushSettings, target: PaintTileTarget, effect: RetouchDabEffect);
684
+ push(points: readonly StrokePoint[]): RasterRect[];
685
+ finish(last?: StrokePoint): RasterRect[];
686
+ private smooth;
687
+ private paint;
688
+ }
689
+ /** The Smudge's per-dab effect: a `SmudgeTip` whose strength carries and lays the paint. */
690
+ declare function smudgeEffect(brush: BrushSettings, strength: number, mixing?: SmudgeSettings['mixing']): RetouchDabEffect;
691
+ /** The Sponge's per-dab effect: each dab moves saturation by about half its flow, compounding over passes. */
692
+ declare function spongeEffect(brush: BrushSettings, saturate: boolean, vibrance: boolean): RetouchDabEffect;
693
+ /**
694
+ * An RGBA view of one-channel tiles (masks), for the sequential-dab tools: reads expand grey to
695
+ * opaque RGB, writes land in RGBA copies, and `flush` writes their red channel back through
696
+ * `target.writeTile`. Alpha is locked, so a mask's values are all a dab changes.
697
+ */
698
+ declare function rgbaViewOfGrey(target: PaintTileTarget): {
699
+ target: PaintTileTarget;
700
+ flush(): void;
701
+ };
702
+
703
+ export { cleanMixer as $, type PixelSource as A, type BrushSettings as B, CoverageMap as C, type Dab as D, EMPTY_MIXER_LOAD as E, RETOUCH_SAMPLES as F, RegionPixelSource as G, type RetouchDabEffect as H, RetouchDabStroke as I, type RetouchSample as J, SPOT_HEAL_TYPES as K, type SmudgeDab as L, type MixerSettings as M, SmudgeTip as N, type SpotHealType as O, type PaintTileTarget as P, TileMedium as Q, type RgbTriple as R, type SmudgeSettings as S, TONE_RANGES as T, type TileMediumOptions as U, TilePixelSource as V, type ToneRange as W, applyRetouchToTile as X, applyStrokeToTile as Y, blendRadius as Z, blenderDab as _, type MixingModel as a, coverageTileCoord as a0, createBlenderScratch as a1, dabCoverage as a2, dabRect as a3, dodgeBurn as a4, dodgeBurnCurve as a5, exchangeRates as a6, healPixels as a7, loadMixer as a8, luma as a9, mixerRates as aa, normalizeBlender as ab, normalizeBrush as ac, normalizeMixer as ad, normalizeRetouch as ae, normalizeSmudge as af, perDabStrength as ag, rasterizeDab as ah, readSourceRegion as ai, rgbaViewOfGrey as aj, saturationOf as ak, smoothPoints as al, smudgeEffect as am, sponge as an, spongeEffect as ao, spotHealPixels as ap, spotHealWindow as aq, tipFalloff as ar, tipReach as as, tipShape as at, toneOf as au, walkDabs as av, type BlenderSettings as b, type StrokePoint as c, type MixerLoad as d, MAX_BRUSH_SIZE as e, type RetouchSettings as f, StrokeCoverage as g, type MixerTarget as h, MixerStroke as i, type RetouchApply as j, type RetouchPaint as k, type StrokeApply as l, type BlenderScratch as m, DEFAULT_BLENDER as n, DEFAULT_BRUSH as o, DEFAULT_MIXER as p, DEFAULT_RETOUCH as q, DEFAULT_SMUDGE as r, DabWalker as s, type ExchangeRates as t, MIXER_DRAIN as u, MIXER_PICKUP_RATE as v, MIXING_MODELS as w, PaintExchange as x, type PaintMedium as y, type PaintSample as z };