mirror of
https://github.com/Azornes/Comfyui-LayerForge.git
synced 2026-03-24 22:12:17 -03:00
Refactor mask editor cropping and formatting in Canvas.js
Updated the mask processing logic to crop the mask based on the viewport pan position instead of scaling, ensuring accurate mask editing. Also standardized object formatting in logging and context creation for consistency.
This commit is contained in:
78
js/Canvas.js
78
js/Canvas.js
@@ -26,7 +26,7 @@ export class Canvas {
|
|||||||
this.node = node;
|
this.node = node;
|
||||||
this.widget = widget;
|
this.widget = widget;
|
||||||
this.canvas = document.createElement('canvas');
|
this.canvas = document.createElement('canvas');
|
||||||
this.ctx = this.canvas.getContext('2d', { willReadFrequently: true });
|
this.ctx = this.canvas.getContext('2d', {willReadFrequently: true});
|
||||||
this.width = 512;
|
this.width = 512;
|
||||||
this.height = 512;
|
this.height = 512;
|
||||||
this.layers = [];
|
this.layers = [];
|
||||||
@@ -60,7 +60,7 @@ export class Canvas {
|
|||||||
log.debug('Canvas widget element:', this.node);
|
log.debug('Canvas widget element:', this.node);
|
||||||
log.info('Canvas initialized', {
|
log.info('Canvas initialized', {
|
||||||
nodeId: this.node.id,
|
nodeId: this.node.id,
|
||||||
dimensions: { width: this.width, height: this.height },
|
dimensions: {width: this.width, height: this.height},
|
||||||
viewport: this.viewport
|
viewport: this.viewport
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ export class Canvas {
|
|||||||
* @param {boolean} replaceLast - Czy zastąpić ostatni stan w historii
|
* @param {boolean} replaceLast - Czy zastąpić ostatni stan w historii
|
||||||
*/
|
*/
|
||||||
saveState(replaceLast = false) {
|
saveState(replaceLast = false) {
|
||||||
log.debug('Saving canvas state', { replaceLast, layersCount: this.layers.length });
|
log.debug('Saving canvas state', {replaceLast, layersCount: this.layers.length});
|
||||||
this.canvasState.saveState(replaceLast);
|
this.canvasState.saveState(replaceLast);
|
||||||
this.incrementOperationCount();
|
this.incrementOperationCount();
|
||||||
this._notifyStateChange();
|
this._notifyStateChange();
|
||||||
@@ -683,7 +683,7 @@ export class Canvas {
|
|||||||
throw new Error("Old mask editor canvas not found");
|
throw new Error("Old mask editor canvas not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
const maskCtx = maskCanvas.getContext('2d', { willReadFrequently: true });
|
const maskCtx = maskCanvas.getContext('2d', {willReadFrequently: true});
|
||||||
|
|
||||||
const maskColor = {r: 255, g: 255, b: 255};
|
const maskColor = {r: 255, g: 255, b: 255};
|
||||||
const processedMask = await this.processMaskForEditor(maskData, maskCanvas.width, maskCanvas.height, maskColor);
|
const processedMask = await this.processMaskForEditor(maskData, maskCanvas.width, maskCanvas.height, maskColor);
|
||||||
@@ -699,59 +699,58 @@ export class Canvas {
|
|||||||
* @param {number} targetHeight - Docelowa wysokość
|
* @param {number} targetHeight - Docelowa wysokość
|
||||||
* @param {Object} maskColor - Kolor maski {r, g, b}
|
* @param {Object} maskColor - Kolor maski {r, g, b}
|
||||||
* @returns {HTMLCanvasElement} Przetworzona maska
|
* @returns {HTMLCanvasElement} Przetworzona maska
|
||||||
*/
|
*/async processMaskForEditor(maskData, targetWidth, targetHeight, maskColor) {
|
||||||
async processMaskForEditor(maskData, targetWidth, targetHeight, maskColor) {
|
// Współrzędne przesunięcia (pan) widoku edytora
|
||||||
const originalWidth = maskData.width || maskData.naturalWidth || this.width;
|
const panX = this.maskTool.x;
|
||||||
const originalHeight = maskData.height || maskData.naturalHeight || this.height;
|
const panY = this.maskTool.y;
|
||||||
|
|
||||||
log.info("Processing mask for editor:", {
|
log.info("Processing mask for editor:", {
|
||||||
originalSize: {width: originalWidth, height: originalHeight},
|
sourceSize: {width: maskData.width, height: maskData.height},
|
||||||
targetSize: {width: targetWidth, height: targetHeight},
|
targetSize: {width: targetWidth, height: targetHeight},
|
||||||
canvasSize: {width: this.width, height: this.height}
|
viewportPan: {x: panX, y: panY}
|
||||||
});
|
});
|
||||||
|
|
||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
tempCanvas.width = targetWidth;
|
tempCanvas.width = targetWidth;
|
||||||
tempCanvas.height = targetHeight;
|
tempCanvas.height = targetHeight;
|
||||||
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });
|
const tempCtx = tempCanvas.getContext('2d', {willReadFrequently: true});
|
||||||
|
|
||||||
tempCtx.clearRect(0, 0, targetWidth, targetHeight);
|
const sourceX = -panX;
|
||||||
|
const sourceY = -panY;
|
||||||
|
|
||||||
|
tempCtx.drawImage(
|
||||||
|
maskData, // Źródło: pełna maska z "output area"
|
||||||
|
sourceX, // sx: Prawdziwa współrzędna X na dużej masce (np. 1000)
|
||||||
|
sourceY, // sy: Prawdziwa współrzędna Y na dużej masce (np. 1000)
|
||||||
|
targetWidth, // sWidth: Szerokość wycinanego fragmentu
|
||||||
|
targetHeight, // sHeight: Wysokość wycinanego fragmentu
|
||||||
|
0, // dx: Gdzie wkleić w płótnie docelowym (zawsze 0)
|
||||||
|
0, // dy: Gdzie wkleić w płótnie docelowym (zawsze 0)
|
||||||
|
targetWidth, // dWidth: Szerokość wklejanego obrazu
|
||||||
|
targetHeight // dHeight: Wysokość wklejanego obrazu
|
||||||
|
);
|
||||||
|
|
||||||
const scaleToOriginal = Math.min(originalWidth / this.width, originalHeight / this.height);
|
log.info("Mask viewport cropped correctly.", {
|
||||||
|
source: "maskData",
|
||||||
const scaledWidth = this.width * scaleToOriginal;
|
cropArea: {x: sourceX, y: sourceY, width: targetWidth, height: targetHeight}
|
||||||
const scaledHeight = this.height * scaleToOriginal;
|
|
||||||
|
|
||||||
const offsetX = (targetWidth - scaledWidth) / 2;
|
|
||||||
const offsetY = (targetHeight - scaledHeight) / 2;
|
|
||||||
|
|
||||||
tempCtx.drawImage(maskData, offsetX, offsetY, scaledWidth, scaledHeight);
|
|
||||||
|
|
||||||
log.info("Mask drawn scaled to original image size:", {
|
|
||||||
originalSize: {width: originalWidth, height: originalHeight},
|
|
||||||
targetSize: {width: targetWidth, height: targetHeight},
|
|
||||||
canvasSize: {width: this.width, height: this.height},
|
|
||||||
scaleToOriginal: scaleToOriginal,
|
|
||||||
finalSize: {width: scaledWidth, height: scaledHeight},
|
|
||||||
offset: {x: offsetX, y: offsetY}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Reszta kodu (zmiana koloru) pozostaje bez zmian
|
||||||
const imageData = tempCtx.getImageData(0, 0, targetWidth, targetHeight);
|
const imageData = tempCtx.getImageData(0, 0, targetWidth, targetHeight);
|
||||||
const data = imageData.data;
|
const data = imageData.data;
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
const alpha = data[i + 3]; // Oryginalny kanał alpha
|
const alpha = data[i + 3];
|
||||||
|
if (alpha > 0) {
|
||||||
data[i] = maskColor.r; // R
|
data[i] = maskColor.r;
|
||||||
data[i + 1] = maskColor.g; // G
|
data[i + 1] = maskColor.g;
|
||||||
data[i + 2] = maskColor.b; // B
|
data[i + 2] = maskColor.b;
|
||||||
data[i + 3] = alpha; // Zachowaj oryginalny alpha
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tempCtx.putImageData(imageData, 0, 0);
|
tempCtx.putImageData(imageData, 0, 0);
|
||||||
|
|
||||||
log.info("Mask processing completed - full size scaling applied");
|
log.info("Mask processing completed - color applied.");
|
||||||
return tempCanvas;
|
return tempCanvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,6 +783,7 @@ export class Canvas {
|
|||||||
setTimeout(this.waitWhileMaskEditing.bind(this), 100);
|
setTimeout(this.waitWhileMaskEditing.bind(this), 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zapisuje obecny stan maski przed otwarciem editora
|
* Zapisuje obecny stan maski przed otwarciem editora
|
||||||
* @returns {Object} Zapisany stan maski
|
* @returns {Object} Zapisany stan maski
|
||||||
@@ -797,7 +797,7 @@ export class Canvas {
|
|||||||
const savedCanvas = document.createElement('canvas');
|
const savedCanvas = document.createElement('canvas');
|
||||||
savedCanvas.width = maskCanvas.width;
|
savedCanvas.width = maskCanvas.width;
|
||||||
savedCanvas.height = maskCanvas.height;
|
savedCanvas.height = maskCanvas.height;
|
||||||
const savedCtx = savedCanvas.getContext('2d', { willReadFrequently: true });
|
const savedCtx = savedCanvas.getContext('2d', {willReadFrequently: true});
|
||||||
savedCtx.drawImage(maskCanvas, 0, 0);
|
savedCtx.drawImage(maskCanvas, 0, 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -893,7 +893,7 @@ export class Canvas {
|
|||||||
const tempCanvas = document.createElement('canvas');
|
const tempCanvas = document.createElement('canvas');
|
||||||
tempCanvas.width = this.width;
|
tempCanvas.width = this.width;
|
||||||
tempCanvas.height = this.height;
|
tempCanvas.height = this.height;
|
||||||
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });
|
const tempCtx = tempCanvas.getContext('2d', {willReadFrequently: true});
|
||||||
|
|
||||||
tempCtx.drawImage(resultImage, 0, 0, this.width, this.height);
|
tempCtx.drawImage(resultImage, 0, 0, this.width, this.height);
|
||||||
|
|
||||||
@@ -920,7 +920,7 @@ export class Canvas {
|
|||||||
const destX = -this.maskTool.x;
|
const destX = -this.maskTool.x;
|
||||||
const destY = -this.maskTool.y;
|
const destY = -this.maskTool.y;
|
||||||
|
|
||||||
log.debug("Applying mask to canvas", { destX, destY });
|
log.debug("Applying mask to canvas", {destX, destY});
|
||||||
|
|
||||||
maskCtx.globalCompositeOperation = 'source-over';
|
maskCtx.globalCompositeOperation = 'source-over';
|
||||||
maskCtx.clearRect(destX, destY, this.width, this.height);
|
maskCtx.clearRect(destX, destY, this.width, this.height);
|
||||||
|
|||||||
Reference in New Issue
Block a user