emf-converter 4.8.5 → 4.8.6
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 +40 -156
- package/dist/browser.mjs +40 -156
- package/dist/index.js +40 -156
- package/dist/index.mjs +40 -156
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -16534,153 +16534,26 @@ function applyTint(src, hue, amount) {
|
|
|
16534
16534
|
var TINT_FULL = 254;
|
|
16535
16535
|
function applyRedEyeCorrection(src, width, height, areas) {
|
|
16536
16536
|
const out = new Uint8ClampedArray(src);
|
|
16537
|
+
const carry = { x: 0, y: 0 };
|
|
16537
16538
|
for (const a of areas) {
|
|
16538
|
-
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height));
|
|
16539
|
+
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height), carry);
|
|
16539
16540
|
}
|
|
16540
16541
|
return out;
|
|
16541
16542
|
}
|
|
16542
|
-
var RED_EYE_FALLOFF = new Float64Array(
|
|
16543
|
-
[
|
|
16544
|
-
24930,
|
|
16545
|
-
24570,
|
|
16546
|
-
24201,
|
|
16547
|
-
23836,
|
|
16548
|
-
23471,
|
|
16549
|
-
23107,
|
|
16550
|
-
22744,
|
|
16551
|
-
22367,
|
|
16552
|
-
21976,
|
|
16553
|
-
21587,
|
|
16554
|
-
21198,
|
|
16555
|
-
20824,
|
|
16556
|
-
20490,
|
|
16557
|
-
20165,
|
|
16558
|
-
19832,
|
|
16559
|
-
19499,
|
|
16560
|
-
19157,
|
|
16561
|
-
18817,
|
|
16562
|
-
18480,
|
|
16563
|
-
18151,
|
|
16564
|
-
17820,
|
|
16565
|
-
17490,
|
|
16566
|
-
17160,
|
|
16567
|
-
16831,
|
|
16568
|
-
16506,
|
|
16569
|
-
16189,
|
|
16570
|
-
15878,
|
|
16571
|
-
15569,
|
|
16572
|
-
15273,
|
|
16573
|
-
14973,
|
|
16574
|
-
14668,
|
|
16575
|
-
14362,
|
|
16576
|
-
14059,
|
|
16577
|
-
13768,
|
|
16578
|
-
13484,
|
|
16579
|
-
13203,
|
|
16580
|
-
12923,
|
|
16581
|
-
12642,
|
|
16582
|
-
12366,
|
|
16583
|
-
12094,
|
|
16584
|
-
11828,
|
|
16585
|
-
11564,
|
|
16586
|
-
11301,
|
|
16587
|
-
11034,
|
|
16588
|
-
10770,
|
|
16589
|
-
10507,
|
|
16590
|
-
10253,
|
|
16591
|
-
10011,
|
|
16592
|
-
9771,
|
|
16593
|
-
9530,
|
|
16594
|
-
9290,
|
|
16595
|
-
9053,
|
|
16596
|
-
8819,
|
|
16597
|
-
8588,
|
|
16598
|
-
8359,
|
|
16599
|
-
8134,
|
|
16600
|
-
7914,
|
|
16601
|
-
7697,
|
|
16602
|
-
7481,
|
|
16603
|
-
7267,
|
|
16604
|
-
7056,
|
|
16605
|
-
6851,
|
|
16606
|
-
6651,
|
|
16607
|
-
6453,
|
|
16608
|
-
6256,
|
|
16609
|
-
6061,
|
|
16610
|
-
5871,
|
|
16611
|
-
5684,
|
|
16612
|
-
5499,
|
|
16613
|
-
5317,
|
|
16614
|
-
5138,
|
|
16615
|
-
4962,
|
|
16616
|
-
4789,
|
|
16617
|
-
4619,
|
|
16618
|
-
4452,
|
|
16619
|
-
4289,
|
|
16620
|
-
4130,
|
|
16621
|
-
3974,
|
|
16622
|
-
3820,
|
|
16623
|
-
3669,
|
|
16624
|
-
3520,
|
|
16625
|
-
3375,
|
|
16626
|
-
3232,
|
|
16627
|
-
3093,
|
|
16628
|
-
2958,
|
|
16629
|
-
2825,
|
|
16630
|
-
2695,
|
|
16631
|
-
2568,
|
|
16632
|
-
2444,
|
|
16633
|
-
2325,
|
|
16634
|
-
2207,
|
|
16635
|
-
2092,
|
|
16636
|
-
1980,
|
|
16637
|
-
1872,
|
|
16638
|
-
1768,
|
|
16639
|
-
1666,
|
|
16640
|
-
1567,
|
|
16641
|
-
1470,
|
|
16642
|
-
1377,
|
|
16643
|
-
1287,
|
|
16644
|
-
1200,
|
|
16645
|
-
1116,
|
|
16646
|
-
1034,
|
|
16647
|
-
956,
|
|
16648
|
-
881,
|
|
16649
|
-
808,
|
|
16650
|
-
739,
|
|
16651
|
-
674,
|
|
16652
|
-
612,
|
|
16653
|
-
541,
|
|
16654
|
-
462,
|
|
16655
|
-
381,
|
|
16656
|
-
299,
|
|
16657
|
-
220,
|
|
16658
|
-
147,
|
|
16659
|
-
85,
|
|
16660
|
-
36,
|
|
16661
|
-
3,
|
|
16662
|
-
0
|
|
16663
|
-
].map((v) => v / 1e5)
|
|
16664
|
-
);
|
|
16665
|
-
function redEyeFalloff(u) {
|
|
16666
|
-
const t = u * 128;
|
|
16667
|
-
const i = Math.floor(t);
|
|
16668
|
-
if (i >= RED_EYE_FALLOFF.length - 1) {
|
|
16669
|
-
return 0;
|
|
16670
|
-
}
|
|
16671
|
-
return RED_EYE_FALLOFF[i] + (t - i) * (RED_EYE_FALLOFF[i + 1] - RED_EYE_FALLOFF[i]);
|
|
16672
|
-
}
|
|
16673
16543
|
var RED_EYE_SECTORS = 60;
|
|
16674
16544
|
var RED_EYE_BLUE_WEIGHT = 0.225;
|
|
16675
|
-
var
|
|
16676
|
-
var
|
|
16677
|
-
var
|
|
16678
|
-
var
|
|
16679
|
-
var
|
|
16680
|
-
function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
16545
|
+
var RED_EYE_PURE_WEIGHT = 1 / (1 + RED_EYE_BLUE_WEIGHT);
|
|
16546
|
+
var RED_EYE_CARRY = 0.81;
|
|
16547
|
+
var RED_EYE_GREEN_SHARE = 5 / 16;
|
|
16548
|
+
var RED_EYE_SPREAD_STEPS = [31.5, 50, 98.78];
|
|
16549
|
+
var RED_EYE_STRENGTHS = [0.25, 0.5, 0.661, 0.75];
|
|
16550
|
+
function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
16681
16551
|
const w = x1 - x0;
|
|
16682
16552
|
const h = y1 - y0;
|
|
16683
16553
|
const count = w * h;
|
|
16554
|
+
if (!(count > 0)) {
|
|
16555
|
+
return;
|
|
16556
|
+
}
|
|
16684
16557
|
const redness = new Float64Array(count);
|
|
16685
16558
|
const dark = new Float64Array(count);
|
|
16686
16559
|
let sx = 0;
|
|
@@ -16693,34 +16566,44 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16693
16566
|
const g = out[i + 1];
|
|
16694
16567
|
const b = out[i + 2];
|
|
16695
16568
|
const k = y * w + x;
|
|
16696
|
-
|
|
16569
|
+
const d = g + RED_EYE_BLUE_WEIGHT * b;
|
|
16570
|
+
dark[k] = d;
|
|
16697
16571
|
const v = r - Math.max(g, b);
|
|
16698
16572
|
if (v > 0) {
|
|
16699
16573
|
redness[k] = v;
|
|
16700
|
-
const
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
sy += weight * (y + 0.5);
|
|
16705
|
-
sw += weight;
|
|
16706
|
-
}
|
|
16574
|
+
const weight = d >= 1 ? v / d : RED_EYE_PURE_WEIGHT;
|
|
16575
|
+
sx += weight * (x + 0.5);
|
|
16576
|
+
sy += weight * (y + 0.5);
|
|
16577
|
+
sw += weight;
|
|
16707
16578
|
}
|
|
16708
16579
|
}
|
|
16709
16580
|
}
|
|
16710
16581
|
if (sw === 0) {
|
|
16711
|
-
|
|
16712
|
-
return;
|
|
16713
|
-
}
|
|
16714
|
-
sx = w / 2;
|
|
16715
|
-
sy = h / 2;
|
|
16716
|
-
sw = 1;
|
|
16582
|
+
return;
|
|
16717
16583
|
}
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
|
|
16584
|
+
let cx = (sx + RED_EYE_CARRY * carry.x) / sw;
|
|
16585
|
+
let cy = (sy + RED_EYE_CARRY * carry.y) / sw;
|
|
16586
|
+
carry.x = x0 + cx;
|
|
16587
|
+
carry.y = y0 + cy;
|
|
16588
|
+
if (Math.hypot(cx - w / 2, cy - h / 2) >= Math.max(Math.min(w, h) / 2, (w + h) / 6)) {
|
|
16589
|
+
cx = w / 2;
|
|
16590
|
+
cy = h / 2;
|
|
16591
|
+
}
|
|
16592
|
+
const ax = x0 + cx;
|
|
16593
|
+
const ay = y0 + cy;
|
|
16594
|
+
const edgeX = Math.round(cx) > w / 2 ? w - cx + 0.5 : cx - 0.5;
|
|
16595
|
+
const edgeY = Math.round(cy) > h / 2 ? h - cy + 0.5 : cy - 0.5;
|
|
16596
|
+
const radius = ax > ay ? Math.min(edgeX, ay - 0.5) : Math.min(edgeY, ax - 0.5);
|
|
16721
16597
|
if (!(radius > 0)) {
|
|
16722
16598
|
return;
|
|
16723
16599
|
}
|
|
16600
|
+
const sorted = Float64Array.from(dark).sort();
|
|
16601
|
+
const spread = sorted[Math.floor(0.7 * count)] - sorted[Math.floor(0.3 * count)];
|
|
16602
|
+
let level = 0;
|
|
16603
|
+
while (level < RED_EYE_SPREAD_STEPS.length && spread >= RED_EYE_SPREAD_STEPS[level]) {
|
|
16604
|
+
level++;
|
|
16605
|
+
}
|
|
16606
|
+
const strength = RED_EYE_STRENGTHS[level];
|
|
16724
16607
|
const sector = new Uint8Array(count);
|
|
16725
16608
|
const distance = new Float64Array(count);
|
|
16726
16609
|
const sectorSum = new Float64Array(RED_EYE_SECTORS);
|
|
@@ -16758,7 +16641,8 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16758
16641
|
const mean = sectorSum[s] / sectorCount[s];
|
|
16759
16642
|
const meanDark = sectorDark[s] / sectorCount[s];
|
|
16760
16643
|
const ratio = meanDark > 0 ? dark[k] / meanDark : 1;
|
|
16761
|
-
const
|
|
16644
|
+
const u = distance[k] / radius;
|
|
16645
|
+
const falloff = Math.max(strength * (1 - u) * (1 - u), 0.5 * Math.max(0, 1 - ratio) ** 2);
|
|
16762
16646
|
const rest = (1 - falloff) * mean;
|
|
16763
16647
|
if (rest >= v) {
|
|
16764
16648
|
continue;
|
package/dist/browser.mjs
CHANGED
|
@@ -16532,153 +16532,26 @@ function applyTint(src, hue, amount) {
|
|
|
16532
16532
|
var TINT_FULL = 254;
|
|
16533
16533
|
function applyRedEyeCorrection(src, width, height, areas) {
|
|
16534
16534
|
const out = new Uint8ClampedArray(src);
|
|
16535
|
+
const carry = { x: 0, y: 0 };
|
|
16535
16536
|
for (const a of areas) {
|
|
16536
|
-
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height));
|
|
16537
|
+
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height), carry);
|
|
16537
16538
|
}
|
|
16538
16539
|
return out;
|
|
16539
16540
|
}
|
|
16540
|
-
var RED_EYE_FALLOFF = new Float64Array(
|
|
16541
|
-
[
|
|
16542
|
-
24930,
|
|
16543
|
-
24570,
|
|
16544
|
-
24201,
|
|
16545
|
-
23836,
|
|
16546
|
-
23471,
|
|
16547
|
-
23107,
|
|
16548
|
-
22744,
|
|
16549
|
-
22367,
|
|
16550
|
-
21976,
|
|
16551
|
-
21587,
|
|
16552
|
-
21198,
|
|
16553
|
-
20824,
|
|
16554
|
-
20490,
|
|
16555
|
-
20165,
|
|
16556
|
-
19832,
|
|
16557
|
-
19499,
|
|
16558
|
-
19157,
|
|
16559
|
-
18817,
|
|
16560
|
-
18480,
|
|
16561
|
-
18151,
|
|
16562
|
-
17820,
|
|
16563
|
-
17490,
|
|
16564
|
-
17160,
|
|
16565
|
-
16831,
|
|
16566
|
-
16506,
|
|
16567
|
-
16189,
|
|
16568
|
-
15878,
|
|
16569
|
-
15569,
|
|
16570
|
-
15273,
|
|
16571
|
-
14973,
|
|
16572
|
-
14668,
|
|
16573
|
-
14362,
|
|
16574
|
-
14059,
|
|
16575
|
-
13768,
|
|
16576
|
-
13484,
|
|
16577
|
-
13203,
|
|
16578
|
-
12923,
|
|
16579
|
-
12642,
|
|
16580
|
-
12366,
|
|
16581
|
-
12094,
|
|
16582
|
-
11828,
|
|
16583
|
-
11564,
|
|
16584
|
-
11301,
|
|
16585
|
-
11034,
|
|
16586
|
-
10770,
|
|
16587
|
-
10507,
|
|
16588
|
-
10253,
|
|
16589
|
-
10011,
|
|
16590
|
-
9771,
|
|
16591
|
-
9530,
|
|
16592
|
-
9290,
|
|
16593
|
-
9053,
|
|
16594
|
-
8819,
|
|
16595
|
-
8588,
|
|
16596
|
-
8359,
|
|
16597
|
-
8134,
|
|
16598
|
-
7914,
|
|
16599
|
-
7697,
|
|
16600
|
-
7481,
|
|
16601
|
-
7267,
|
|
16602
|
-
7056,
|
|
16603
|
-
6851,
|
|
16604
|
-
6651,
|
|
16605
|
-
6453,
|
|
16606
|
-
6256,
|
|
16607
|
-
6061,
|
|
16608
|
-
5871,
|
|
16609
|
-
5684,
|
|
16610
|
-
5499,
|
|
16611
|
-
5317,
|
|
16612
|
-
5138,
|
|
16613
|
-
4962,
|
|
16614
|
-
4789,
|
|
16615
|
-
4619,
|
|
16616
|
-
4452,
|
|
16617
|
-
4289,
|
|
16618
|
-
4130,
|
|
16619
|
-
3974,
|
|
16620
|
-
3820,
|
|
16621
|
-
3669,
|
|
16622
|
-
3520,
|
|
16623
|
-
3375,
|
|
16624
|
-
3232,
|
|
16625
|
-
3093,
|
|
16626
|
-
2958,
|
|
16627
|
-
2825,
|
|
16628
|
-
2695,
|
|
16629
|
-
2568,
|
|
16630
|
-
2444,
|
|
16631
|
-
2325,
|
|
16632
|
-
2207,
|
|
16633
|
-
2092,
|
|
16634
|
-
1980,
|
|
16635
|
-
1872,
|
|
16636
|
-
1768,
|
|
16637
|
-
1666,
|
|
16638
|
-
1567,
|
|
16639
|
-
1470,
|
|
16640
|
-
1377,
|
|
16641
|
-
1287,
|
|
16642
|
-
1200,
|
|
16643
|
-
1116,
|
|
16644
|
-
1034,
|
|
16645
|
-
956,
|
|
16646
|
-
881,
|
|
16647
|
-
808,
|
|
16648
|
-
739,
|
|
16649
|
-
674,
|
|
16650
|
-
612,
|
|
16651
|
-
541,
|
|
16652
|
-
462,
|
|
16653
|
-
381,
|
|
16654
|
-
299,
|
|
16655
|
-
220,
|
|
16656
|
-
147,
|
|
16657
|
-
85,
|
|
16658
|
-
36,
|
|
16659
|
-
3,
|
|
16660
|
-
0
|
|
16661
|
-
].map((v) => v / 1e5)
|
|
16662
|
-
);
|
|
16663
|
-
function redEyeFalloff(u) {
|
|
16664
|
-
const t = u * 128;
|
|
16665
|
-
const i = Math.floor(t);
|
|
16666
|
-
if (i >= RED_EYE_FALLOFF.length - 1) {
|
|
16667
|
-
return 0;
|
|
16668
|
-
}
|
|
16669
|
-
return RED_EYE_FALLOFF[i] + (t - i) * (RED_EYE_FALLOFF[i + 1] - RED_EYE_FALLOFF[i]);
|
|
16670
|
-
}
|
|
16671
16541
|
var RED_EYE_SECTORS = 60;
|
|
16672
16542
|
var RED_EYE_BLUE_WEIGHT = 0.225;
|
|
16673
|
-
var
|
|
16674
|
-
var
|
|
16675
|
-
var
|
|
16676
|
-
var
|
|
16677
|
-
var
|
|
16678
|
-
function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
16543
|
+
var RED_EYE_PURE_WEIGHT = 1 / (1 + RED_EYE_BLUE_WEIGHT);
|
|
16544
|
+
var RED_EYE_CARRY = 0.81;
|
|
16545
|
+
var RED_EYE_GREEN_SHARE = 5 / 16;
|
|
16546
|
+
var RED_EYE_SPREAD_STEPS = [31.5, 50, 98.78];
|
|
16547
|
+
var RED_EYE_STRENGTHS = [0.25, 0.5, 0.661, 0.75];
|
|
16548
|
+
function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
16679
16549
|
const w = x1 - x0;
|
|
16680
16550
|
const h = y1 - y0;
|
|
16681
16551
|
const count = w * h;
|
|
16552
|
+
if (!(count > 0)) {
|
|
16553
|
+
return;
|
|
16554
|
+
}
|
|
16682
16555
|
const redness = new Float64Array(count);
|
|
16683
16556
|
const dark = new Float64Array(count);
|
|
16684
16557
|
let sx = 0;
|
|
@@ -16691,34 +16564,44 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16691
16564
|
const g = out[i + 1];
|
|
16692
16565
|
const b = out[i + 2];
|
|
16693
16566
|
const k = y * w + x;
|
|
16694
|
-
|
|
16567
|
+
const d = g + RED_EYE_BLUE_WEIGHT * b;
|
|
16568
|
+
dark[k] = d;
|
|
16695
16569
|
const v = r - Math.max(g, b);
|
|
16696
16570
|
if (v > 0) {
|
|
16697
16571
|
redness[k] = v;
|
|
16698
|
-
const
|
|
16699
|
-
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
sy += weight * (y + 0.5);
|
|
16703
|
-
sw += weight;
|
|
16704
|
-
}
|
|
16572
|
+
const weight = d >= 1 ? v / d : RED_EYE_PURE_WEIGHT;
|
|
16573
|
+
sx += weight * (x + 0.5);
|
|
16574
|
+
sy += weight * (y + 0.5);
|
|
16575
|
+
sw += weight;
|
|
16705
16576
|
}
|
|
16706
16577
|
}
|
|
16707
16578
|
}
|
|
16708
16579
|
if (sw === 0) {
|
|
16709
|
-
|
|
16710
|
-
return;
|
|
16711
|
-
}
|
|
16712
|
-
sx = w / 2;
|
|
16713
|
-
sy = h / 2;
|
|
16714
|
-
sw = 1;
|
|
16580
|
+
return;
|
|
16715
16581
|
}
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16582
|
+
let cx = (sx + RED_EYE_CARRY * carry.x) / sw;
|
|
16583
|
+
let cy = (sy + RED_EYE_CARRY * carry.y) / sw;
|
|
16584
|
+
carry.x = x0 + cx;
|
|
16585
|
+
carry.y = y0 + cy;
|
|
16586
|
+
if (Math.hypot(cx - w / 2, cy - h / 2) >= Math.max(Math.min(w, h) / 2, (w + h) / 6)) {
|
|
16587
|
+
cx = w / 2;
|
|
16588
|
+
cy = h / 2;
|
|
16589
|
+
}
|
|
16590
|
+
const ax = x0 + cx;
|
|
16591
|
+
const ay = y0 + cy;
|
|
16592
|
+
const edgeX = Math.round(cx) > w / 2 ? w - cx + 0.5 : cx - 0.5;
|
|
16593
|
+
const edgeY = Math.round(cy) > h / 2 ? h - cy + 0.5 : cy - 0.5;
|
|
16594
|
+
const radius = ax > ay ? Math.min(edgeX, ay - 0.5) : Math.min(edgeY, ax - 0.5);
|
|
16719
16595
|
if (!(radius > 0)) {
|
|
16720
16596
|
return;
|
|
16721
16597
|
}
|
|
16598
|
+
const sorted = Float64Array.from(dark).sort();
|
|
16599
|
+
const spread = sorted[Math.floor(0.7 * count)] - sorted[Math.floor(0.3 * count)];
|
|
16600
|
+
let level = 0;
|
|
16601
|
+
while (level < RED_EYE_SPREAD_STEPS.length && spread >= RED_EYE_SPREAD_STEPS[level]) {
|
|
16602
|
+
level++;
|
|
16603
|
+
}
|
|
16604
|
+
const strength = RED_EYE_STRENGTHS[level];
|
|
16722
16605
|
const sector = new Uint8Array(count);
|
|
16723
16606
|
const distance = new Float64Array(count);
|
|
16724
16607
|
const sectorSum = new Float64Array(RED_EYE_SECTORS);
|
|
@@ -16756,7 +16639,8 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16756
16639
|
const mean = sectorSum[s] / sectorCount[s];
|
|
16757
16640
|
const meanDark = sectorDark[s] / sectorCount[s];
|
|
16758
16641
|
const ratio = meanDark > 0 ? dark[k] / meanDark : 1;
|
|
16759
|
-
const
|
|
16642
|
+
const u = distance[k] / radius;
|
|
16643
|
+
const falloff = Math.max(strength * (1 - u) * (1 - u), 0.5 * Math.max(0, 1 - ratio) ** 2);
|
|
16760
16644
|
const rest = (1 - falloff) * mean;
|
|
16761
16645
|
if (rest >= v) {
|
|
16762
16646
|
continue;
|
package/dist/index.js
CHANGED
|
@@ -16535,153 +16535,26 @@ function applyTint(src, hue, amount) {
|
|
|
16535
16535
|
var TINT_FULL = 254;
|
|
16536
16536
|
function applyRedEyeCorrection(src, width, height, areas) {
|
|
16537
16537
|
const out = new Uint8ClampedArray(src);
|
|
16538
|
+
const carry = { x: 0, y: 0 };
|
|
16538
16539
|
for (const a of areas) {
|
|
16539
|
-
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height));
|
|
16540
|
+
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height), carry);
|
|
16540
16541
|
}
|
|
16541
16542
|
return out;
|
|
16542
16543
|
}
|
|
16543
|
-
var RED_EYE_FALLOFF = new Float64Array(
|
|
16544
|
-
[
|
|
16545
|
-
24930,
|
|
16546
|
-
24570,
|
|
16547
|
-
24201,
|
|
16548
|
-
23836,
|
|
16549
|
-
23471,
|
|
16550
|
-
23107,
|
|
16551
|
-
22744,
|
|
16552
|
-
22367,
|
|
16553
|
-
21976,
|
|
16554
|
-
21587,
|
|
16555
|
-
21198,
|
|
16556
|
-
20824,
|
|
16557
|
-
20490,
|
|
16558
|
-
20165,
|
|
16559
|
-
19832,
|
|
16560
|
-
19499,
|
|
16561
|
-
19157,
|
|
16562
|
-
18817,
|
|
16563
|
-
18480,
|
|
16564
|
-
18151,
|
|
16565
|
-
17820,
|
|
16566
|
-
17490,
|
|
16567
|
-
17160,
|
|
16568
|
-
16831,
|
|
16569
|
-
16506,
|
|
16570
|
-
16189,
|
|
16571
|
-
15878,
|
|
16572
|
-
15569,
|
|
16573
|
-
15273,
|
|
16574
|
-
14973,
|
|
16575
|
-
14668,
|
|
16576
|
-
14362,
|
|
16577
|
-
14059,
|
|
16578
|
-
13768,
|
|
16579
|
-
13484,
|
|
16580
|
-
13203,
|
|
16581
|
-
12923,
|
|
16582
|
-
12642,
|
|
16583
|
-
12366,
|
|
16584
|
-
12094,
|
|
16585
|
-
11828,
|
|
16586
|
-
11564,
|
|
16587
|
-
11301,
|
|
16588
|
-
11034,
|
|
16589
|
-
10770,
|
|
16590
|
-
10507,
|
|
16591
|
-
10253,
|
|
16592
|
-
10011,
|
|
16593
|
-
9771,
|
|
16594
|
-
9530,
|
|
16595
|
-
9290,
|
|
16596
|
-
9053,
|
|
16597
|
-
8819,
|
|
16598
|
-
8588,
|
|
16599
|
-
8359,
|
|
16600
|
-
8134,
|
|
16601
|
-
7914,
|
|
16602
|
-
7697,
|
|
16603
|
-
7481,
|
|
16604
|
-
7267,
|
|
16605
|
-
7056,
|
|
16606
|
-
6851,
|
|
16607
|
-
6651,
|
|
16608
|
-
6453,
|
|
16609
|
-
6256,
|
|
16610
|
-
6061,
|
|
16611
|
-
5871,
|
|
16612
|
-
5684,
|
|
16613
|
-
5499,
|
|
16614
|
-
5317,
|
|
16615
|
-
5138,
|
|
16616
|
-
4962,
|
|
16617
|
-
4789,
|
|
16618
|
-
4619,
|
|
16619
|
-
4452,
|
|
16620
|
-
4289,
|
|
16621
|
-
4130,
|
|
16622
|
-
3974,
|
|
16623
|
-
3820,
|
|
16624
|
-
3669,
|
|
16625
|
-
3520,
|
|
16626
|
-
3375,
|
|
16627
|
-
3232,
|
|
16628
|
-
3093,
|
|
16629
|
-
2958,
|
|
16630
|
-
2825,
|
|
16631
|
-
2695,
|
|
16632
|
-
2568,
|
|
16633
|
-
2444,
|
|
16634
|
-
2325,
|
|
16635
|
-
2207,
|
|
16636
|
-
2092,
|
|
16637
|
-
1980,
|
|
16638
|
-
1872,
|
|
16639
|
-
1768,
|
|
16640
|
-
1666,
|
|
16641
|
-
1567,
|
|
16642
|
-
1470,
|
|
16643
|
-
1377,
|
|
16644
|
-
1287,
|
|
16645
|
-
1200,
|
|
16646
|
-
1116,
|
|
16647
|
-
1034,
|
|
16648
|
-
956,
|
|
16649
|
-
881,
|
|
16650
|
-
808,
|
|
16651
|
-
739,
|
|
16652
|
-
674,
|
|
16653
|
-
612,
|
|
16654
|
-
541,
|
|
16655
|
-
462,
|
|
16656
|
-
381,
|
|
16657
|
-
299,
|
|
16658
|
-
220,
|
|
16659
|
-
147,
|
|
16660
|
-
85,
|
|
16661
|
-
36,
|
|
16662
|
-
3,
|
|
16663
|
-
0
|
|
16664
|
-
].map((v) => v / 1e5)
|
|
16665
|
-
);
|
|
16666
|
-
function redEyeFalloff(u) {
|
|
16667
|
-
const t = u * 128;
|
|
16668
|
-
const i = Math.floor(t);
|
|
16669
|
-
if (i >= RED_EYE_FALLOFF.length - 1) {
|
|
16670
|
-
return 0;
|
|
16671
|
-
}
|
|
16672
|
-
return RED_EYE_FALLOFF[i] + (t - i) * (RED_EYE_FALLOFF[i + 1] - RED_EYE_FALLOFF[i]);
|
|
16673
|
-
}
|
|
16674
16544
|
var RED_EYE_SECTORS = 60;
|
|
16675
16545
|
var RED_EYE_BLUE_WEIGHT = 0.225;
|
|
16676
|
-
var
|
|
16677
|
-
var
|
|
16678
|
-
var
|
|
16679
|
-
var
|
|
16680
|
-
var
|
|
16681
|
-
function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
16546
|
+
var RED_EYE_PURE_WEIGHT = 1 / (1 + RED_EYE_BLUE_WEIGHT);
|
|
16547
|
+
var RED_EYE_CARRY = 0.81;
|
|
16548
|
+
var RED_EYE_GREEN_SHARE = 5 / 16;
|
|
16549
|
+
var RED_EYE_SPREAD_STEPS = [31.5, 50, 98.78];
|
|
16550
|
+
var RED_EYE_STRENGTHS = [0.25, 0.5, 0.661, 0.75];
|
|
16551
|
+
function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
16682
16552
|
const w = x1 - x0;
|
|
16683
16553
|
const h = y1 - y0;
|
|
16684
16554
|
const count = w * h;
|
|
16555
|
+
if (!(count > 0)) {
|
|
16556
|
+
return;
|
|
16557
|
+
}
|
|
16685
16558
|
const redness = new Float64Array(count);
|
|
16686
16559
|
const dark = new Float64Array(count);
|
|
16687
16560
|
let sx = 0;
|
|
@@ -16694,34 +16567,44 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16694
16567
|
const g = out[i + 1];
|
|
16695
16568
|
const b = out[i + 2];
|
|
16696
16569
|
const k = y * w + x;
|
|
16697
|
-
|
|
16570
|
+
const d = g + RED_EYE_BLUE_WEIGHT * b;
|
|
16571
|
+
dark[k] = d;
|
|
16698
16572
|
const v = r - Math.max(g, b);
|
|
16699
16573
|
if (v > 0) {
|
|
16700
16574
|
redness[k] = v;
|
|
16701
|
-
const
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
sy += weight * (y + 0.5);
|
|
16706
|
-
sw += weight;
|
|
16707
|
-
}
|
|
16575
|
+
const weight = d >= 1 ? v / d : RED_EYE_PURE_WEIGHT;
|
|
16576
|
+
sx += weight * (x + 0.5);
|
|
16577
|
+
sy += weight * (y + 0.5);
|
|
16578
|
+
sw += weight;
|
|
16708
16579
|
}
|
|
16709
16580
|
}
|
|
16710
16581
|
}
|
|
16711
16582
|
if (sw === 0) {
|
|
16712
|
-
|
|
16713
|
-
return;
|
|
16714
|
-
}
|
|
16715
|
-
sx = w / 2;
|
|
16716
|
-
sy = h / 2;
|
|
16717
|
-
sw = 1;
|
|
16583
|
+
return;
|
|
16718
16584
|
}
|
|
16719
|
-
|
|
16720
|
-
|
|
16721
|
-
|
|
16585
|
+
let cx = (sx + RED_EYE_CARRY * carry.x) / sw;
|
|
16586
|
+
let cy = (sy + RED_EYE_CARRY * carry.y) / sw;
|
|
16587
|
+
carry.x = x0 + cx;
|
|
16588
|
+
carry.y = y0 + cy;
|
|
16589
|
+
if (Math.hypot(cx - w / 2, cy - h / 2) >= Math.max(Math.min(w, h) / 2, (w + h) / 6)) {
|
|
16590
|
+
cx = w / 2;
|
|
16591
|
+
cy = h / 2;
|
|
16592
|
+
}
|
|
16593
|
+
const ax = x0 + cx;
|
|
16594
|
+
const ay = y0 + cy;
|
|
16595
|
+
const edgeX = Math.round(cx) > w / 2 ? w - cx + 0.5 : cx - 0.5;
|
|
16596
|
+
const edgeY = Math.round(cy) > h / 2 ? h - cy + 0.5 : cy - 0.5;
|
|
16597
|
+
const radius = ax > ay ? Math.min(edgeX, ay - 0.5) : Math.min(edgeY, ax - 0.5);
|
|
16722
16598
|
if (!(radius > 0)) {
|
|
16723
16599
|
return;
|
|
16724
16600
|
}
|
|
16601
|
+
const sorted = Float64Array.from(dark).sort();
|
|
16602
|
+
const spread = sorted[Math.floor(0.7 * count)] - sorted[Math.floor(0.3 * count)];
|
|
16603
|
+
let level = 0;
|
|
16604
|
+
while (level < RED_EYE_SPREAD_STEPS.length && spread >= RED_EYE_SPREAD_STEPS[level]) {
|
|
16605
|
+
level++;
|
|
16606
|
+
}
|
|
16607
|
+
const strength = RED_EYE_STRENGTHS[level];
|
|
16725
16608
|
const sector = new Uint8Array(count);
|
|
16726
16609
|
const distance = new Float64Array(count);
|
|
16727
16610
|
const sectorSum = new Float64Array(RED_EYE_SECTORS);
|
|
@@ -16759,7 +16642,8 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16759
16642
|
const mean = sectorSum[s] / sectorCount[s];
|
|
16760
16643
|
const meanDark = sectorDark[s] / sectorCount[s];
|
|
16761
16644
|
const ratio = meanDark > 0 ? dark[k] / meanDark : 1;
|
|
16762
|
-
const
|
|
16645
|
+
const u = distance[k] / radius;
|
|
16646
|
+
const falloff = Math.max(strength * (1 - u) * (1 - u), 0.5 * Math.max(0, 1 - ratio) ** 2);
|
|
16763
16647
|
const rest = (1 - falloff) * mean;
|
|
16764
16648
|
if (rest >= v) {
|
|
16765
16649
|
continue;
|
package/dist/index.mjs
CHANGED
|
@@ -16533,153 +16533,26 @@ function applyTint(src, hue, amount) {
|
|
|
16533
16533
|
var TINT_FULL = 254;
|
|
16534
16534
|
function applyRedEyeCorrection(src, width, height, areas) {
|
|
16535
16535
|
const out = new Uint8ClampedArray(src);
|
|
16536
|
+
const carry = { x: 0, y: 0 };
|
|
16536
16537
|
for (const a of areas) {
|
|
16537
|
-
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height));
|
|
16538
|
+
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height), carry);
|
|
16538
16539
|
}
|
|
16539
16540
|
return out;
|
|
16540
16541
|
}
|
|
16541
|
-
var RED_EYE_FALLOFF = new Float64Array(
|
|
16542
|
-
[
|
|
16543
|
-
24930,
|
|
16544
|
-
24570,
|
|
16545
|
-
24201,
|
|
16546
|
-
23836,
|
|
16547
|
-
23471,
|
|
16548
|
-
23107,
|
|
16549
|
-
22744,
|
|
16550
|
-
22367,
|
|
16551
|
-
21976,
|
|
16552
|
-
21587,
|
|
16553
|
-
21198,
|
|
16554
|
-
20824,
|
|
16555
|
-
20490,
|
|
16556
|
-
20165,
|
|
16557
|
-
19832,
|
|
16558
|
-
19499,
|
|
16559
|
-
19157,
|
|
16560
|
-
18817,
|
|
16561
|
-
18480,
|
|
16562
|
-
18151,
|
|
16563
|
-
17820,
|
|
16564
|
-
17490,
|
|
16565
|
-
17160,
|
|
16566
|
-
16831,
|
|
16567
|
-
16506,
|
|
16568
|
-
16189,
|
|
16569
|
-
15878,
|
|
16570
|
-
15569,
|
|
16571
|
-
15273,
|
|
16572
|
-
14973,
|
|
16573
|
-
14668,
|
|
16574
|
-
14362,
|
|
16575
|
-
14059,
|
|
16576
|
-
13768,
|
|
16577
|
-
13484,
|
|
16578
|
-
13203,
|
|
16579
|
-
12923,
|
|
16580
|
-
12642,
|
|
16581
|
-
12366,
|
|
16582
|
-
12094,
|
|
16583
|
-
11828,
|
|
16584
|
-
11564,
|
|
16585
|
-
11301,
|
|
16586
|
-
11034,
|
|
16587
|
-
10770,
|
|
16588
|
-
10507,
|
|
16589
|
-
10253,
|
|
16590
|
-
10011,
|
|
16591
|
-
9771,
|
|
16592
|
-
9530,
|
|
16593
|
-
9290,
|
|
16594
|
-
9053,
|
|
16595
|
-
8819,
|
|
16596
|
-
8588,
|
|
16597
|
-
8359,
|
|
16598
|
-
8134,
|
|
16599
|
-
7914,
|
|
16600
|
-
7697,
|
|
16601
|
-
7481,
|
|
16602
|
-
7267,
|
|
16603
|
-
7056,
|
|
16604
|
-
6851,
|
|
16605
|
-
6651,
|
|
16606
|
-
6453,
|
|
16607
|
-
6256,
|
|
16608
|
-
6061,
|
|
16609
|
-
5871,
|
|
16610
|
-
5684,
|
|
16611
|
-
5499,
|
|
16612
|
-
5317,
|
|
16613
|
-
5138,
|
|
16614
|
-
4962,
|
|
16615
|
-
4789,
|
|
16616
|
-
4619,
|
|
16617
|
-
4452,
|
|
16618
|
-
4289,
|
|
16619
|
-
4130,
|
|
16620
|
-
3974,
|
|
16621
|
-
3820,
|
|
16622
|
-
3669,
|
|
16623
|
-
3520,
|
|
16624
|
-
3375,
|
|
16625
|
-
3232,
|
|
16626
|
-
3093,
|
|
16627
|
-
2958,
|
|
16628
|
-
2825,
|
|
16629
|
-
2695,
|
|
16630
|
-
2568,
|
|
16631
|
-
2444,
|
|
16632
|
-
2325,
|
|
16633
|
-
2207,
|
|
16634
|
-
2092,
|
|
16635
|
-
1980,
|
|
16636
|
-
1872,
|
|
16637
|
-
1768,
|
|
16638
|
-
1666,
|
|
16639
|
-
1567,
|
|
16640
|
-
1470,
|
|
16641
|
-
1377,
|
|
16642
|
-
1287,
|
|
16643
|
-
1200,
|
|
16644
|
-
1116,
|
|
16645
|
-
1034,
|
|
16646
|
-
956,
|
|
16647
|
-
881,
|
|
16648
|
-
808,
|
|
16649
|
-
739,
|
|
16650
|
-
674,
|
|
16651
|
-
612,
|
|
16652
|
-
541,
|
|
16653
|
-
462,
|
|
16654
|
-
381,
|
|
16655
|
-
299,
|
|
16656
|
-
220,
|
|
16657
|
-
147,
|
|
16658
|
-
85,
|
|
16659
|
-
36,
|
|
16660
|
-
3,
|
|
16661
|
-
0
|
|
16662
|
-
].map((v) => v / 1e5)
|
|
16663
|
-
);
|
|
16664
|
-
function redEyeFalloff(u) {
|
|
16665
|
-
const t = u * 128;
|
|
16666
|
-
const i = Math.floor(t);
|
|
16667
|
-
if (i >= RED_EYE_FALLOFF.length - 1) {
|
|
16668
|
-
return 0;
|
|
16669
|
-
}
|
|
16670
|
-
return RED_EYE_FALLOFF[i] + (t - i) * (RED_EYE_FALLOFF[i + 1] - RED_EYE_FALLOFF[i]);
|
|
16671
|
-
}
|
|
16672
16542
|
var RED_EYE_SECTORS = 60;
|
|
16673
16543
|
var RED_EYE_BLUE_WEIGHT = 0.225;
|
|
16674
|
-
var
|
|
16675
|
-
var
|
|
16676
|
-
var
|
|
16677
|
-
var
|
|
16678
|
-
var
|
|
16679
|
-
function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
16544
|
+
var RED_EYE_PURE_WEIGHT = 1 / (1 + RED_EYE_BLUE_WEIGHT);
|
|
16545
|
+
var RED_EYE_CARRY = 0.81;
|
|
16546
|
+
var RED_EYE_GREEN_SHARE = 5 / 16;
|
|
16547
|
+
var RED_EYE_SPREAD_STEPS = [31.5, 50, 98.78];
|
|
16548
|
+
var RED_EYE_STRENGTHS = [0.25, 0.5, 0.661, 0.75];
|
|
16549
|
+
function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
16680
16550
|
const w = x1 - x0;
|
|
16681
16551
|
const h = y1 - y0;
|
|
16682
16552
|
const count = w * h;
|
|
16553
|
+
if (!(count > 0)) {
|
|
16554
|
+
return;
|
|
16555
|
+
}
|
|
16683
16556
|
const redness = new Float64Array(count);
|
|
16684
16557
|
const dark = new Float64Array(count);
|
|
16685
16558
|
let sx = 0;
|
|
@@ -16692,34 +16565,44 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16692
16565
|
const g = out[i + 1];
|
|
16693
16566
|
const b = out[i + 2];
|
|
16694
16567
|
const k = y * w + x;
|
|
16695
|
-
|
|
16568
|
+
const d = g + RED_EYE_BLUE_WEIGHT * b;
|
|
16569
|
+
dark[k] = d;
|
|
16696
16570
|
const v = r - Math.max(g, b);
|
|
16697
16571
|
if (v > 0) {
|
|
16698
16572
|
redness[k] = v;
|
|
16699
|
-
const
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
sy += weight * (y + 0.5);
|
|
16704
|
-
sw += weight;
|
|
16705
|
-
}
|
|
16573
|
+
const weight = d >= 1 ? v / d : RED_EYE_PURE_WEIGHT;
|
|
16574
|
+
sx += weight * (x + 0.5);
|
|
16575
|
+
sy += weight * (y + 0.5);
|
|
16576
|
+
sw += weight;
|
|
16706
16577
|
}
|
|
16707
16578
|
}
|
|
16708
16579
|
}
|
|
16709
16580
|
if (sw === 0) {
|
|
16710
|
-
|
|
16711
|
-
return;
|
|
16712
|
-
}
|
|
16713
|
-
sx = w / 2;
|
|
16714
|
-
sy = h / 2;
|
|
16715
|
-
sw = 1;
|
|
16581
|
+
return;
|
|
16716
16582
|
}
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16583
|
+
let cx = (sx + RED_EYE_CARRY * carry.x) / sw;
|
|
16584
|
+
let cy = (sy + RED_EYE_CARRY * carry.y) / sw;
|
|
16585
|
+
carry.x = x0 + cx;
|
|
16586
|
+
carry.y = y0 + cy;
|
|
16587
|
+
if (Math.hypot(cx - w / 2, cy - h / 2) >= Math.max(Math.min(w, h) / 2, (w + h) / 6)) {
|
|
16588
|
+
cx = w / 2;
|
|
16589
|
+
cy = h / 2;
|
|
16590
|
+
}
|
|
16591
|
+
const ax = x0 + cx;
|
|
16592
|
+
const ay = y0 + cy;
|
|
16593
|
+
const edgeX = Math.round(cx) > w / 2 ? w - cx + 0.5 : cx - 0.5;
|
|
16594
|
+
const edgeY = Math.round(cy) > h / 2 ? h - cy + 0.5 : cy - 0.5;
|
|
16595
|
+
const radius = ax > ay ? Math.min(edgeX, ay - 0.5) : Math.min(edgeY, ax - 0.5);
|
|
16720
16596
|
if (!(radius > 0)) {
|
|
16721
16597
|
return;
|
|
16722
16598
|
}
|
|
16599
|
+
const sorted = Float64Array.from(dark).sort();
|
|
16600
|
+
const spread = sorted[Math.floor(0.7 * count)] - sorted[Math.floor(0.3 * count)];
|
|
16601
|
+
let level = 0;
|
|
16602
|
+
while (level < RED_EYE_SPREAD_STEPS.length && spread >= RED_EYE_SPREAD_STEPS[level]) {
|
|
16603
|
+
level++;
|
|
16604
|
+
}
|
|
16605
|
+
const strength = RED_EYE_STRENGTHS[level];
|
|
16723
16606
|
const sector = new Uint8Array(count);
|
|
16724
16607
|
const distance = new Float64Array(count);
|
|
16725
16608
|
const sectorSum = new Float64Array(RED_EYE_SECTORS);
|
|
@@ -16757,7 +16640,8 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1) {
|
|
|
16757
16640
|
const mean = sectorSum[s] / sectorCount[s];
|
|
16758
16641
|
const meanDark = sectorDark[s] / sectorCount[s];
|
|
16759
16642
|
const ratio = meanDark > 0 ? dark[k] / meanDark : 1;
|
|
16760
|
-
const
|
|
16643
|
+
const u = distance[k] / radius;
|
|
16644
|
+
const falloff = Math.max(strength * (1 - u) * (1 - u), 0.5 * Math.max(0, 1 - ratio) ** 2);
|
|
16761
16645
|
const rest = (1 - falloff) * mean;
|
|
16762
16646
|
if (rest >= v) {
|
|
16763
16647
|
continue;
|