fix: limit scale patch composite to edit regions
This commit is contained in:
parent
5a4e087b3d
commit
0a591456c4
@ -3900,6 +3900,7 @@ export async function POST(request: NextRequest) {
|
||||
featherMaxPx: 42,
|
||||
featherMinPx: 10,
|
||||
featherRatio: 0.018,
|
||||
regions: scaleAdjustCompositeRegions,
|
||||
sourceImageUrl,
|
||||
workspaceRegion: scaleAdjustPatchReference.workspaceRect,
|
||||
}
|
||||
|
||||
@ -56,6 +56,7 @@ export interface CanvasLocalEditCompositeConfig {
|
||||
export interface CanvasScaleAdjustPatchCompositeConfig {
|
||||
sourceImageUrl: string;
|
||||
workspaceRegion: CanvasLocalEditCompositeRegion;
|
||||
regions?: CanvasLocalEditCompositeRegion[];
|
||||
featherMinPx?: number;
|
||||
featherMaxPx?: number;
|
||||
featherRatio?: number;
|
||||
@ -384,10 +385,18 @@ function normalizeScaleAdjustPatchCompositeConfig(
|
||||
if (!/^https?:\/\//i.test(sourceImageUrl)) return null;
|
||||
const workspaceRegion = normalizeCanvasRegion(value.workspaceRegion);
|
||||
if (!workspaceRegion) return null;
|
||||
const regions = Array.isArray(value.regions)
|
||||
? value.regions
|
||||
.map((region) => normalizeCanvasRegion(region))
|
||||
.filter((region): region is CanvasLocalEditCompositeRegion =>
|
||||
Boolean(region)
|
||||
)
|
||||
: [];
|
||||
|
||||
return {
|
||||
sourceImageUrl,
|
||||
workspaceRegion,
|
||||
...(regions.length > 0 ? { regions } : {}),
|
||||
featherMaxPx: normalizeOptionalNumber(value.featherMaxPx, {
|
||||
max: 180,
|
||||
min: 0,
|
||||
@ -2335,6 +2344,7 @@ function buildScaleAdjustPatchCompositeMaskSvg(params: {
|
||||
width: number;
|
||||
height: number;
|
||||
featherPx: number;
|
||||
regions?: Array<{ left: number; top: number; width: number; height: number }>;
|
||||
touchesLeft: boolean;
|
||||
touchesTop: boolean;
|
||||
touchesRight: boolean;
|
||||
@ -2342,6 +2352,46 @@ function buildScaleAdjustPatchCompositeMaskSvg(params: {
|
||||
}) {
|
||||
const { height, width } = params;
|
||||
const featherPx = Math.max(0, Math.round(params.featherPx));
|
||||
const regions = params.regions?.filter(
|
||||
(region) => region.width > 0 && region.height > 0
|
||||
);
|
||||
if (regions?.length) {
|
||||
const blur = Math.max(1, featherPx);
|
||||
const softPad = Math.max(2, Math.round(featherPx * 1.35));
|
||||
const corePad = Math.max(0, Math.round(featherPx * 0.22));
|
||||
const softRects = regions
|
||||
.map((region) => {
|
||||
const left = Math.max(0, region.left - softPad);
|
||||
const top = Math.max(0, region.top - softPad);
|
||||
const right = Math.min(width, region.left + region.width + softPad);
|
||||
const bottom = Math.min(height, region.top + region.height + softPad);
|
||||
return `<rect x="${left}" y="${top}" width="${Math.max(1, right - left)}" height="${Math.max(1, bottom - top)}" fill="#ffffff" filter="url(#scale-adjust-patch-soft-mask)" />`;
|
||||
})
|
||||
.join("");
|
||||
const coreRects = regions
|
||||
.map((region) => {
|
||||
const left = Math.max(0, region.left - corePad);
|
||||
const top = Math.max(0, region.top - corePad);
|
||||
const right = Math.min(width, region.left + region.width + corePad);
|
||||
const bottom = Math.min(height, region.top + region.height + corePad);
|
||||
return `<rect x="${left}" y="${top}" width="${Math.max(1, right - left)}" height="${Math.max(1, bottom - top)}" fill="#ffffff" />`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
return Buffer.from(`
|
||||
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<filter id="scale-adjust-patch-soft-mask" x="-50%" y="-50%" width="200%" height="200%" color-interpolation-filters="sRGB">
|
||||
<feGaussianBlur stdDeviation="${blur}" />
|
||||
</filter>
|
||||
</defs>
|
||||
<rect x="0" y="0" width="${width}" height="${height}" fill="rgba(0,0,0,0)" />
|
||||
${softRects}
|
||||
${coreRects}
|
||||
</svg>
|
||||
`);
|
||||
}
|
||||
|
||||
if (featherPx <= 0) {
|
||||
return Buffer.from(`
|
||||
<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg">
|
||||
@ -2671,9 +2721,37 @@ async function applyScaleAdjustPatchCompositeToImages(params: {
|
||||
const touchesTop = workspaceBox.top <= 0;
|
||||
const touchesRight = workspaceBox.left + workspaceBox.width >= sourceWidth;
|
||||
const touchesBottom = workspaceBox.top + workspaceBox.height >= sourceHeight;
|
||||
const maskRegionBoxes = composite.regions
|
||||
?.map((region) =>
|
||||
rectToPixelBox({
|
||||
height: sourceHeight,
|
||||
region,
|
||||
width: sourceWidth,
|
||||
})
|
||||
)
|
||||
.map((box) => {
|
||||
const left = Math.max(0, box.left - workspaceBox.left);
|
||||
const top = Math.max(0, box.top - workspaceBox.top);
|
||||
const right = Math.min(
|
||||
workspaceBox.width,
|
||||
box.left + box.width - workspaceBox.left
|
||||
);
|
||||
const bottom = Math.min(
|
||||
workspaceBox.height,
|
||||
box.top + box.height - workspaceBox.top
|
||||
);
|
||||
return {
|
||||
left,
|
||||
top,
|
||||
width: Math.max(0, right - left),
|
||||
height: Math.max(0, bottom - top),
|
||||
};
|
||||
})
|
||||
.filter((box) => box.width > 0 && box.height > 0);
|
||||
const patchMask = buildScaleAdjustPatchCompositeMaskSvg({
|
||||
featherPx,
|
||||
height: workspaceBox.height,
|
||||
regions: maskRegionBoxes,
|
||||
touchesBottom,
|
||||
touchesLeft,
|
||||
touchesRight,
|
||||
@ -2733,6 +2811,7 @@ async function applyScaleAdjustPatchCompositeToImages(params: {
|
||||
debugLabel,
|
||||
featherPx,
|
||||
imageCount: mergedImages.length,
|
||||
maskRegionCount: maskRegionBoxes?.length || 0,
|
||||
sourceHeight,
|
||||
sourceWidth,
|
||||
workspaceBox,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user