emf-converter 4.6.7 → 4.6.9

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/browser.js CHANGED
@@ -16485,11 +16485,11 @@ function mirror(p, n) {
16485
16485
  }
16486
16486
  return p;
16487
16487
  }
16488
- function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical = false, edgeWidth = w, edgeHeight = h, verticalRows = Math.ceil(h / w)) {
16488
+ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, verticalRows = Math.ceil(h / w)) {
16489
16489
  const k = blurKernel(radius);
16490
16490
  const taps = (k.length - 1) / 2;
16491
- const horizontalIndex = taps >= edgeWidth ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
16492
- const verticalIndex = taps >= edgeHeight ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
16491
+ const horizontalIndex = taps >= w ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
16492
+ const verticalIndex = taps >= h ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
16493
16493
  const out = new Float64Array(w * h * 4);
16494
16494
  for (let y = 0; y < h; y++) {
16495
16495
  const row2 = y * w * 4;
@@ -16500,22 +16500,22 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical
16500
16500
  let s3 = 0;
16501
16501
  for (let j = -taps; j <= taps; j++) {
16502
16502
  const p = row2 + horizontalIndex(x + j) * 4;
16503
- const kw = k[j + taps];
16504
- s0 += kw * src[p];
16505
- s1 += kw * src[p + 1];
16506
- s2 += kw * src[p + 2];
16507
- s3 += kw * src[p + 3];
16503
+ const kw = k[j + taps] * 256;
16504
+ s0 += Math.round(kw * src[p]);
16505
+ s1 += Math.round(kw * src[p + 1]);
16506
+ s2 += Math.round(kw * src[p + 2]);
16507
+ s3 += Math.round(kw * src[p + 3]);
16508
16508
  }
16509
16509
  const o = row2 + x * 4;
16510
- out[o] = Math.round(s0);
16511
- out[o + 1] = Math.round(s1);
16512
- out[o + 2] = Math.round(s2);
16513
- out[o + 3] = Math.round(s3);
16510
+ out[o] = Math.floor((s0 + 128) / 256);
16511
+ out[o + 1] = Math.floor((s1 + 128) / 256);
16512
+ out[o + 2] = Math.floor((s2 + 128) / 256);
16513
+ out[o + 3] = Math.floor((s3 + 128) / 256);
16514
16514
  }
16515
16515
  }
