emf-converter 4.8.2 → 4.8.3

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.js CHANGED
@@ -17040,13 +17040,17 @@ function expandedBlur(rgba, width, height, radius, x0, y0, x1, y1, cropped) {
17040
17040
  const blurred = blurReduction(radius) > 1 ? effectBlur(buf, bw, bh, radius, cropped ? { x: r, y: r, w: x1 - x0, h: y1 - y0 } : void 0, true) : gdipBlur(buf, bw, bh, radius, cropped ? r : 0, cropped, Math.ceil((y1 - y0) / (x1 - x0)));
17041
17041
  const w = x1 - x0;
17042
17042
  const out = new Uint8ClampedArray(w * (y1 - y0) * 4);
17043
+ const halo = new Uint8ClampedArray((y1 - y0) * 4);
17043
17044
  for (let y = 0; y < y1 - y0; y++) {
17044
17045
  const from = ((y + r) * bw + r) * 4;
17045
17046
  for (let i = 0; i < w * 4; i++) {
17046
17047
  out[y * w * 4 + i] = Math.round(blurred[from + i]);
17047
17048
  }
17049
+ for (let i = 0; i < 4; i++) {
17050
+ halo[y * 4 + i] = Math.round(blurred[from + w * 4 + i]);
17051
+ }
17048
17052
  }
17049
- return out;
17053
+ return { out, halo };
17050
17054
  }
