emf-converter 4.6.9 → 4.7.0

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
@@ -31568,82 +31568,64 @@ function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
31568
31568
  }
31569
31569
  }
31570
31570
  }
31571
- var SPECKLE_OVERSHOOT = 4;
31572
31571
  function halftoneDespeckle(px, w, h) {
31572
+ if (w < 2 || h < 2) {
31573
+ return;
31574
+ }
31573
31575
  const src = px.slice();
31574
- const at = (x, y, c) => src[(y * w + x) * 3 + c];
31575
- const over = (v) => v < -SPECKLE_OVERSHOOT * 4 || v > (255 + SPECKLE_OVERSHOOT) * 4;
31576
- const loneX = w > 2 && w % 2 === 1 ? w - 1 : -1;
31577
- const loneY = h > 2 && h % 2 === 1 ? h - 1 : -1;
31578
- const mirror2 = (i, n, d) => {
31579
- const j = i + d;
31580
- return j < 0 || j >= n ? i - d : j;
31576
+ const index = (x, y) => {
31577
+ const mx = x < 0 ? -x : x >= w ? 2 * (w - 1) - x : x;
31578
+ const my = y < 0 ? -y : y >= h ? 2 * (h - 1) - y : y;
31579
+ return (Math.max(0, Math.min(h - 1, my)) * w + Math.max(0, Math.min(w - 1, mx))) * 3;
31581
31580
  };
31582
- const vBlur = (x, y, c) => at(x, mirror2(y, h, -1), c) + 2 * at(x, y, c) + at(x, mirror2(y, h, 1), c) + 2 >> 2;
31583
- const hBlur = (x, y, c) => at(mirror2(x, w, -1), y, c) + 2 * at(x, y, c) + at(mirror2(x, w, 1), y, c) + 2 >> 2;
31584
- const differs = (x0, y0, x1, y1) => at(x0, y0, 0) !== at(x1, y1, 0) || at(x0, y0, 1) !== at(x1, y1, 1) || at(x0, y0, 2) !== at(x1, y1, 2);
31585
- const loneColumn = (y) => loneX > 0 && differs(loneX, y, loneX - 1, y);
31586
- const loneRow = (x) => loneY > 0 && differs(x, loneY, x, loneY - 1);
31587
- const loneColumnValue = (y, c) => y === loneY && loneRow(loneX) ? at(loneX, y - 1, c) + 3 * at(loneX, y, c) + 2 >> 2 : vBlur(loneX, y, c);
31588
- const loneRowValue = (x, c) => x === loneX && loneColumn(loneY) ? at(x - 1, loneY, c) + 3 * at(x, loneY, c) + 2 >> 2 : hBlur(x, loneY, c);
31589
- const speckled = (x, y) => {
31590
- const up = mirror2(y, h, -1);
31591
- const down = mirror2(y, h, 1);
31592
- const left = mirror2(x, w, -1);
31593
- const right = mirror2(x, w, 1);
31594
- let hClip = 0;
31595
- let vClip = 0;
31596
- let alternating = 0;
31597
- for (let c = 0; c < 3; c++) {
31598
- const v = at(x, y, c);
31599
- const axial = Math.max(
31600
- Math.abs(v - at(left, y, c)),
31601
- Math.abs(v - at(right, y, c)),
31602
- Math.abs(v - at(x, up, c)),
31603
- Math.abs(v - at(x, down, c))
31604
- );
31605
- const diagonal = Math.min(
31606
- Math.abs(v - at(left, up, c)),
31607
- Math.abs(v - at(right, up, c)),
31608
- Math.abs(v - at(left, down, c)),
31609
- Math.abs(v - at(right, down, c))
31610
- );
31611
- if (diagonal < axial) alternating++;
31612
- if (over(6 * v - at(left, y, c) - at(right, y, c))) {
31613
- hClip++;
31614
- }
31615
- if (over(6 * v - at(x, up, c) - at(x, down, c))) {
31616
- vClip++;
31581
+ const same = (i, j) => src[i] === src[j] && src[i + 1] === src[j + 1] && src[i + 2] === src[j + 2];
31582
+ const stride = w + 1;
31583
+ const flags = new Uint8Array(stride * (h + 1));
31584
+ for (let y = -1; y < h; y++) {
31585
+ for (let x = -1; x < w; x++) {
31586
+ const a = index(x, y);
31587
+ const b = index(x + 1, y);
31588
+ const c = index(x, y + 1);
31589
+ const d = index(x + 1, y + 1);
31590
+ flags[(y + 1) * stride + x + 1] = same(a, d) && same(b, c) && !same(a, b) ? 1 : 0;
31591
+ }
31592
+ }
31593
+ const checker = (x, y) => flags[(y + 1) * stride + x + 1] === 1;
31594
+ for (let y = 0; y < h - 1; y++) {
31595
+ for (let x = 0; x < w - 1; x++) {
31596
+ if (!checker(x, y)) {
31597
+ continue;
31617
31598
  }
31618
- }
31619
- return hClip >= 2 && vClip >= 2 && alternating >= 2;
31620
- };
31621
- for (let y = 0; y < h; y++) {
31622
- for (let x = 0; x < w; x++) {
31623
- if (!speckled(x, y)) {
31599
+ const ia = index(x, y);
31600
+ const ib = index(x + 1, y);
31601
+ const members = [
31602
+ [x, y, 1, 1, true],
31603
+ [x + 1, y + 1, -1, -1, true],
31604
+ [x + 1, y, -1, 1, false],
31605
+ [x, y + 1, 1, -1, false]
31606
+ ];
31607
+ if (checker(x - 1, y) && checker(x + 1, y) || checker(x, y - 1) && checker(x, y + 1)) {
31608
+ for (const [mx, my] of members) {
31609
+ const o = (my * w + mx) * 3;
31610
+ for (let c = 0; c < 3; c++) {
31611
+ px[o + c] = src[ia + c] + src[ib + c] + 1 >> 1;
31612
+ }
31613
+ }
31624
31614
  continue;
31625
31615
  }
31626
- const left = mirror2(x, w, -1);
31627
- const right = mirror2(x, w, 1);
31628
- const up = mirror2(y, h, -1);
31629
- const down = mirror2(y, h, 1);
31630
- const lonelyColumn = x === loneX && loneColumn(y);
31631
- const lonelyRow = y === loneY && loneRow(x);
31632
- const nearLoneX = x === loneX - 1 && loneX > 0 && loneColumn(y) && !speckled(loneX, y);
31633
- const nearLoneY = y === loneY - 1 && loneY > 0 && loneRow(x) && !speckled(x, loneY);
31634
- const cornerRepeats = lonelyColumn && lonelyRow && (!speckled(x, y - 1) || !speckled(x - 1, y));
31635
- for (let c = 0; c < 3; c++) {
31636
- const v = at(x, y, c);
31637
- let r;
31638
- if (lonelyColumn && lonelyRow) {
31639
- r = cornerRepeats ? at(left, y, c) + 3 * v + 2 >> 2 : hBlur(x, y, c);
31640
- } else {
31641
- let sum = lonelyColumn ? at(x, up, c) + 2 * v + at(x, down, c) : at(left, y, c) + 2 * v + at(right, y, c);
31642
- if (nearLoneX) sum += loneColumnValue(y, c) - at(loneX, y, c);
31643
- if (nearLoneY) sum += loneRowValue(x, c) - at(x, loneY, c);
31644
- r = sum + 2 >> 2;
31616
+ const brighter = 4 * (src[ia] - src[ib]) + 8 * (src[ia + 1] - src[ib + 1]) + (src[ia + 2] - src[ib + 2]);
31617
+ for (const [mx, my, sx, sy, isA] of members) {
31618
+ if (isA ? brighter < 0 : brighter >= 0) {
31619
+ continue;
31620
+ }
31621
+ const o = (my * w + mx) * 3;
31622
+ const t1 = index(mx + sx, my);
31623
+ const t2 = index(mx, my + sy);
31624
+ const t3 = index(mx + 2 * sx, my);
31625
+ const t4 = index(mx, my + 2 * sy);
31626
+ for (let c = 0; c < 3; c++) {
31627
+ px[o + c] = 12 * px[o + c] + src[t1 + c] + src[t2 + c] + src[t3 + c] + src[t4 + c] + 8 >> 4;
31645
31628
  }
31646
- px[(y * w + x) * 3 + c] = r;
31647
31629
  }
31648
31630
  }
31649
31631
  }
package/dist/browser.mjs CHANGED
@@ -31566,82 +31566,64 @@ function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
31566
31566
  }
31567
31567
  }
31568
31568
  }
31569
- var SPECKLE_OVERSHOOT = 4;
31570
31569
  function halftoneDespeckle(px, w, h) {
31570
+ if (w < 2 || h < 2) {
31571
+ return;
31572
+ }
31571
31573
  const src = px.slice();
31572
- const at = (x, y, c) => src[(y * w + x) * 3 + c];
31573
- const over = (v) => v < -SPECKLE_OVERSHOOT * 4 || v > (255 + SPECKLE_OVERSHOOT) * 4;
31574
- const loneX = w > 2 && w % 2 === 1 ? w - 1 : -1;
31575
- const loneY = h > 2 && h % 2 === 1 ? h - 1 : -1;
31576
- const mirror2 = (i, n, d) => {
31577
- const j = i + d;
31578
- return j < 0 || j >= n ? i - d : j;
31574
+ const index = (x, y) => {
31575
+ const mx = x < 0 ? -x : x >= w ? 2 * (w - 1) - x : x;
31576
+ const my = y < 0 ? -y : y >= h ? 2 * (h - 1) - y : y;
31577
+ return (Math.max(0, Math.min(h - 1, my)) * w + Math.max(0, Math.min(w - 1, mx))) * 3;
31579
31578
  };
31580
- const vBlur = (x, y, c) => at(x, mirror2(y, h, -1), c) + 2 * at(x, y, c) + at(x, mirror2(y, h, 1), c) + 2 >> 2;
31581
- const hBlur = (x, y, c) => at(mirror2(x, w, -1), y, c) + 2 * at(x, y, c) + at(mirror2(x, w, 1), y, c) + 2 >> 2;
31582
- const differs = (x0, y0, x1, y1) => at(x0, y0, 0) !== at(x1, y1, 0) || at(x0, y0, 1) !== at(x1, y1, 1) || at(x0, y0, 2) !== at(x1, y1, 2);
31583
- const loneColumn = (y) => loneX > 0 && differs(loneX, y, loneX - 1, y);
31584
- const loneRow = (x) => loneY > 0 && differs(x, loneY, x, loneY - 1);
31585
- const loneColumnValue = (y, c) => y === loneY && loneRow(loneX) ? at(loneX, y - 1, c) + 3 * at(loneX, y, c) + 2 >> 2 : vBlur(loneX, y, c);
31586
- const loneRowValue = (x, c) => x === loneX && loneColumn(loneY) ? at(x - 1, loneY, c) + 3 * at(x, loneY, c) + 2 >> 2 : hBlur(x, loneY, c);
31587
- const speckled = (x, y) => {
31588
- const up = mirror2(y, h, -1);
31589
- const down = mirror2(y, h, 1);
31590
- const left = mirror2(x, w, -1);
31591
- const right = mirror2(x, w, 1);
31592
- let hClip = 0;
31593
- let vClip = 0;
31594
- let alternating = 0;
31595
- for (let c = 0; c < 3; c++) {
31596
- const v = at(x, y, c);
31597
- const axial = Math.max(
31598
- Math.abs(v - at(left, y, c)),
31599
- Math.abs(v - at(right, y, c)),
31600
- Math.abs(v - at(x, up, c)),
31601
- Math.abs(v - at(x, down, c))
31602
- );
31603
- const diagonal = Math.min(
31604
- Math.abs(v - at(left, up, c)),
31605
- Math.abs(v - at(right, up, c)),
31606
- Math.abs(v - at(left, down, c)),
31607
- Math.abs(v - at(right, down, c))
31608
- );
31609
- if (diagonal < axial) alternating++;
31610
- if (over(6 * v - at(left, y, c) - at(right, y, c))) {
31611
- hClip++;
31612
- }
31613
- if (over(6 * v - at(x, up, c) - at(x, down, c))) {
31614
- vClip++;
31579
+ const same = (i, j) => src[i] === src[j] && src[i + 1] === src[j + 1] && src[i + 2] === src[j + 2];
31580
+ const stride = w + 1;
31581
+ const flags = new Uint8Array(stride * (h + 1));
31582
+ for (let y = -1; y < h; y++) {
31583
+ for (let x = -1; x < w; x++) {
31584
+ const a = index(x, y);
31585
+ const b = index(x + 1, y);
31586
+ const c = index(x, y + 1);
31587
+ const d = index(x + 1, y + 1);
31588
+ flags[(y + 1) * stride + x + 1] = same(a, d) && same(b, c) && !same(a, b) ? 1 : 0;
31589
+ }
31590
+ }
31591
+ const checker = (x, y) => flags[(y + 1) * stride + x + 1] === 1;
31592
+ for (let y = 0; y < h - 1; y++) {
31593
+ for (let x = 0; x < w - 1; x++) {
31594
+ if (!checker(x, y)) {
31595
+ continue;
31615
31596
  }
31616
- }
31617
- return hClip >= 2 && vClip >= 2 && alternating >= 2;
31618
- };
31619
- for (let y = 0; y < h; y++) {
31620
- for (let x = 0; x < w; x++) {
31621
- if (!speckled(x, y)) {
31597
+ const ia = index(x, y);
31598
+ const ib = index(x + 1, y);
31599
+ const members = [
31600
+ [x, y, 1, 1, true],
31601
+ [x + 1, y + 1, -1, -1, true],
31602
+ [x + 1, y, -1, 1, false],
31603
+ [x, y + 1, 1, -1, false]
31604
+ ];
31605
+ if (checker(x - 1, y) && checker(x + 1, y) || checker(x, y - 1) && checker(x, y + 1)) {
31606
+ for (const [mx, my] of members) {
31607
+ const o = (my * w + mx) * 3;
31608
+ for (let c = 0; c < 3; c++) {
31609
+ px[o + c] = src[ia + c] + src[ib + c] + 1 >> 1;
31610
+ }
31611
+ }
31622
31612
  continue;
31623
31613
  }
31624
- const left = mirror2(x, w, -1);
31625
- const right = mirror2(x, w, 1);
31626
- const up = mirror2(y, h, -1);
31627
- const down = mirror2(y, h, 1);
31628
- const lonelyColumn = x === loneX && loneColumn(y);
31629
- const lonelyRow = y === loneY && loneRow(x);
31630
- const nearLoneX = x === loneX - 1 && loneX > 0 && loneColumn(y) && !speckled(loneX, y);
31631
- const nearLoneY = y === loneY - 1 && loneY > 0 && loneRow(x) && !speckled(x, loneY);
31632
- const cornerRepeats = lonelyColumn && lonelyRow && (!speckled(x, y - 1) || !speckled(x - 1, y));
31633
- for (let c = 0; c < 3; c++) {
31634
- const v = at(x, y, c);
31635
- let r;
31636
- if (lonelyColumn && lonelyRow) {
31637
- r = cornerRepeats ? at(left, y, c) + 3 * v + 2 >> 2 : hBlur(x, y, c);
31638
- } else {
31639
- let sum = lonelyColumn ? at(x, up, c) + 2 * v + at(x, down, c) : at(left, y, c) + 2 * v + at(right, y, c);
31640
- if (nearLoneX) sum += loneColumnValue(y, c) - at(loneX, y, c);
31641
- if (nearLoneY) sum += loneRowValue(x, c) - at(x, loneY, c);
31642
- r = sum + 2 >> 2;
31614
+ const brighter = 4 * (src[ia] - src[ib]) + 8 * (src[ia + 1] - src[ib + 1]) + (src[ia + 2] - src[ib + 2]);
31615
+ for (const [mx, my, sx, sy, isA] of members) {
31616
+ if (isA ? brighter < 0 : brighter >= 0) {
31617
+ continue;
31618
+ }
31619
+ const o = (my * w + mx) * 3;
31620
+ const t1 = index(mx + sx, my);
31621
+ const t2 = index(mx, my + sy);
31622
+ const t3 = index(mx + 2 * sx, my);
31623
+ const t4 = index(mx, my + 2 * sy);
31624
+ for (let c = 0; c < 3; c++) {
31625
+ px[o + c] = 12 * px[o + c] + src[t1 + c] + src[t2 + c] + src[t3 + c] + src[t4 + c] + 8 >> 4;
31643
31626
  }
31644
- px[(y * w + x) * 3 + c] = r;
31645
31627
  }
31646
31628
  }
31647
31629
  }
package/dist/index.js CHANGED
@@ -31569,82 +31569,64 @@ function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
31569
31569
  }
31570
31570
  }
31571
31571
  }
31572
- var SPECKLE_OVERSHOOT = 4;
31573
31572
  function halftoneDespeckle(px, w, h) {
31573
+ if (w < 2 || h < 2) {
31574
+ return;
31575
+ }
31574
31576
  const src = px.slice();
31575
- const at = (x, y, c) => src[(y * w + x) * 3 + c];
31576
- const over = (v) => v < -SPECKLE_OVERSHOOT * 4 || v > (255 + SPECKLE_OVERSHOOT) * 4;
31577
- const loneX = w > 2 && w % 2 === 1 ? w - 1 : -1;
31578
- const loneY = h > 2 && h % 2 === 1 ? h - 1 : -1;
31579
- const mirror2 = (i, n, d) => {
31580
- const j = i + d;
31581
- return j < 0 || j >= n ? i - d : j;
31577
+ const index = (x, y) => {
31578
+ const mx = x < 0 ? -x : x >= w ? 2 * (w - 1) - x : x;
31579
+ const my = y < 0 ? -y : y >= h ? 2 * (h - 1) - y : y;
31580
+ return (Math.max(0, Math.min(h - 1, my)) * w + Math.max(0, Math.min(w - 1, mx))) * 3;
31582
31581
  };
31583
- const vBlur = (x, y, c) => at(x, mirror2(y, h, -1), c) + 2 * at(x, y, c) + at(x, mirror2(y, h, 1), c) + 2 >> 2;
31584
- const hBlur = (x, y, c) => at(mirror2(x, w, -1), y, c) + 2 * at(x, y, c) + at(mirror2(x, w, 1), y, c) + 2 >> 2;
31585
- const differs = (x0, y0, x1, y1) => at(x0, y0, 0) !== at(x1, y1, 0) || at(x0, y0, 1) !== at(x1, y1, 1) || at(x0, y0, 2) !== at(x1, y1, 2);
31586
- const loneColumn = (y) => loneX > 0 && differs(loneX, y, loneX - 1, y);
31587
- const loneRow = (x) => loneY > 0 && differs(x, loneY, x, loneY - 1);
31588
- const loneColumnValue = (y, c) => y === loneY && loneRow(loneX) ? at(loneX, y - 1, c) + 3 * at(loneX, y, c) + 2 >> 2 : vBlur(loneX, y, c);
31589
- const loneRowValue = (x, c) => x === loneX && loneColumn(loneY) ? at(x - 1, loneY, c) + 3 * at(x, loneY, c) + 2 >> 2 : hBlur(x, loneY, c);
31590
- const speckled = (x, y) => {
31591
- const up = mirror2(y, h, -1);
31592
- const down = mirror2(y, h, 1);
31593
- const left = mirror2(x, w, -1);
31594
- const right = mirror2(x, w, 1);
31595
- let hClip = 0;
31596
- let vClip = 0;
31597
- let alternating = 0;
31598
- for (let c = 0; c < 3; c++) {
31599
- const v = at(x, y, c);
31600
- const axial = Math.max(
31601
- Math.abs(v - at(left, y, c)),
31602
- Math.abs(v - at(right, y, c)),
31603
- Math.abs(v - at(x, up, c)),
31604
- Math.abs(v - at(x, down, c))
31605
- );
31606
- const diagonal = Math.min(
31607
- Math.abs(v - at(left, up, c)),
31608
- Math.abs(v - at(right, up, c)),
31609
- Math.abs(v - at(left, down, c)),
31610
- Math.abs(v - at(right, down, c))
31611
- );
31612
- if (diagonal < axial) alternating++;
31613
- if (over(6 * v - at(left, y, c) - at(right, y, c))) {
31614
- hClip++;
31615
- }
31616
- if (over(6 * v - at(x, up, c) - at(x, down, c))) {
31617
- vClip++;
31582
+ const same = (i, j) => src[i] === src[j] && src[i + 1] === src[j + 1] && src[i + 2] === src[j + 2];
31583
+ const stride = w + 1;
31584
+ const flags = new Uint8Array(stride * (h + 1));
31585
+ for (let y = -1; y < h; y++) {
31586
+ for (let x = -1; x < w; x++) {
31587
+ const a = index(x, y);
31588
+ const b = index(x + 1, y);
31589
+ const c = index(x, y + 1);
31590
+ const d = index(x + 1, y + 1);
31591
+ flags[(y + 1) * stride + x + 1] = same(a, d) && same(b, c) && !same(a, b) ? 1 : 0;
31592
+ }
31593
+ }
31594
+ const checker = (x, y) => flags[(y + 1) * stride + x + 1] === 1;
31595
+ for (let y = 0; y < h - 1; y++) {
31596
+ for (let x = 0; x < w - 1; x++) {
31597
+ if (!checker(x, y)) {
31598
+ continue;
31618
31599
  }
31619
- }
31620
- return hClip >= 2 && vClip >= 2 && alternating >= 2;
31621
- };
31622
- for (let y = 0; y < h; y++) {
31623
- for (let x = 0; x < w; x++) {
31624
- if (!speckled(x, y)) {
31600
+ const ia = index(x, y);
31601
+ const ib = index(x + 1, y);
31602
+ const members = [
31603
+ [x, y, 1, 1, true],
31604
+ [x + 1, y + 1, -1, -1, true],
31605
+ [x + 1, y, -1, 1, false],
31606
+ [x, y + 1, 1, -1, false]
31607
+ ];
31608
+ if (checker(x - 1, y) && checker(x + 1, y) || checker(x, y - 1) && checker(x, y + 1)) {
31609
+ for (const [mx, my] of members) {
31610
+ const o = (my * w + mx) * 3;
31611
+ for (let c = 0; c < 3; c++) {
31612
+ px[o + c] = src[ia + c] + src[ib + c] + 1 >> 1;
31613
+ }
31614
+ }
31625
31615
  continue;
31626
31616
  }
31627
- const left = mirror2(x, w, -1);
31628
- const right = mirror2(x, w, 1);
31629
- const up = mirror2(y, h, -1);
31630
- const down = mirror2(y, h, 1);
31631
- const lonelyColumn = x === loneX && loneColumn(y);
31632
- const lonelyRow = y === loneY && loneRow(x);
31633
- const nearLoneX = x === loneX - 1 && loneX > 0 && loneColumn(y) && !speckled(loneX, y);
31634
- const nearLoneY = y === loneY - 1 && loneY > 0 && loneRow(x) && !speckled(x, loneY);
31635
- const cornerRepeats = lonelyColumn && lonelyRow && (!speckled(x, y - 1) || !speckled(x - 1, y));
31636
- for (let c = 0; c < 3; c++) {
31637
- const v = at(x, y, c);
31638
- let r;
31639
- if (lonelyColumn && lonelyRow) {
31640
- r = cornerRepeats ? at(left, y, c) + 3 * v + 2 >> 2 : hBlur(x, y, c);
31641
- } else {
31642
- let sum = lonelyColumn ? at(x, up, c) + 2 * v + at(x, down, c) : at(left, y, c) + 2 * v + at(right, y, c);
31643
- if (nearLoneX) sum += loneColumnValue(y, c) - at(loneX, y, c);
31644
- if (nearLoneY) sum += loneRowValue(x, c) - at(x, loneY, c);
31645
- r = sum + 2 >> 2;
31617
+ const brighter = 4 * (src[ia] - src[ib]) + 8 * (src[ia + 1] - src[ib + 1]) + (src[ia + 2] - src[ib + 2]);
31618
+ for (const [mx, my, sx, sy, isA] of members) {
31619
+ if (isA ? brighter < 0 : brighter >= 0) {
31620
+ continue;
31621
+ }
31622
+ const o = (my * w + mx) * 3;
31623
+ const t1 = index(mx + sx, my);
31624
+ const t2 = index(mx, my + sy);
31625
+ const t3 = index(mx + 2 * sx, my);
31626
+ const t4 = index(mx, my + 2 * sy);
31627
+ for (let c = 0; c < 3; c++) {
31628
+ px[o + c] = 12 * px[o + c] + src[t1 + c] + src[t2 + c] + src[t3 + c] + src[t4 + c] + 8 >> 4;
31646
31629
  }
31647
- px[(y * w + x) * 3 + c] = r;
31648
31630
  }
31649
31631
  }
31650
31632
  }
package/dist/index.mjs CHANGED
@@ -31567,82 +31567,64 @@ function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
31567
31567
  }
31568
31568
  }
31569
31569
  }
31570
- var SPECKLE_OVERSHOOT = 4;
31571
31570
  function halftoneDespeckle(px, w, h) {
31571
+ if (w < 2 || h < 2) {
31572
+ return;
31573
+ }
31572
31574
  const src = px.slice();
31573
- const at = (x, y, c) => src[(y * w + x) * 3 + c];
31574
- const over = (v) => v < -SPECKLE_OVERSHOOT * 4 || v > (255 + SPECKLE_OVERSHOOT) * 4;
31575
- const loneX = w > 2 && w % 2 === 1 ? w - 1 : -1;
31576
- const loneY = h > 2 && h % 2 === 1 ? h - 1 : -1;
31577
- const mirror2 = (i, n, d) => {
31578
- const j = i + d;
31579
- return j < 0 || j >= n ? i - d : j;
31575
+ const index = (x, y) => {
31576
+ const mx = x < 0 ? -x : x >= w ? 2 * (w - 1) - x : x;
31577
+ const my = y < 0 ? -y : y >= h ? 2 * (h - 1) - y : y;
31578
+ return (Math.max(0, Math.min(h - 1, my)) * w + Math.max(0, Math.min(w - 1, mx))) * 3;
31580
31579
  };
31581
- const vBlur = (x, y, c) => at(x, mirror2(y, h, -1), c) + 2 * at(x, y, c) + at(x, mirror2(y, h, 1), c) + 2 >> 2;
31582
- const hBlur = (x, y, c) => at(mirror2(x, w, -1), y, c) + 2 * at(x, y, c) + at(mirror2(x, w, 1), y, c) + 2 >> 2;
31583
- const differs = (x0, y0, x1, y1) => at(x0, y0, 0) !== at(x1, y1, 0) || at(x0, y0, 1) !== at(x1, y1, 1) || at(x0, y0, 2) !== at(x1, y1, 2);
31584
- const loneColumn = (y) => loneX > 0 && differs(loneX, y, loneX - 1, y);
31585
- const loneRow = (x) => loneY > 0 && differs(x, loneY, x, loneY - 1);
31586
- const loneColumnValue = (y, c) => y === loneY && loneRow(loneX) ? at(loneX, y - 1, c) + 3 * at(loneX, y, c) + 2 >> 2 : vBlur(loneX, y, c);
31587
- const loneRowValue = (x, c) => x === loneX && loneColumn(loneY) ? at(x - 1, loneY, c) + 3 * at(x, loneY, c) + 2 >> 2 : hBlur(x, loneY, c);
31588
- const speckled = (x, y) => {
31589
- const up = mirror2(y, h, -1);
31590
- const down = mirror2(y, h, 1);
31591
- const left = mirror2(x, w, -1);
31592
- const right = mirror2(x, w, 1);
31593
- let hClip = 0;
31594
- let vClip = 0;
31595
- let alternating = 0;
31596
- for (let c = 0; c < 3; c++) {
31597
- const v = at(x, y, c);
31598
- const axial = Math.max(
31599
- Math.abs(v - at(left, y, c)),
31600
- Math.abs(v - at(right, y, c)),
31601
- Math.abs(v - at(x, up, c)),
31602
- Math.abs(v - at(x, down, c))
31603
- );
31604
- const diagonal = Math.min(
31605
- Math.abs(v - at(left, up, c)),
31606
- Math.abs(v - at(right, up, c)),
31607
- Math.abs(v - at(left, down, c)),
31608
- Math.abs(v - at(right, down, c))
31609
- );
31610
- if (diagonal < axial) alternating++;
31611
- if (over(6 * v - at(left, y, c) - at(right, y, c))) {
31612
- hClip++;
31613
- }
31614
- if (over(6 * v - at(x, up, c) - at(x, down, c))) {
31615
- vClip++;
31580
+ const same = (i, j) => src[i] === src[j] && src[i + 1] === src[j + 1] && src[i + 2] === src[j + 2];
31581
+ const stride = w + 1;
31582
+ const flags = new Uint8Array(stride * (h + 1));
31583
+ for (let y = -1; y < h; y++) {
31584
+ for (let x = -1; x < w; x++) {
31585
+ const a = index(x, y);
31586
+ const b = index(x + 1, y);
31587
+ const c = index(x, y + 1);
31588
+ const d = index(x + 1, y + 1);
31589
+ flags[(y + 1) * stride + x + 1] = same(a, d) && same(b, c) && !same(a, b) ? 1 : 0;
31590
+ }
31591
+ }
31592
+ const checker = (x, y) => flags[(y + 1) * stride + x + 1] === 1;
31593
+ for (let y = 0; y < h - 1; y++) {
31594
+ for (let x = 0; x < w - 1; x++) {
31595
+ if (!checker(x, y)) {
31596
+ continue;
31616
31597
  }
31617
- }
31618
- return hClip >= 2 && vClip >= 2 && alternating >= 2;
31619
- };
31620
- for (let y = 0; y < h; y++) {
31621
- for (let x = 0; x < w; x++) {
31622
- if (!speckled(x, y)) {
31598
+ const ia = index(x, y);
31599
+ const ib = index(x + 1, y);
31600
+ const members = [
31601
+ [x, y, 1, 1, true],
31602
+ [x + 1, y + 1, -1, -1, true],
31603
+ [x + 1, y, -1, 1, false],
31604
+ [x, y + 1, 1, -1, false]
31605
+ ];
31606
+ if (checker(x - 1, y) && checker(x + 1, y) || checker(x, y - 1) && checker(x, y + 1)) {
31607
+ for (const [mx, my] of members) {
31608
+ const o = (my * w + mx) * 3;
31609
+ for (let c = 0; c < 3; c++) {
31610
+ px[o + c] = src[ia + c] + src[ib + c] + 1 >> 1;
31611
+ }
31612
+ }
31623
31613
  continue;
31624
31614
  }
31625
- const left = mirror2(x, w, -1);
31626
- const right = mirror2(x, w, 1);
31627
- const up = mirror2(y, h, -1);
31628
- const down = mirror2(y, h, 1);
31629
- const lonelyColumn = x === loneX && loneColumn(y);
31630
- const lonelyRow = y === loneY && loneRow(x);
31631
- const nearLoneX = x === loneX - 1 && loneX > 0 && loneColumn(y) && !speckled(loneX, y);
31632
- const nearLoneY = y === loneY - 1 && loneY > 0 && loneRow(x) && !speckled(x, loneY);
31633
- const cornerRepeats = lonelyColumn && lonelyRow && (!speckled(x, y - 1) || !speckled(x - 1, y));
31634
- for (let c = 0; c < 3; c++) {
31635
- const v = at(x, y, c);
31636
- let r;
31637
- if (lonelyColumn && lonelyRow) {
31638
- r = cornerRepeats ? at(left, y, c) + 3 * v + 2 >> 2 : hBlur(x, y, c);
31639
- } else {
31640
- let sum = lonelyColumn ? at(x, up, c) + 2 * v + at(x, down, c) : at(left, y, c) + 2 * v + at(right, y, c);
31641
- if (nearLoneX) sum += loneColumnValue(y, c) - at(loneX, y, c);
31642
- if (nearLoneY) sum += loneRowValue(x, c) - at(x, loneY, c);
31643
- r = sum + 2 >> 2;
31615
+ const brighter = 4 * (src[ia] - src[ib]) + 8 * (src[ia + 1] - src[ib + 1]) + (src[ia + 2] - src[ib + 2]);
31616
+ for (const [mx, my, sx, sy, isA] of members) {
31617
+ if (isA ? brighter < 0 : brighter >= 0) {
31618
+ continue;
31619
+ }
31620
+ const o = (my * w + mx) * 3;
31621
+ const t1 = index(mx + sx, my);
31622
+ const t2 = index(mx, my + sy);
31623
+ const t3 = index(mx + 2 * sx, my);
31624
+ const t4 = index(mx, my + 2 * sy);
31625
+ for (let c = 0; c < 3; c++) {
31626
+ px[o + c] = 12 * px[o + c] + src[t1 + c] + src[t2 + c] + src[t3 + c] + src[t4 + c] + 8 >> 4;
31644
31627
  }
31645
- px[(y * w + x) * 3 + c] = r;
31646
31628
  }
31647
31629
  }
31648
31630
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "4.6.9",
3
+ "version": "4.7.0",
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",