16516
16516
  if (taps > 0 && vRow >= 0 && vRow < h) {
16517
16517
  const horizontal = out.slice();
16518
- const endRow = fullVertical ? h : Math.min(h, vRow + verticalRows);
16518
+ const endRow = Math.min(h, vRow + verticalRows);
16519
16519
  for (let row2 = vRow; row2 < endRow; row2++) {
16520
16520
  const col = new Float64Array(w * 4);
16521
16521
  for (let j = -taps; j <= taps; j++) {
@@ -16525,7 +16525,7 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical
16525
16525
  }
16526
16526
  const base = verticalIndex(yy) * w * 4;
16527
16527
  for (let i = 0; i < w * 4; i++) {
16528
- col[i] += k[j + taps] * horizontal[base + i];
16528
+ col[i] += Math.round(k[j + taps] * horizontal[base + i] * 256) / 256;
16529
16529
  }
16530
16530
  }
16531
16531
  out.set(col, row2 * w * 4);
@@ -16536,48 +16536,56 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical
16536
16536
  function blurReduction(radius) {
16537
16537
  return radius < 20 ? 1 : radius < 40 ? 2 : radius <= 80 ? 4 : radius < 160 ? 8 : 16;
16538
16538
  }
16539
- function effectBlur(src, width, height, radius, expanded = false) {
16540
- const factor = blurReduction(radius);
16541
- if (factor === 1 || (width < 4 || height < 4) && (width % factor !== 0 || height % factor !== 0)) {
16542
- return gdipBlur(src, width, height, radius);
16543
- }
16544
- const w = Math.ceil(width / factor);
16545
- const h = Math.ceil(height / factor);
16546
- const reduced = new Uint8ClampedArray(w * h * 4);
16547
- for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
16548
- const x1 = Math.min(width, (x + 1) * factor), y1 = Math.min(height, (y + 1) * factor);
16549
- const count = (x1 - x * factor) * (y1 - y * factor);
16550
- for (let c = 0; c < 4; c++) {
16539
+ function blurAxis(length, lanes, factor, k, edgeLength, get, put, span = { start: 0, size: length, pad: 0 }) {
16540
+ const inner = Math.ceil(span.size / factor);
16541
+ const n = inner + 2 * span.pad;
16542
+ const taps = (k.length - 1) / 2;
16543
+ const index = taps >= edgeLength ? (i) => clamp(i, 0, n - 1) : (i) => mirror(i, n);
16544
+ const reduced = new Float64Array(n);
16545
+ const filtered = new Float64Array(n);
16546
+ const k256 = k.map((w) => w * 256);
16547
+ for (let lane = 0; lane < lanes; lane++) for (let c = 0; c < 4; c++) {
16548
+ for (let b = span.pad; b < span.pad + inner; b++) {
16549
+ const from = span.start + (b - span.pad) * factor;
16550
+ const end = Math.min(span.start + span.size, from + factor);
16551
16551
  let sum = 0;
16552
- for (let yy = y * factor; yy < y1; yy++) for (let xx = x * factor; xx < x1; xx++) sum += src[(yy * width + xx) * 4 + c];
16553
- reduced[(y * w + x) * 4 + c] = Math.floor(sum / count);
16552
+ for (let i = from; i < end; i++) sum += get(i, lane, c);
16553
+ reduced[b] = Math.floor(sum / (end - from));
16554
16554
  }
16555
- }
16556
- const filtered = gdipBlur(reduced, w, h, radius / factor, 0, false, true, Math.floor(width / factor), Math.floor(height / factor));
16557
- if (!expanded) {
16558
- const out2 = new Float64Array(src.length);
16559
- for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
16560
- const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
16561
- const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
16562
- const x1 = Math.min(w - 1, ix + 1), y1 = Math.min(h - 1, iy + 1);
16563
- for (let c = 0; c < 4; c++) {
16564
- const at = (xx, yy) => filtered[(yy * w + xx) * 4 + c];
16565
- const top = Math.floor((1 - fx) * at(ix, iy) + fx * at(x1, iy));
16566
- const bottom = Math.floor((1 - fx) * at(ix, y1) + fx * at(x1, y1));
16567
- out2[(y * width + x) * 4 + c] = Math.floor((1 - fy) * top + fy * bottom);
16555
+ for (let b = 0; b < n; b++) {
16556
+ let sum = 0;
16557
+ if (b >= taps && b + taps < n) {
16558
+ for (let j = 0; j < k256.length; j++) sum += Math.round(k256[j] * reduced[b - taps + j]);
16559
+ } else {
16560
+ for (let j = 0; j < k256.length; j++) sum += Math.round(k256[j] * reduced[index(b - taps + j)]);
16568
16561
  }
16562
+ filtered[b] = Math.floor((sum + 128) / 256);
16563
+ }
16564
+ for (let i = 0; i < length; i++) {
16565
+ const p = (i - span.start + 0.5) / factor - 0.5 + span.pad;
16566
+ const a = clamp(Math.floor(p), 0, Math.max(0, n - 2));
16567
+ const t = p - a;
16568
+ put(i, lane, c, clamp(Math.floor((1 - t) * filtered[a] + t * filtered[Math.min(n - 1, a + 1)] + 1e-9), 0, 255));
16569
16569
  }
16570
- return out2;
16571
16570
  }
16572
- for (let i = 0; i < filtered.length; i++) filtered[i] = Math.round(filtered[i]);
16573
- const out = new Float64Array(src.length);
16574
- for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
16575
- const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
16576
- const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
16577
- const a = (iy * w + ix) * 4, b = (iy * w + Math.min(w - 1, ix + 1)) * 4;
16578
- const d = (Math.min(h - 1, iy + 1) * w + ix) * 4, e = (Math.min(h - 1, iy + 1) * w + Math.min(w - 1, ix + 1)) * 4;
16579
- for (let c = 0; c < 4; c++) out[(y * width + x) * 4 + c] = Math.round((1 - fy) * ((1 - fx) * filtered[a + c] + fx * filtered[b + c]) + fy * ((1 - fx) * filtered[d + c] + fx * filtered[e + c]));
16571
+ }
16572
+ function effectBlur(src, width, height, radius, region) {
16573
+ const factor = blurReduction(radius);
16574
+ if (factor === 1) {
16575
+ return gdipBlur(src, width, height, radius);
16580
16576
  }
16577
+ const k = blurKernel(radius / factor);
16578
+ const pad = region ? Math.ceil(Math.ceil(radius) / factor) : 0;
16579
+ const spanX = region ? { start: region.x, size: region.w, pad } : void 0;
16580
+ const spanY = region ? { start: region.y, size: region.h, pad } : void 0;
16581
+ const rows = new Uint8Array(src.length);
16582
+ blurAxis(width, height, factor, k, Math.floor(width / factor), (i, lane, c) => src[(lane * width + i) * 4 + c], (i, lane, c, v) => {
16583
+ rows[(lane * width + i) * 4 + c] = v;
16584
+ }, spanX);
16585
+ const out = new Float64Array(src.length);
16586
+ blurAxis(height, width, factor, k, Math.floor(height / factor), (i, lane, c) => rows[(i * width + lane) * 4 + c], (i, lane, c, v) => {
16587
+ out[(i * width + lane) * 4 + c] = v;
16588
+ }, spanY);
16581
16589
  return out;
16582
16590
  }
16583
16591
  function applyBlur(src, w, h, radius) {
@@ -16663,7 +16671,7 @@ function expandedBlur(rgba, width, height, radius, x0, y0, x1, y1, cropped) {
16663
16671
  const gy1 = Math.min(height, y1 + r);
16664
16672
  copyBlock(rgba, width, gx0, gy0, gx1 - gx0, gy1 - gy0, buf, bw, gx0 - (x0 - r), gy0 - (y0 - r));
16665
16673
  }
16666
- const blurred = blurReduction(radius) > 1 ? effectBlur(buf, bw, bh, radius, true) : gdipBlur(buf, bw, bh, radius, cropped ? r : 0, cropped, false, bw, bh, Math.ceil((y1 - y0) / (x1 - x0)));
16674
+ const blurred = blurReduction(radius) > 1 ? effectBlur(buf, bw, bh, radius, cropped ? { x: r, y: r, w: x1 - x0, h: y1 - y0 } : void 0) : gdipBlur(buf, bw, bh, radius, cropped ? r : 0, cropped, Math.ceil((y1 - y0) / (x1 - x0)));
16667
16675
  const w = x1 - x0;
16668
16676
  const out = new Uint8ClampedArray(w * (y1 - y0) * 4);
16669
16677
  for (let y = 0; y < y1 - y0; y++) {
@@ -31460,28 +31468,92 @@ function halftoneAxis(start, srcLen, dstLen, reverse) {
31460
31468
  if (reverse) taps.reverse();
31461
31469
  return taps;
31462
31470
  }
31463
- var SOFT_TENT_SIGMA = 0.25;
31464
- var SOFT_TENT_STEPS = 31;
31465
- var SOFT_TENT_SPAN = 3;
31466
- var softTentCache = /* @__PURE__ */ new Map();
31467
- function softTent(d) {
31468
- const key = Math.round(d * 1024);
31469
- const cached = softTentCache.get(key);
31470
- if (cached !== void 0) {
31471
- return cached;
31471
+ function halftoneReduceTaps(srcLen, dstLen, reverse) {
31472
+ if (dstLen >= srcLen) return halftoneAxis(0, srcLen, dstLen, reverse);
31473
+ const taps = [];
31474
+ for (let i = 0; i < dstLen; i++) {
31475
+ const from = i * srcLen;
31476
+ const to = (i + 1) * srcLen;
31477
+ const run = [];
31478
+ let rest = 0;
31479
+ for (let k = Math.floor(from / dstLen); k * dstLen < to; k++) {
31480
+ const overlap = Math.min(to, (k + 1) * dstLen) - Math.max(from, k * dstLen);
31481
+ if (overlap <= 0) continue;
31482
+ const w = Math.ceil(overlap * FIX / srcLen);
31483
+ run.push([k, w]);
31484
+ if (run.length > 1) rest += w;
31485
+ }
31486
+ if (run.length > 1) run[0][1] = FIX - rest;
31487
+ taps.push(run);
31472
31488
  }
31473
- let sum = 0;
31489
+ if (reverse) taps.reverse();
31490
+ return taps;
31491
+ }
31492
+ var ENLARGE_KERNEL = [
31493
+ 0.7598,
31494
+ 0.7276,
31495
+ 0.6829,
31496
+ 0.6528,
31497
+ 0.6106,
31498
+ 0.5745,
31499
+ 0.5362,
31500
+ 0.4955,
31501
+ 0.457,
31502
+ 0.4121,
31503
+ 0.3762,
31504
+ 0.3233,
31505
+ 0.2741,
31506
+ 0.226,
31507
+ 0.1822,
31508
+ 0.1412,
31509
+ 0.1021,
31510
+ 0.0685,
31511
+ 0.0382,
31512
+ 0.0138,
31513
+ 0
31514
+ ];
31515
+ var ENLARGE_BOX = 0.2429;
31516
+ var ENLARGE_STEP = 0.05;
31517
+ function enlargeKernel(u) {
31518
+ const edge = u / ENLARGE_STEP;
31519
+ const i = Math.floor(edge);
31520
+ const smooth = i >= ENLARGE_KERNEL.length - 1 ? 0 : ENLARGE_KERNEL[i] + (ENLARGE_KERNEL[i + 1] - ENLARGE_KERNEL[i]) * (edge - i);
31521
+ return smooth + ENLARGE_BOX * (Math.abs(u - 0.5) < 1e-9 ? 0.5 : u < 0.5 ? 1 : 0);
31522
+ }
31523
+ function halftoneEnlargeTaps(src, dst) {
31524
+ const ratio = dst / src;
31525
+ const reach = Math.ceil((ENLARGE_KERNEL.length - 1) * ENLARGE_STEP * ratio);
31526
+ const fir = [];
31474
31527
  let total = 0;
31475
- const half = (SOFT_TENT_STEPS - 1) / 2;
31476
- for (let i = -half; i <= half; i++) {
31477
- const x = i / half * SOFT_TENT_SPAN * SOFT_TENT_SIGMA;
31478
- const g = Math.exp(-(x * x) / (2 * SOFT_TENT_SIGMA * SOFT_TENT_SIGMA));
31479
- total += g;
31480
- sum += g * Math.max(0, 1 - Math.abs(key / 1024 + x));
31528
+ for (let k = 0; k <= reach; k++) {
31529
+ const w = enlargeKernel(k / ratio);
31530
+ fir.push(w);
31531
+ total += k === 0 ? w : 2 * w;
31532
+ }
31533
+ const cover = [];
31534
+ for (let x = 0; x < dst; x++) {
31535
+ const lo = x / ratio;
31536
+ const hi = (x + 1) / ratio;
31537
+ const run = [];
31538
+ for (let j = Math.max(0, Math.floor(lo)); j < Math.min(src, hi); j++) {
31539
+ const overlap = Math.min(hi, j + 1) - Math.max(lo, j);
31540
+ if (overlap > 0) run.push([j, overlap * ratio]);
31541
+ }
31542
+ cover.push(run);
31543
+ }
31544
+ const taps = [];
31545
+ for (let x = 0; x < dst; x++) {
31546
+ const weights = /* @__PURE__ */ new Map();
31547
+ for (let k = -reach; k <= reach; k++) {
31548
+ const w = fir[Math.abs(k)] / total;
31549
+ if (w === 0) continue;
31550
+ for (const [j, v] of cover[Math.max(0, Math.min(dst - 1, x + k))]) {
31551
+ weights.set(j, (weights.get(j) ?? 0) + w * v);
31552
+ }
31553
+ }
31554
+ taps.push([...weights.entries()]);
31481
31555
  }
31482
- const value = sum / total;
31483
- softTentCache.set(key, value);
31484
- return value;
31556
+ return taps;
31485
31557
  }
31486
31558
  function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
31487
31559
  for (let y = 0; y < h; y++) {
@@ -31623,7 +31695,7 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
31623
31695
  const mixed = W > SW && H < SH || W < SW && H > SH;
31624
31696
  const dithered = !!dither && !!adjust && !adjustAfterSampling;
31625
31697
  const nearestMixed = mixed && (!adjust || adjustAfterSampling || dithered) && (W < SW && W * 2 > SW || H < SH && H * 2 > SH);
31626
- const nativeMixed = mixed && (!adjust || adjustAfterSampling || dithered) && Math.min(SW, W) >= 2 && Math.min(SH, H) >= 2 && (W > SW && H * 2 <= SH || H > SH && W * 2 <= SW);
31698
+ const nativeMixed = mixed && (!adjust || adjustAfterSampling || dithered) && (W > SW && H * 2 <= SH || H > SH && W * 2 <= SW);
31627
31699
  if ((enlarging || nearestMixed) && !directDib) {
31628
31700
  halftoneDespeckle(rect, SW, SH);
31629
31701
  }
@@ -31637,8 +31709,9 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
31637
31709
  }
31638
31710
  const sampleW = nativeMixed ? Math.min(SW, W) : W;
31639
31711
  const sampleH = nativeMixed ? Math.min(SH, H) : H;
31640
- const cols = halftoneAxis(0, SW, sampleW, flipX);
31641
- const rows = halftoneAxis(0, SH, sampleH, flipY);
31712
+ const axis = nativeMixed ? (n, d, r) => halftoneReduceTaps(n, d, r) : (n, d, r) => halftoneAxis(0, n, d, r);
31713
+ const cols = axis(SW, sampleW, flipX);
31714
+ const rows = axis(SH, sampleH, flipY);
31642
31715
  if (nearestMixed) {
31643
31716
  const nearest = (taps, src2, dst, reverse) => {
31644
31717
  for (let i = 0; i < dst; i++) {
@@ -31710,29 +31783,15 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
31710
31783
  const source = out;
31711
31784
  out = new Int32Array(W * H * 3);
31712
31785
  const axisTaps = (src2, dst) => {
31713
- const r = [];
31714
- for (let i = 0; i < dst; i++) {
31715
- if (src2 === dst) {
31716
- r.push([[i, 1]]);
31717
- continue;
31718
- }
31719
- const raw = (i + 0.5) * src2 / dst - 0.5;
31720
- const pos = Math.max(0, Math.min(src2 - 1, raw));
31721
- const i0 = Math.floor(pos);
31722
- if (dst === 2 * src2) {
31723
- r.push([[i0, 1 - (pos - i0)], [Math.min(src2 - 1, i0 + 1), pos - i0]]);
31724
- continue;
31725
- }
31726
- const taps = [];
31727
- let total = 0;
31728
- for (let k = i0 - 2; k <= i0 + 3; k++) {
31729
- const w = softTent(raw - k);
31730
- taps.push([Math.max(0, Math.min(src2 - 1, k)), w]);
31731
- total += w;
31732
- }
31733
- r.push(taps.map(([k, w]) => [k, w / total]));
31786
+ if (src2 === dst) return Array.from({ length: dst }, (_, i) => [[i, 1]]);
31787
+ if (dst === 2 * src2) {
31788
+ return Array.from({ length: dst }, (_, i) => {
31789
+ const pos = Math.max(0, Math.min(src2 - 1, (i + 0.5) * src2 / dst - 0.5));
31790
+ const i0 = Math.floor(pos);
31791
+ return [[i0, 1 - (pos - i0)], [Math.min(src2 - 1, i0 + 1), pos - i0]];
31792
+ });
31734
31793
  }
31735
- return r;
31794
+ return halftoneEnlargeTaps(src2, dst);
31736
31795
  };
31737
31796
  const xt = axisTaps(sampleW, W), yt = axisTaps(sampleH, H);
31738
31797
  for (let y = 0; y < H; y++) {
@@ -31740,7 +31799,7 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
31740
31799
  for (let c = 0; c < 3; c++) {
31741
31800
  let v = 0;
31742
31801
  for (const [yy, wy] of yt[y]) for (const [xx, wx] of xt[x]) v += source[(yy * sampleW + xx) * 3 + c] * wy * wx;
31743
- out[(y * W + x) * 3 + c] = Math.max(0, Math.min(255, Math.floor(v + 0.5)));
31802
+ out[(y * W + x) * 3 + c] = Math.max(0, Math.min(255, Math.floor(v + 0.5 + 1e-7)));
31744
31803
  }
31745
31804
  }
31746
31805
  }