mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 20:52:12 -03:00
Unify mask scaling logic with scaleImageToFit util
Refactored mask scaling and drawing into the scaleImageToFit method in ImageUtils.ts. Updated CanvasIO.ts to use this utility, reducing code duplication and improving maintainability.
This commit is contained in:
@@ -2,6 +2,7 @@ import { createCanvas } from "./utils/CommonUtils.js";
|
|||||||
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
import { createModuleLogger } from "./utils/LoggerUtils.js";
|
||||||
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
import { showErrorNotification } from "./utils/NotificationUtils.js";
|
||||||
import { webSocketManager } from "./utils/WebSocketManager.js";
|
import { webSocketManager } from "./utils/WebSocketManager.js";
|
||||||
|
import { scaleImageToFit } from "./utils/ImageUtils.js";
|
||||||
import type { Canvas } from './Canvas';
|
import type { Canvas } from './Canvas';
|
||||||
import type { Layer, Shape } from './types';
|
import type { Layer, Shape } from './types';
|
||||||
|
|
||||||
@@ -665,19 +666,7 @@ export class CanvasIO {
|
|||||||
let finalMaskImg: HTMLImageElement = maskImg;
|
let finalMaskImg: HTMLImageElement = maskImg;
|
||||||
if (shouldFit) {
|
if (shouldFit) {
|
||||||
const bounds = this.canvas.outputAreaBounds;
|
const bounds = this.canvas.outputAreaBounds;
|
||||||
const scale = Math.min(bounds.width / maskImg.width, bounds.height / maskImg.height);
|
finalMaskImg = await scaleImageToFit(maskImg, bounds.width, bounds.height);
|
||||||
const scaledWidth = Math.max(1, Math.round(maskImg.width * scale));
|
|
||||||
const scaledHeight = Math.max(1, Math.round(maskImg.height * scale));
|
|
||||||
const { canvas: scaledCanvas, ctx: scaledCtx } = createCanvas(scaledWidth, scaledHeight, '2d', { willReadFrequently: true });
|
|
||||||
if (!scaledCtx) throw new Error("Could not create scaled mask context");
|
|
||||||
scaledCtx.drawImage(maskImg, 0, 0, scaledWidth, scaledHeight);
|
|
||||||
|
|
||||||
finalMaskImg = await new Promise<HTMLImageElement>((resolve, reject) => {
|
|
||||||
const img = new Image();
|
|
||||||
img.onload = () => resolve(img);
|
|
||||||
img.onerror = reject;
|
|
||||||
img.src = scaledCanvas.toDataURL();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply to MaskTool (centers internally)
|
// Apply to MaskTool (centers internally)
|
||||||
@@ -880,41 +869,15 @@ export class CanvasIO {
|
|||||||
const fitOnAddWidget2 = this.canvas.node.widgets.find((w) => w.name === "fit_on_add");
|
const fitOnAddWidget2 = this.canvas.node.widgets.find((w) => w.name === "fit_on_add");
|
||||||
const shouldFit = fitOnAddWidget2 && fitOnAddWidget2.value;
|
const shouldFit = fitOnAddWidget2 && fitOnAddWidget2.value;
|
||||||
|
|
||||||
|
let finalMaskImg: HTMLImageElement = maskImg;
|
||||||
if (shouldFit && this.canvas.maskTool) {
|
if (shouldFit && this.canvas.maskTool) {
|
||||||
// Scale mask to fit output area if fit_on_add is enabled
|
|
||||||
const bounds = this.canvas.outputAreaBounds;
|
const bounds = this.canvas.outputAreaBounds;
|
||||||
const scale = Math.min(
|
finalMaskImg = await scaleImageToFit(maskImg, bounds.width, bounds.height);
|
||||||
bounds.width / maskImg.width,
|
}
|
||||||
bounds.height / maskImg.height
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create scaled mask canvas
|
// Apply to MaskTool (centers internally)
|
||||||
const scaledWidth = Math.round(maskImg.width * scale);
|
if (this.canvas.maskTool) {
|
||||||
const scaledHeight = Math.round(maskImg.height * scale);
|
this.canvas.maskTool.setMask(finalMaskImg, true);
|
||||||
const { canvas: scaledCanvas, ctx: scaledCtx } = createCanvas(
|
|
||||||
scaledWidth,
|
|
||||||
scaledHeight,
|
|
||||||
'2d',
|
|
||||||
{ willReadFrequently: true }
|
|
||||||
);
|
|
||||||
if (!scaledCtx) throw new Error("Could not create scaled mask context");
|
|
||||||
|
|
||||||
// Draw scaled mask
|
|
||||||
scaledCtx.drawImage(maskImg, 0, 0, scaledWidth, scaledHeight);
|
|
||||||
|
|
||||||
// Convert scaled canvas to image
|
|
||||||
const scaledMaskImg = new Image();
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
scaledMaskImg.onload = resolve;
|
|
||||||
scaledMaskImg.onerror = reject;
|
|
||||||
scaledMaskImg.src = scaledCanvas.toDataURL();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Apply scaled mask to mask tool
|
|
||||||
this.canvas.maskTool.setMask(scaledMaskImg, true);
|
|
||||||
} else if (this.canvas.maskTool) {
|
|
||||||
// Apply mask at original size
|
|
||||||
this.canvas.maskTool.setMask(maskImg, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(this.canvas as any).maskAppliedFromInput = true;
|
(this.canvas as any).maskAppliedFromInput = true;
|
||||||
|
|||||||
@@ -386,3 +386,28 @@ export function canvasToMaskImage(canvas: HTMLCanvasElement): Promise<HTMLImageE
|
|||||||
img.src = canvas.toDataURL();
|
img.src = canvas.toDataURL();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scales an image to fit within specified bounds while maintaining aspect ratio
|
||||||
|
* @param image - Image to scale
|
||||||
|
* @param targetWidth - Target width to fit within
|
||||||
|
* @param targetHeight - Target height to fit within
|
||||||
|
* @returns Promise with scaled Image element
|
||||||
|
*/
|
||||||
|
export async function scaleImageToFit(image: HTMLImageElement, targetWidth: number, targetHeight: number): Promise<HTMLImageElement> {
|
||||||
|
const scale = Math.min(targetWidth / image.width, targetHeight / image.height);
|
||||||
|
const scaledWidth = Math.max(1, Math.round(image.width * scale));
|
||||||
|
const scaledHeight = Math.max(1, Math.round(image.height * scale));
|
||||||
|
|
||||||
|
const { canvas, ctx } = createCanvas(scaledWidth, scaledHeight, '2d', { willReadFrequently: true });
|
||||||
|
if (!ctx) throw new Error("Could not create scaled image context");
|
||||||
|
|
||||||
|
ctx.drawImage(image, 0, 0, scaledWidth, scaledHeight);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const scaledImg = new Image();
|
||||||
|
scaledImg.onload = () => resolve(scaledImg);
|
||||||
|
scaledImg.onerror = reject;
|
||||||
|
scaledImg.src = canvas.toDataURL();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user