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