@pixerate/editor 0.219.1 → 0.220.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/{chunk-3X244IZ5.js → chunk-A7GJ6BXI.js} +43 -26
- package/dist/{chunk-SRMDF2VN.cjs → chunk-JBBJE76O.cjs} +43 -26
- package/dist/{chunk-S55JFWDA.cjs → chunk-R35YOUP2.cjs} +407 -161
- package/dist/{chunk-F7Z2MKY2.js → chunk-S6KKLFZO.js} +261 -15
- package/dist/image-editor/controller.d.cts +25 -1
- package/dist/image-editor/controller.d.ts +25 -1
- package/dist/image-editor/index.cjs +1257 -1125
- package/dist/image-editor/index.d.cts +1 -0
- package/dist/image-editor/index.d.ts +1 -0
- package/dist/image-editor/index.js +148 -16
- package/dist/image-editor/layers/hybrid-mask.d.cts +31 -0
- package/dist/image-editor/layers/hybrid-mask.d.ts +31 -0
- package/dist/image-editor/layers/model.d.cts +17 -0
- package/dist/image-editor/layers/model.d.ts +17 -0
- package/dist/image-editor/layers/serialize.d.cts +2 -0
- package/dist/image-editor/layers/serialize.d.ts +2 -0
- package/dist/image-editor/layers/vector-mask.d.cts +10 -5
- package/dist/image-editor/layers/vector-mask.d.ts +10 -5
- package/dist/image-editor/path-edit.d.cts +4 -0
- package/dist/image-editor/path-edit.d.ts +4 -0
- package/dist/image-editor/selection-worker.cjs +3 -3
- package/dist/image-editor/selection-worker.js +1 -1
- package/dist/paint-editor/index.cjs +6 -6
- package/dist/paint-editor/index.js +1 -1
- package/package.json +1 -1
- package/skills/pixerate-image-editor/SKILL.md +2 -1
- package/skills/pixerate-image-editor/references/paths.md +6 -0
- package/skills/pixerate-image-selection-masking/SKILL.md +4 -4
|
@@ -810,54 +810,62 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
810
810
|
let half = Math.max(24, Math.round(0.3 * Math.max(w, h)));
|
|
811
811
|
let seed = null;
|
|
812
812
|
let reseeds = 0;
|
|
813
|
+
let small;
|
|
813
814
|
for (; ; ) {
|
|
814
815
|
const rx = Math.max(0, px - half);
|
|
815
816
|
const ry = Math.max(0, py - half);
|
|
816
817
|
const roi = { x: rx, y: ry, width: Math.min(w, px + half + 1) - rx, height: Math.min(h, py + half + 1) - ry };
|
|
817
818
|
const whole = roi.width === w && roi.height === h;
|
|
818
819
|
const band = Math.max(4, Math.round(0.15 * half));
|
|
819
|
-
const radius = seed ?? 0.3 * half;
|
|
820
820
|
const n = roi.width * roi.height;
|
|
821
|
-
const initial = new Uint8Array(n);
|
|
822
821
|
const hardBg = new Uint8Array(n);
|
|
823
822
|
const hardFg = new Uint8Array(n);
|
|
824
823
|
const inBand = (x, y) => rx > 0 && x < band || ry > 0 && y < band || rx + roi.width < w && x >= roi.width - band || ry + roi.height < h && y >= roi.height - band;
|
|
825
824
|
for (let y = 0; y < roi.height; y++) {
|
|
826
825
|
for (let x = 0; x < roi.width; x++) {
|
|
827
826
|
const p = y * roi.width + x;
|
|
828
|
-
const d = Math.hypot(rx + x - px, ry + y - py);
|
|
829
827
|
if (inBand(x, y)) hardBg[p] = 1;
|
|
830
|
-
|
|
831
|
-
if (d <= 1.5) hardFg[p] = 1;
|
|
828
|
+
if (Math.hypot(rx + x - px, ry + y - py) <= 1.5) hardFg[p] = 1;
|
|
832
829
|
}
|
|
833
830
|
}
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
831
|
+
const cut = (radius) => {
|
|
832
|
+
const initial = new Uint8Array(n);
|
|
833
|
+
let seeded2 = 0;
|
|
834
|
+
for (let y = 0; y < roi.height; y++) {
|
|
835
|
+
for (let x = 0; x < roi.width; x++) {
|
|
836
|
+
const p = y * roi.width + x;
|
|
837
|
+
if (!hardBg[p] && Math.hypot(rx + x - px, ry + y - py) <= radius) {
|
|
838
|
+
initial[p] = 1;
|
|
839
|
+
seeded2++;
|
|
840
|
+
}
|
|
842
841
|
}
|
|
843
842
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
let
|
|
847
|
-
let
|
|
848
|
-
for (let
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
seed = Math.max(2, 0.7 * Math.sqrt(found / Math.PI));
|
|
855
|
-
continue;
|
|
843
|
+
const label2 = grabCutLabels(work, { roi, initial, hardBg, hardFg }, iterations, round);
|
|
844
|
+
keepMainPieces(label2, roi.width, roi.height, (py - ry) * roi.width + (px - rx));
|
|
845
|
+
let found2 = 0;
|
|
846
|
+
let touches2 = false;
|
|
847
|
+
for (let y = 0; y < roi.height; y++) {
|
|
848
|
+
for (let x = 0; x < roi.width; x++) {
|
|
849
|
+
if (!label2[y * roi.width + x]) continue;
|
|
850
|
+
found2++;
|
|
851
|
+
if (inBand(x - 1, y) || inBand(x + 1, y) || inBand(x, y - 1) || inBand(x, y + 1)) touches2 = true;
|
|
852
|
+
}
|
|
856
853
|
}
|
|
854
|
+
return { label: label2, seeded: seeded2, found: found2, touches: touches2 };
|
|
855
|
+
};
|
|
856
|
+
const { label, seeded, found, touches } = cut(seed ?? 0.3 * half);
|
|
857
|
+
if (!touches && reseeds < 2 && found * 2 < seeded) {
|
|
858
|
+
reseeds++;
|
|
859
|
+
seed = Math.max(2, 0.7 * Math.sqrt(found / Math.PI));
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
if (touches && small === void 0) {
|
|
863
|
+
const s = cut(Math.max(2, 0.05 * half));
|
|
864
|
+
small = !s.touches && s.found > 1.5 * s.seeded ? { roi, label: s.label } : null;
|
|
857
865
|
}
|
|
858
866
|
if (!touches || whole) {
|
|
859
867
|
report?.(0.9, "Scaling up");
|
|
860
|
-
const out = upscaleRegion(work, pixels, roi, label, enhance);
|
|
868
|
+
const out = small && edgesReached(label, roi, w, h) >= 3 ? upscaleRegion(work, pixels, small.roi, small.label, enhance) : upscaleRegion(work, pixels, roi, label, enhance);
|
|
861
869
|
report?.(1, "Done");
|
|
862
870
|
return out;
|
|
863
871
|
}
|
|
@@ -865,6 +873,15 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
865
873
|
seed = null;
|
|
866
874
|
}
|
|
867
875
|
}
|
|
876
|
+
function edgesReached(label, roi, w, h) {
|
|
877
|
+
const { x: rx, y: ry, width: rw, height: rh } = roi;
|
|
878
|
+
const row = (y) => label.subarray(y * rw, (y + 1) * rw).includes(1);
|
|
879
|
+
const col = (x) => {
|
|
880
|
+
for (let y = 0; y < rh; y++) if (label[y * rw + x]) return true;
|
|
881
|
+
return false;
|
|
882
|
+
};
|
|
883
|
+
return +(rx === 0 && col(0)) + +(ry === 0 && row(0)) + +(rx + rw === w && col(rw - 1)) + +(ry + rh === h && row(rh - 1));
|
|
884
|
+
}
|
|
868
885
|
|
|
869
886
|
// src/image-editor/selection/segment/quick.ts
|
|
870
887
|
var BINS = 16;
|
|
@@ -810,54 +810,62 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
810
810
|
let half = Math.max(24, Math.round(0.3 * Math.max(w, h)));
|
|
811
811
|
let seed = null;
|
|
812
812
|
let reseeds = 0;
|
|
813
|
+
let small;
|
|
813
814
|
for (; ; ) {
|
|
814
815
|
const rx = Math.max(0, px - half);
|
|
815
816
|
const ry = Math.max(0, py - half);
|
|
816
817
|
const roi = { x: rx, y: ry, width: Math.min(w, px + half + 1) - rx, height: Math.min(h, py + half + 1) - ry };
|
|
817
818
|
const whole = roi.width === w && roi.height === h;
|
|
818
819
|
const band = Math.max(4, Math.round(0.15 * half));
|
|
819
|
-
const radius = _nullishCoalesce(seed, () => ( 0.3 * half));
|
|
820
820
|
const n = roi.width * roi.height;
|
|
821
|
-
const initial = new Uint8Array(n);
|
|
822
821
|
const hardBg = new Uint8Array(n);
|
|
823
822
|
const hardFg = new Uint8Array(n);
|
|
824
823
|
const inBand = (x, y) => rx > 0 && x < band || ry > 0 && y < band || rx + roi.width < w && x >= roi.width - band || ry + roi.height < h && y >= roi.height - band;
|
|
825
824
|
for (let y = 0; y < roi.height; y++) {
|
|
826
825
|
for (let x = 0; x < roi.width; x++) {
|
|
827
826
|
const p = y * roi.width + x;
|
|
828
|
-
const d = Math.hypot(rx + x - px, ry + y - py);
|
|
829
827
|
if (inBand(x, y)) hardBg[p] = 1;
|
|
830
|
-
|
|
831
|
-
if (d <= 1.5) hardFg[p] = 1;
|
|
828
|
+
if (Math.hypot(rx + x - px, ry + y - py) <= 1.5) hardFg[p] = 1;
|
|
832
829
|
}
|
|
833
830
|
}
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
831
|
+
const cut = (radius) => {
|
|
832
|
+
const initial = new Uint8Array(n);
|
|
833
|
+
let seeded2 = 0;
|
|
834
|
+
for (let y = 0; y < roi.height; y++) {
|
|
835
|
+
for (let x = 0; x < roi.width; x++) {
|
|
836
|
+
const p = y * roi.width + x;
|
|
837
|
+
if (!hardBg[p] && Math.hypot(rx + x - px, ry + y - py) <= radius) {
|
|
838
|
+
initial[p] = 1;
|
|
839
|
+
seeded2++;
|
|
840
|
+
}
|
|
842
841
|
}
|
|
843
842
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
let
|
|
847
|
-
let
|
|
848
|
-
for (let
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
seed = Math.max(2, 0.7 * Math.sqrt(found / Math.PI));
|
|
855
|
-
continue;
|
|
843
|
+
const label2 = grabCutLabels(work, { roi, initial, hardBg, hardFg }, iterations, round);
|
|
844
|
+
keepMainPieces(label2, roi.width, roi.height, (py - ry) * roi.width + (px - rx));
|
|
845
|
+
let found2 = 0;
|
|
846
|
+
let touches2 = false;
|
|
847
|
+
for (let y = 0; y < roi.height; y++) {
|
|
848
|
+
for (let x = 0; x < roi.width; x++) {
|
|
849
|
+
if (!label2[y * roi.width + x]) continue;
|
|
850
|
+
found2++;
|
|
851
|
+
if (inBand(x - 1, y) || inBand(x + 1, y) || inBand(x, y - 1) || inBand(x, y + 1)) touches2 = true;
|
|
852
|
+
}
|
|
856
853
|
}
|
|
854
|
+
return { label: label2, seeded: seeded2, found: found2, touches: touches2 };
|
|
855
|
+
};
|
|
856
|
+
const { label, seeded, found, touches } = cut(_nullishCoalesce(seed, () => ( 0.3 * half)));
|
|
857
|
+
if (!touches && reseeds < 2 && found * 2 < seeded) {
|
|
858
|
+
reseeds++;
|
|
859
|
+
seed = Math.max(2, 0.7 * Math.sqrt(found / Math.PI));
|
|
860
|
+
continue;
|
|
861
|
+
}
|
|
862
|
+
if (touches && small === void 0) {
|
|
863
|
+
const s = cut(Math.max(2, 0.05 * half));
|
|
864
|
+
small = !s.touches && s.found > 1.5 * s.seeded ? { roi, label: s.label } : null;
|
|
857
865
|
}
|
|
858
866
|
if (!touches || whole) {
|
|
859
867
|
_optionalChain([report, 'optionalCall', _10 => _10(0.9, "Scaling up")]);
|
|
860
|
-
const out = upscaleRegion(work, pixels, roi, label, enhance);
|
|
868
|
+
const out = small && edgesReached(label, roi, w, h) >= 3 ? upscaleRegion(work, pixels, small.roi, small.label, enhance) : upscaleRegion(work, pixels, roi, label, enhance);
|
|
861
869
|
_optionalChain([report, 'optionalCall', _11 => _11(1, "Done")]);
|
|
862
870
|
return out;
|
|
863
871
|
}
|
|
@@ -865,6 +873,15 @@ function selectObjectIn(pixels, target, options = {}) {
|
|
|
865
873
|
seed = null;
|
|
866
874
|
}
|
|
867
875
|
}
|
|
876
|
+
function edgesReached(label, roi, w, h) {
|
|
877
|
+
const { x: rx, y: ry, width: rw, height: rh } = roi;
|
|
878
|
+
const row = (y) => label.subarray(y * rw, (y + 1) * rw).includes(1);
|
|
879
|
+
const col = (x) => {
|
|
880
|
+
for (let y = 0; y < rh; y++) if (label[y * rw + x]) return true;
|
|
881
|
+
return false;
|
|
882
|
+
};
|
|
883
|
+
return +(rx === 0 && col(0)) + +(ry === 0 && row(0)) + +(rx + rw === w && col(rw - 1)) + +(ry + rh === h && row(rh - 1));
|
|
884
|
+
}
|
|
868
885
|
|
|
869
886
|
// src/image-editor/selection/segment/quick.ts
|
|
870
887
|
var BINS = 16;
|