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