@flighthq/surface 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.
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/surface.d.ts +16 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/surface.js +84 -0
- package/dist/surface.js.map +1 -0
- package/dist/surfaceAffine.d.ts +27 -0
- package/dist/surfaceAffine.d.ts.map +1 -0
- package/dist/surfaceAffine.js +159 -0
- package/dist/surfaceAffine.js.map +1 -0
- package/dist/surfaceAlpha.d.ts +27 -0
- package/dist/surfaceAlpha.d.ts.map +1 -0
- package/dist/surfaceAlpha.js +83 -0
- package/dist/surfaceAlpha.js.map +1 -0
- package/dist/surfaceBevel.d.ts +42 -0
- package/dist/surfaceBevel.d.ts.map +1 -0
- package/dist/surfaceBevel.js +102 -0
- package/dist/surfaceBevel.js.map +1 -0
- package/dist/surfaceBlur.d.ts +62 -0
- package/dist/surfaceBlur.d.ts.map +1 -0
- package/dist/surfaceBlur.js +263 -0
- package/dist/surfaceBlur.js.map +1 -0
- package/dist/surfaceChannel.d.ts +24 -0
- package/dist/surfaceChannel.d.ts.map +1 -0
- package/dist/surfaceChannel.js +126 -0
- package/dist/surfaceChannel.js.map +1 -0
- package/dist/surfaceColorMatrix.d.ts +57 -0
- package/dist/surfaceColorMatrix.d.ts.map +1 -0
- package/dist/surfaceColorMatrix.js +127 -0
- package/dist/surfaceColorMatrix.js.map +1 -0
- package/dist/surfaceCompare.d.ts +18 -0
- package/dist/surfaceCompare.d.ts.map +1 -0
- package/dist/surfaceCompare.js +64 -0
- package/dist/surfaceCompare.js.map +1 -0
- package/dist/surfaceComposite.d.ts +53 -0
- package/dist/surfaceComposite.d.ts.map +1 -0
- package/dist/surfaceComposite.js +230 -0
- package/dist/surfaceComposite.js.map +1 -0
- package/dist/surfaceConvolution.d.ts +27 -0
- package/dist/surfaceConvolution.d.ts.map +1 -0
- package/dist/surfaceConvolution.js +103 -0
- package/dist/surfaceConvolution.js.map +1 -0
- package/dist/surfaceCopy.d.ts +23 -0
- package/dist/surfaceCopy.d.ts.map +1 -0
- package/dist/surfaceCopy.js +78 -0
- package/dist/surfaceCopy.js.map +1 -0
- package/dist/surfaceCoverage.d.ts +11 -0
- package/dist/surfaceCoverage.d.ts.map +1 -0
- package/dist/surfaceCoverage.js +29 -0
- package/dist/surfaceCoverage.js.map +1 -0
- package/dist/surfaceCrop.d.ts +33 -0
- package/dist/surfaceCrop.d.ts.map +1 -0
- package/dist/surfaceCrop.js +174 -0
- package/dist/surfaceCrop.js.map +1 -0
- package/dist/surfaceDisplacement.d.ts +48 -0
- package/dist/surfaceDisplacement.d.ts.map +1 -0
- package/dist/surfaceDisplacement.js +131 -0
- package/dist/surfaceDisplacement.js.map +1 -0
- package/dist/surfaceDissolve.d.ts +21 -0
- package/dist/surfaceDissolve.d.ts.map +1 -0
- package/dist/surfaceDissolve.js +97 -0
- package/dist/surfaceDissolve.js.map +1 -0
- package/dist/surfaceDraw.d.ts +8 -0
- package/dist/surfaceDraw.d.ts.map +1 -0
- package/dist/surfaceDraw.js +14 -0
- package/dist/surfaceDraw.js.map +1 -0
- package/dist/surfaceEncode.d.ts +3 -0
- package/dist/surfaceEncode.d.ts.map +1 -0
- package/dist/surfaceEncode.js +18 -0
- package/dist/surfaceEncode.js.map +1 -0
- package/dist/surfaceFill.d.ts +12 -0
- package/dist/surfaceFill.d.ts.map +1 -0
- package/dist/surfaceFill.js +85 -0
- package/dist/surfaceFill.js.map +1 -0
- package/dist/surfaceFingerprint.d.ts +26 -0
- package/dist/surfaceFingerprint.d.ts.map +1 -0
- package/dist/surfaceFingerprint.js +99 -0
- package/dist/surfaceFingerprint.js.map +1 -0
- package/dist/surfaceFlip.d.ts +16 -0
- package/dist/surfaceFlip.d.ts.map +1 -0
- package/dist/surfaceFlip.js +98 -0
- package/dist/surfaceFlip.js.map +1 -0
- package/dist/surfaceFormat.d.ts +26 -0
- package/dist/surfaceFormat.d.ts.map +1 -0
- package/dist/surfaceFormat.js +80 -0
- package/dist/surfaceFormat.js.map +1 -0
- package/dist/surfaceFrom.d.ts +14 -0
- package/dist/surfaceFrom.d.ts.map +1 -0
- package/dist/surfaceFrom.js +87 -0
- package/dist/surfaceFrom.js.map +1 -0
- package/dist/surfaceGradient.d.ts +57 -0
- package/dist/surfaceGradient.d.ts.map +1 -0
- package/dist/surfaceGradient.js +176 -0
- package/dist/surfaceGradient.js.map +1 -0
- package/dist/surfaceGradientFill.d.ts +32 -0
- package/dist/surfaceGradientFill.d.ts.map +1 -0
- package/dist/surfaceGradientFill.js +120 -0
- package/dist/surfaceGradientFill.js.map +1 -0
- package/dist/surfaceHistogram.d.ts +20 -0
- package/dist/surfaceHistogram.d.ts.map +1 -0
- package/dist/surfaceHistogram.js +61 -0
- package/dist/surfaceHistogram.js.map +1 -0
- package/dist/surfaceImageChannel.d.ts +2 -0
- package/dist/surfaceImageChannel.d.ts.map +1 -0
- package/dist/surfaceImageChannel.js +2 -0
- package/dist/surfaceImageChannel.js.map +1 -0
- package/dist/surfaceMedian.d.ts +14 -0
- package/dist/surfaceMedian.d.ts.map +1 -0
- package/dist/surfaceMedian.js +77 -0
- package/dist/surfaceMedian.js.map +1 -0
- package/dist/surfaceMorphological.d.ts +29 -0
- package/dist/surfaceMorphological.d.ts.map +1 -0
- package/dist/surfaceMorphological.js +81 -0
- package/dist/surfaceMorphological.js.map +1 -0
- package/dist/surfaceNoise.d.ts +48 -0
- package/dist/surfaceNoise.d.ts.map +1 -0
- package/dist/surfaceNoise.js +245 -0
- package/dist/surfaceNoise.js.map +1 -0
- package/dist/surfacePaletteMap.d.ts +17 -0
- package/dist/surfacePaletteMap.d.ts.map +1 -0
- package/dist/surfacePaletteMap.js +45 -0
- package/dist/surfacePaletteMap.js.map +1 -0
- package/dist/surfacePixel.d.ts +9 -0
- package/dist/surfacePixel.d.ts.map +1 -0
- package/dist/surfacePixel.js +36 -0
- package/dist/surfacePixel.js.map +1 -0
- package/dist/surfacePixelate.d.ts +13 -0
- package/dist/surfacePixelate.d.ts.map +1 -0
- package/dist/surfacePixelate.js +61 -0
- package/dist/surfacePixelate.js.map +1 -0
- package/dist/surfaceQuery.d.ts +13 -0
- package/dist/surfaceQuery.d.ts.map +1 -0
- package/dist/surfaceQuery.js +46 -0
- package/dist/surfaceQuery.js.map +1 -0
- package/dist/surfaceRegion.d.ts +20 -0
- package/dist/surfaceRegion.d.ts.map +1 -0
- package/dist/surfaceRegion.js +28 -0
- package/dist/surfaceRegion.js.map +1 -0
- package/dist/surfaceResize.d.ts +27 -0
- package/dist/surfaceResize.d.ts.map +1 -0
- package/dist/surfaceResize.js +191 -0
- package/dist/surfaceResize.js.map +1 -0
- package/dist/surfaceRotate.d.ts +32 -0
- package/dist/surfaceRotate.d.ts.map +1 -0
- package/dist/surfaceRotate.js +143 -0
- package/dist/surfaceRotate.js.map +1 -0
- package/dist/surfaceShadow.d.ts +107 -0
- package/dist/surfaceShadow.d.ts.map +1 -0
- package/dist/surfaceShadow.js +173 -0
- package/dist/surfaceShadow.js.map +1 -0
- package/dist/surfaceSharpen.d.ts +25 -0
- package/dist/surfaceSharpen.d.ts.map +1 -0
- package/dist/surfaceSharpen.js +47 -0
- package/dist/surfaceSharpen.js.map +1 -0
- package/dist/surfaceTone.d.ts +28 -0
- package/dist/surfaceTone.d.ts.map +1 -0
- package/dist/surfaceTone.js +69 -0
- package/dist/surfaceTone.js.map +1 -0
- package/dist/surfaceTransform.d.ts +40 -0
- package/dist/surfaceTransform.d.ts.map +1 -0
- package/dist/surfaceTransform.js +163 -0
- package/dist/surfaceTransform.js.map +1 -0
- package/dist/surfaceWarp.d.ts +48 -0
- package/dist/surfaceWarp.d.ts.map +1 -0
- package/dist/surfaceWarp.js +284 -0
- package/dist/surfaceWarp.js.map +1 -0
- package/package.json +39 -0
- package/src/surface.test.ts +78 -0
- package/src/surfaceAffine.test.ts +98 -0
- package/src/surfaceAlpha.test.ts +113 -0
- package/src/surfaceBevel.test.ts +67 -0
- package/src/surfaceBlur.test.ts +240 -0
- package/src/surfaceChannel.test.ts +97 -0
- package/src/surfaceColorMatrix.test.ts +220 -0
- package/src/surfaceCompare.test.ts +92 -0
- package/src/surfaceComposite.test.ts +256 -0
- package/src/surfaceConvolution.test.ts +136 -0
- package/src/surfaceCopy.test.ts +54 -0
- package/src/surfaceCoverage.test.ts +39 -0
- package/src/surfaceCrop.test.ts +116 -0
- package/src/surfaceDisplacement.test.ts +142 -0
- package/src/surfaceDissolve.test.ts +99 -0
- package/src/surfaceDraw.test.ts +38 -0
- package/src/surfaceEncode.test.ts +18 -0
- package/src/surfaceFill.test.ts +89 -0
- package/src/surfaceFingerprint.test.ts +103 -0
- package/src/surfaceFlip.test.ts +59 -0
- package/src/surfaceFormat.test.ts +124 -0
- package/src/surfaceFrom.test.ts +62 -0
- package/src/surfaceGradient.test.ts +91 -0
- package/src/surfaceGradientFill.test.ts +107 -0
- package/src/surfaceHistogram.test.ts +70 -0
- package/src/surfaceImageChannel.test.ts +19 -0
- package/src/surfaceMedian.test.ts +45 -0
- package/src/surfaceMorphological.test.ts +75 -0
- package/src/surfaceNoise.test.ts +169 -0
- package/src/surfacePaletteMap.test.ts +55 -0
- package/src/surfacePixel.test.ts +99 -0
- package/src/surfacePixelate.test.ts +46 -0
- package/src/surfaceQuery.test.ts +48 -0
- package/src/surfaceRegion.test.ts +34 -0
- package/src/surfaceResize.test.ts +112 -0
- package/src/surfaceRotate.test.ts +119 -0
- package/src/surfaceShadow.test.ts +165 -0
- package/src/surfaceSharpen.test.ts +50 -0
- package/src/surfaceTone.test.ts +104 -0
- package/src/surfaceTransform.test.ts +134 -0
- package/src/surfaceWarp.test.ts +124 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { blurSurfacePixelsHorizontal, blurSurfacePixelsVertical } from './surfaceBlur';
|
|
2
|
+
/**
|
|
3
|
+
* Produces the blurred shadow mask for a drop shadow effect, writing into
|
|
4
|
+
* `out`. The result is a tinted, blurred alpha mask derived from `source`.
|
|
5
|
+
*
|
|
6
|
+
* To complete the effect, composite `out` onto the destination at the shadow
|
|
7
|
+
* offset, then optionally composite the original source on top:
|
|
8
|
+
*
|
|
9
|
+
* compositeSurfacePixels(destRegion, out); // shadow at (dx+offsetX, dy+offsetY)
|
|
10
|
+
* compositeSurfaceRegion(destRegion, source); // omit if hideObject
|
|
11
|
+
*
|
|
12
|
+
* `scratch` must be at least `source.width * source.height * 4` bytes.
|
|
13
|
+
* Its contents are undefined after the call.
|
|
14
|
+
*
|
|
15
|
+
* Safe to pass `source.surface.data` as `out` when the region covers the
|
|
16
|
+
* full surface.
|
|
17
|
+
*/
|
|
18
|
+
export function dropShadowSurface(out, scratch, source, options = {}) {
|
|
19
|
+
tintSurfaceAlphaMask(out, source, options.color ?? 0x000000ff, options.intensity ?? 1);
|
|
20
|
+
applyBlurPasses(out, scratch, source.width, source.height, options);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Produces the blurred glow mask for a glow effect, writing into `out`.
|
|
24
|
+
* The result is a tinted, blurred alpha mask derived from `source`.
|
|
25
|
+
*
|
|
26
|
+
* To complete the effect, composite `out` onto the destination, then
|
|
27
|
+
* optionally composite the original source on top:
|
|
28
|
+
*
|
|
29
|
+
* compositeSurfacePixels(destRegion, out); // glow
|
|
30
|
+
* compositeSurfaceRegion(destRegion, source); // omit if knockout
|
|
31
|
+
*
|
|
32
|
+
* `scratch` must be at least `source.width * source.height * 4` bytes.
|
|
33
|
+
* Its contents are undefined after the call.
|
|
34
|
+
*
|
|
35
|
+
* Safe to pass `source.surface.data` as `out` when the region covers the
|
|
36
|
+
* full surface.
|
|
37
|
+
*/
|
|
38
|
+
export function glowSurface(out, scratch, source, options = {}) {
|
|
39
|
+
tintSurfaceAlphaMask(out, source, options.color ?? 0xff0000ff, options.intensity ?? 1);
|
|
40
|
+
applyBlurPasses(out, scratch, source.width, source.height, options);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Produces the inner glow mask for a glow that hugs the inside of the source's
|
|
44
|
+
* alpha boundary, writing into `out`. The inverted source alpha is blurred so
|
|
45
|
+
* that the "outside" bleeds inward, then clipped by the original source alpha so
|
|
46
|
+
* the effect stays within the shape, then tinted.
|
|
47
|
+
*
|
|
48
|
+
* To complete the effect, composite `out` over the original source:
|
|
49
|
+
*
|
|
50
|
+
* compositeSurfaceRegion(destRegion, source);
|
|
51
|
+
* compositeSurfacePixels(destRegion, out); // glow on top, inside the shape
|
|
52
|
+
*
|
|
53
|
+
* `scratch` must be at least `source.width * source.height * 4` bytes; its
|
|
54
|
+
* contents are undefined after the call.
|
|
55
|
+
*
|
|
56
|
+
* `out` must NOT alias `source.surface.data`: the original source alpha is read
|
|
57
|
+
* again after blurring, so overwriting the source destroys the clip mask.
|
|
58
|
+
*/
|
|
59
|
+
export function innerGlowSurface(out, scratch, source, options = {}) {
|
|
60
|
+
// Inner glow hugs the boundary symmetrically, so no directional offset (0, 0).
|
|
61
|
+
applyInnerEffect(out, scratch, source, options.color ?? 0xff0000ff, options, 0, 0);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Produces the inner shadow mask for a shadow that hugs the inside of the
|
|
65
|
+
* source's alpha boundary, writing into `out`. Like `innerGlowSurface` but with
|
|
66
|
+
* an opaque-black default color and a directional `offsetX`/`offsetY`: the
|
|
67
|
+
* inverted-alpha field is sampled shifted by the offset before blurring, so the
|
|
68
|
+
* shadow gathers toward one edge instead of ringing the boundary evenly.
|
|
69
|
+
*
|
|
70
|
+
* To complete the effect, composite `out` over the original source.
|
|
71
|
+
*
|
|
72
|
+
* `scratch` must be at least `source.width * source.height * 4` bytes; its
|
|
73
|
+
* contents are undefined after the call.
|
|
74
|
+
*
|
|
75
|
+
* `out` must NOT alias `source.surface.data` — the original source alpha is read
|
|
76
|
+
* again after blurring to clip the result.
|
|
77
|
+
*/
|
|
78
|
+
export function innerShadowSurface(out, scratch, source, options = {}) {
|
|
79
|
+
applyInnerEffect(out, scratch, source, options.color ?? 0x000000ff, options, options.offsetX ?? 0, options.offsetY ?? 0);
|
|
80
|
+
}
|
|
81
|
+
function applyBlurPasses(out, scratch, width, height, options) {
|
|
82
|
+
const radiusX = Math.max(0, Math.round(options.radiusX ?? 2));
|
|
83
|
+
const radiusY = Math.max(0, Math.round(options.radiusY ?? 2));
|
|
84
|
+
const passes = Math.max(1, Math.round(options.passes ?? 1));
|
|
85
|
+
let a = out;
|
|
86
|
+
let b = scratch;
|
|
87
|
+
for (let pass = 0; pass < passes; pass++) {
|
|
88
|
+
if (radiusX > 0) {
|
|
89
|
+
blurSurfacePixelsHorizontal(b, a, width, height, radiusX);
|
|
90
|
+
const t = a;
|
|
91
|
+
a = b;
|
|
92
|
+
b = t;
|
|
93
|
+
}
|
|
94
|
+
if (radiusY > 0) {
|
|
95
|
+
blurSurfacePixelsVertical(b, a, width, height, radiusY);
|
|
96
|
+
const t = a;
|
|
97
|
+
a = b;
|
|
98
|
+
b = t;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (a !== out) {
|
|
102
|
+
out.set(a.subarray(0, width * height * 4));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function applyInnerEffect(out, scratch, source, color, options, offsetX, offsetY) {
|
|
106
|
+
const w = source.width;
|
|
107
|
+
const h = source.height;
|
|
108
|
+
// Step 1: write the inverted source alpha into out (rgb 0). High outside the
|
|
109
|
+
// shape, low inside — so the blur bleeds the exterior inward across the edge.
|
|
110
|
+
// The field is sampled shifted by (offsetX, offsetY): a nonzero offset pulls the
|
|
111
|
+
// exterior in from one side, so the blurred shadow gathers against the opposite
|
|
112
|
+
// edge (the inner-shadow direction). Zero offset rings the boundary evenly (glow).
|
|
113
|
+
for (let py = 0; py < h; py++) {
|
|
114
|
+
for (let px = 0; px < w; px++) {
|
|
115
|
+
const di = (py * w + px) * 4;
|
|
116
|
+
out[di] = 0;
|
|
117
|
+
out[di + 1] = 0;
|
|
118
|
+
out[di + 2] = 0;
|
|
119
|
+
out[di + 3] = 255 - readSourceAlpha(source, px - offsetX, py - offsetY);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Step 2: blur the inverted-alpha field in place (ping-ponging through scratch).
|
|
123
|
+
applyBlurPasses(out, scratch, w, h, options);
|
|
124
|
+
// Step 3: tint, and clip by the original source alpha so the glow stays inside.
|
|
125
|
+
const cr = (color >>> 24) & 0xff;
|
|
126
|
+
const cg = (color >> 16) & 0xff;
|
|
127
|
+
const cb = (color >> 8) & 0xff;
|
|
128
|
+
const ca = (color & 0xff) / 255;
|
|
129
|
+
const scale = Math.max(0, options.intensity ?? 1) * ca;
|
|
130
|
+
for (let py = 0; py < h; py++) {
|
|
131
|
+
for (let px = 0; px < w; px++) {
|
|
132
|
+
const di = (py * w + px) * 4;
|
|
133
|
+
const blurred = out[di + 3];
|
|
134
|
+
const sourceAlpha = readSourceAlpha(source, px, py);
|
|
135
|
+
out[di] = cr;
|
|
136
|
+
out[di + 1] = cg;
|
|
137
|
+
out[di + 2] = cb;
|
|
138
|
+
out[di + 3] = Math.min(255, Math.round((blurred * sourceAlpha * scale) / 255));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function readSourceAlpha(source, px, py) {
|
|
143
|
+
const sx = source.x + px;
|
|
144
|
+
const sy = source.y + py;
|
|
145
|
+
if (sx < 0 || sx >= source.surface.width || sy < 0 || sy >= source.surface.height)
|
|
146
|
+
return 0;
|
|
147
|
+
return source.surface.data[(sy * source.surface.width + sx) * 4 + 3];
|
|
148
|
+
}
|
|
149
|
+
// Used internally by drop-shadow and glow effects.
|
|
150
|
+
function tintSurfaceAlphaMask(out, source, color, intensity) {
|
|
151
|
+
const cr = (color >>> 24) & 0xff;
|
|
152
|
+
const cg = (color >> 16) & 0xff;
|
|
153
|
+
const cb = (color >> 8) & 0xff;
|
|
154
|
+
const ca = (color & 0xff) / 255;
|
|
155
|
+
const alphaScale = Math.max(0, intensity) * ca;
|
|
156
|
+
for (let py = 0; py < source.height; py++) {
|
|
157
|
+
const sourceY = source.y + py;
|
|
158
|
+
if (sourceY < 0 || sourceY >= source.surface.height)
|
|
159
|
+
continue;
|
|
160
|
+
for (let px = 0; px < source.width; px++) {
|
|
161
|
+
const sourceX = source.x + px;
|
|
162
|
+
if (sourceX < 0 || sourceX >= source.surface.width)
|
|
163
|
+
continue;
|
|
164
|
+
const si = (sourceY * source.surface.width + sourceX) * 4;
|
|
165
|
+
const di = (py * source.width + px) * 4;
|
|
166
|
+
out[di] = cr;
|
|
167
|
+
out[di + 1] = cg;
|
|
168
|
+
out[di + 2] = cb;
|
|
169
|
+
out[di + 3] = Math.min(255, Math.round(source.surface.data[si + 3] * alphaScale));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=surfaceShadow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceShadow.js","sourceRoot":"","sources":["../src/surfaceShadow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { SurfaceRegion } from '@flighthq/types';
|
|
2
|
+
export interface SurfaceSharpenOptions {
|
|
3
|
+
/** Sharpen strength. 0 is a no-op; 1 is a moderate sharpen; >1 is stronger. Default 1. */
|
|
4
|
+
amount?: number;
|
|
5
|
+
/** Blur radius of the unsharp mask, in pixels. Larger radii sharpen coarser detail. Default 2. */
|
|
6
|
+
radiusX?: number;
|
|
7
|
+
radiusY?: number;
|
|
8
|
+
/** Blur pass count, forwarded to the box blur. Default 1. */
|
|
9
|
+
passes?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Sharpens `source` into `out` using an unsharp mask: it blurs the source, then
|
|
13
|
+
* adds back `amount × (source − blurred)` so edges are accentuated. This is the
|
|
14
|
+
* radius-based sharpen photo tools use; a fixed 3×3 sharpen is also available
|
|
15
|
+
* via `convolveSurface`.
|
|
16
|
+
*
|
|
17
|
+
* `scratch` is ping-pong scratch, at least `source.width * source.height * 4`
|
|
18
|
+
* bytes; its contents are undefined after the call. Alpha is left as the source
|
|
19
|
+
* alpha (only RGB is sharpened).
|
|
20
|
+
*
|
|
21
|
+
* `out` must NOT alias `source.surface.data`: `out` holds the blurred image
|
|
22
|
+
* while the original source pixels are read again to form the mask.
|
|
23
|
+
*/
|
|
24
|
+
export declare function sharpenSurface(out: Uint8ClampedArray, scratch: Uint8ClampedArray, source: Readonly<SurfaceRegion>, options?: Readonly<SurfaceSharpenOptions>): void;
|
|
25
|
+
//# sourceMappingURL=surfaceSharpen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceSharpen.d.ts","sourceRoot":"","sources":["../src/surfaceSharpen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAIrD,MAAM,WAAW,qBAAqB;IACpC,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kGAAkG;IAClG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,iBAAiB,EACtB,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,OAAO,GAAE,QAAQ,CAAC,qBAAqB,CAAM,GAC5C,IAAI,CA8BN"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { boxBlurSurface } from './surfaceBlur';
|
|
2
|
+
/**
|
|
3
|
+
* Sharpens `source` into `out` using an unsharp mask: it blurs the source, then
|
|
4
|
+
* adds back `amount × (source − blurred)` so edges are accentuated. This is the
|
|
5
|
+
* radius-based sharpen photo tools use; a fixed 3×3 sharpen is also available
|
|
6
|
+
* via `convolveSurface`.
|
|
7
|
+
*
|
|
8
|
+
* `scratch` is ping-pong scratch, at least `source.width * source.height * 4`
|
|
9
|
+
* bytes; its contents are undefined after the call. Alpha is left as the source
|
|
10
|
+
* alpha (only RGB is sharpened).
|
|
11
|
+
*
|
|
12
|
+
* `out` must NOT alias `source.surface.data`: `out` holds the blurred image
|
|
13
|
+
* while the original source pixels are read again to form the mask.
|
|
14
|
+
*/
|
|
15
|
+
export function sharpenSurface(out, scratch, source, options = {}) {
|
|
16
|
+
const amount = options.amount ?? 1;
|
|
17
|
+
boxBlurSurface(out, scratch, source, {
|
|
18
|
+
radiusX: options.radiusX ?? 2,
|
|
19
|
+
radiusY: options.radiusY ?? 2,
|
|
20
|
+
passes: options.passes ?? 1,
|
|
21
|
+
});
|
|
22
|
+
const w = source.width;
|
|
23
|
+
const h = source.height;
|
|
24
|
+
const surfaceWidth = source.surface.width;
|
|
25
|
+
const surfaceHeight = source.surface.height;
|
|
26
|
+
const data = source.surface.data;
|
|
27
|
+
for (let py = 0; py < h; py++) {
|
|
28
|
+
const sy = source.y + py;
|
|
29
|
+
if (sy < 0 || sy >= surfaceHeight)
|
|
30
|
+
continue;
|
|
31
|
+
for (let px = 0; px < w; px++) {
|
|
32
|
+
const sx = source.x + px;
|
|
33
|
+
if (sx < 0 || sx >= surfaceWidth)
|
|
34
|
+
continue;
|
|
35
|
+
const si = (sy * surfaceWidth + sx) * 4;
|
|
36
|
+
const di = (py * w + px) * 4;
|
|
37
|
+
const r = data[si];
|
|
38
|
+
const g = data[si + 1];
|
|
39
|
+
const b = data[si + 2];
|
|
40
|
+
out[di] = r + amount * (r - out[di]);
|
|
41
|
+
out[di + 1] = g + amount * (g - out[di + 1]);
|
|
42
|
+
out[di + 2] = b + amount * (b - out[di + 2]);
|
|
43
|
+
out[di + 3] = data[si + 3];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=surfaceSharpen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceSharpen.js","sourceRoot":"","sources":["../src/surfaceSharpen.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAY/C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,cAAc,CAC5B,GAAsB,EACtB,OAA0B,EAC1B,MAA+B,EAC/B,UAA2C,EAAE;IAE7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;IACnC,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE;QACnC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC;QAC7B,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,CAAC;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC;KAC5B,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC;IACvB,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;IACxB,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1C,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;IAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;IACjC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,aAAa;YAAE,SAAS;QAC5C,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;YACzB,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,YAAY;gBAAE,SAAS;YAC3C,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,YAAY,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACvB,MAAM,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACvB,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YACrC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7C,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;YAC7C,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SurfaceRegion } from '@flighthq/types';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a 256-entry per-channel lookup table (LUT) to `out`. The LUT maps
|
|
4
|
+
* each channel's input value (0–255) to an output value (0–255). To apply
|
|
5
|
+
* a single curve to all RGB channels, pass the same array for R, G, and B.
|
|
6
|
+
* To leave a channel unchanged, pass `null`; that channel is copied unchanged.
|
|
7
|
+
*
|
|
8
|
+
* All non-null LUT arrays must have exactly 256 entries. The alpha channel
|
|
9
|
+
* is never remapped unless `alpha` is provided.
|
|
10
|
+
*
|
|
11
|
+
* `out` and `source` may alias the same region — each pixel is read before
|
|
12
|
+
* it is written.
|
|
13
|
+
*/
|
|
14
|
+
export declare function applySurfaceCurve(out: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, redLut: Readonly<Uint8Array | Uint8ClampedArray | null>, greenLut: Readonly<Uint8Array | Uint8ClampedArray | null>, blueLut: Readonly<Uint8Array | Uint8ClampedArray | null>, alphaLut?: Readonly<Uint8Array | Uint8ClampedArray | null>): void;
|
|
15
|
+
/**
|
|
16
|
+
* Applies a levels adjustment to `out`, stretching pixel values from the input
|
|
17
|
+
* range `[blackPoint, whitePoint]` to the full 0–255 output range, with a
|
|
18
|
+
* mid-tone `gamma` correction applied before the output stretch.
|
|
19
|
+
*
|
|
20
|
+
* - `blackPoint` (default 0): input value that maps to 0 (blacks point).
|
|
21
|
+
* - `whitePoint` (default 255): input value that maps to 255 (whites point).
|
|
22
|
+
* - `gamma` (default 1): exponent for the midtone curve. Values < 1 lighten
|
|
23
|
+
* midtones; values > 1 darken them.
|
|
24
|
+
*
|
|
25
|
+
* Alpha channel is passed through unchanged. `out` and `source` may alias.
|
|
26
|
+
*/
|
|
27
|
+
export declare function applySurfaceLevels(out: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, blackPoint?: number, whitePoint?: number, gamma?: number): void;
|
|
28
|
+
//# sourceMappingURL=surfaceTone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceTone.d.ts","sourceRoot":"","sources":["../src/surfaceTone.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC5B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,MAAM,EAAE,QAAQ,CAAC,UAAU,GAAG,iBAAiB,GAAG,IAAI,CAAC,EACvD,QAAQ,EAAE,QAAQ,CAAC,UAAU,GAAG,iBAAiB,GAAG,IAAI,CAAC,EACzD,OAAO,EAAE,QAAQ,CAAC,UAAU,GAAG,iBAAiB,GAAG,IAAI,CAAC,EACxD,QAAQ,GAAE,QAAQ,CAAC,UAAU,GAAG,iBAAiB,GAAG,IAAI,CAAQ,GAC/D,IAAI,CA2BN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC5B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,UAAU,GAAE,MAAU,EACtB,UAAU,GAAE,MAAY,EACxB,KAAK,GAAE,MAAU,GAChB,IAAI,CAYN"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { invalidateImageResource } from '@flighthq/image';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a 256-entry per-channel lookup table (LUT) to `out`. The LUT maps
|
|
4
|
+
* each channel's input value (0–255) to an output value (0–255). To apply
|
|
5
|
+
* a single curve to all RGB channels, pass the same array for R, G, and B.
|
|
6
|
+
* To leave a channel unchanged, pass `null`; that channel is copied unchanged.
|
|
7
|
+
*
|
|
8
|
+
* All non-null LUT arrays must have exactly 256 entries. The alpha channel
|
|
9
|
+
* is never remapped unless `alpha` is provided.
|
|
10
|
+
*
|
|
11
|
+
* `out` and `source` may alias the same region — each pixel is read before
|
|
12
|
+
* it is written.
|
|
13
|
+
*/
|
|
14
|
+
export function applySurfaceCurve(out, source, redLut, greenLut, blueLut, alphaLut = null) {
|
|
15
|
+
const w = Math.min(out.width, source.width);
|
|
16
|
+
const h = Math.min(out.height, source.height);
|
|
17
|
+
const od = out.surface.data;
|
|
18
|
+
const sd = source.surface.data;
|
|
19
|
+
for (let py = 0; py < h; py++) {
|
|
20
|
+
const sy = source.y + py;
|
|
21
|
+
const oy = out.y + py;
|
|
22
|
+
if (sy < 0 || sy >= source.surface.height || oy < 0 || oy >= out.surface.height)
|
|
23
|
+
continue;
|
|
24
|
+
for (let px = 0; px < w; px++) {
|
|
25
|
+
const sx = source.x + px;
|
|
26
|
+
const ox = out.x + px;
|
|
27
|
+
if (sx < 0 || sx >= source.surface.width || ox < 0 || ox >= out.surface.width)
|
|
28
|
+
continue;
|
|
29
|
+
const si = (sy * source.surface.width + sx) * 4;
|
|
30
|
+
const oi = (oy * out.surface.width + ox) * 4;
|
|
31
|
+
// Read inputs before writing (alias-safe).
|
|
32
|
+
const r = sd[si];
|
|
33
|
+
const g = sd[si + 1];
|
|
34
|
+
const b = sd[si + 2];
|
|
35
|
+
const a = sd[si + 3];
|
|
36
|
+
od[oi] = redLut !== null ? redLut[r] : r;
|
|
37
|
+
od[oi + 1] = greenLut !== null ? greenLut[g] : g;
|
|
38
|
+
od[oi + 2] = blueLut !== null ? blueLut[b] : b;
|
|
39
|
+
od[oi + 3] = alphaLut !== null ? alphaLut[a] : a;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
invalidateImageResource(out.surface);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Applies a levels adjustment to `out`, stretching pixel values from the input
|
|
46
|
+
* range `[blackPoint, whitePoint]` to the full 0–255 output range, with a
|
|
47
|
+
* mid-tone `gamma` correction applied before the output stretch.
|
|
48
|
+
*
|
|
49
|
+
* - `blackPoint` (default 0): input value that maps to 0 (blacks point).
|
|
50
|
+
* - `whitePoint` (default 255): input value that maps to 255 (whites point).
|
|
51
|
+
* - `gamma` (default 1): exponent for the midtone curve. Values < 1 lighten
|
|
52
|
+
* midtones; values > 1 darken them.
|
|
53
|
+
*
|
|
54
|
+
* Alpha channel is passed through unchanged. `out` and `source` may alias.
|
|
55
|
+
*/
|
|
56
|
+
export function applySurfaceLevels(out, source, blackPoint = 0, whitePoint = 255, gamma = 1) {
|
|
57
|
+
const bp = Math.max(0, Math.min(254, blackPoint));
|
|
58
|
+
const wp = Math.max(bp + 1, Math.min(255, whitePoint));
|
|
59
|
+
const span = wp - bp;
|
|
60
|
+
const invGamma = gamma > 0 ? 1 / gamma : 1;
|
|
61
|
+
// Build a 256-entry LUT so the pixel loop is a fast table lookup.
|
|
62
|
+
const lut = new Uint8ClampedArray(256);
|
|
63
|
+
for (let i = 0; i < 256; i++) {
|
|
64
|
+
const normalized = Math.max(0, Math.min(1, (i - bp) / span));
|
|
65
|
+
lut[i] = Math.round(Math.pow(normalized, invGamma) * 255);
|
|
66
|
+
}
|
|
67
|
+
applySurfaceCurve(out, source, lut, lut, lut, null);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=surfaceTone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceTone.js","sourceRoot":"","sources":["../src/surfaceTone.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ColorTransformLike, Surface, SurfaceRegion, ThresholdOperation } from '@flighthq/types';
|
|
2
|
+
/**
|
|
3
|
+
* Applies a color transform to `source`, writing into `dest`. The transformed
|
|
4
|
+
* size is the overlap of the two regions; pixels outside either surface are
|
|
5
|
+
* skipped. Safe to pass the same surface and region in `dest` and `source` for
|
|
6
|
+
* in-place modification (each pixel is read before it is written).
|
|
7
|
+
*/
|
|
8
|
+
export declare function applySurfaceColorTransform(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, ct: Readonly<ColorTransformLike>): void;
|
|
9
|
+
/**
|
|
10
|
+
* Tests each pixel of `source` and writes `color` into `dest` where the test
|
|
11
|
+
* passes, or optionally copies the source pixel where it fails. The tested size
|
|
12
|
+
* is the overlap of the two regions. Returns the number of pixels that passed.
|
|
13
|
+
*
|
|
14
|
+
* The comparison is performed on the full packed 0xRRGGBBAA pixel value under
|
|
15
|
+
* `mask`. To test a single channel, supply a mask that isolates it — for
|
|
16
|
+
* example 0x000000ff tests only the alpha byte, and 0xff000000 tests only red.
|
|
17
|
+
*
|
|
18
|
+
* Safe to pass the same surface and region in `dest` and `source` (each pixel
|
|
19
|
+
* is read before it is written).
|
|
20
|
+
*/
|
|
21
|
+
export declare function applySurfaceThreshold(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, operation: ThresholdOperation, thresholdValue: number, color?: number, mask?: number, copySource?: boolean): number;
|
|
22
|
+
/**
|
|
23
|
+
* Blends each channel of `source` into `dest` using per-channel multipliers in
|
|
24
|
+
* [0, 1]: 0 keeps `dest`, 1 replaces with `source`, intermediate values blend
|
|
25
|
+
* proportionally. The blended size is the overlap of the two regions; pixels
|
|
26
|
+
* outside either surface are skipped.
|
|
27
|
+
*
|
|
28
|
+
* `dest` and `source` must not reference the same surface when their regions
|
|
29
|
+
* overlap at different offsets — the blend reads both, so a write to `dest`
|
|
30
|
+
* corrupts later reads from `source`. The same region in both is safe (the
|
|
31
|
+
* result equals `dest` for every multiplier).
|
|
32
|
+
*/
|
|
33
|
+
export declare function mergeSurface(dest: Readonly<SurfaceRegion>, source: Readonly<SurfaceRegion>, redMultiplier: number, greenMultiplier: number, blueMultiplier: number, alphaMultiplier: number): void;
|
|
34
|
+
/**
|
|
35
|
+
* Scrolls the content of `out` by `(dx, dy)`, wrapping at the edges.
|
|
36
|
+
* Uses a module-level scratch buffer that grows as needed and is reused
|
|
37
|
+
* across calls.
|
|
38
|
+
*/
|
|
39
|
+
export declare function scrollSurface(out: Surface, dx: number, dy: number): void;
|
|
40
|
+
//# sourceMappingURL=surfaceTransform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceTransform.d.ts","sourceRoot":"","sources":["../src/surfaceTransform.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAItG;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,EAAE,EAAE,QAAQ,CAAC,kBAAkB,CAAC,GAC/B,IAAI,CAwBN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,SAAS,EAAE,kBAAkB,EAC7B,cAAc,EAAE,MAAM,EACtB,KAAK,GAAE,MAAU,EACjB,IAAI,GAAE,MAAmB,EACzB,UAAU,GAAE,OAAe,GAC1B,MAAM,CAkCR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC7B,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAC/B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,MAAM,GACtB,IAAI,CAsBN;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAoBxE"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { invalidateImageResource } from '@flighthq/image';
|
|
2
|
+
let _scrollScratch = null;
|
|
3
|
+
/**
|
|
4
|
+
* Applies a color transform to `source`, writing into `dest`. The transformed
|
|
5
|
+
* size is the overlap of the two regions; pixels outside either surface are
|
|
6
|
+
* skipped. Safe to pass the same surface and region in `dest` and `source` for
|
|
7
|
+
* in-place modification (each pixel is read before it is written).
|
|
8
|
+
*/
|
|
9
|
+
export function applySurfaceColorTransform(dest, source, ct) {
|
|
10
|
+
const w = Math.min(dest.width, source.width);
|
|
11
|
+
const h = Math.min(dest.height, source.height);
|
|
12
|
+
for (let py = 0; py < h; py++) {
|
|
13
|
+
const sy = source.y + py;
|
|
14
|
+
const dy = dest.y + py;
|
|
15
|
+
if (sy < 0 || sy >= source.surface.height || dy < 0 || dy >= dest.surface.height)
|
|
16
|
+
continue;
|
|
17
|
+
for (let px = 0; px < w; px++) {
|
|
18
|
+
const sx = source.x + px;
|
|
19
|
+
const dx = dest.x + px;
|
|
20
|
+
if (sx < 0 || sx >= source.surface.width || dx < 0 || dx >= dest.surface.width)
|
|
21
|
+
continue;
|
|
22
|
+
const si = (sy * source.surface.width + sx) * 4;
|
|
23
|
+
const di = (dy * dest.surface.width + dx) * 4;
|
|
24
|
+
const r = source.surface.data[si];
|
|
25
|
+
const g = source.surface.data[si + 1];
|
|
26
|
+
const b = source.surface.data[si + 2];
|
|
27
|
+
const a = source.surface.data[si + 3];
|
|
28
|
+
dest.surface.data[di] = Math.max(0, Math.min(255, Math.round(r * ct.redMultiplier + ct.redOffset)));
|
|
29
|
+
dest.surface.data[di + 1] = Math.max(0, Math.min(255, Math.round(g * ct.greenMultiplier + ct.greenOffset)));
|
|
30
|
+
dest.surface.data[di + 2] = Math.max(0, Math.min(255, Math.round(b * ct.blueMultiplier + ct.blueOffset)));
|
|
31
|
+
dest.surface.data[di + 3] = Math.max(0, Math.min(255, Math.round(a * ct.alphaMultiplier + ct.alphaOffset)));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
invalidateImageResource(dest.surface);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Tests each pixel of `source` and writes `color` into `dest` where the test
|
|
38
|
+
* passes, or optionally copies the source pixel where it fails. The tested size
|
|
39
|
+
* is the overlap of the two regions. Returns the number of pixels that passed.
|
|
40
|
+
*
|
|
41
|
+
* The comparison is performed on the full packed 0xRRGGBBAA pixel value under
|
|
42
|
+
* `mask`. To test a single channel, supply a mask that isolates it — for
|
|
43
|
+
* example 0x000000ff tests only the alpha byte, and 0xff000000 tests only red.
|
|
44
|
+
*
|
|
45
|
+
* Safe to pass the same surface and region in `dest` and `source` (each pixel
|
|
46
|
+
* is read before it is written).
|
|
47
|
+
*/
|
|
48
|
+
export function applySurfaceThreshold(dest, source, operation, thresholdValue, color = 0, mask = 0xffffffff, copySource = false) {
|
|
49
|
+
const w = Math.min(dest.width, source.width);
|
|
50
|
+
const h = Math.min(dest.height, source.height);
|
|
51
|
+
const sd = source.surface.data;
|
|
52
|
+
const dd = dest.surface.data;
|
|
53
|
+
let changed = 0;
|
|
54
|
+
for (let py = 0; py < h; py++) {
|
|
55
|
+
const sy = source.y + py;
|
|
56
|
+
const dy = dest.y + py;
|
|
57
|
+
if (sy < 0 || sy >= source.surface.height || dy < 0 || dy >= dest.surface.height)
|
|
58
|
+
continue;
|
|
59
|
+
for (let px = 0; px < w; px++) {
|
|
60
|
+
const sx = source.x + px;
|
|
61
|
+
const dx = dest.x + px;
|
|
62
|
+
if (sx < 0 || sx >= source.surface.width || dx < 0 || dx >= dest.surface.width)
|
|
63
|
+
continue;
|
|
64
|
+
const si = (sy * source.surface.width + sx) * 4;
|
|
65
|
+
const di = (dy * dest.surface.width + dx) * 4;
|
|
66
|
+
const pixel = (((sd[si] << 24) | (sd[si + 1] << 16) | (sd[si + 2] << 8) | sd[si + 3]) & mask) >>> 0;
|
|
67
|
+
const passes = compare(pixel, operation, thresholdValue >>> 0);
|
|
68
|
+
if (passes) {
|
|
69
|
+
dd[di] = (color >>> 24) & 0xff;
|
|
70
|
+
dd[di + 1] = (color >> 16) & 0xff;
|
|
71
|
+
dd[di + 2] = (color >> 8) & 0xff;
|
|
72
|
+
dd[di + 3] = color & 0xff;
|
|
73
|
+
changed++;
|
|
74
|
+
}
|
|
75
|
+
else if (copySource) {
|
|
76
|
+
dd[di] = sd[si];
|
|
77
|
+
dd[di + 1] = sd[si + 1];
|
|
78
|
+
dd[di + 2] = sd[si + 2];
|
|
79
|
+
dd[di + 3] = sd[si + 3];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
invalidateImageResource(dest.surface);
|
|
84
|
+
return changed;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Blends each channel of `source` into `dest` using per-channel multipliers in
|
|
88
|
+
* [0, 1]: 0 keeps `dest`, 1 replaces with `source`, intermediate values blend
|
|
89
|
+
* proportionally. The blended size is the overlap of the two regions; pixels
|
|
90
|
+
* outside either surface are skipped.
|
|
91
|
+
*
|
|
92
|
+
* `dest` and `source` must not reference the same surface when their regions
|
|
93
|
+
* overlap at different offsets — the blend reads both, so a write to `dest`
|
|
94
|
+
* corrupts later reads from `source`. The same region in both is safe (the
|
|
95
|
+
* result equals `dest` for every multiplier).
|
|
96
|
+
*/
|
|
97
|
+
export function mergeSurface(dest, source, redMultiplier, greenMultiplier, blueMultiplier, alphaMultiplier) {
|
|
98
|
+
const w = Math.min(dest.width, source.width);
|
|
99
|
+
const h = Math.min(dest.height, source.height);
|
|
100
|
+
const sd = source.surface.data;
|
|
101
|
+
const dd = dest.surface.data;
|
|
102
|
+
for (let py = 0; py < h; py++) {
|
|
103
|
+
const sy = source.y + py;
|
|
104
|
+
const dy = dest.y + py;
|
|
105
|
+
if (sy < 0 || sy >= source.surface.height || dy < 0 || dy >= dest.surface.height)
|
|
106
|
+
continue;
|
|
107
|
+
for (let px = 0; px < w; px++) {
|
|
108
|
+
const sx = source.x + px;
|
|
109
|
+
const dx = dest.x + px;
|
|
110
|
+
if (sx < 0 || sx >= source.surface.width || dx < 0 || dx >= dest.surface.width)
|
|
111
|
+
continue;
|
|
112
|
+
const si = (sy * source.surface.width + sx) * 4;
|
|
113
|
+
const di = (dy * dest.surface.width + dx) * 4;
|
|
114
|
+
dd[di] = Math.round(sd[si] * redMultiplier + dd[di] * (1 - redMultiplier));
|
|
115
|
+
dd[di + 1] = Math.round(sd[si + 1] * greenMultiplier + dd[di + 1] * (1 - greenMultiplier));
|
|
116
|
+
dd[di + 2] = Math.round(sd[si + 2] * blueMultiplier + dd[di + 2] * (1 - blueMultiplier));
|
|
117
|
+
dd[di + 3] = Math.round(sd[si + 3] * alphaMultiplier + dd[di + 3] * (1 - alphaMultiplier));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
invalidateImageResource(dest.surface);
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Scrolls the content of `out` by `(dx, dy)`, wrapping at the edges.
|
|
124
|
+
* Uses a module-level scratch buffer that grows as needed and is reused
|
|
125
|
+
* across calls.
|
|
126
|
+
*/
|
|
127
|
+
export function scrollSurface(out, dx, dy) {
|
|
128
|
+
const needed = out.data.length;
|
|
129
|
+
if (_scrollScratch === null || _scrollScratch.length < needed) {
|
|
130
|
+
_scrollScratch = new Uint8ClampedArray(needed);
|
|
131
|
+
}
|
|
132
|
+
_scrollScratch.set(out.data, 0);
|
|
133
|
+
for (let py = 0; py < out.height; py++) {
|
|
134
|
+
const srcY = (((py - dy) % out.height) + out.height) % out.height;
|
|
135
|
+
for (let px = 0; px < out.width; px++) {
|
|
136
|
+
const srcX = (((px - dx) % out.width) + out.width) % out.width;
|
|
137
|
+
const si = (srcY * out.width + srcX) * 4;
|
|
138
|
+
const di = (py * out.width + px) * 4;
|
|
139
|
+
out.data[di] = _scrollScratch[si];
|
|
140
|
+
out.data[di + 1] = _scrollScratch[si + 1];
|
|
141
|
+
out.data[di + 2] = _scrollScratch[si + 2];
|
|
142
|
+
out.data[di + 3] = _scrollScratch[si + 3];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
invalidateImageResource(out);
|
|
146
|
+
}
|
|
147
|
+
function compare(a, op, b) {
|
|
148
|
+
switch (op) {
|
|
149
|
+
case '<':
|
|
150
|
+
return a < b;
|
|
151
|
+
case '<=':
|
|
152
|
+
return a <= b;
|
|
153
|
+
case '>':
|
|
154
|
+
return a > b;
|
|
155
|
+
case '>=':
|
|
156
|
+
return a >= b;
|
|
157
|
+
case '==':
|
|
158
|
+
return a === b;
|
|
159
|
+
case '!=':
|
|
160
|
+
return a !== b;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=surfaceTransform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaceTransform.js","sourceRoot":"","sources":["../src/surfaceTransform.ts"],"names":[],"mappings":"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"}
|