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