fix: composite scale patches with diff masks
This commit is contained in:
parent
026164f86d
commit
b4db755c45
@ -780,6 +780,16 @@ function buildScaleAdjustCompositeRegions(
|
||||
});
|
||||
}
|
||||
|
||||
function buildScaleAdjustPatchCompositeRegions(
|
||||
regions: NormalizedLocalEditRegion[],
|
||||
scalePercent?: ScaleAdjustPercent | null
|
||||
) {
|
||||
return regions.flatMap((region) => [
|
||||
region.rect,
|
||||
getScaleAdjustTargetRect(region, scalePercent),
|
||||
]);
|
||||
}
|
||||
|
||||
function getScaleAdjustPatchWorkspaceRect(
|
||||
regions: NormalizedLocalEditRegion[],
|
||||
scalePercent?: ScaleAdjustPercent | null
|
||||
@ -3860,6 +3870,9 @@ export async function POST(request: NextRequest) {
|
||||
const scaleAdjustCompositeRegions = isScaleAdjustOperation
|
||||
? buildScaleAdjustCompositeRegions(regions, scalePercent)
|
||||
: [];
|
||||
const scaleAdjustPatchCompositeRegions = isScaleAdjustOperation
|
||||
? buildScaleAdjustPatchCompositeRegions(regions, scalePercent)
|
||||
: [];
|
||||
const scaleAdjustProtectedRegions =
|
||||
isScaleAdjustOperation && scaleAdjustPatchReference
|
||||
? [...scaleAdjustCompositeRegions, scaleAdjustPatchReference.workspaceRect]
|
||||
@ -4060,9 +4073,14 @@ export async function POST(request: NextRequest) {
|
||||
referenceImages,
|
||||
scaleAdjustPatchComposite: scaleAdjustPatchReference
|
||||
? {
|
||||
diffCompareBlurPx: 0.8,
|
||||
diffHighThreshold: 42,
|
||||
diffLowThreshold: 14,
|
||||
featherMaxPx: 42,
|
||||
featherMinPx: 10,
|
||||
featherRatio: 0.018,
|
||||
maskMode: "diff",
|
||||
regions: scaleAdjustPatchCompositeRegions,
|
||||
sourceImageUrl,
|
||||
workspaceRegion: scaleAdjustPatchReference.workspaceRect,
|
||||
}
|
||||
|
||||
@ -57,6 +57,10 @@ export interface CanvasScaleAdjustPatchCompositeConfig {
|
||||
sourceImageUrl: string;
|
||||
workspaceRegion: CanvasLocalEditCompositeRegion;
|
||||
regions?: CanvasLocalEditCompositeRegion[];
|
||||
maskMode?: "workspace" | "diff";
|
||||
diffLowThreshold?: number;
|
||||
diffHighThreshold?: number;
|
||||
diffCompareBlurPx?: number;
|
||||
featherMinPx?: number;
|
||||
featherMaxPx?: number;
|
||||
featherRatio?: number;
|
||||
@ -397,6 +401,19 @@ function normalizeScaleAdjustPatchCompositeConfig(
|
||||
sourceImageUrl,
|
||||
workspaceRegion,
|
||||
...(regions.length > 0 ? { regions } : {}),
|
||||
maskMode: value.maskMode === "diff" ? "diff" : "workspace",
|
||||
diffHighThreshold: normalizeOptionalNumber(value.diffHighThreshold, {
|
||||
max: 120,
|
||||
min: 1,
|
||||
}),
|
||||
diffLowThreshold: normalizeOptionalNumber(value.diffLowThreshold, {
|
||||
max: 80,
|
||||
min: 0,
|
||||
}),
|
||||
diffCompareBlurPx: normalizeOptionalNumber(value.diffCompareBlurPx, {
|
||||
max: 12,
|
||||
min: 0,
|
||||
}),
|
||||
featherMaxPx: normalizeOptionalNumber(value.featherMaxPx, {
|
||||
max: 180,
|
||||
min: 0,
|
||||
@ -2748,27 +2765,69 @@ async function applyScaleAdjustPatchCompositeToImages(params: {
|
||||
};
|
||||
})
|
||||
.filter((box) => box.width > 0 && box.height > 0);
|
||||
const patchMask = buildScaleAdjustPatchCompositeMaskSvg({
|
||||
featherPx,
|
||||
height: workspaceBox.height,
|
||||
regions: maskRegionBoxes,
|
||||
touchesBottom,
|
||||
touchesLeft,
|
||||
touchesRight,
|
||||
touchesTop,
|
||||
width: workspaceBox.width,
|
||||
});
|
||||
const staticPatchMask =
|
||||
composite.maskMode === "diff"
|
||||
? null
|
||||
: buildScaleAdjustPatchCompositeMaskSvg({
|
||||
featherPx,
|
||||
height: workspaceBox.height,
|
||||
regions: maskRegionBoxes,
|
||||
touchesBottom,
|
||||
touchesLeft,
|
||||
touchesRight,
|
||||
touchesTop,
|
||||
width: workspaceBox.width,
|
||||
});
|
||||
const sourcePatchBuffer = await sharp(sourceBuffer, { failOn: "none" })
|
||||
.extract(workspaceBox)
|
||||
.png({ compressionLevel: 6 })
|
||||
.toBuffer();
|
||||
const diffRegions = (maskRegionBoxes?.length
|
||||
? maskRegionBoxes
|
||||
: [{ left: 0, top: 0, width: workspaceBox.width, height: workspaceBox.height }]
|
||||
).map((box) => ({
|
||||
x: box.left / Math.max(1, workspaceBox.width),
|
||||
y: box.top / Math.max(1, workspaceBox.height),
|
||||
width: box.width / Math.max(1, workspaceBox.width),
|
||||
height: box.height / Math.max(1, workspaceBox.height),
|
||||
}));
|
||||
|
||||
const mergedImages: ParsedImage[] = [];
|
||||
for (const [index, image] of images.entries()) {
|
||||
const generatedUrl = image.originalUrl || image.thumbnailUrl;
|
||||
const generatedBuffer = await fetchImageBufferFromUrl(generatedUrl);
|
||||
const patchOverlayBuffer = await sharp(generatedBuffer, { failOn: "none" })
|
||||
const resizedGeneratedBuffer = await sharp(generatedBuffer, { failOn: "none" })
|
||||
.rotate()
|
||||
.resize(workspaceBox.width, workspaceBox.height, {
|
||||
fit: "cover",
|
||||
position: "center",
|
||||
})
|
||||
.png({ compressionLevel: 6 })
|
||||
.toBuffer();
|
||||
const patchMask =
|
||||
composite.maskMode === "diff"
|
||||
? await buildLocalEditDiffCompositeMask({
|
||||
composite: {
|
||||
diffCompareBlurPx: composite.diffCompareBlurPx,
|
||||
diffHighThreshold: composite.diffHighThreshold,
|
||||
diffLowThreshold: composite.diffLowThreshold,
|
||||
featherMaxPx: composite.featherMaxPx,
|
||||
featherMinPx: composite.featherMinPx,
|
||||
featherRatio: composite.featherRatio,
|
||||
maskMode: "diff",
|
||||
regions: diffRegions,
|
||||
sourceImageUrl: composite.sourceImageUrl,
|
||||
},
|
||||
generatedBuffer: resizedGeneratedBuffer,
|
||||
height: workspaceBox.height,
|
||||
sourceBuffer: sourcePatchBuffer,
|
||||
width: workspaceBox.width,
|
||||
})
|
||||
: staticPatchMask;
|
||||
if (!patchMask) {
|
||||
throw new Error("比例调整局部结果合成失败:无法生成合成蒙版");
|
||||
}
|
||||
const patchOverlayBuffer = await sharp(resizedGeneratedBuffer, { failOn: "none" })
|
||||
.ensureAlpha()
|
||||
.composite([{ input: patchMask, blend: "dest-in" }])
|
||||
.png({ compressionLevel: 6 })
|
||||
@ -2811,6 +2870,7 @@ async function applyScaleAdjustPatchCompositeToImages(params: {
|
||||
debugLabel,
|
||||
featherPx,
|
||||
imageCount: mergedImages.length,
|
||||
maskMode: composite.maskMode || "workspace",
|
||||
maskRegionCount: maskRegionBoxes?.length || 0,
|
||||
sourceHeight,
|
||||
sourceWidth,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user