17051
17055
  function applyImageEffectToRect(rgba, width, height, effect, src) {
17052
17056
  if (width <= 0 || height <= 0 || rgba.length !== width * height * 4) {
@@ -17079,7 +17083,12 @@ function applyImageEffectToRect(rgba, width, height, effect, src) {
17079
17083
  };
17080
17084
  if (src && effect.kind === "blur" && effect.expandEdge) {
17081
17085
  const cropped = Math.ceil(src.x + src.w) < width && Math.ceil(src.y + src.h) < height;
17082
- return result(expandedBlur(rgba, width, height, effect.radius, x0, y0, x1, y1, cropped));
17086
+ const { out: out2, halo } = expandedBlur(rgba, width, height, effect.radius, x0, y0, x1, y1, cropped);
17087
+ const region2 = result(out2);
17088
+ if (shownWidth === w && shownHeight === h) {
17089
+ region2.haloRight = halo;
17090
+ }
17091
+ return region2;
17083
17092
  }
17084
17093
  let region = rgba;
17085
17094
  if (w !== width || h !== height) {
@@ -20451,6 +20460,22 @@ function cubicIntegral(t, a) {
20451
20460
  }
20452
20461
  return Math.sign(t) * v;
20453
20462
  }
20463
+ var FAR_FADE = [1, 1, 0.985, 0.95, 0.91, 0.85, 0.8, 0.745, 0.69, 0.63, 0.56, 0.5, 0.43, 0.35, 0.28, 0.22, 0.16, 0.11, 0.065, 0.03, 0];
20464
+ function fadeAt(d, bilinear) {
20465
+ if (d >= 1) {
20466
+ return 0;
20467
+ }
20468
+ if (bilinear) {
20469
+ return 1 - Math.max(0, d);
20470
+ }
20471
+ const x = Math.max(0, d) * 20;
20472
+ const i = Math.floor(x);
20473
+ return FAR_FADE[i] + (FAR_FADE[i + 1] - FAR_FADE[i]) * (x - i);
20474
+ }
20475
+ function nearSourceExtent(deviceLen, srcLen) {
20476
+ const d = Math.ceil(deviceLen - 1e-6) - srcLen;
20477
+ return d >= -1 && d <= 1;
20478
+ }
20454
20479
  var BICUBIC_A = -0.5;
20455
20480
  var HQ_BICUBIC_A = -1;
20456
20481
  function axisFilter(kernel, scale, copy) {
@@ -20555,13 +20580,39 @@ function mirroredOrigin(o) {
20555
20580
  return f === 0 ? o : Math.floor(o) + 1 - f;
20556
20581
  }
20557
20582
  function resampleImage(rgba, width, height, spec, surface) {
20583
+ if (spec.rightHalo && spec.rightHalo.length === height * 4) {
20584
+ const grown = new Uint8ClampedArray((width + 1) * height * 4);
20585
+ for (let y = 0; y < height; y++) {
20586
+ grown.set(rgba.subarray(y * width * 4, (y + 1) * width * 4), y * (width + 1) * 4);
20587
+ grown.set(spec.rightHalo.subarray(y * 4, y * 4 + 4), (y * (width + 1) + width) * 4);
20588
+ }
20589
+ return resampleImage(grown, width + 1, height, { ...spec, rightHalo: void 0 }, surface);
20590
+ }
20558
20591
  if (spec.kernel === "nearest" && !spec.wrap) {
20559
20592
  return resampleNearest(rgba, width, height, spec, surface);
20560
20593
  }
20561
20594
  let m = snapToDeviceGrid(spec);
20562
- const kernel = spec.kernel;
20595
+ let kernel = spec.kernel;
20563
20596
  const hq = kernel === "hq-bilinear" || kernel === "hq-bicubic";
20564
20597
  const axisAligned = m[1] === 0 && m[2] === 0;
20598
+ let farFade = false;
20599
+ let shiftX = 0;
20600
+ let shiftY = 0;
20601
+ if (hq && !axisAligned) {
20602
+ const extentU = Math.hypot(m[0], m[1]) * spec.srcW;
20603
+ const extentV = Math.hypot(m[2], m[3]) * spec.srcH;
20604
+ if (nearSourceExtent(extentU, spec.srcW) || nearSourceExtent(extentV, spec.srcH)) {
20605
+ kernel = kernel === "hq-bicubic" ? "bicubic" : "bilinear";
20606
+ } else {
20607
+ farFade = true;
20608
+ if (spec.halfPixelOffset) {
20609
+ const lu = Math.hypot(m[0], m[1]);
20610
+ const lv = Math.hypot(m[2], m[3]);
20611
+ shiftX = 0.5 * m[0] / lu + 0.5 * m[2] / lv;
20612
+ shiftY = 0.5 * m[1] / lu + 0.5 * m[3] / lv;
20613
+ }
20614
+ }
20615
+ }
20565
20616
  if (hq && axisAligned) {
20566
20617
  const ox = m[0] * spec.srcX + m[4];
20567
20618
  m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
@@ -20616,6 +20667,8 @@ function resampleImage(rgba, width, height, spec, surface) {
20616
20667
  const vMax = spec.srcY + spec.srcH;
20617
20668
  const wu = [];
20618
20669
  const wv = [];
20670
+ const gradU = Math.hypot(inv2[0], inv2[2]);
20671
+ const gradV = Math.hypot(inv2[1], inv2[3]);
20619
20672
  const c = spec.clampArgb ?? 0;
20620
20673
  const edge = {
20621
20674
  wrap: spec.wrap,
@@ -20627,8 +20680,8 @@ function resampleImage(rgba, width, height, spec, surface) {
20627
20680
  const py = by0 + j + o;
20628
20681
  for (let i = 0; i < w; i++) {
20629
20682
  const px = bx0 + i + o;
20630
- const u = inv2[0] * px + inv2[2] * py + inv2[4];
20631
- const v = inv2[1] * px + inv2[3] * py + inv2[5];
20683
+ const u = inv2[0] * (px - shiftX) + inv2[2] * (py - shiftY) + inv2[4];
20684
+ const v = inv2[1] * (px - shiftX) + inv2[3] * (py - shiftY) + inv2[5];
20632
20685
  const cx = px + COVERAGE_NUDGE_X;
20633
20686
  const cy = py + COVERAGE_NUDGE_Y;
20634
20687
  const eu = inv2[0] * cx + inv2[2] * cy + inv2[4];
@@ -20636,31 +20689,35 @@ function resampleImage(rgba, width, height, spec, surface) {
20636
20689
  if (eu < spec.srcX || ev < spec.srcY || eu >= uMax || ev >= vMax) {
20637
20690
  continue;
20638
20691
  }
20639
- const cu = u;
20640
- const cv = v;
20641
- const iu0 = Math.ceil(cu - fu.radius);
20642
- const iu1 = Math.floor(cu + fu.radius);
20643
- const iv0 = Math.ceil(cv - fv.radius);
20644
- const iv1 = Math.floor(cv + fv.radius);
20645
- wu.length = 0;
20646
- wv.length = 0;
20647
- for (let t = iu0; t <= iu1; t++) {
20648
- wu.push(fu.weight(t, cu));
20649
- }
20650
- for (let t = iv0; t <= iv1; t++) {
20651
- wv.push(fv.weight(t, cv));
20652
- }
20653
- const [r, g, b, a] = blendSeparable(
20654
- rgba,
20655
- width,
20656
- spec.wrap ? { x0: 0, y0: 0, x1: width, y1: height } : { x0: sx0, y0: sy0, x1: sx1, y1: sy1 },
20657
- iu0,
20658
- wu,
20659
- iv0,
20660
- wv,
20661
- kernel === "bicubic",
20662
- edge
20663
- );
20692
+ const box = { x0: 0, y0: 0, x1: width, y1: height };
20693
+ const sampleAt = (cu, cv) => {
20694
+ const iu0 = Math.ceil(cu - fu.radius);
20695
+ const iu1 = Math.floor(cu + fu.radius);
20696
+ const iv0 = Math.ceil(cv - fv.radius);
20697
+ const iv1 = Math.floor(cv + fv.radius);
20698
+ wu.length = 0;
20699
+ wv.length = 0;
20700
+ for (let t = iu0; t <= iu1; t++) {
20701
+ wu.push(fu.weight(t, cu));
20702
+ }
20703
+ for (let t = iv0; t <= iv1; t++) {
20704
+ wv.push(fv.weight(t, cv));
20705
+ }
20706
+ return blendSeparable(rgba, width, box, iu0, wu, iv0, wv, kernel === "bicubic", edge);
20707
+ };
20708
+ let [r, g, b, a] = sampleAt(u, v);
20709
+ if (farFade && !spec.wrap && a > 0) {
20710
+ const du = (uMax - u) / gradU;
20711
+ const dv = (vMax - v) / gradV;
20712
+ const k = 1 - (du < 1 ? fadeAt(du, kernel === "hq-bilinear") * (sampleAt(uMax, v)[3] / a) : 0) - (dv < 1 ? fadeAt(dv, kernel === "hq-bilinear") * (sampleAt(u, vMax)[3] / a) : 0);
20713
+ if (k < 1) {
20714
+ const f = Math.max(0, k);
20715
+ r *= f;
20716
+ g *= f;
20717
+ b *= f;
20718
+ a *= f;
20719
+ }
20720
+ }
20664
20721
  if (a <= 0) {
20665
20722
  continue;
20666
20723
  }
@@ -23487,7 +23544,8 @@ function effectedDraw(img, bitmap, effect, draw, source) {
23487
23544
  srcY,
23488
23545
  srcW,
23489
23546
  srcH,
23490
- toDevice: mulMatrix(draw.resample.toDevice, shift)
23547
+ toDevice: mulMatrix(draw.resample.toDevice, shift),
23548
+ rightHalo: region.haloRight
23491
23549
  }
23492
23550
  }
23493
23551
  };
@@ -31426,6 +31484,15 @@ function illuminantCube(index) {
31426
31484
  }
31427
31485
  return cube;
31428
31486
  }
31487
+ var ILLUMINANT_MATRICES = {
31488
+ 1: [[1.64737, -0.59174, -0.05494], [0.02963, 0.96126, 881e-5], [0.2911, 0.40189, 0.30769]],
31489
+ 2: [[1.22319, -0.17765, -0.04515], [275e-5, 0.99054, 645e-5], [0.05514, 0.12795, 0.81816]],
31490
+ 3: [[1.02833, -0.01775, -0.01086], [861e-5, 0.98431, 728e-5], [-0.01616, -0.0448, 1.05995]],
31491
+ 4: [[1.17271, -0.14059, -0.03174], [-474e-5, 1.00266, 183e-5], [0.05783, 0.14663, 0.79683]],
31492
+ 5: [[1.10431, -0.08327, -0.02067], [-336e-5, 1.0025, 67e-5], [0.03344, 0.09072, 0.87702]],
31493
+ 7: [[0.92515, 0.05628, 0.01822], [318e-5, 0.9967, 34e-5], [-0.02086, -0.06817, 1.08783]],
31494
+ 8: [[1.31275, -0.26259, -0.04977], [-244e-5, 0.99695, 524e-5], [0.10854, 0.23443, 0.65827]]
31495
+ };
31429
31496
  function hasIlluminant(ca) {
31430
31497
  return illuminantCube(ca.illuminant) !== null;
31431
31498
  }
@@ -31496,9 +31563,9 @@ var BRIGHTNESS_STEP = 0.95625;
31496
31563
  var COLORFULNESS_SCALE = 1 / 100;
31497
31564
  var TINT_RADIANS = -Math.PI / 3;
31498
31565
  var RGB_TO_XYZ = [
31499
- [0.4124, 0.3576, 0.1805],
31500
- [0.2126, 0.7152, 0.0722],
31501
- [0.0193, 0.1192, 0.9505]
31566
+ [0.4123908, 0.3575843, 0.1804808],
31567
+ [0.212639, 0.7151687, 0.0721923],
31568
+ [0.0193308, 0.1191948, 0.9505322]
31502
31569
  ];
31503
31570
  var XYZ_TO_RGB = invert3(RGB_TO_XYZ);
31504
31571
  var WHITE = RGB_TO_XYZ.map((row2) => row2[0] + row2[1] + row2[2]);
@@ -31526,13 +31593,13 @@ function adjustChroma(r, g, b, scale, angle) {
31526
31593
  const z = RGB_TO_XYZ[2][0] * r + RGB_TO_XYZ[2][1] * g + RGB_TO_XYZ[2][2] * b;
31527
31594
  const d = x + 15 * y + 3 * z;
31528
31595
  if (d <= 1e-9 || y <= 1e-9) {
31529
- return [r, g, b];
31596
+ return [clamp255(r), clamp255(g), clamp255(b)];
31530
31597
  }
31531
31598
  const du = 4 * x / d - WHITE_U;
31532
31599
  const dv = 9 * y / d - WHITE_V;
31533
31600
  const cos = Math.cos(angle) * scale;
31534
31601
  const sin = Math.sin(angle) * scale;
31535
- const u = WHITE_U + du * cos - dv * sin;
31602
+ const u = Math.max(0, WHITE_U + du * cos - dv * sin);
31536
31603
  const v = Math.max(1e-6, WHITE_V + du * sin + dv * cos);
31537
31604
  const x2 = y * 9 * u / (4 * v);
31538
31605
  const z2 = y * (12 - 3 * u - 20 * v) / (4 * v);
@@ -31551,6 +31618,7 @@ function adjustChroma(r, g, b, scale, angle) {
31551
31618
  }
31552
31619
  function colorAdjustmentMapper(ca) {
31553
31620
  const illuminant = illuminantCube(ca.illuminant);
31621
+ const matrix = ILLUMINANT_MATRICES[ca.illuminant];
31554
31622
  const gammas = [ca.redGamma / 1e4, ca.greenGamma / 1e4, ca.blueGamma / 1e4];
31555
31623
  const black = ca.referenceBlack / 1e4 * 255;
31556
31624
  const span = Math.max(1e-6, ca.referenceWhite / 1e4 * 255 - black);
@@ -31579,16 +31647,17 @@ function colorAdjustmentMapper(ca) {
31579
31647
  }
31580
31648
  return (rgb2) => {
31581
31649
  let c = [rgb2 >> 16 & 255, rgb2 >> 8 & 255, rgb2 & 255];
31582
- if (illuminant) {
31583
- const mapped = lookupIlluminant(illuminant, c[0] / 255, c[1] / 255, c[2] / 255);
31584
- c = [mapped[0] * 255, mapped[1] * 255, mapped[2] * 255];
31585
- }
31586
31650
  if (chroma) {
31587
- if (!illuminant) {
31588
- c = c.map(exactPaletteLevel);
31651
+ c = c.map(exactPaletteLevel);
31652
+ if (matrix) {
31653
+ const [r, g, b] = c;
31654
+ c = matrix.map((row2) => row2[0] * r + row2[1] * g + row2[2] * b);
31589
31655
  }
31590
- c = adjustChroma(clamp255(c[0]), clamp255(c[1]), clamp255(c[2]), scale, angle);
31656
+ c = adjustChroma(c[0], c[1], c[2], scale, angle);
31591
31657
  c = c.map(roundHalfUp);
31658
+ } else if (illuminant) {
31659
+ const mapped = lookupIlluminant(illuminant, c[0] / 255, c[1] / 255, c[2] / 255);
31660
+ c = [mapped[0] * 255, mapped[1] * 255, mapped[2] * 255];
31592
31661
  }
31593
31662
  return curve(c[0], 0) << 16 | curve(c[1], 1) << 8 | curve(c[2], 2);
31594
31663
  };
@@ -31942,20 +32011,6 @@ function halftoneDespeckle(px, w, h) {
31942
32011
  }
31943
32012
  }
31944
32013
  }
31945
- function halftoneSharpen(px, w, h) {
31946
- const src = px.slice();
31947
- const at = (x, y, c) => src[(Math.max(0, Math.min(h - 1, y)) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
31948
- for (let y = 0; y < h; y++) {
31949
- for (let x = 0; x < w; x++) {
31950
- for (let c = 0; c < 3; c++) {
31951
- const v = at(x, y, c);
31952
- const sum = at(x - 1, y, c) + at(x + 1, y, c) + at(x, y - 1, c) + at(x, y + 1, c);
31953
- const out = v + Math.floor((4 * v - sum) / 8);
31954
- px[(y * w + x) * 3 + c] = out < 0 ? 0 : out > 255 ? 255 : out;
31955
- }
31956
- }
31957
- }
31958
- }
31959
32014
  function halftonePairDespeckle(px, w, h, rows) {
31960
32015
  const n = rows ? w : h;
31961
32016
  const at = (k, side) => (rows ? side * w + k : k * w + side) * 3;
@@ -31978,6 +32033,46 @@ function halftoneKeepLast(px, w, h, rows) {
31978
32033
  }
31979
32034
  return out;
31980
32035
  }
32036
+ function halftoneReduceBoth(rect, sw, sh, dw, dh, flipX, flipY) {
32037
+ const cols = halftoneReduceTaps(sw, dw, flipX);
32038
+ const rows = halftoneReduceTaps(sh, dh, flipY);
32039
+ const wide = new Int32Array(dw * sh * 3);
32040
+ for (let y = 0; y < sh; y++) {
32041
+ for (let x = 0; x < dw; x++) {
32042
+ let total = 0;
32043
+ for (const [, w] of cols[x]) total += w;
32044
+ for (let c = 0; c < 3; c++) {
32045
+ let sum = 0;
32046
+ for (const [xx, w] of cols[x]) sum += rect[(y * sw + xx) * 3 + c] * w;
32047
+ wide[(y * dw + x) * 3 + c] = Math.floor((2 * sum + total) / (2 * total));
32048
+ }
32049
+ }
32050
+ }
32051
+ const avg = new Float64Array(dw * dh * 3);
32052
+ for (let y = 0; y < dh; y++) {
32053
+ let total = 0;
32054
+ for (const [, w] of rows[y]) total += w;
32055
+ for (let x = 0; x < dw; x++) {
32056
+ for (let c = 0; c < 3; c++) {
32057
+ let sum = 0;
32058
+ for (const [yy, w] of rows[y]) sum += wide[(yy * dw + x) * 3 + c] * w;
32059
+ avg[(y * dw + x) * 3 + c] = sum / total;
32060
+ }
32061
+ }
32062
+ }
32063
+ const at = (x, y, c) => avg[(Math.max(0, Math.min(dh - 1, y)) * dw + Math.max(0, Math.min(dw - 1, x))) * 3 + c];
32064
+ const out = new Int32Array(dw * dh * 3);
32065
+ for (let y = 0; y < dh; y++) {
32066
+ for (let x = 0; x < dw; x++) {
32067
+ for (let c = 0; c < 3; c++) {
32068
+ const v = at(x, y, c);
32069
+ const sum = at(x - 1, y, c) + at(x + 1, y, c) + at(x, y - 1, c) + at(x, y + 1, c);
32070
+ out[(y * dw + x) * 3 + c] = Math.max(0, Math.min(255, Math.floor(v + (4 * v - sum) / 8)));
32071
+ }
32072
+ }
32073
+ }
32074
+ return out;
32075
+ }
31981
32076
  function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSampling = false, directDib = false, dither, curves) {
31982
32077
  const W = Math.max(0, Math.round(Math.abs(dw)));
31983
32078
  const H = Math.max(0, Math.round(Math.abs(dh)));
@@ -32029,11 +32124,18 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
32029
32124
  }
32030
32125
  const reducedEven = W < SW ? SW % 2 === 0 && H % SH === 0 : SH % 2 === 0 && W % SW === 0;
32031
32126
  const ditherAtSource = dithered && (W >= SW && H >= SH || nativeMixed && reducedEven);
32127
+ const extendRow = ditherAtSource && nativeMixed && W < SW && H > SH && !flipY;
32128
+ if (extendRow) {
32129
+ const bigger = new Int32Array((SH + 1) * SW * 3);
32130
+ bigger.set(rect);
32131
+ bigger.copyWithin(SH * SW * 3, (SH - 1) * SW * 3, SH * SW * 3);
32132
+ rect = bigger;
32133
+ }
32032
32134
  if (ditherAtSource) {
32033
32135
  ditherPixels(
32034
32136
  rect,
32035
32137
  SW,
32036
- SH,
32138
+ extendRow ? SH + 1 : SH,
32037
32139
  dither,
32038
32140
  false,
32039
32141
  false,
@@ -32073,7 +32175,10 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
32073
32175
  linear(rows, SH, H, flipY);
32074
32176
  }
32075
32177
  let out = nativeMixed ? new Float64Array(sampleW * sampleH * 3) : new Int32Array(W * H * 3);
32076
- for (let y = 0; y < sampleH; y++) {
32178
+ if (reducing) {
32179
+ out = halftoneReduceBoth(rect, SW, SH, W, H, flipX, flipY);
32180
+ }
32181
+ for (let y = 0; !reducing && y < sampleH; y++) {
32077
32182
  const ys = rows[y];
32078
32183
  for (let x = 0; x < sampleW; x++) {
32079
32184
  const xs = cols[x];
@@ -32098,15 +32203,38 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
32098
32203
  out[o + 2] = round(b);
32099
32204
  }
32100
32205
  }
32101
- if (reducing) {
32102
- halftoneSharpen(out, W, H);
32103
- }
32104
32206
  if (nativeMixed) {
32105
32207
  const reduceHorizontal = W < SW;
32208
+ let extension;
32209
+ if (extendRow) {
32210
+ const reduced = new Float64Array(sampleW * 3);
32211
+ for (let x = 0; x < sampleW; x++) {
32212
+ let total = 0;
32213
+ const sums = [0, 0, 0];
32214
+ for (const [xx, wx] of cols[x]) {
32215
+ total += wx;
32216
+ for (let c = 0; c < 3; c++) sums[c] += rect[(SH * SW + xx) * 3 + c] * wx;
32217
+ }
32218
+ for (let c = 0; c < 3; c++) reduced[x * 3 + c] = sums[c] / total;
32219
+ }
32220
+ extension = reduced;
32221
+ }
32106
32222
  for (const horizontal of [reduceHorizontal, !reduceHorizontal]) {
32107
32223
  const source2 = out;
32108
32224
  out = new Int32Array(source2.length);
32109
- const at = (x, y, c) => source2[(Math.max(0, Math.min(sampleH - 1, y)) * sampleW + Math.max(0, Math.min(sampleW - 1, x))) * 3 + c];
32225
+ const ext = extension;
32226
+ const at = (x, y, c) => y >= sampleH && ext ? ext[Math.max(0, Math.min(sampleW - 1, x)) * 3 + c] : source2[(Math.max(0, Math.min(sampleH - 1, y)) * sampleW + Math.max(0, Math.min(sampleW - 1, x))) * 3 + c];
32227
+ if (horizontal && ext) {
32228
+ const next = new Int32Array(sampleW * 3);
32229
+ for (let x = 0; x < sampleW; x++) {
32230
+ for (let c = 0; c < 3; c++) {
32231
+ const v = ext[x * 3 + c];
32232
+ const sum = at(x - 1, sampleH, c) + at(x + 1, sampleH, c);
32233
+ next[x * 3 + c] = Math.max(0, Math.min(255, Math.floor(v + (2 * v - sum) / 4)));
32234
+ }
32235
+ }
32236
+ extension = next;
32237
+ }
32110
32238
  for (let y = 0; y < sampleH; y++) {
32111
32239
  for (let x = 0; x < sampleW; x++) {
32112
32240
  for (let c = 0; c < 3; c++) {