fix: reject banded rmbg scale drafts
This commit is contained in:
parent
01e17361c8
commit
5ec43fa8a3
@ -1709,6 +1709,83 @@ function getScaleAdjustAlphaBoundingBox(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function thresholdScaleAdjustAlphaMask(params: {
|
||||||
|
maskBuffer: Buffer | Uint8Array;
|
||||||
|
threshold?: number;
|
||||||
|
}) {
|
||||||
|
const { maskBuffer, threshold = 96 } = params;
|
||||||
|
const output = new Uint8Array(maskBuffer.length);
|
||||||
|
for (let index = 0; index < maskBuffer.length; index += 1) {
|
||||||
|
output[index] = (maskBuffer[index] || 0) >= threshold ? 255 : 0;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getScaleAdjustAlphaBandingStats(params: {
|
||||||
|
height: number;
|
||||||
|
maskBuffer: Buffer | Uint8Array;
|
||||||
|
threshold?: number;
|
||||||
|
width: number;
|
||||||
|
}) {
|
||||||
|
const { height, maskBuffer, threshold = 24, width } = params;
|
||||||
|
const mask = thresholdScaleAdjustAlphaMask({ maskBuffer, threshold });
|
||||||
|
const bbox = getScaleAdjustMaskBoundingBox({ height, mask, width });
|
||||||
|
if (!bbox) {
|
||||||
|
return {
|
||||||
|
activeRowRatio: 0,
|
||||||
|
bboxHeightRatio: 0,
|
||||||
|
bboxWidthRatio: 0,
|
||||||
|
detected: false,
|
||||||
|
transitionRatio: 0,
|
||||||
|
wideRowRatio: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let activeRows = 0;
|
||||||
|
let transitions = 0;
|
||||||
|
let wideRows = 0;
|
||||||
|
let previousCoverage: number | null = null;
|
||||||
|
for (let y = bbox.top; y < bbox.top + bbox.height; y += 1) {
|
||||||
|
let rowCount = 0;
|
||||||
|
for (let x = bbox.left; x < bbox.left + bbox.width; x += 1) {
|
||||||
|
if (mask[y * width + x] !== 0) rowCount += 1;
|
||||||
|
}
|
||||||
|
const coverage = rowCount / Math.max(1, bbox.width);
|
||||||
|
if (coverage >= 0.08) activeRows += 1;
|
||||||
|
if (coverage >= 0.45) wideRows += 1;
|
||||||
|
if (
|
||||||
|
previousCoverage !== null &&
|
||||||
|
Math.abs(coverage - previousCoverage) >= 0.28
|
||||||
|
) {
|
||||||
|
transitions += 1;
|
||||||
|
}
|
||||||
|
previousCoverage = coverage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bboxHeightRatio = bbox.height / Math.max(1, height);
|
||||||
|
const bboxWidthRatio = bbox.width / Math.max(1, width);
|
||||||
|
const activeRowRatio = activeRows / Math.max(1, bbox.height);
|
||||||
|
const transitionRatio = transitions / Math.max(1, bbox.height - 1);
|
||||||
|
const wideRowRatio = wideRows / Math.max(1, bbox.height);
|
||||||
|
const detected =
|
||||||
|
(bboxWidthRatio >= 0.38 &&
|
||||||
|
bboxHeightRatio >= 0.22 &&
|
||||||
|
wideRowRatio >= 0.18 &&
|
||||||
|
transitionRatio >= 0.12) ||
|
||||||
|
(bboxWidthRatio >= 0.55 &&
|
||||||
|
activeRowRatio >= 0.45 &&
|
||||||
|
transitionRatio >= 0.09);
|
||||||
|
|
||||||
|
return {
|
||||||
|
activeRowRatio: Number(activeRowRatio.toFixed(3)),
|
||||||
|
bboxHeightRatio: Number(bboxHeightRatio.toFixed(3)),
|
||||||
|
bboxWidthRatio: Number(bboxWidthRatio.toFixed(3)),
|
||||||
|
detected,
|
||||||
|
transitionRatio: Number(transitionRatio.toFixed(3)),
|
||||||
|
wideRowRatio: Number(wideRowRatio.toFixed(3)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async function cleanScaleAdjustAlphaChannel(params: {
|
async function cleanScaleAdjustAlphaChannel(params: {
|
||||||
height: number;
|
height: number;
|
||||||
referenceRawRgb?: Buffer | null;
|
referenceRawRgb?: Buffer | null;
|
||||||
@ -1883,14 +1960,45 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
|
|||||||
targetWidth: placement.sourceBox.width,
|
targetWidth: placement.sourceBox.width,
|
||||||
width: cutoutWidth,
|
width: cutoutWidth,
|
||||||
});
|
});
|
||||||
|
const alphaBandingStats = getScaleAdjustAlphaBandingStats({
|
||||||
|
height: placement.sourceBox.height,
|
||||||
|
maskBuffer: sourceMaskBuffer,
|
||||||
|
width: placement.sourceBox.width,
|
||||||
|
});
|
||||||
|
if (alphaBandingStats.detected) {
|
||||||
|
console.warn(
|
||||||
|
"[Canvas Local Edit] Scale adjust RMBG alpha banding detected; fallback to pixel mask:",
|
||||||
|
alphaBandingStats
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const background = estimateScaleAdjustBoxBackground({
|
const background = estimateScaleAdjustBoxBackground({
|
||||||
box: placement.sourceBox,
|
box: placement.sourceBox,
|
||||||
raw,
|
raw,
|
||||||
width: sourceWidth,
|
width: sourceWidth,
|
||||||
});
|
});
|
||||||
|
const highConfidenceSourceMask = thresholdScaleAdjustAlphaMask({
|
||||||
|
maskBuffer: sourceMaskBuffer,
|
||||||
|
threshold: 96,
|
||||||
|
});
|
||||||
|
const filteredSourceMask = filterScaleAdjustStructureComponents({
|
||||||
|
box: placement.sourceBox,
|
||||||
|
mask: highConfidenceSourceMask,
|
||||||
|
});
|
||||||
|
const filteredSourceBbox = getScaleAdjustMaskBoundingBox({
|
||||||
|
height: placement.sourceBox.height,
|
||||||
|
mask: filteredSourceMask,
|
||||||
|
width: placement.sourceBox.width,
|
||||||
|
});
|
||||||
|
const sourceWashBaseMask = filteredSourceBbox
|
||||||
|
? solidifyScaleAdjustStructureMask({
|
||||||
|
box: placement.sourceBox,
|
||||||
|
mask: filteredSourceMask,
|
||||||
|
})
|
||||||
|
: highConfidenceSourceMask;
|
||||||
const sourceWashMask = dilateScaleAdjustStructureMask({
|
const sourceWashMask = dilateScaleAdjustStructureMask({
|
||||||
height: placement.sourceBox.height,
|
height: placement.sourceBox.height,
|
||||||
mask: new Uint8Array(sourceMaskBuffer),
|
mask: sourceWashBaseMask,
|
||||||
radius: Math.max(
|
radius: Math.max(
|
||||||
2,
|
2,
|
||||||
Math.round(
|
Math.round(
|
||||||
@ -1977,6 +2085,7 @@ async function buildScaleAdjustRmbgStructureLockedComposite(params: {
|
|||||||
placedHeight,
|
placedHeight,
|
||||||
placedWidth,
|
placedWidth,
|
||||||
sameSizeCutout,
|
sameSizeCutout,
|
||||||
|
alphaBandingStats,
|
||||||
sourceHeight: placement.sourceBox.height,
|
sourceHeight: placement.sourceBox.height,
|
||||||
sourceWidth: placement.sourceBox.width,
|
sourceWidth: placement.sourceBox.width,
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user