@remotion/effects 4.0.541 → 4.0.543
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/THIRD_PARTY_LICENSES.md +10 -0
- package/dist/esm/lightning.mjs +603 -0
- package/dist/esm/magnify.mjs +403 -0
- package/dist/esm/preview/barrel-distortion.mjs +303 -0
- package/dist/esm/preview/bevel-alpha.mjs +525 -0
- package/dist/esm/preview/blur.mjs +435 -0
- package/dist/esm/preview/brightness.mjs +95 -0
- package/dist/esm/preview/burlap.mjs +481 -0
- package/dist/esm/preview/checkerboard.mjs +8 -0
- package/dist/esm/preview/chromatic-aberration.mjs +308 -0
- package/dist/esm/preview/color-correction.mjs +522 -0
- package/dist/esm/preview/color-key.mjs +440 -0
- package/dist/esm/preview/contour-lines.mjs +608 -0
- package/dist/esm/preview/contrast.mjs +95 -0
- package/dist/esm/preview/corner-pin.mjs +6 -0
- package/dist/esm/preview/curves.mjs +357 -0
- package/dist/esm/preview/cylinder.mjs +273 -0
- package/dist/esm/preview/dot-grid.mjs +333 -0
- package/dist/esm/preview/drop-shadow.mjs +607 -0
- package/dist/esm/preview/duotone.mjs +344 -0
- package/dist/esm/preview/emboss.mjs +479 -0
- package/dist/esm/preview/evolve.mjs +485 -0
- package/dist/esm/preview/exposure.mjs +264 -0
- package/dist/esm/preview/film-burn.mjs +298 -0
- package/dist/esm/preview/fisheye.mjs +422 -0
- package/dist/esm/preview/flannel.mjs +401 -0
- package/dist/esm/preview/fractal-noise.mjs +642 -0
- package/dist/esm/preview/glow.mjs +598 -0
- package/dist/esm/preview/grayscale.mjs +86 -0
- package/dist/esm/preview/gridlines.mjs +8 -0
- package/dist/esm/preview/halftone-linear-gradient.mjs +523 -0
- package/dist/esm/preview/halftone.mjs +552 -0
- package/dist/esm/preview/hue.mjs +83 -0
- package/dist/esm/preview/index-00v3hr66.mjs +299 -0
- package/dist/esm/preview/index-0w4eqht8.mjs +351 -0
- package/dist/esm/preview/index-18y0zcy2.mjs +440 -0
- package/dist/esm/preview/index-1m1b1ad7.mjs +520 -0
- package/dist/esm/preview/index-34fxm3ax.mjs +518 -0
- package/dist/esm/preview/index-4fvp93ps.mjs +32 -0
- package/dist/esm/preview/index-4scpn12x.mjs +224 -0
- package/dist/esm/preview/index-4z6pt3ka.mjs +104 -0
- package/dist/esm/preview/index-618ky75w.mjs +51 -0
- package/dist/esm/preview/index-6agxdrvr.mjs +411 -0
- package/dist/esm/preview/index-6jkps947.mjs +120 -0
- package/dist/esm/preview/index-8agtsbw4.mjs +617 -0
- package/dist/esm/preview/index-8jx11jyn.mjs +29 -0
- package/dist/esm/preview/index-8p04sssx.mjs +123 -0
- package/dist/esm/preview/index-afdtmrh2.mjs +596 -0
- package/dist/esm/preview/index-b86qstcs.mjs +18 -0
- package/dist/esm/preview/index-cb77qg3g.mjs +587 -0
- package/dist/esm/preview/index-cdp7tr8x.mjs +122 -0
- package/dist/esm/preview/index-evy8hyah.mjs +55 -0
- package/dist/esm/preview/index-gnsce796.mjs +6 -0
- package/dist/esm/preview/index-kkvzt8b7.mjs +199 -0
- package/dist/esm/preview/index-r0v18b2n.mjs +425 -0
- package/dist/esm/preview/index-rswpzmm5.mjs +926 -0
- package/dist/esm/preview/index-s9mrx750.mjs +97 -0
- package/dist/esm/preview/index-tvfexb7s.mjs +164 -0
- package/dist/esm/preview/index-vp56k1gj.mjs +215 -0
- package/dist/esm/preview/index-wxhvgv2s.mjs +79 -0
- package/dist/esm/preview/index-wy95a41r.mjs +407 -0
- package/dist/esm/preview/index-ysnwfc4t.mjs +306 -0
- package/dist/esm/preview/index.mjs +51 -0
- package/dist/esm/preview/invert.mjs +84 -0
- package/dist/esm/preview/iris-wipe.mjs +315 -0
- package/dist/esm/preview/lens-blur.mjs +563 -0
- package/dist/esm/preview/levels.mjs +400 -0
- package/dist/esm/preview/light-leak.mjs +8 -0
- package/dist/esm/preview/light-trail.mjs +516 -0
- package/dist/esm/preview/lightning.mjs +603 -0
- package/dist/esm/preview/linear-gradient-tint.mjs +6 -0
- package/dist/esm/preview/linear-gradient.mjs +6 -0
- package/dist/esm/preview/linear-progressive-blur.mjs +516 -0
- package/dist/esm/preview/linear-progressive-pixelate.mjs +176 -0
- package/dist/esm/preview/lines.mjs +536 -0
- package/dist/esm/preview/liquid-contours.mjs +512 -0
- package/dist/esm/preview/long-shadows.mjs +437 -0
- package/dist/esm/preview/lut.mjs +601 -0
- package/dist/esm/preview/magnify.mjs +403 -0
- package/dist/esm/preview/mirror.mjs +341 -0
- package/dist/esm/preview/noise-displacement.mjs +584 -0
- package/dist/esm/preview/noise.mjs +318 -0
- package/dist/esm/preview/outline.mjs +725 -0
- package/dist/esm/preview/page-turn.mjs +302 -0
- package/dist/esm/preview/paper.mjs +1249 -0
- package/dist/esm/preview/pattern.mjs +6 -0
- package/dist/esm/preview/pixel-dissolve.mjs +360 -0
- package/dist/esm/preview/pixelate.mjs +249 -0
- package/dist/esm/preview/radial-progressive-blur.mjs +582 -0
- package/dist/esm/preview/radial-progressive-pixelate.mjs +220 -0
- package/dist/esm/preview/radial-wipe.mjs +224 -0
- package/dist/esm/preview/rain-fall.mjs +114 -0
- package/dist/esm/preview/region-blur.mjs +500 -0
- package/dist/esm/preview/rings.mjs +8 -0
- package/dist/esm/preview/roughen-edges.mjs +590 -0
- package/dist/esm/preview/saturation.mjs +86 -0
- package/dist/esm/preview/scale.mjs +109 -0
- package/dist/esm/preview/scanlines.mjs +362 -0
- package/dist/esm/preview/shadows-highlights.mjs +284 -0
- package/dist/esm/preview/shatter.mjs +868 -0
- package/dist/esm/preview/shine.mjs +368 -0
- package/dist/esm/preview/shrinkwrap.mjs +769 -0
- package/dist/esm/preview/skew.mjs +300 -0
- package/dist/esm/preview/snow-fall.mjs +170 -0
- package/dist/esm/preview/speckle.mjs +356 -0
- package/dist/esm/preview/sphere.mjs +252 -0
- package/dist/esm/preview/starburst.mjs +8 -0
- package/dist/esm/preview/tear.mjs +375 -0
- package/dist/esm/preview/thermal-vision.mjs +387 -0
- package/dist/esm/preview/tile.mjs +7 -0
- package/dist/esm/preview/tint.mjs +125 -0
- package/dist/esm/preview/translate.mjs +151 -0
- package/dist/esm/preview/turbulent-displace.mjs +613 -0
- package/dist/esm/preview/tv-signal-off.mjs +308 -0
- package/dist/esm/preview/venetian-blinds.mjs +341 -0
- package/dist/esm/preview/vibrance.mjs +254 -0
- package/dist/esm/preview/vignette.mjs +458 -0
- package/dist/esm/preview/wave.mjs +384 -0
- package/dist/esm/preview/waves.mjs +599 -0
- package/dist/esm/preview/white-balance.mjs +280 -0
- package/dist/esm/preview/white-noise.mjs +244 -0
- package/dist/esm/preview/zigzag.mjs +8 -0
- package/dist/esm/preview/zoom-blur.mjs +389 -0
- package/dist/lightning/geometry.d.ts +10 -0
- package/dist/lightning/index.d.ts +4 -0
- package/dist/lightning/mask.d.ts +2 -0
- package/dist/lightning/params.d.ts +259 -0
- package/dist/lightning/shaders.d.ts +2 -0
- package/dist/lightning.d.ts +2 -0
- package/dist/magnify/shader.d.ts +1 -0
- package/dist/magnify/webgpu-shader.d.ts +1 -0
- package/dist/magnify.d.ts +28 -0
- package/package.json +30 -6
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertOptionalFiniteNumber,
|
|
3
|
+
validateUnitInterval,
|
|
4
|
+
validateNonNegative
|
|
5
|
+
} from "./index-wxhvgv2s.mjs";
|
|
6
|
+
import {
|
|
7
|
+
WEBGPU_SINGLE_PASS_VERTEX,
|
|
8
|
+
setupWebGpuSinglePass,
|
|
9
|
+
cleanupWebGpuSinglePass,
|
|
10
|
+
applyWebGpuSinglePass
|
|
11
|
+
} from "./index-tvfexb7s.mjs";
|
|
12
|
+
import {
|
|
13
|
+
assertEffectParamsObject
|
|
14
|
+
} from "./index-4fvp93ps.mjs";
|
|
15
|
+
|
|
16
|
+
// src/roughen-edges.ts
|
|
17
|
+
import { Internals } from "remotion";
|
|
18
|
+
|
|
19
|
+
// src/roughen-edges-webgpu-shader.ts
|
|
20
|
+
var ROUGHEN_EDGES_WEBGPU_SHADER = `
|
|
21
|
+
${WEBGPU_SINGLE_PASS_VERTEX}
|
|
22
|
+
@group(0) @binding(0) var source: texture_2d<f32>;
|
|
23
|
+
@group(0) @binding(1) var sourceSampler: sampler;
|
|
24
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
25
|
+
|
|
26
|
+
struct Params { size: vec2f, amount: f32, border: f32, scale: f32, seed: f32, }
|
|
27
|
+
@group(0) @binding(3) var noiseTexture: texture_2d<f32>;
|
|
28
|
+
fn sampleSource(uv: vec2f) -> vec4f { return textureSampleLevel(source,sourceSampler,clamp(vec2f(uv.x,1.0-uv.y),vec2f(0),vec2f(1)),0); }
|
|
29
|
+
fn sampleAlpha(uv: vec2f) -> f32 { return sampleSource(uv).a; }
|
|
30
|
+
fn seedOffset(salt: f32) -> vec2f {
|
|
31
|
+
let seeded=params.seed+salt;
|
|
32
|
+
return fract(sin(vec2f(seeded*12.9898+78.233,seeded*39.3468+11.135))*43758.5453);
|
|
33
|
+
}
|
|
34
|
+
fn randomR(p: vec2f) -> f32 {
|
|
35
|
+
let uv=fract(floor(p)/100.0+vec2f(0.5));
|
|
36
|
+
return textureLoad(noiseTexture,vec2i(floor(uv*vec2f(textureDimensions(noiseTexture)))),0).r;
|
|
37
|
+
}
|
|
38
|
+
fn valueNoise(st: vec2f) -> f32 {
|
|
39
|
+
let i=floor(st); let f=fract(st); let u=f*f*(vec2f(3.0)-2.0*f);
|
|
40
|
+
let a=randomR(i);let b=randomR(i+vec2f(1,0));let c=randomR(i+vec2f(0,1));let d=randomR(i+vec2f(1,1));
|
|
41
|
+
return mix(mix(a,b,u.x),mix(c,d,u.x),u.y);
|
|
42
|
+
}
|
|
43
|
+
fn fbm(point: vec2f) -> f32 {
|
|
44
|
+
var n=point; var total=0.0; var amplitude=0.5;
|
|
45
|
+
for(var i=0;i<4;i++) { total += valueNoise(n)*amplitude; n *= 2.03; amplitude *= 0.55; }
|
|
46
|
+
return total;
|
|
47
|
+
}
|
|
48
|
+
fn edgeProximity(uv: vec2f,alpha: f32) -> f32 {
|
|
49
|
+
if(params.border<=0.0) { return 0.0; }
|
|
50
|
+
let reach=vec2f(max(params.border,1.0))/params.size;
|
|
51
|
+
var minAlpha=alpha;var maxAlpha=alpha;
|
|
52
|
+
for(var y=-1;y<=1;y++) { for(var x=-1;x<=1;x++) {
|
|
53
|
+
let a=sampleAlpha(uv+vec2f(f32(x),f32(y))*reach);minAlpha=min(minAlpha,a);maxAlpha=max(maxAlpha,a);
|
|
54
|
+
} }
|
|
55
|
+
return smoothstep(0.02,0.35,maxAlpha-minAlpha);
|
|
56
|
+
}
|
|
57
|
+
fn alphaGradient(uv: vec2f) -> vec2f {
|
|
58
|
+
let reach=vec2f(max(params.border*0.25,1.0))/params.size;
|
|
59
|
+
return vec2f(sampleAlpha(uv+vec2f(reach.x,0))-sampleAlpha(uv-vec2f(reach.x,0)),sampleAlpha(uv+vec2f(0,reach.y))-sampleAlpha(uv-vec2f(0,reach.y)));
|
|
60
|
+
}
|
|
61
|
+
fn edgeNoise(uv: vec2f,salt: f32) -> f32 {
|
|
62
|
+
var patternUV=uv-vec2f(0.5);
|
|
63
|
+
patternUV *= vec2f(params.size.x/max(params.size.y,1.0),1.0);
|
|
64
|
+
patternUV *= 7.0/max(params.scale,0.001);
|
|
65
|
+
patternUV += 64.0*seedOffset(salt);
|
|
66
|
+
return fbm(patternUV);
|
|
67
|
+
}
|
|
68
|
+
@fragment fn fragment(input: VertexOutput) -> @location(0) vec4f {
|
|
69
|
+
let uv=vec2f(input.uv.x,1.0-input.uv.y);
|
|
70
|
+
let color=sampleSource(uv);
|
|
71
|
+
if(params.amount<=0.0 || params.border<=0.0) { return color; }
|
|
72
|
+
let proximity=edgeProximity(uv,color.a);
|
|
73
|
+
if(proximity<=0.001) { return color; }
|
|
74
|
+
let gradient=alphaGradient(uv);
|
|
75
|
+
let noiseVector=vec2f(edgeNoise(uv+vec2f(0.17,0),2.0),edgeNoise(uv+vec2f(0,0.31),3.0))*2.0-vec2f(1.0);
|
|
76
|
+
var direction=gradient+0.7*noiseVector;
|
|
77
|
+
if(length(direction)<=0.0001) { direction=select(noiseVector,vec2f(1,0),length(noiseVector)<=0.0001); }
|
|
78
|
+
direction=normalize(direction);
|
|
79
|
+
let scalar=edgeNoise(uv,4.0)*2.0-1.0;
|
|
80
|
+
let offset=direction*scalar*params.border/params.size;
|
|
81
|
+
return mix(color,sampleSource(uv+offset),clamp(proximity*params.amount,0.0,1.0));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
// src/roughen-edges.ts
|
|
87
|
+
var { createEffect, createWebGL2ContextError } = Internals;
|
|
88
|
+
var DEFAULT_AMOUNT = 1;
|
|
89
|
+
var DEFAULT_BORDER = 26.5;
|
|
90
|
+
var DEFAULT_SCALE = 0.07;
|
|
91
|
+
var DEFAULT_SEED = 231.2;
|
|
92
|
+
var MAX_BORDER = 200;
|
|
93
|
+
var MAX_SEED = 1000;
|
|
94
|
+
var NOISE_TEXTURE_SIZE = 256;
|
|
95
|
+
var roughenEdgesSchema = {
|
|
96
|
+
amount: {
|
|
97
|
+
type: "number",
|
|
98
|
+
min: 0,
|
|
99
|
+
max: 1,
|
|
100
|
+
step: 0.01,
|
|
101
|
+
default: DEFAULT_AMOUNT,
|
|
102
|
+
description: "Amount",
|
|
103
|
+
hiddenFromList: false
|
|
104
|
+
},
|
|
105
|
+
border: {
|
|
106
|
+
type: "number",
|
|
107
|
+
min: 0,
|
|
108
|
+
max: MAX_BORDER,
|
|
109
|
+
step: 0.1,
|
|
110
|
+
default: DEFAULT_BORDER,
|
|
111
|
+
description: "Border",
|
|
112
|
+
hiddenFromList: false
|
|
113
|
+
},
|
|
114
|
+
scale: {
|
|
115
|
+
type: "number",
|
|
116
|
+
min: 0.01,
|
|
117
|
+
max: 4,
|
|
118
|
+
step: 0.01,
|
|
119
|
+
default: DEFAULT_SCALE,
|
|
120
|
+
description: "Scale",
|
|
121
|
+
hiddenFromList: false
|
|
122
|
+
},
|
|
123
|
+
seed: {
|
|
124
|
+
type: "number",
|
|
125
|
+
min: 0,
|
|
126
|
+
max: MAX_SEED,
|
|
127
|
+
step: 0.01,
|
|
128
|
+
default: DEFAULT_SEED,
|
|
129
|
+
description: "Seed",
|
|
130
|
+
hiddenFromList: false
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
var resolve = (p) => ({
|
|
134
|
+
amount: p.amount ?? DEFAULT_AMOUNT,
|
|
135
|
+
border: p.border ?? DEFAULT_BORDER,
|
|
136
|
+
scale: p.scale ?? DEFAULT_SCALE,
|
|
137
|
+
seed: p.seed ?? DEFAULT_SEED
|
|
138
|
+
});
|
|
139
|
+
var validateAtMost = (value, max, name) => {
|
|
140
|
+
if (value > max) {
|
|
141
|
+
throw new TypeError(`"${name}" must be <= ${max}, but got ${JSON.stringify(value)}`);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
var validateRoughenEdgesParams = (params) => {
|
|
145
|
+
assertEffectParamsObject(params, "Roughen edges");
|
|
146
|
+
assertOptionalFiniteNumber(params.amount, "amount");
|
|
147
|
+
assertOptionalFiniteNumber(params.border, "border");
|
|
148
|
+
assertOptionalFiniteNumber(params.scale, "scale");
|
|
149
|
+
assertOptionalFiniteNumber(params.seed, "seed");
|
|
150
|
+
const r = resolve(params);
|
|
151
|
+
validateUnitInterval(r.amount, "amount");
|
|
152
|
+
validateNonNegative(r.border, "border");
|
|
153
|
+
validateAtMost(r.border, MAX_BORDER, "border");
|
|
154
|
+
if (r.scale <= 0) {
|
|
155
|
+
throw new TypeError(`"scale" must be greater than 0, but got ${JSON.stringify(r.scale)}`);
|
|
156
|
+
}
|
|
157
|
+
validateAtMost(r.scale, 4, "scale");
|
|
158
|
+
validateNonNegative(r.seed, "seed");
|
|
159
|
+
validateAtMost(r.seed, MAX_SEED, "seed");
|
|
160
|
+
};
|
|
161
|
+
var ROUGHEN_EDGES_VS = `#version 300 es
|
|
162
|
+
in vec2 aPos;
|
|
163
|
+
in vec2 aUv;
|
|
164
|
+
out vec2 vUv;
|
|
165
|
+
|
|
166
|
+
void main() {
|
|
167
|
+
vUv = aUv;
|
|
168
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
169
|
+
}
|
|
170
|
+
`;
|
|
171
|
+
var ROUGHEN_EDGES_FS = `#version 300 es
|
|
172
|
+
precision highp float;
|
|
173
|
+
|
|
174
|
+
in vec2 vUv;
|
|
175
|
+
out vec4 fragColor;
|
|
176
|
+
|
|
177
|
+
uniform sampler2D uSource;
|
|
178
|
+
uniform vec2 uResolution;
|
|
179
|
+
uniform float uAmount;
|
|
180
|
+
uniform float uBorder;
|
|
181
|
+
uniform float uScale;
|
|
182
|
+
uniform float uSeed;
|
|
183
|
+
uniform sampler2D uNoiseTexture;
|
|
184
|
+
|
|
185
|
+
float sampleAlpha(vec2 uv) {
|
|
186
|
+
return texture(uSource, clamp(uv, vec2(0.0), vec2(1.0))).a;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
vec2 seedOffset(float salt) {
|
|
190
|
+
float seeded = uSeed + salt;
|
|
191
|
+
return fract(
|
|
192
|
+
sin(
|
|
193
|
+
vec2(
|
|
194
|
+
seeded * 12.9898 + 78.233,
|
|
195
|
+
seeded * 39.3468 + 11.135
|
|
196
|
+
)
|
|
197
|
+
) * 43758.5453
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
float randomR(vec2 p) {
|
|
202
|
+
vec2 uv = floor(p) / 100.0 + 0.5;
|
|
203
|
+
return texture(uNoiseTexture, fract(uv)).r;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
float valueNoise(vec2 st) {
|
|
207
|
+
vec2 i = floor(st);
|
|
208
|
+
vec2 f = fract(st);
|
|
209
|
+
float a = randomR(i);
|
|
210
|
+
float b = randomR(i + vec2(1.0, 0.0));
|
|
211
|
+
float c = randomR(i + vec2(0.0, 1.0));
|
|
212
|
+
float d = randomR(i + vec2(1.0, 1.0));
|
|
213
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
214
|
+
float x1 = mix(a, b, u.x);
|
|
215
|
+
float x2 = mix(c, d, u.x);
|
|
216
|
+
return mix(x1, x2, u.y);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
float fbm(vec2 n) {
|
|
220
|
+
float total = 0.0;
|
|
221
|
+
float amplitude = 0.5;
|
|
222
|
+
for (int i = 0; i < 4; i++) {
|
|
223
|
+
total += valueNoise(n) * amplitude;
|
|
224
|
+
n *= 2.03;
|
|
225
|
+
amplitude *= 0.55;
|
|
226
|
+
}
|
|
227
|
+
return total;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
void addAlphaSample(
|
|
231
|
+
vec2 uv,
|
|
232
|
+
vec2 offset,
|
|
233
|
+
inout float minAlpha,
|
|
234
|
+
inout float maxAlpha
|
|
235
|
+
) {
|
|
236
|
+
float alpha = sampleAlpha(uv + offset);
|
|
237
|
+
minAlpha = min(minAlpha, alpha);
|
|
238
|
+
maxAlpha = max(maxAlpha, alpha);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
float edgeProximity(vec2 uv, float alpha) {
|
|
242
|
+
if (uBorder <= 0.0) {
|
|
243
|
+
return 0.0;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
vec2 reach = max(uBorder, 1.0) / uResolution;
|
|
247
|
+
float minAlpha = alpha;
|
|
248
|
+
float maxAlpha = alpha;
|
|
249
|
+
|
|
250
|
+
addAlphaSample(uv, vec2(reach.x, 0.0), minAlpha, maxAlpha);
|
|
251
|
+
addAlphaSample(uv, vec2(-reach.x, 0.0), minAlpha, maxAlpha);
|
|
252
|
+
addAlphaSample(uv, vec2(0.0, reach.y), minAlpha, maxAlpha);
|
|
253
|
+
addAlphaSample(uv, vec2(0.0, -reach.y), minAlpha, maxAlpha);
|
|
254
|
+
addAlphaSample(uv, vec2(reach.x, reach.y), minAlpha, maxAlpha);
|
|
255
|
+
addAlphaSample(uv, vec2(-reach.x, reach.y), minAlpha, maxAlpha);
|
|
256
|
+
addAlphaSample(uv, vec2(reach.x, -reach.y), minAlpha, maxAlpha);
|
|
257
|
+
addAlphaSample(uv, vec2(-reach.x, -reach.y), minAlpha, maxAlpha);
|
|
258
|
+
|
|
259
|
+
return smoothstep(0.02, 0.35, maxAlpha - minAlpha);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
vec2 alphaGradient(vec2 uv) {
|
|
263
|
+
vec2 reach = max(uBorder * 0.25, 1.0) / uResolution;
|
|
264
|
+
return vec2(
|
|
265
|
+
sampleAlpha(uv + vec2(reach.x, 0.0)) -
|
|
266
|
+
sampleAlpha(uv - vec2(reach.x, 0.0)),
|
|
267
|
+
sampleAlpha(uv + vec2(0.0, reach.y)) -
|
|
268
|
+
sampleAlpha(uv - vec2(0.0, reach.y))
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
float edgeNoise(vec2 uv, float salt) {
|
|
273
|
+
vec2 patternUV = uv - 0.5;
|
|
274
|
+
patternUV *= vec2(uResolution.x / max(uResolution.y, 1.0), 1.0);
|
|
275
|
+
patternUV *= 7.0 / max(uScale, 0.001);
|
|
276
|
+
patternUV += 64.0 * seedOffset(salt);
|
|
277
|
+
return fbm(patternUV);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
void main() {
|
|
281
|
+
vec4 source = texture(uSource, vUv);
|
|
282
|
+
|
|
283
|
+
if (uAmount <= 0.0 || uBorder <= 0.0) {
|
|
284
|
+
fragColor = source;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
float alpha = source.a;
|
|
289
|
+
float proximity = edgeProximity(vUv, alpha);
|
|
290
|
+
|
|
291
|
+
if (proximity <= 0.001) {
|
|
292
|
+
fragColor = source;
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
vec2 gradient = alphaGradient(vUv);
|
|
297
|
+
vec2 noiseVector = vec2(
|
|
298
|
+
edgeNoise(vUv + vec2(0.17, 0.0), 2.0),
|
|
299
|
+
edgeNoise(vUv + vec2(0.0, 0.31), 3.0)
|
|
300
|
+
) * 2.0 - 1.0;
|
|
301
|
+
vec2 direction = gradient + 0.7 * noiseVector;
|
|
302
|
+
if (length(direction) <= 0.0001) {
|
|
303
|
+
direction = length(noiseVector) <= 0.0001 ? vec2(1.0, 0.0) : noiseVector;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
direction = normalize(direction);
|
|
307
|
+
|
|
308
|
+
float scalar = edgeNoise(vUv, 4.0) * 2.0 - 1.0;
|
|
309
|
+
vec2 offset = direction * scalar * uBorder / uResolution;
|
|
310
|
+
vec4 roughened = texture(
|
|
311
|
+
uSource,
|
|
312
|
+
clamp(vUv + offset, vec2(0.0), vec2(1.0))
|
|
313
|
+
);
|
|
314
|
+
float blend = clamp(proximity * uAmount, 0.0, 1.0);
|
|
315
|
+
|
|
316
|
+
fragColor = mix(source, roughened, blend);
|
|
317
|
+
}
|
|
318
|
+
`;
|
|
319
|
+
var compileShader = (gl, type, source) => {
|
|
320
|
+
const shader = gl.createShader(type);
|
|
321
|
+
if (!shader) {
|
|
322
|
+
throw new Error("Failed to create WebGL shader");
|
|
323
|
+
}
|
|
324
|
+
gl.shaderSource(shader, source);
|
|
325
|
+
gl.compileShader(shader);
|
|
326
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
327
|
+
const log = gl.getShaderInfoLog(shader);
|
|
328
|
+
gl.deleteShader(shader);
|
|
329
|
+
throw new Error(`Roughen edges shader compile failed: ${log ?? "(no log)"}`);
|
|
330
|
+
}
|
|
331
|
+
return shader;
|
|
332
|
+
};
|
|
333
|
+
var linkProgram = (gl, vs, fs) => {
|
|
334
|
+
const program = gl.createProgram();
|
|
335
|
+
if (!program) {
|
|
336
|
+
throw new Error("Failed to create WebGL program");
|
|
337
|
+
}
|
|
338
|
+
gl.attachShader(program, vs);
|
|
339
|
+
gl.attachShader(program, fs);
|
|
340
|
+
gl.linkProgram(program);
|
|
341
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
342
|
+
const log = gl.getProgramInfoLog(program);
|
|
343
|
+
gl.deleteProgram(program);
|
|
344
|
+
throw new Error(`Roughen edges program link failed: ${log ?? "(no log)"}`);
|
|
345
|
+
}
|
|
346
|
+
return program;
|
|
347
|
+
};
|
|
348
|
+
var createSourceTexture = (gl) => {
|
|
349
|
+
const texture = gl.createTexture();
|
|
350
|
+
if (!texture) {
|
|
351
|
+
throw new Error("Failed to create WebGL texture");
|
|
352
|
+
}
|
|
353
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
354
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
355
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
356
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
357
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
358
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
359
|
+
return texture;
|
|
360
|
+
};
|
|
361
|
+
var initialNoiseState = (seed) => {
|
|
362
|
+
const scaledSeed = Math.round(seed * 1000);
|
|
363
|
+
const mixedState = (2654435769 ^ Math.imul(scaledSeed, 2246822507)) >>> 0;
|
|
364
|
+
return mixedState === 0 ? 2654435769 : mixedState;
|
|
365
|
+
};
|
|
366
|
+
var nextNoiseState = (state) => {
|
|
367
|
+
let next = state;
|
|
368
|
+
next ^= next << 13;
|
|
369
|
+
next ^= next >>> 17;
|
|
370
|
+
next ^= next << 5;
|
|
371
|
+
return next >>> 0;
|
|
372
|
+
};
|
|
373
|
+
var createNoiseData = (seed) => {
|
|
374
|
+
const data = new Uint8Array(NOISE_TEXTURE_SIZE * NOISE_TEXTURE_SIZE * 4);
|
|
375
|
+
let state = initialNoiseState(seed);
|
|
376
|
+
for (let i = 0;i < data.length; i += 4) {
|
|
377
|
+
state = nextNoiseState(state);
|
|
378
|
+
data[i] = state & 255;
|
|
379
|
+
state = nextNoiseState(state);
|
|
380
|
+
data[i + 1] = state & 255;
|
|
381
|
+
state = nextNoiseState(state);
|
|
382
|
+
data[i + 2] = state & 255;
|
|
383
|
+
data[i + 3] = 255;
|
|
384
|
+
}
|
|
385
|
+
return data;
|
|
386
|
+
};
|
|
387
|
+
var uploadNoiseTexture = (gl, texture, seed) => {
|
|
388
|
+
const data = createNoiseData(seed);
|
|
389
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
390
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
391
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
392
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, NOISE_TEXTURE_SIZE, NOISE_TEXTURE_SIZE, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
|
|
393
|
+
};
|
|
394
|
+
var createNoiseTexture = (gl) => {
|
|
395
|
+
const texture = gl.createTexture();
|
|
396
|
+
if (!texture) {
|
|
397
|
+
throw new Error("Failed to create WebGL noise texture");
|
|
398
|
+
}
|
|
399
|
+
uploadNoiseTexture(gl, texture, DEFAULT_SEED);
|
|
400
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
401
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
402
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
|
|
403
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
|
|
404
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
405
|
+
return texture;
|
|
406
|
+
};
|
|
407
|
+
var setupRoughenEdges = (target) => {
|
|
408
|
+
const gl = target.getContext("webgl2", {
|
|
409
|
+
premultipliedAlpha: true,
|
|
410
|
+
alpha: true,
|
|
411
|
+
preserveDrawingBuffer: true
|
|
412
|
+
});
|
|
413
|
+
if (!gl) {
|
|
414
|
+
throw createWebGL2ContextError("roughen edges effect");
|
|
415
|
+
}
|
|
416
|
+
const vs = compileShader(gl, gl.VERTEX_SHADER, ROUGHEN_EDGES_VS);
|
|
417
|
+
const fs = compileShader(gl, gl.FRAGMENT_SHADER, ROUGHEN_EDGES_FS);
|
|
418
|
+
const program = linkProgram(gl, vs, fs);
|
|
419
|
+
gl.deleteShader(vs);
|
|
420
|
+
gl.deleteShader(fs);
|
|
421
|
+
const vao = gl.createVertexArray();
|
|
422
|
+
if (!vao) {
|
|
423
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
424
|
+
}
|
|
425
|
+
gl.bindVertexArray(vao);
|
|
426
|
+
const data = new Float32Array([
|
|
427
|
+
-1,
|
|
428
|
+
-1,
|
|
429
|
+
0,
|
|
430
|
+
0,
|
|
431
|
+
1,
|
|
432
|
+
-1,
|
|
433
|
+
1,
|
|
434
|
+
0,
|
|
435
|
+
-1,
|
|
436
|
+
1,
|
|
437
|
+
0,
|
|
438
|
+
1,
|
|
439
|
+
1,
|
|
440
|
+
1,
|
|
441
|
+
1,
|
|
442
|
+
1
|
|
443
|
+
]);
|
|
444
|
+
const vbo = gl.createBuffer();
|
|
445
|
+
if (!vbo) {
|
|
446
|
+
throw new Error("Failed to create WebGL buffer");
|
|
447
|
+
}
|
|
448
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
449
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
450
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
451
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
452
|
+
gl.enableVertexAttribArray(aPos);
|
|
453
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
454
|
+
gl.enableVertexAttribArray(aUv);
|
|
455
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
456
|
+
gl.bindVertexArray(null);
|
|
457
|
+
const sourceTexture = createSourceTexture(gl);
|
|
458
|
+
const noiseTexture = createNoiseTexture(gl);
|
|
459
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
460
|
+
return {
|
|
461
|
+
gl,
|
|
462
|
+
program,
|
|
463
|
+
vao,
|
|
464
|
+
vbo,
|
|
465
|
+
sourceTexture,
|
|
466
|
+
noiseTexture,
|
|
467
|
+
uniforms: {
|
|
468
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
469
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
470
|
+
uAmount: gl.getUniformLocation(program, "uAmount"),
|
|
471
|
+
uBorder: gl.getUniformLocation(program, "uBorder"),
|
|
472
|
+
uScale: gl.getUniformLocation(program, "uScale"),
|
|
473
|
+
uSeed: gl.getUniformLocation(program, "uSeed"),
|
|
474
|
+
uNoiseTexture: gl.getUniformLocation(program, "uNoiseTexture")
|
|
475
|
+
},
|
|
476
|
+
cachedNoiseSeed: DEFAULT_SEED
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
var roughenEdges = createEffect({
|
|
480
|
+
type: "dev.remotion.effects.roughen-edges",
|
|
481
|
+
label: "roughenEdges()",
|
|
482
|
+
documentationLink: "https://www.remotion.dev/docs/effects/roughen-edges",
|
|
483
|
+
calculateKey: (params) => {
|
|
484
|
+
const r = resolve(params);
|
|
485
|
+
return `roughen-edges-${r.amount}-${r.border}-${r.scale}-${r.seed}`;
|
|
486
|
+
},
|
|
487
|
+
implementations: {
|
|
488
|
+
webgpu: Internals.createEffectImplementation({
|
|
489
|
+
setup: (target) => ({
|
|
490
|
+
...setupWebGpuSinglePass(target, "roughen-edges"),
|
|
491
|
+
noiseData: new Uint8Array(0),
|
|
492
|
+
noiseSeed: null
|
|
493
|
+
}),
|
|
494
|
+
apply: ({ source, width, height, params, state, gpuDevice }) => {
|
|
495
|
+
if (!gpuDevice)
|
|
496
|
+
throw new Error("A WebGPU device is required for the roughen-edges effect");
|
|
497
|
+
const r = resolve(params);
|
|
498
|
+
const uniformData = new Float32Array([
|
|
499
|
+
width,
|
|
500
|
+
height,
|
|
501
|
+
r.amount,
|
|
502
|
+
r.border,
|
|
503
|
+
r.scale,
|
|
504
|
+
r.seed,
|
|
505
|
+
0,
|
|
506
|
+
0
|
|
507
|
+
]);
|
|
508
|
+
if (state.noiseSeed !== r.seed) {
|
|
509
|
+
state.noiseData = createNoiseData(r.seed);
|
|
510
|
+
state.noiseSeed = r.seed;
|
|
511
|
+
}
|
|
512
|
+
applyWebGpuSinglePass({
|
|
513
|
+
state,
|
|
514
|
+
source,
|
|
515
|
+
width,
|
|
516
|
+
height,
|
|
517
|
+
device: gpuDevice,
|
|
518
|
+
shader: ROUGHEN_EDGES_WEBGPU_SHADER,
|
|
519
|
+
uniformData
|
|
520
|
+
}, {
|
|
521
|
+
sourceFilter: null,
|
|
522
|
+
auxiliaryTexture: {
|
|
523
|
+
data: state.noiseData,
|
|
524
|
+
width: NOISE_TEXTURE_SIZE,
|
|
525
|
+
height: NOISE_TEXTURE_SIZE,
|
|
526
|
+
format: "rgba8unorm"
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
},
|
|
530
|
+
cleanup: cleanupWebGpuSinglePass
|
|
531
|
+
}),
|
|
532
|
+
webgl2: Internals.createEffectImplementation({
|
|
533
|
+
setup: (target) => setupRoughenEdges(target),
|
|
534
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
535
|
+
const r = resolve(params);
|
|
536
|
+
const { gl, program, vao, sourceTexture, noiseTexture, uniforms } = state;
|
|
537
|
+
gl.viewport(0, 0, width, height);
|
|
538
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
539
|
+
gl.clearColor(0, 0, 0, 0);
|
|
540
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
541
|
+
gl.useProgram(program);
|
|
542
|
+
gl.bindVertexArray(vao);
|
|
543
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
544
|
+
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
|
|
545
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
546
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
547
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
548
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
549
|
+
gl.bindTexture(gl.TEXTURE_2D, noiseTexture);
|
|
550
|
+
if (state.cachedNoiseSeed !== r.seed) {
|
|
551
|
+
uploadNoiseTexture(gl, noiseTexture, r.seed);
|
|
552
|
+
state.cachedNoiseSeed = r.seed;
|
|
553
|
+
}
|
|
554
|
+
if (uniforms.uSource)
|
|
555
|
+
gl.uniform1i(uniforms.uSource, 0);
|
|
556
|
+
if (uniforms.uResolution)
|
|
557
|
+
gl.uniform2f(uniforms.uResolution, width, height);
|
|
558
|
+
if (uniforms.uAmount)
|
|
559
|
+
gl.uniform1f(uniforms.uAmount, r.amount);
|
|
560
|
+
if (uniforms.uBorder)
|
|
561
|
+
gl.uniform1f(uniforms.uBorder, r.border);
|
|
562
|
+
if (uniforms.uScale)
|
|
563
|
+
gl.uniform1f(uniforms.uScale, r.scale);
|
|
564
|
+
if (uniforms.uSeed)
|
|
565
|
+
gl.uniform1f(uniforms.uSeed, r.seed);
|
|
566
|
+
if (uniforms.uNoiseTexture)
|
|
567
|
+
gl.uniform1i(uniforms.uNoiseTexture, 1);
|
|
568
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
569
|
+
gl.bindVertexArray(null);
|
|
570
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
571
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
572
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
573
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
574
|
+
gl.useProgram(null);
|
|
575
|
+
},
|
|
576
|
+
cleanup: ({ gl, program, vao, vbo, sourceTexture, noiseTexture }) => {
|
|
577
|
+
gl.deleteTexture(sourceTexture);
|
|
578
|
+
gl.deleteTexture(noiseTexture);
|
|
579
|
+
gl.deleteBuffer(vbo);
|
|
580
|
+
gl.deleteProgram(program);
|
|
581
|
+
gl.deleteVertexArray(vao);
|
|
582
|
+
}
|
|
583
|
+
})
|
|
584
|
+
},
|
|
585
|
+
schema: roughenEdgesSchema,
|
|
586
|
+
validateParams: validateRoughenEdgesParams
|
|
587
|
+
});
|
|
588
|
+
export {
|
|
589
|
+
roughenEdges
|
|
590
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import"./index-8p04sssx.mjs";
|
|
2
|
+
import {
|
|
3
|
+
createColorMatrixImplementations
|
|
4
|
+
} from "./index-cdp7tr8x.mjs";
|
|
5
|
+
import {
|
|
6
|
+
DEFAULT_AMOUNT,
|
|
7
|
+
colorMultiplierSchema,
|
|
8
|
+
assertOptionalFiniteNumber,
|
|
9
|
+
validateNonNegative
|
|
10
|
+
} from "./index-wxhvgv2s.mjs";
|
|
11
|
+
import {
|
|
12
|
+
assertEffectParamsObject
|
|
13
|
+
} from "./index-4fvp93ps.mjs";
|
|
14
|
+
|
|
15
|
+
// src/saturation.ts
|
|
16
|
+
import { Internals } from "remotion";
|
|
17
|
+
var { createEffect } = Internals;
|
|
18
|
+
var saturationSchema = {
|
|
19
|
+
amount: colorMultiplierSchema
|
|
20
|
+
};
|
|
21
|
+
var resolve = (p) => ({
|
|
22
|
+
amount: p.amount ?? DEFAULT_AMOUNT
|
|
23
|
+
});
|
|
24
|
+
var validateSaturationParams = (params) => {
|
|
25
|
+
assertEffectParamsObject(params, "Saturation");
|
|
26
|
+
assertOptionalFiniteNumber(params.amount, "amount");
|
|
27
|
+
const { amount } = resolve(params);
|
|
28
|
+
validateNonNegative(amount, "amount");
|
|
29
|
+
};
|
|
30
|
+
var saturation = createEffect({
|
|
31
|
+
type: "dev.remotion.effects.saturation",
|
|
32
|
+
label: "saturation()",
|
|
33
|
+
documentationLink: "https://www.remotion.dev/docs/effects/saturation",
|
|
34
|
+
calculateKey: (params) => {
|
|
35
|
+
const r = resolve(params);
|
|
36
|
+
return `saturation-${r.amount}`;
|
|
37
|
+
},
|
|
38
|
+
implementations: {
|
|
39
|
+
...createColorMatrixImplementations("saturation", (params) => {
|
|
40
|
+
const { amount } = resolve(params);
|
|
41
|
+
const red = 0.213 * (1 - amount);
|
|
42
|
+
const green = 0.715 * (1 - amount);
|
|
43
|
+
const blue = 0.072 * (1 - amount);
|
|
44
|
+
return new Float32Array([
|
|
45
|
+
red + amount,
|
|
46
|
+
green,
|
|
47
|
+
blue,
|
|
48
|
+
0,
|
|
49
|
+
red,
|
|
50
|
+
green + amount,
|
|
51
|
+
blue,
|
|
52
|
+
0,
|
|
53
|
+
red,
|
|
54
|
+
green,
|
|
55
|
+
blue + amount,
|
|
56
|
+
0,
|
|
57
|
+
0,
|
|
58
|
+
0,
|
|
59
|
+
amount === 1 ? 1 : 0,
|
|
60
|
+
0
|
|
61
|
+
]);
|
|
62
|
+
}),
|
|
63
|
+
"2d": Internals.createEffectImplementation({
|
|
64
|
+
setup: () => null,
|
|
65
|
+
apply: ({ source, target, width, height, params }) => {
|
|
66
|
+
const ctx = target.getContext("2d");
|
|
67
|
+
if (!ctx) {
|
|
68
|
+
throw new Error("Failed to acquire 2D context for saturation effect. The canvas may have been assigned a different context type.");
|
|
69
|
+
}
|
|
70
|
+
const r = resolve(params);
|
|
71
|
+
ctx.clearRect(0, 0, width, height);
|
|
72
|
+
ctx.filter = `saturate(${r.amount * 100}%)`;
|
|
73
|
+
ctx.drawImage(source, 0, 0, width, height);
|
|
74
|
+
ctx.filter = "none";
|
|
75
|
+
},
|
|
76
|
+
cleanup: () => {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
},
|
|
81
|
+
schema: saturationSchema,
|
|
82
|
+
validateParams: validateSaturationParams
|
|
83
|
+
});
|
|
84
|
+
export {
|
|
85
|
+
saturation
|
|
86
|
+
};
|