UNPKG

@xdadda/mini-gl

Version:

webgl image editing library with filters and effects

1,228 lines (1,141 loc) 46 kB
function j(e, o) { const { gl: t, img: r } = e; o = o || { translateX: 0, translateY: 0, angle: 0, scale: 0, flipv: 0, fliph: 0 }; let { translateX: n, translateY: a, angle: l, scale: c, flipv: u, fliph: x } = o; c += 1; let s = [c, c]; const f = [ Math.round(t.canvas.width * n * 100) / 100, Math.round(t.canvas.height * a * 100) / 100 ], v = `#version 300 es in vec2 vertex; uniform mat3 matrix; out vec2 texCoord; void main() { texCoord = vertex; gl_Position = vec4((matrix * vec3(vertex, 1)).xy, 0, 1); } `, i = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; void main() { outColor = texture(_texture, vec2(texCoord.x, texCoord.y)); } `; if (t.canvas.width === e.height) { const C = r.width / r.height; s[0] *= C, s[1] /= C; } const g = T.projection(t.canvas.width, t.canvas.height), h = T.translation(f[0], f[1]), d = T.rotation(-l * Math.PI / 180), m = T.scaling(s[0] * (-x || 1), s[1] * (-u || 1)); let p = [1, 0, 0, 0, 1, 0, 0, 0, 1]; p = T.multiply(p, g), p = T.multiply(p, h), p = T.multiply(p, T.translation(t.canvas.width / 2, t.canvas.height / 2)), p = T.multiply(p, d), p = T.multiply(p, m), p = T.multiply(p, T.translation(-t.canvas.width / 2, -t.canvas.height / 2)), p = T.multiply(p, T.scaling(t.canvas.width, t.canvas.height)), e._.$matrix = e._.$matrix || new b(t, v, i), e.runFilter(e._.$matrix, { matrix: p }); } var T = { projection: function(o, t) { return [ 2 / o, 0, 0, 0, 2 / t, 0, -1, -1, 1 ]; }, translation: function(o, t) { return [ 1, 0, 0, 0, 1, 0, o, t, 1 ]; }, rotation: function(o) { var t = Math.cos(o), r = Math.sin(o); return [ t, -r, 0, r, t, 0, 0, 0, 1 ]; }, scaling: function(o, t) { return [ o, 0, 0, 0, t, 0, 0, 0, 1 ]; }, multiply: function(o, t) { var r = o[0], n = o[1], a = o[2], l = o[3], c = o[4], u = o[5], x = o[6], s = o[7], f = o[8], v = t[0], i = t[1], g = t[2], h = t[3], d = t[4], m = t[5], p = t[6], C = t[7], y = t[8]; return [ v * r + i * l + g * x, v * n + i * c + g * s, v * a + i * u + g * f, h * r + d * l + m * x, h * n + d * c + m * s, h * a + d * u + m * f, p * r + C * l + y * x, p * n + C * c + y * s, p * a + C * u + y * f ]; } }; function V(e, o, t) { const { gl: r } = e; t += 1; const n = ` vec3 fromLinear(vec3 linearRGB) { bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308)); vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055); vec3 lower = linearRGB.rgb * vec3(12.92); return vec3(mix(higher, lower, cutoff)); } vec3 toLinear(vec3 sRGB) { bvec3 cutoff = lessThan(sRGB.rgb, vec3(0.04045)); vec3 higher = pow((sRGB.rgb + vec3(0.055))/vec3(1.055), vec3(2.4)); vec3 lower = sRGB.rgb/vec3(12.92); return vec3(mix(higher, lower, cutoff)); }`; if (o.type === "1") { const a = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D map; uniform float filterStrength; ${n} vec4 lut(vec4 color) { vec3 texel = color.rgb; texel = fromLinear(texel); float size = 33.0; float sliceSize = 1.0 / size; float slicePixelSize = sliceSize / size; float sliceInnerSize = slicePixelSize * (size - 1.0); float xOffset = 0.5 * sliceSize + texel.x * (1.0 - sliceSize); float yOffset = 0.5 * slicePixelSize + texel.y * sliceInnerSize; float zOffset = texel.z * (size - 1.0); float zSlice0 = floor(zOffset); float zSlice1 = zSlice0 + 1.0; float s0 = yOffset + (zSlice0 * sliceSize); float s1 = yOffset + (zSlice1 * sliceSize); vec4 slice0Color = texture(map, vec2(xOffset, s0)); vec4 slice1Color = texture(map, vec2(xOffset, s1)); texel = mix(slice0Color, slice1Color, zOffset - zSlice0).rgb; texel = toLinear(texel); return vec4(texel, color.a); } void main() { vec4 color = texture(_texture, texCoord); outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength; } `; e._.$insta1 = e._.$insta1 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt1.use(1), e.runFilter(e._.$insta1, { filterStrength: t ?? 1, map: { unit: 1 } }); } else if (o.type === "2") { const a = `#version 300 es precision highp float; precision highp int; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D map; uniform sampler2D map2; uniform float filterStrength; ${n} vec4 lut(vec4 color) { vec3 texel = color.rgb; texel = fromLinear(texel); texel.r = texture(map, vec2(texel.r, 0.5)).r; texel.g = texture(map, vec2(texel.g, 0.5)).g; texel.b = texture(map, vec2(texel.b, 0.5)).b; float luma = dot(vec3(0.2126, 0.7152, 0.0722), texel); float shadowCoeff = 0.35 * max(0.0, 1.0 - luma); texel = mix(texel, max(vec3(0.0), 2.0 * texel - 1.0), shadowCoeff); texel = mix(texel, vec3(luma), -0.3); texel.r = texture(map2, vec2(texel.r, 0.5)).r; texel.g = texture(map2, vec2(texel.g, 0.5)).g; texel.b = texture(map2, vec2(texel.b, 0.5)).b; texel = toLinear(texel); return vec4(texel, color.a); } void main() { vec4 color = texture(_texture, texCoord); color = color * (1.0 - filterStrength) + lut(color) * filterStrength; outColor = color; } `; e._.$insta2 = e._.$insta2 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r), e._.$instatxt2 = e._.$instatxt2 || new E(r), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta2, { filterStrength: t ?? 1, map: { unit: 1 }, map2: { unit: 2 } }); } else if (o.type === "3") { const a = `#version 300 es precision highp float; precision highp int; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D map; uniform sampler2D mapLgg; uniform float filterStrength; ${n} vec4 lut(vec4 color) { vec3 texel = color.rgb; texel = fromLinear(texel); texel = min(texel * 1.1343, vec3(1.0)); texel.r = texture(map, vec2(texel.r, 0.5)).r; texel.g = texture(map, vec2(texel.g, 0.5)).g; texel.b = texture(map, vec2(texel.b, 0.5)).b; vec3 shadowColor = vec3(0.956862, 0.0, 0.83529); float luma = dot(vec3(0.309, 0.609, 0.082), texel); vec3 shadowBlend = 2.0 * shadowColor * texel; float shadowAmount = 0.6 * max(0.0, (1.0 - 4.0 * luma)); texel = mix(texel, shadowBlend, shadowAmount); vec3 lgg; lgg.r = texture(mapLgg, vec2(texel.r, 0.5)).r; lgg.g = texture(mapLgg, vec2(texel.g, 0.5)).g; lgg.b = texture(mapLgg, vec2(texel.b, 0.5)).b; texel = mix(texel, lgg, min(1.0, 0.8 + luma)); texel = toLinear(texel); return vec4(texel, color.a); } void main() { vec4 color = texture(_texture, texCoord); outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength; } `; e._.$insta3 = e._.$insta3 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2 = e._.$instatxt2 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta3, { filterStrength: t ?? 1, map: { unit: 1 }, mapLgg: { unit: 2 } }); } else if (o.type === "4") { const a = `#version 300 es precision highp float; precision highp int; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D map; uniform sampler2D map2; uniform float filterStrength; ${n} vec4 lut(vec4 color) { vec3 texel = color.rgb; texel = fromLinear(texel); texel.r = texture(map, vec2(texel.r, 0.5)).r; texel.g = texture(map, vec2(texel.g, 0.5)).g; texel.b = texture(map, vec2(texel.b, 0.5)).b; vec3 desat = vec3(dot(vec3(0.7, 0.2, 0.1), texel)); texel = mix(texel, desat, 0.79); texel = vec3(min(1.0, 1.2 * dot(vec3(0.2, 0.7, 0.1), texel))); texel.r = texture(map2, vec2(texel.r, 0.5)).r; texel.g = texture(map2, vec2(texel.g, 0.5)).g; texel.b = texture(map2, vec2(texel.b, 0.5)).b; texel = toLinear(texel); return vec4(texel, color.a); } void main() { vec4 color = texture(_texture, texCoord); outColor = color * (1.0 - filterStrength) + lut(color) * filterStrength; } `; e._.$insta4 = e._.$insta4 || new b(r, null, a), e._.$instatxt1 = e._.$instatxt1 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt1.loadImage(o.map1, r.RGBA), e._.$instatxt2 = e._.$instatxt2 || new E(r, 0, 0, r.RGBA, r.UNSIGNED_BYTE), e._.$instatxt2.loadImage(o.map2, r.RGBA), e._.$instatxt1.use(1), e._.$instatxt2.use(2), e.runFilter(e._.$insta4, { filterStrength: t ?? 1, map: { unit: 1 }, map2: { unit: 2 } }); } else if (o.type === "MTX") { const a = `#version 300 es precision highp float; precision highp int; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform float filterStrength; uniform mat4 uColorMatrix; uniform vec4 uColorOffset; vec4 applyColorMatrix(vec4 c, mat4 m, vec4 o) { vec4 res = (c * m) + (o * c.a); res = clamp(res, 0.0, 1.0); return res; } void main() { vec4 color = texture(_texture, texCoord); color = applyColorMatrix(color, uColorMatrix, uColorOffset); outColor = color; } `; let l = { //[r,g,b,a,w] identity: [ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0] ], polaroid: [ [1 + 0.438 * t, -0.062 * t, -0.062 * t, 0, 0], [-0.122 * t, 1 + 0.378 * t, -0.122 * t, 0, 0], [-0.016 * t, -0.016 * t, 1 + 0.483 * t, 0, 0], [0, 0, 0, 1, 0] ], kodachrome: [ [(1 + 0.1285582396593525 * t) * ((t / 2 + 1) / 2 + 0.5), -0.3967382283601348 * t, -0.03992559172921793 * t, 0, 0.06372958762196503 * t], [-0.16404339962244616 * t, (1 + 0.0835251566291304 * t) * ((t / 2 + 1) / 2 + 0.5), -0.05498805115633132 * t, 0, 0.024732407896706204 * t], [-0.16786010706155763 * t, -0.5603416277695248 * t, (1 + 0.6014850761964943 * t) * ((t / 2 + 1) / 2 + 0.5), 0, 0.03562982807460946 * t], [0, 0, 0, 1, 0] ], browni: [ [(1 - 0.4002976502 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.34553243048391263 * t, -0.2708298674538042 * t, 0, 0.09486385711201746 * t], [-0.037703249837783157 * t, (1 - 0.1390422412 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.15059552388459913 * t, 0, -0.07393682996638255 * t], [0.24113635128153335 * t, -0.07441037908422492 * t, (1 - 0.5502781794 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0, -0.015124150555182566 * t], [0, 0, 0, 1, 0] ], vintage: [ [(1 - 0.3720654364 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.3202183420819367 * t, -0.03965408211312453 * t, 0, 0.009651285835294123 * t], [0.02578397704808868 * t, (1 - 0.3558811356 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0.03259127616149294 * t, 0, 0.007462829176470591 * t], [0.0466055556782719 * t, -0.0851232987247891 * t, (1 - 0.4758351981 * t) * ((t / 1.5 + 1) / 2 + 0.5), 0, 0.005159190588235296 * t], [0, 0, 0, 1, 0] ] }, c = l.identity, u = [0, 0, 0, 0]; t && (c = Y(c, l[o.mtx], 4)), t && (u = [0, 1, 2, 3].map((f) => u[f] + l[o.mtx][f][4])), e._.$insta5 = e._.$insta5 || new b(r, null, a); const x = c.flat(), s = u; e.runFilter(e._.$insta5, { uColorMatrix: x, uColorOffset: s }); } } function Y(e, o, t = 3) { let r = []; for (var n = 0; n < t; n++) { r.push([]); for (var a = 0; a < t; a++) { r[n].push(0); for (var l = 0; l < t; l++) e[n] && o[l] && (r[n][a] += e[n][l] * o[l][a]); } } return r; } function N(e) { var o = e.length; this.xa = [], this.ya = [], this.u = [], this.y2 = [], e.sort(function(c, u) { return c[0] - u[0]; }); for (var t = 0; t < o; t++) this.xa.push(e[t][0]), this.ya.push(e[t][1]); this.u[0] = 0, this.y2[0] = 0; for (var t = 1; t < o - 1; ++t) { var r = this.xa[t + 1] - this.xa[t - 1], n = (this.xa[t] - this.xa[t - 1]) / r, a = n * this.y2[t - 1] + 2; this.y2[t] = (n - 1) / a; var l = (this.ya[t + 1] - this.ya[t]) / (this.xa[t + 1] - this.xa[t]) - (this.ya[t] - this.ya[t - 1]) / (this.xa[t] - this.xa[t - 1]); this.u[t] = (6 * l / r - n * this.u[t - 1]) / a; } this.y2[o - 1] = 0; for (var t = o - 2; t >= 0; --t) this.y2[t] = this.y2[t] * this.y2[t + 1] + this.u[t]; } N.prototype.at = function(e) { for (var o = this.ya.length, t = 0, r = o - 1; r - t > 1; ) { var n = r + t >> 1; this.xa[n] > e ? r = n : t = n; } var a = this.xa[r] - this.xa[t], l = (this.xa[r] - e) / a, c = (e - this.xa[t]) / a; return l * this.ya[t] + c * this.ya[r] + ((l * l * l - l) * this.y2[t] + (c * c * c - c) * this.y2[r]) * (a * a) / 6; }; function L(e) { for (var o = new N(e), t = [], r = 0; r < 256; r++) t.push(H(0, Math.floor(o.at(r / 255) * 256), 255)); return t; } function H(e, o, t) { return Math.max(e, Math.min(o, t)); } function K(e, a) { if (a.every((x) => x === null)) return; a[0] || (a[0] = [[0, 0], [1, 1]]); let t = a[1] || a[0], r = a[2] || a[0], n = a[3] || a[0]; if (t = L(t), r = L(r), n = L(n), t.length !== 256 || r.length !== 256 || n.length !== 256) return console.error("curves: input unknown"); for (var a = [], l = 0; l < 256; l++) a.splice(a.length, 0, t[l], r[l], n[l], 255); const c = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D curvemap; void main() { vec4 color = texture(_texture, texCoord); color.r = texture(curvemap, vec2(color.r)).r; color.g = texture(curvemap, vec2(color.g)).g; color.b = texture(curvemap, vec2(color.b)).b; outColor = color; } `, { gl: u } = e; e._.$curvestexture = e._.$curvestexture || new E(u), e._.$curvestexture.initFromBytes(256, 1, a, u.RGBA), e._.$curvestexture.use(2), e._.$curves = e._.$curves || new b(u, null, c), e.runFilter(e._.$curves, { curvemap: { unit: 2 } }); } function W(e, o, t, r) { const n = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; uniform vec2 uResolution; uniform mat3 matrix; uniform bool useTextureSpace; out vec4 outColor; void main() { vec2 coord = texCoord * uResolution; if (useTextureSpace) coord = coord / uResolution * 2.0 - 1.0; vec3 warp = matrix * vec3(coord, 1.0); coord = warp.xy / warp.z; if (useTextureSpace) coord = (coord * 0.5 + 0.5) * uResolution; vec4 color = texture(_texture, coord / uResolution); vec2 clampedCoord = clamp(coord, vec2(0.0), uResolution); if (coord != clampedCoord) { //color.a *= max(0.0, 1.0 - length(coord - clampedCoord)); color.a = 0.; } outColor = color; } `, { gl: a, img: l } = e; if (e._.$warp = e._.$warp || new b(a, null, n), o = Array.prototype.concat.apply([], o), o.length == 4) o = [ o[0], o[1], 0, o[2], o[3], 0, 0, 0, 1 ]; else if (o.length != 9) throw "can only warp with 2x2 or 3x3 matrix"; const c = [a.canvas.width, a.canvas.height]; e.runFilter(e._.$warp, { matrix: t ? X(o) : o, uResolution: c, useTextureSpace: r | 0 }); } function Z(e, o, t, r, n) { o = o.flat(), t = t.flat(); var a = U.apply(null, t), l = U.apply(null, o), c = q(X(a), l); return W(e, c, r, n); } function U(e, o, t, r, n, a, l, c) { var u = t - n, x = r - a, s = l - n, f = c - a, v = e - t + n - l, i = o - r + a - c, g = u * f - s * x, h = (v * f - s * i) / g, d = (u * i - v * x) / g; return [ t - e + h * t, r - o + h * r, h, l - e + d * l, c - o + d * c, d, e, o, 1 ]; } function X(e) { var o = e[0], t = e[1], r = e[2], n = e[3], a = e[4], l = e[5], c = e[6], u = e[7], x = e[8], s = o * a * x - o * l * u - t * n * x + t * l * c + r * n * u - r * a * c; return [ (a * x - l * u) / s, (r * u - t * x) / s, (t * l - r * a) / s, (l * c - n * x) / s, (o * x - r * c) / s, (r * n - o * l) / s, (n * u - a * c) / s, (t * c - o * u) / s, (o * a - t * n) / s ]; } function q(e, o) { return [ e[0] * o[0] + e[1] * o[3] + e[2] * o[6], e[0] * o[1] + e[1] * o[4] + e[2] * o[7], e[0] * o[2] + e[1] * o[5] + e[2] * o[8], e[3] * o[0] + e[4] * o[3] + e[5] * o[6], e[3] * o[1] + e[4] * o[4] + e[5] * o[7], e[3] * o[2] + e[4] * o[5] + e[5] * o[8], e[6] * o[0] + e[7] * o[3] + e[8] * o[6], e[6] * o[1] + e[7] * o[4] + e[8] * o[7], e[6] * o[2] + e[7] * o[5] + e[8] * o[8] ]; } function Q(e, o, t) { const { gl: r } = e, n = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform sampler2D map; uniform float filterStrength; vec4 fromLinear(vec4 linearRGB) { bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308)); vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055); vec3 lower = linearRGB.rgb * vec3(12.92); return vec4(mix(higher, lower, cutoff), linearRGB.a); } vec4 toLinear(vec4 sRGB) { bvec3 cutoff = lessThan(sRGB.rgb, vec3(0.04045)); vec3 higher = pow((sRGB.rgb + vec3(0.055))/vec3(1.055), vec3(2.4)); vec3 lower = sRGB.rgb/vec3(12.92); return vec4(mix(higher, lower, cutoff), sRGB.a); } void main(){ vec4 color = texture(_texture, texCoord); vec4 texc = texture(map, texCoord); color = toLinear(color); texc = toLinear(texc); color = mix(color, texc, filterStrength); color = fromLinear(color); outColor = color; }`; e._.$blend = e._.$blend || new b(r, null, n), e._.$blendtxt = e._.$blendtxt || new E(r), e._.$blendtxt.loadImage(o), e._.$blendtxt.use(1), e.runFilter(e._.$blend, { filterStrength: t ?? 1, map: { unit: 1 } }); } function J(e, o) { const t = `#version 300 es //Bokeh disc. by David Hoskins. //https://www.shadertoy.com/view/4d2Xzw precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform float bokehstrength; uniform float bokehlensin; uniform float bokehlensout; uniform float centerX; uniform float centerY; #define GOLDEN_ANGLE 2.39996323 #define ITERATIONS 512 const mat2 rot = mat2(cos(GOLDEN_ANGLE), sin(GOLDEN_ANGLE), -sin(GOLDEN_ANGLE), cos(GOLDEN_ANGLE)); vec3 Bokeh(sampler2D tex, vec2 uv, float radius) { vec3 acc = vec3(0), div = acc; float r = 1.; vec2 vangle = vec2(0.0,radius*.01 / sqrt(float(ITERATIONS))); for (int j = 0; j < ITERATIONS; j++) { // the approx increase in the scale of sqrt(0, 1, 2, 3...) r += 1. / r; vangle = rot * vangle; vec3 col = texture(tex, uv + (r-1.) * vangle).xyz; /// ... Sample the image //col = col * col *1.8; // ... Contrast it for better highlights - leave this out elsewhere. vec3 bokeh = pow(col, vec3(4)); acc += col * bokeh; div += bokeh; } return acc / div; } void main() { vec4 color = texture(_texture, texCoord); vec4 bcolor = vec4(Bokeh(_texture, texCoord, bokehstrength), 1.); //vignette used to control alpha //to blur inside circle smoothstep(lensin, lensout, dist) //to blur outside circle smoothstep(lensout, lensin, dist) float dist = distance(texCoord.xy, vec2(centerX,centerY)); float vigfin = pow(1.-smoothstep(max(0.001,bokehlensout), bokehlensin, dist),2.); outColor = mix( color, bcolor, vigfin); } `, { gl: r } = e; let { bokehstrength: n = 0.5, bokehlensin: a = 0, bokehlensout: l = 0.5, centerX: c = 0, centerY: u = 0 } = o || {}; e._.$lensblur = e._.$lensblur || new b(r, null, t), e.runFilter(e._.$lensblur, { bokehstrength: n, bokehlensin: a, bokehlensout: l, centerX: c, centerY: u }); } function ee(e, o) { const t = `#version 300 es //https://www.shadertoy.com/view/XdfGDH precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform vec2 uResolution; uniform float gaussianstrength; uniform float gaussianlensin; uniform float gaussianlensout; uniform float centerX; uniform float centerY; float normpdf(in float x, in float sigma) { return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma; } void main() { vec4 color = texture(_texture, texCoord); //declare stuff const int mSize = 11; const int kSize = (mSize-1)/2; float kernel[mSize]; vec3 final_colour = vec3(0.0); //create the 1-D kernel float sigma = 7.0*gaussianstrength; float Z = 0.0; for (int j = 0; j <= kSize; ++j) { kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), sigma); } //get the normalization factor (as the gaussian has been clamped) for (int j = 0; j < mSize; ++j) { Z += kernel[j]; } //read out the texels for (int i=-kSize; i <= kSize; ++i) { for (int j=-kSize; j <= kSize; ++j) { final_colour += kernel[kSize+j]*kernel[kSize+i]*texture(_texture, (texCoord.xy+vec2(float(i),float(j))/uResolution)).rgb; } } //vignette used to control alpha //to blur inside circle smoothstep(lensin, lensout, dist) //to blur outside circle smoothstep(lensout, lensin, dist) float dist = distance(texCoord.xy, vec2(centerX,centerY)); float vigfin = pow(1.-smoothstep(max(0.001,gaussianlensout), gaussianlensin, dist),2.); outColor = mix( color, vec4(final_colour/(Z*Z), 1.0), vigfin); } `, { gl: r } = e; let { gaussianstrength: n = 0.5, gaussianlensin: a = 0, gaussianlensout: l = 0.5, centerX: c = 0, centerY: u = 0 } = o || {}; const x = [r.canvas.width, r.canvas.height]; e._.$gaussianblur = e._.$gaussianblur || new b(r, null, t), e.runFilter(e._.$gaussianblur, { gaussianstrength: n, gaussianlensin: a, gaussianlensout: l, centerX: c, centerY: u, uResolution: x }); } function te(e, o) { const t = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform vec2 uTextureSize; uniform mat4 uColorMatrix; uniform vec4 uColorOffset; uniform float uClarityKernel[9]; uniform float uClarityKernelWeight; uniform float uColorGamma; uniform float uVibrance; uniform float uColorVignette; uniform vec2 uVignettePos; uniform float vibrance; vec4 applyGamma(vec4 c, float g) { c.r = pow(c.r, g); c.g = pow(c.g, g); c.b = pow(c.b, g); return c; } vec4 applyVibrance(vec4 c, float v){ float max = max(c.r, max(c.g, c.b)); float avg = (c.r + c.g + c.b) / 3.0; float amt = (abs(max - avg) * 2.0) * -v; c.r += max != c.r ? (max - c.r) * amt : 0.00; c.g += max != c.g ? (max - c.g) * amt : 0.00; c.b += max != c.b ? (max - c.b) * amt : 0.00; return c; } vec4 applyColorMatrix(vec4 c, mat4 m, vec4 o) { vec4 res = (c * m) + (o * c.a); res = clamp(res, 0.0, 1.0); return res; } vec4 applyConvolutionMatrix(vec4 c, float k0, float k1, float k2, float k3, float k4, float k5, float k6, float k7, float k8, float w) { vec2 pixel = vec2(1) / uTextureSize; vec4 colorSum = texture(_texture, texCoord - pixel) * k0 + texture(_texture, texCoord + pixel * vec2(0.0, -1.0)) * k1 + texture(_texture, texCoord + pixel * vec2(1.0, -1.0)) * k2 + texture(_texture, texCoord + pixel * vec2(-1.0, 0.0)) * k3 + texture(_texture, texCoord) * k4 + texture(_texture, texCoord + pixel * vec2(1.0, 0.0)) * k5 + texture(_texture, texCoord + pixel * vec2(-1.0, 1.0)) * k6 + texture(_texture, texCoord + pixel * vec2(0.0, 1.0)) * k7 + texture(_texture, texCoord + pixel) * k8; vec4 color = vec4(clamp((colorSum / w), 0.0, 1.0).rgb, c.a); return color; } vec4 applyVignette2(vec4 c, vec2 pos, float v, vec2 upos){ #define inner .20 #define outer 1.1 #define curvature .65 vec2 curve = pow(abs(pos),vec2(1./curvature)); float edge = pow(length(curve),curvature); float scale = 1.-abs(upos.x); float vignette = 1.-v*smoothstep(inner*scale,outer*scale,edge); vec4 color = vec4(c.rgb *= vignette , c.a); return color; } vec4 vignette3(vec4 c, vec2 pos, float radius) { float ambientlight = 0.14; float circle = length(pos) - radius; float v = 1.0 - smoothstep(0.0, 0.4f, circle) + ambientlight; return vec4(c.rgb*v,c.a); } void main() { vec4 color = texture(_texture, texCoord); if (uClarityKernelWeight != -1.0) { color = applyConvolutionMatrix(color, uClarityKernel[0], uClarityKernel[1], uClarityKernel[2], uClarityKernel[3], uClarityKernel[4], uClarityKernel[5], uClarityKernel[6], uClarityKernel[7], uClarityKernel[8], uClarityKernelWeight); } color = applyGamma(color, uColorGamma); color = applyVibrance(color, uVibrance); color = applyColorMatrix(color, uColorMatrix, uColorOffset); if (uColorVignette != 0.0) { vec2 pos = texCoord.xy*2.-1. - uVignettePos; //color = vignette3(color, pos, uColorVignette); color = applyVignette2(color, pos, uColorVignette, uVignettePos); } outColor = color; } `, { gl: r } = e; let n = [0, 0], { brightness: a = 0, contrast: l = 0, saturation: c = 0, exposure: u = 0, temperature: x = 0, gamma: s = 0, clarity: f = 0, vibrance: v = 0, vignette: i = 0, tint: g = 0, sepia: h = 0 } = o; a = a / 4, l = (l + 1) / 2 + 0.5, c = c + 1, u = ((u > 0 ? u * 3 : u * 1.5) + 1) / 2 + 0.5, s += 1, x *= 2, g *= 2; let d = { //[r,g,b,a,w] //brightness t (0-2) brightness: [ [1, 0, 0, 0, a], [0, 1, 0, 0, a], [0, 0, 1, 0, a], [0, 0, 0, 1, 0] ], //constrast t (0-2) contrast: [ [l, 0, 0, 0, 0.5 * (1 - l)], [0, l, 0, 0, 0.5 * (1 - l)], [0, 0, l, 0, 0.5 * (1 - l)], [0, 0, 0, 1, 0] ], //saturation (0-2) saturation: [ [0.213 + 0.787 * c, 0.715 - 0.715 * c, 0.072 - 0.072 * c, 0, 0], [0.213 - 0.213 * c, 0.715 + 0.285 * c, 0.072 - 0.072 * c, 0, 0], [0.213 - 0.213 * c, 0.715 - 0.715 * c, 0.072 + 0.928 * c, 0, 0], [0, 0, 0, 1, 0] ], //exposure (0-2) exposure: [ [u, 0, 0, 0, 0], [0, u, 0, 0, 0], [0, 0, u, 0, 0], [0, 0, 0, 1, 0] ], //temperature (-1 +1) temperature: x > 0 ? [ [1 + 0.1 * x, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1 + 0.1 * -x, 0, 0], [0, 0, 0, 1, 0] ] : [ [1 + 0.15 * x, 0, 0, 0, 0], [0, 1 + 0.05 * x, 0, 0, 0], [0, 0, 1 + 0.15 * -x, 0, 0], [0, 0, 0, 1, 0] ], //tint tint: [ [1, 0, 0, 0, 0], [0, 1 + 0.1 * g, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0] ], //sepia sepia: [ [1 - 0.607 * h, 0.769 * h, 0.189 * h, 0, 0], [0.349 * h, 1 - 0.314 * h, 0.168 * h, 0, 0], [0.272 * h, 0.534 * h, 1 - 0.869 * h, 0, 0], [0, 0, 0, 1, 0] ], /* //same as saturation! gray: [ [1-.7874*g,.7152*g,.0722*g,0,0], [.2126*g,1-.2848*g,.0722*g,0,0], [.2126*g,.7152*g,1-.9278*g,0,0], [0,0,0,1,0], ], */ identity: [ [1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0] ] }, m = d.identity, p = [0, 0, 0, 0]; m = B(m, d.brightness, 4), p = [0, 1, 2, 3].map((S) => p[S] + d.brightness[S][4]), m = B(m, d.contrast, 4), p = [0, 1, 2, 3].map((S) => p[S] + d.contrast[S][4]), m = B(m, d.saturation, 4), m = B(m, d.exposure, 4), m = B(m, d.temperature, 4), m = B(m, d.tint, 4), m = B(m, d.sepia, 4); let C = f >= 0 ? [ 0, -1 * f, 0, -1 * f, 1 + 4 * f, -1 * f, 0, -1 * f, 0 ] : [ -1 * f, -2 * f, -1 * f, -2 * f, 1 + -3 * f, -2 * f, -1 * f, -2 * f, -1 * f ], y = C.reduce(((S, A) => S + A), 0); y = y <= 0 ? 1 : y, C = [C]; const z = m.flat(), D = p, I = [r.canvas.width, r.canvas.height], M = v, F = i, _ = C, w = y, R = n; e._.$adj = e._.$adj || new b(r, null, t), e.runFilter(e._.$adj, { uColorMatrix: z, uColorOffset: D, uColorGamma: 1 / s, uClarityKernel: _, uClarityKernelWeight: w, uTextureSize: I, uVibrance: M, uColorVignette: F, uVignettePos: R }); } function re(e, o, t) { const r = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform float shadows; uniform float highlights; const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721); void main() { vec4 color = texture(_texture, texCoord); float luminance = dot(color.rgb, luminanceWeighting); float shadow = clamp((pow(luminance, 1.0/shadows) + (-0.76)*pow(luminance, 2.0/shadows)) - luminance, 0.0, 1.0); float highlight = clamp((1.0 - (pow(1.0-luminance, 1.0/(2.0-highlights)) + (-0.8)*pow(1.0-luminance, 2.0/(2.0-highlights)))) - luminance, -1.0, 0.0); vec3 result = vec3(0.0, 0.0, 0.0) + (luminance + shadow + highlight) * ((color.rgb - vec3(0.0, 0.0, 0.0))/luminance ); // blend toward white if highlights is more than 1 float contrastedLuminance = ((luminance - 0.5) * 1.5) + 0.5; float whiteInterp = contrastedLuminance*contrastedLuminance*contrastedLuminance; float whiteTarget = clamp(highlights, 0.0, 2.0) - 1.0; result = mix(result, vec3(1.0), whiteInterp*whiteTarget); // blend toward black if shadows is less than 1 float invContrastedLuminance = 1.0 - contrastedLuminance; float blackInterp = invContrastedLuminance*invContrastedLuminance*invContrastedLuminance; float blackTarget = 1.0 - clamp(shadows, 0.0, 1.0); result = mix(result, vec3(0.0), blackInterp*blackTarget); outColor = vec4(result, color.a); } `, { gl: n } = e; e._.$sg = e._.$sg || new b(n, null, r), e.runFilter(e._.$sg, { highlights: o + 1, shadows: t / 2 + 1 }); } function oe(e, o) { const t = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform vec2 uResolution; uniform float filterStrength; vec4 BlurColor (in vec2 Coord, in sampler2D Tex, in float MipBias) { vec2 TexelSize = MipBias/uResolution.xy; vec4 Color = texture(Tex, Coord, MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,0.0), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,0.0), MipBias); Color += texture(Tex, Coord + vec2(0.0,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(0.0,-TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(TexelSize.x,-TexelSize.y), MipBias); Color += texture(Tex, Coord + vec2(-TexelSize.x,-TexelSize.y), MipBias); return Color/9.0; } void main() { float Threshold = 0.4; float Intensity = filterStrength*1.0; float BlurSize = 3.0 * Intensity; vec4 color = texture(_texture, texCoord); vec4 Highlight = clamp(BlurColor(texCoord.xy, _texture, BlurSize)-Threshold,0.0,1.0)*1.0/(1.0-Threshold); outColor = 1.0-(1.0-color)*(1.0-Highlight*Intensity); //Screen Blend Mode } `, { gl: r } = e, n = [r.canvas.width, r.canvas.height]; e._.$bloom = e._.$bloom || new b(r, null, t), e.runFilter(e._.$bloom, { filterStrength: o, uResolution: n }); } function ae(e, o) { const t = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; uniform vec2 uResolution; uniform float filterStrength; #define SIGMA 10.0 #define BSIGMA 0.1 #define MSIZE 15 float normpdf(in float x, in float sigma) { return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma; } float normpdf3(in vec3 v, in float sigma) { return 0.39894*exp(-0.5*dot(v,v)/(sigma*sigma))/sigma; } vec4 applyFilter(vec4 c, sampler2D _texture, vec2 texCoord) { const int kSize = (MSIZE-1)/2; float kernel[MSIZE] = float[MSIZE](0.031225216, 0.033322271, 0.035206333, 0.036826804, 0.038138565, 0.039104044, 0.039695028, 0.039894000, 0.039695028, 0.039104044, 0.038138565, 0.036826804, 0.035206333, 0.033322271, 0.031225216); vec3 final_colour = vec3(0.0); vec3 cc; float factor; float Z = 0.0; float bZ = 1.0/normpdf(0.0, BSIGMA); for (int i=-kSize; i <= kSize; ++i) { for (int j=-kSize; j <= kSize; ++j) { cc = texture(_texture, (texCoord.xy+vec2(float(i),float(j))/uResolution)).rgb; factor = normpdf3(cc-c.rgb, BSIGMA)*bZ*kernel[kSize+j]*kernel[kSize+i]; Z += factor; final_colour += factor*cc; } } return vec4(final_colour/Z, 1.0); } void main() { vec4 color = texture(_texture, texCoord); color = color * (1.0 - filterStrength) + applyFilter(color, _texture, texCoord) * filterStrength; outColor = color; } `, { gl: r } = e, n = [r.canvas.width, r.canvas.height]; e._.$noise = e._.$noise || new b(r, null, t), e.runFilter(e._.$noise, { filterStrength: o, uResolution: n }); } function B(e, o, t = 3) { let r = []; for (var n = 0; n < t; n++) { r.push([]); for (var a = 0; a < t; a++) { r[n].push(0); for (var l = 0; l < t; l++) e[n] && o[l] && (r[n][a] += e[n][l] * o[l][a]); } } return r; } const P = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, filterAdjustments: te, filterBlend: Q, filterBloom: oe, filterBlurBokeh: J, filterBlurGaussian: ee, filterCurves: K, filterHighlightsShadows: re, filterInsta: V, filterMatrix: j, filterNoise: ae, filterPerspective: Z }, Symbol.toStringTag, { value: "Module" })); function le(e, o, t) { let r = e.getContext("webgl2", { antialias: !1, premultipliedAlpha: !0 }); if (!r) return console.error("webgl2 not supported!"); t === "display-p3" ? (r.drawingBufferColorSpace = "display-p3", r.unpackColorSpace = "display-p3") : (r.drawingBufferColorSpace = "srgb", r.unpackColorSpace = "srgb"); const n = { width: 0, height: 0, gl: r, img: o, destroy: f, loadImage: g, paintCanvas: h, crop: z, resetCrop: D, resize: m, resetResize: p, captureImage: I, readPixels: M, runFilter: i, setupFiltersTextures: s, _: {} //for filters' storage }; r.canvas.width = n.width = o.naturalWidth, r.canvas.height = n.height = o.naturalHeight; const a = new E(r); a.loadImage(o); const l = new b(r), c = new b(r, null, ne); let u, x = 0; function s() { u?.length && u.forEach((w) => w.destroy()), u = []; for (var _ = 0; _ < 2; ++_) { const w = new E(r, r.canvas.width, r.canvas.height); u.push(w); } } s(); function f() { u?.length && u.forEach((_) => _.destroy()), C && C.destroy(), a.destroy(), delete n.img_cropped; } let v; function i(_, w) { w && _.uniforms(w), v && v.use(), u[x % 2].drawTo(), _.drawRect(), v = u[x % 2], x++; } function g() { C ? v = C : v = a, i(l, null); } function h() { v && v.use(), r.bindFramebuffer(r.FRAMEBUFFER, null), c.drawRect(); } let d = { width: 0, height: 0 }; function m(_, w) { r.canvas.width = n.width = d.width = _, r.canvas.height = n.height = d.height = w, s(); } function p() { d.width && (d.width = d.height = 0, r.canvas.width = n.width = y.width || o.naturalWidth, r.canvas.height = n.height = y.height || o.naturalHeight, s()); } let C, y = { width: 0, height: 0 }; function z({ left: _, top: w, width: R, height: S }) { const A = R * S * 4, $ = new Uint8Array(A); i(l, {}), r.readPixels(_, w, R, S, r.RGBA, r.UNSIGNED_BYTE, $); const G = r.unpackColorSpace, k = new ImageData(new Uint8ClampedArray($.buffer), R, S, { colorSpace: G }); C = new E(r), C.loadImage(k), r.canvas.width = n.width = y.width = R, r.canvas.height = n.height = y.height = S, s(), n.img_cropped = O(k, G); } function D() { C && (C.destroy(), C = null, y.width = y.height = 0, r.canvas.width = n.width = d.width || o.naturalWidth, r.canvas.height = n.height = d.height || o.naturalHeight, delete n.img_cropped, s()); } function I(_, w) { i(l, {}); const { width: R, height: S } = r.canvas, A = R * S * 4, $ = new Uint8Array(A); r.readPixels(0, 0, R, S, r.RGBA, r.UNSIGNED_BYTE, $); const G = r.unpackColorSpace, k = new ImageData(new Uint8ClampedArray($.buffer), R, S, { colorSpace: G }); return O(k, G, _, w); } function M() { i(l, {}); const { width: _, height: w } = r.canvas, R = _ * w * 4, S = new Uint8Array(R); return r.readPixels(0, 0, _, w, r.RGBA, r.UNSIGNED_BYTE, S), S; } function F(_) { return function(...w) { _(n, ...w); }; } return Object.keys(P).forEach((_) => n[_] = F(P[_])), n; } const ne = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; vec4 fromLinear(vec4 linearRGB) { bvec3 cutoff = lessThan(linearRGB.rgb, vec3(0.0031308)); vec3 higher = vec3(1.055)*pow(linearRGB.rgb, vec3(1.0/2.4)) - vec3(0.055); vec3 lower = linearRGB.rgb * vec3(12.92); return vec4(mix(higher, lower, cutoff), linearRGB.a); } void main() { vec4 color = texture(_texture, vec2(texCoord.x, 1.0 - texCoord.y)); //outColor = color; outColor = fromLinear(color); }`; function b(e, o, t) { const r = `#version 300 es in vec2 vertex; out vec2 texCoord; void main() { texCoord = vertex; gl_Position = vec4(vertex * 2.0 - 1.0, 0.0, 1.0); } `, n = `#version 300 es precision highp float; in vec2 texCoord; uniform sampler2D _texture; out vec4 outColor; void main() { outColor = texture(_texture, texCoord); } `, a = e.createProgram(); let l; e.attachShader(a, x(e, e.VERTEX_SHADER, o || r)), e.attachShader(a, x(e, e.FRAGMENT_SHADER, t || n)), e.linkProgram(a); function c(s = !0, f, v, i, g) { const h = e.getParameter(e.VIEWPORT); f = f !== void 0 ? (f - h[0]) / h[2] : 0, v = v !== void 0 ? (v - h[1]) / h[3] : 0, i = i !== void 0 ? (i - h[0]) / h[2] : 1, g = g !== void 0 ? (g - h[1]) / h[3] : 1, e.useProgram(a), e.vertexBuffer = e.vertexBuffer || e.createBuffer(), e.bindBuffer(e.ARRAY_BUFFER, e.vertexBuffer), e.bufferData( e.ARRAY_BUFFER, new Float32Array([f, v, f, g, i, v, i, g]), e.STATIC_DRAW ), l || (l = e.getAttribLocation(a, "vertex"), e.enableVertexAttribArray(l)), e.vertexAttribPointer(l, 2, e.FLOAT, !1, 0, 0), s && (e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT | e.GL_DEPTH_BUFFER_BIT)), e.drawArrays(e.TRIANGLE_STRIP, 0, 4); } function u(s = {}) { e.useProgram(a); for (let f in s) { const v = e.getUniformLocation(a, f); if (v === null) continue; let i = s[f]; if (Array.isArray(i)) switch (i.length) { case 1: { Array.isArray(i[0]) && (i = i[0]), e.uniform1fv(v, new Float32Array(i)); break; } case 2: e.uniform2fv(v, new Float32Array(i)); break; case 3: e.uniform3fv(v, new Float32Array(i)); break; case 4: e.uniform4fv(v, new Float32Array(i)); break; case 9: e.uniformMatrix3fv(v, !1, new Float32Array(i)); break; case 16: e.uniformMatrix4fv(v, !1, new Float32Array(i)); break; default: throw `dont't know how to load uniform "` + f + '" of length ' + i.length; } else if (i?.unit) e.uniform1i(v, i.unit); else if (typeof i == "number") e.uniform1f(v, i); else throw 'attempted to set uniform "' + f + '" to invalid value ' + (i || "undefined").toString(); } } function x(s, f, v) { var i = s.createShader(f); if (s.shaderSource(i, v), s.compileShader(i), !s.getShaderParameter(i, s.COMPILE_STATUS)) throw "compile error: " + s.getShaderInfoLog(i); return i; } return { drawRect: c, uniforms: u }; } function E(e, o, t) { let r = o, n = t, a = e.createTexture(); e.bindTexture(e.TEXTURE_2D, a), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE); const l = e.SRGB8_ALPHA8; o && t && e.texImage2D(e.TEXTURE_2D, 0, l, o, t, 0, e.RGBA, e.UNSIGNED_BYTE, null); function c(v = 0) { if (!a) return console.error("texture has been destroyed"); e.activeTexture(e.TEXTURE0 + v), e.bindTexture(e.TEXTURE_2D, a); } function u() { e.deleteTexture(a), a = null; } function x() { if (!a) return console.error("texture has been destroyed"); if (e.framebuffer = e.framebuffer || e.createFramebuffer(), e.bindFramebuffer(e.FRAMEBUFFER, e.framebuffer), e.framebufferTexture2D(e.FRAMEBUFFER, e.COLOR_ATTACHMENT0, e.TEXTURE_2D, a, 0), e.checkFramebufferStatus(e.FRAMEBUFFER) !== e.FRAMEBUFFER_COMPLETE) throw new Error("incomplete framebuffer"); e.viewport(0, 0, r, n); } function s(v, i) { if (!a) return console.error("texture has been destroyed"); r = v.naturalWidth, n = v.naturalHeight, e.bindTexture(e.TEXTURE_2D, a); let g = i || e.SRGB8_ALPHA8; e.texImage2D(e.TEXTURE_2D, 0, g, e.RGBA, e.UNSIGNED_BYTE, v); } function f(v, i, g, h) { r = v, n = i, e.bindTexture(e.TEXTURE_2D, a); let d = h || e.SRGB8_ALPHA8; e.texImage2D(e.TEXTURE_2D, 0, d, v, i, 0, e.RGBA, e.UNSIGNED_BYTE, new Uint8Array(g)); } return { use: c, destroy: u, drawTo: x, loadImage: s, initFromBytes: f }; } function O(e, o, t, r) { const n = document.createElement("canvas"); var a = n.getContext("2d", { colorSpace: o }); n.width = e.width, n.height = e.height, a.putImageData(e, 0, 0); var l = new Image(); return l.src = n.toDataURL(t, r), l; } export { b as Shader, N as Spline, E as Texture, le as minigl };