mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-21 20:52:12 -03:00
Add mask drawing tool and improve mask handling
Introduces a new MaskTool for interactive mask drawing with adjustable brush size, strength, and softness. Updates Canvas.js to integrate mask editing, rendering, and saving, including support for saving images with and without masks. Enhances the UI in Canvas_view.js with mask controls and a dialog for canvas resizing. Updates canvas_node.py to load images without masks for processing. These changes improve user control over mask creation and management in the canvas workflow.
This commit is contained in:
142
js/Mask_tool.js
Normal file
142
js/Mask_tool.js
Normal file
@@ -0,0 +1,142 @@
|
||||
export class MaskTool {
|
||||
constructor(canvasInstance) {
|
||||
this.canvasInstance = canvasInstance;
|
||||
this.mainCanvas = canvasInstance.canvas;
|
||||
this.maskCanvas = document.createElement('canvas');
|
||||
this.maskCtx = this.maskCanvas.getContext('2d');
|
||||
|
||||
this.isActive = false;
|
||||
this.brushSize = 20;
|
||||
this.brushStrength = 0.5;
|
||||
this.brushSoftness = 0.5; // Domyślna miękkość pędzla (0 - twardy, 1 - bardzo miękki)
|
||||
this.isDrawing = false;
|
||||
this.lastPosition = null;
|
||||
|
||||
this.initMaskCanvas();
|
||||
}
|
||||
|
||||
setBrushSoftness(softness) {
|
||||
this.brushSoftness = Math.max(0, Math.min(1, softness));
|
||||
}
|
||||
|
||||
initMaskCanvas() {
|
||||
this.maskCanvas.width = this.mainCanvas.width;
|
||||
this.maskCanvas.height = this.mainCanvas.height;
|
||||
this.clear();
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.isActive = true;
|
||||
this.canvasInstance.interaction.mode = 'drawingMask';
|
||||
console.log("Mask tool activated");
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.isActive = false;
|
||||
this.canvasInstance.interaction.mode = 'none';
|
||||
console.log("Mask tool deactivated");
|
||||
}
|
||||
|
||||
setBrushSize(size) {
|
||||
this.brushSize = Math.max(1, size);
|
||||
}
|
||||
|
||||
setBrushStrength(strength) {
|
||||
this.brushStrength = Math.max(0, Math.min(1, strength));
|
||||
}
|
||||
|
||||
handleMouseDown(worldCoords) {
|
||||
if (!this.isActive) return;
|
||||
this.isDrawing = true;
|
||||
this.lastPosition = worldCoords;
|
||||
this.draw(worldCoords);
|
||||
}
|
||||
|
||||
handleMouseMove(worldCoords) {
|
||||
if (!this.isActive || !this.isDrawing) return;
|
||||
this.draw(worldCoords);
|
||||
this.lastPosition = worldCoords;
|
||||
}
|
||||
|
||||
handleMouseUp() {
|
||||
if (!this.isActive) return;
|
||||
this.isDrawing = false;
|
||||
this.lastPosition = null;
|
||||
}
|
||||
|
||||
draw(worldCoords) {
|
||||
if (!this.lastPosition) {
|
||||
this.lastPosition = worldCoords;
|
||||
}
|
||||
|
||||
this.maskCtx.beginPath();
|
||||
this.maskCtx.moveTo(this.lastPosition.x, this.lastPosition.y);
|
||||
this.maskCtx.lineTo(worldCoords.x, worldCoords.y);
|
||||
|
||||
// Utwórz gradient radialny dla miękkości pędzla
|
||||
const gradientRadius = this.brushSize / 2;
|
||||
const softnessFactor = this.brushSoftness * gradientRadius;
|
||||
const gradient = this.maskCtx.createRadialGradient(
|
||||
worldCoords.x, worldCoords.y, gradientRadius - softnessFactor,
|
||||
worldCoords.x, worldCoords.y, gradientRadius
|
||||
);
|
||||
gradient.addColorStop(0, `rgba(255, 255, 255, ${this.brushStrength})`);
|
||||
gradient.addColorStop(1, `rgba(255, 255, 255, 0)`);
|
||||
|
||||
this.maskCtx.strokeStyle = gradient;
|
||||
this.maskCtx.lineWidth = this.brushSize;
|
||||
this.maskCtx.lineCap = 'round';
|
||||
this.maskCtx.lineJoin = 'round';
|
||||
|
||||
this.maskCtx.globalCompositeOperation = 'source-over';
|
||||
this.maskCtx.stroke();
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.maskCtx.clearRect(0, 0, this.maskCanvas.width, this.maskCanvas.height);
|
||||
}
|
||||
|
||||
getMask() {
|
||||
return this.maskCanvas;
|
||||
}
|
||||
|
||||
getMaskImageWithAlpha() {
|
||||
const tempCanvas = document.createElement('canvas');
|
||||
tempCanvas.width = this.maskCanvas.width;
|
||||
tempCanvas.height = this.maskCanvas.height;
|
||||
const tempCtx = tempCanvas.getContext('2d');
|
||||
|
||||
// Kopiuj maskę na tymczasowy canvas
|
||||
tempCtx.drawImage(this.maskCanvas, 0, 0);
|
||||
|
||||
// Pobierz dane pikseli
|
||||
const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
||||
const data = imageData.data;
|
||||
|
||||
// Modyfikuj kanał alfa, aby zachować zróżnicowaną przezroczystość
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const alpha = data[i]; // Wartość alfa (0-255)
|
||||
data[i] = 255; // Czerwony
|
||||
data[i + 1] = 255; // Zielony
|
||||
data[i + 2] = 255; // Niebieski
|
||||
data[i + 3] = alpha; // Alfa (zachowaj oryginalną wartość)
|
||||
}
|
||||
|
||||
// Zapisz zmodyfikowane dane pikseli
|
||||
tempCtx.putImageData(imageData, 0, 0);
|
||||
|
||||
// Utwórz obraz z tymczasowego canvasu
|
||||
const maskImage = new Image();
|
||||
maskImage.src = tempCanvas.toDataURL();
|
||||
return maskImage;
|
||||
}
|
||||
|
||||
resize(width, height){
|
||||
const oldMask = this.maskCanvas;
|
||||
this.maskCanvas = document.createElement('canvas');
|
||||
this.maskCanvas.width = width;
|
||||
this.maskCanvas.height = height;
|
||||
this.maskCtx = this.maskCanvas.getContext('2d');
|
||||
this.maskCtx.drawImage(oldMask, 0, 0);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user