diff --git a/js/CanvasIO.js b/js/CanvasIO.js index 7279a9b..f20c57a 100644 --- a/js/CanvasIO.js +++ b/js/CanvasIO.js @@ -62,25 +62,9 @@ export class CanvasIO { maskCtx.fillStyle = '#ffffff'; maskCtx.fillRect(0, 0, this.canvas.width, this.canvas.height); log.debug(`Canvas contexts created, starting layer rendering`); - const sortedLayers = this.canvas.layers.sort((a, b) => a.zIndex - b.zIndex); - log.debug(`Processing ${sortedLayers.length} layers in order`); - sortedLayers.forEach((layer, index) => { - log.debug(`Processing layer ${index}: zIndex=${layer.zIndex}, size=${layer.width}x${layer.height}, pos=(${layer.x},${layer.y})`); - log.debug(`Layer ${index}: blendMode=${layer.blendMode || 'normal'}, opacity=${layer.opacity !== undefined ? layer.opacity : 1}`); - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - tempCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - log.debug(`Layer ${index} rendered successfully`); - visibilityCtx.save(); - visibilityCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - visibilityCtx.rotate(layer.rotation * Math.PI / 180); - visibilityCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - visibilityCtx.restore(); - }); + this.canvas.canvasLayers.drawLayersToContext(tempCtx, this.canvas.layers); + this.canvas.canvasLayers.drawLayersToContext(visibilityCtx, this.canvas.layers); + log.debug(`Finished rendering layers`); const visibilityData = visibilityCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); const maskData = maskCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); for (let i = 0; i < visibilityData.data.length; i += 4) { @@ -232,21 +216,8 @@ export class CanvasIO { throw new Error("Could not create temp context"); maskCtx.fillStyle = '#ffffff'; // Start with a white mask (nothing masked) maskCtx.fillRect(0, 0, this.canvas.width, this.canvas.height); - const sortedLayers = this.canvas.layers.sort((a, b) => a.zIndex - b.zIndex); - sortedLayers.forEach((layer) => { - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - tempCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - visibilityCtx.save(); - visibilityCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - visibilityCtx.rotate(layer.rotation * Math.PI / 180); - visibilityCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - visibilityCtx.restore(); - }); + this.canvas.canvasLayers.drawLayersToContext(tempCtx, this.canvas.layers); + this.canvas.canvasLayers.drawLayersToContext(visibilityCtx, this.canvas.layers); const visibilityData = visibilityCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); const maskData = maskCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); for (let i = 0; i < visibilityData.data.length; i += 4) { diff --git a/js/CanvasLayers.js b/js/CanvasLayers.js index ecd7acd..e081ee5 100644 --- a/js/CanvasLayers.js +++ b/js/CanvasLayers.js @@ -303,6 +303,34 @@ export class CanvasLayers { } return null; } + _drawLayer(ctx, layer, options = {}) { + if (!layer.image) + return; + const { offsetX = 0, offsetY = 0 } = options; + ctx.save(); + ctx.globalCompositeOperation = layer.blendMode || 'normal'; + ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; + const centerX = layer.x + layer.width / 2 - offsetX; + const centerY = layer.y + layer.height / 2 - offsetY; + ctx.translate(centerX, centerY); + ctx.rotate(layer.rotation * Math.PI / 180); + const scaleH = layer.flipH ? -1 : 1; + const scaleV = layer.flipV ? -1 : 1; + if (layer.flipH || layer.flipV) { + ctx.scale(scaleH, scaleV); + } + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + ctx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); + ctx.restore(); + } + _drawLayers(ctx, layers, options = {}) { + const sortedLayers = [...layers].sort((a, b) => a.zIndex - b.zIndex); + sortedLayers.forEach(layer => this._drawLayer(ctx, layer, options)); + } + drawLayersToContext(ctx, layers, options = {}) { + this._drawLayers(ctx, layers, options); + } async mirrorHorizontal() { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; @@ -329,12 +357,14 @@ export class CanvasLayers { throw new Error("Could not create canvas context"); tempCanvas.width = layer.width; tempCanvas.height = layer.height; - tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height); - tempCtx.save(); - tempCtx.translate(layer.width / 2, layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); + // We need to draw the layer relative to the new canvas, so we "move" it to 0,0 + // by creating a temporary layer object for drawing. + const layerToDraw = { + ...layer, + x: 0, + y: 0, + }; + this._drawLayer(tempCtx, layerToDraw); const dataUrl = tempCanvas.toDataURL('image/png'); if (!dataUrl.startsWith('data:image/png;base64,')) { throw new Error("Invalid image data format"); @@ -568,20 +598,7 @@ export class CanvasLayers { reject(new Error("Could not create canvas context")); return; } - const sortedLayers = [...this.canvas.layers].sort((a, b) => a.zIndex - b.zIndex); - sortedLayers.forEach((layer) => { - if (!layer.image) - return; - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.layers); const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height); const data = imageData.data; const toolMaskCanvas = this.canvas.maskTool.getMask(); @@ -643,20 +660,7 @@ export class CanvasLayers { reject(new Error("Could not create canvas context")); return; } - const sortedLayers = [...this.canvas.layers].sort((a, b) => a.zIndex - b.zIndex); - sortedLayers.forEach((layer) => { - if (!layer.image) - return; - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.layers); tempCanvas.toBlob((blob) => { if (blob) { resolve(blob); @@ -714,25 +718,7 @@ export class CanvasLayers { return; } tempCtx.translate(-minX, -minY); - const sortedSelection = [...this.canvas.canvasSelection.selectedLayers].sort((a, b) => a.zIndex - b.zIndex); - sortedSelection.forEach((layer) => { - if (!layer.image) - return; - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - const scaleH = layer.flipH ? -1 : 1; - const scaleV = layer.flipV ? -1 : 1; - if (layer.flipH || layer.flipV) { - tempCtx.scale(scaleH, scaleV); - } - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.canvasSelection.selectedLayers); tempCanvas.toBlob((blob) => { resolve(blob); }, 'image/png'); @@ -784,25 +770,7 @@ export class CanvasLayers { if (!tempCtx) throw new Error("Could not create canvas context"); tempCtx.translate(-minX, -minY); - const sortedSelection = [...this.canvas.canvasSelection.selectedLayers].sort((a, b) => a.zIndex - b.zIndex); - sortedSelection.forEach((layer) => { - if (!layer.image) - return; - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - const scaleH = layer.flipH ? -1 : 1; - const scaleV = layer.flipV ? -1 : 1; - if (layer.flipH || layer.flipV) { - tempCtx.scale(scaleH, scaleV); - } - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.canvasSelection.selectedLayers); const fusedImage = new Image(); fusedImage.src = tempCanvas.toDataURL(); await new Promise((resolve, reject) => { @@ -842,7 +810,7 @@ export class CanvasLayers { this.canvas.canvasLayersPanel.onLayersChanged(); } log.info("Layers fused successfully", { - originalLayerCount: sortedSelection.length, + originalLayerCount: this.canvas.canvasSelection.selectedLayers.length, fusedDimensions: { width: fusedWidth, height: fusedHeight }, fusedPosition: { x: minX, y: minY } }); diff --git a/js/CanvasState.js b/js/CanvasState.js index eda8532..cbc62e0 100644 --- a/js/CanvasState.js +++ b/js/CanvasState.js @@ -259,13 +259,15 @@ export class CanvasState { const newLayer = { ...layer, imageId: layer.imageId || '' }; delete newLayer.image; if (layer.image instanceof HTMLImageElement) { - log.debug(`Layer ${index}: Using imageId instead of serializing image.`); - if (!layer.imageId) { + if (layer.imageId) { + newLayer.imageId = layer.imageId; + } + else { + log.debug(`Layer ${index}: No imageId found, generating new one and saving image.`); newLayer.imageId = generateUUID(); const imageBitmap = await createImageBitmap(layer.image); await saveImage(newLayer.imageId, imageBitmap); } - newLayer.imageId = layer.imageId; } else if (!layer.imageId) { log.error(`Layer ${index}: No image or imageId found, skipping layer.`); diff --git a/js/CanvasView.js b/js/CanvasView.js index e83da84..ff95d25 100644 --- a/js/CanvasView.js +++ b/js/CanvasView.js @@ -330,7 +330,7 @@ async function createCanvasWidget(node, widget, app) { const mattedImage = new Image(); mattedImage.src = result.matted_image; await mattedImage.decode(); - const newLayer = { ...selectedLayer, image: mattedImage }; + const newLayer = { ...selectedLayer, image: mattedImage, flipH: false, flipV: false }; delete newLayer.imageId; canvas.layers[selectedLayerIndex] = newLayer; canvas.canvasSelection.updateSelection([newLayer]); diff --git a/src/CanvasIO.ts b/src/CanvasIO.ts index db48acf..37d6a6e 100644 --- a/src/CanvasIO.ts +++ b/src/CanvasIO.ts @@ -72,27 +72,11 @@ export class CanvasIO { maskCtx.fillRect(0, 0, this.canvas.width, this.canvas.height); log.debug(`Canvas contexts created, starting layer rendering`); - const sortedLayers = this.canvas.layers.sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - log.debug(`Processing ${sortedLayers.length} layers in order`); - sortedLayers.forEach((layer: Layer, index: number) => { - log.debug(`Processing layer ${index}: zIndex=${layer.zIndex}, size=${layer.width}x${layer.height}, pos=(${layer.x},${layer.y})`); - log.debug(`Layer ${index}: blendMode=${layer.blendMode || 'normal'}, opacity=${layer.opacity !== undefined ? layer.opacity : 1}`); - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - tempCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - - log.debug(`Layer ${index} rendered successfully`); - visibilityCtx.save(); - visibilityCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - visibilityCtx.rotate(layer.rotation * Math.PI / 180); - visibilityCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - visibilityCtx.restore(); - }); + + this.canvas.canvasLayers.drawLayersToContext(tempCtx, this.canvas.layers); + this.canvas.canvasLayers.drawLayersToContext(visibilityCtx, this.canvas.layers); + + log.debug(`Finished rendering layers`); const visibilityData = visibilityCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); const maskData = maskCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); for (let i = 0; i < visibilityData.data.length; i += 4) { @@ -259,23 +243,8 @@ export class CanvasIO { maskCtx.fillStyle = '#ffffff'; // Start with a white mask (nothing masked) maskCtx.fillRect(0, 0, this.canvas.width, this.canvas.height); - const sortedLayers = this.canvas.layers.sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - sortedLayers.forEach((layer: Layer) => { - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - tempCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - tempCtx.restore(); - - visibilityCtx.save(); - visibilityCtx.translate(layer.x + layer.width / 2, layer.y + layer.height / 2); - visibilityCtx.rotate(layer.rotation * Math.PI / 180); - visibilityCtx.drawImage(layer.image, -layer.width / 2, -layer.height / 2, layer.width, layer.height); - visibilityCtx.restore(); - }); + this.canvas.canvasLayers.drawLayersToContext(tempCtx, this.canvas.layers); + this.canvas.canvasLayers.drawLayersToContext(visibilityCtx, this.canvas.layers); const visibilityData = visibilityCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); const maskData = maskCtx.getImageData(0, 0, this.canvas.width, this.canvas.height); diff --git a/src/CanvasLayers.ts b/src/CanvasLayers.ts index 97a7ea6..b1a90ee 100644 --- a/src/CanvasLayers.ts +++ b/src/CanvasLayers.ts @@ -349,6 +349,46 @@ export class CanvasLayers { return null; } + private _drawLayer(ctx: CanvasRenderingContext2D, layer: Layer, options: { offsetX?: number, offsetY?: number } = {}): void { + if (!layer.image) return; + + const { offsetX = 0, offsetY = 0 } = options; + + ctx.save(); + ctx.globalCompositeOperation = layer.blendMode as any || 'normal'; + ctx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; + + const centerX = layer.x + layer.width / 2 - offsetX; + const centerY = layer.y + layer.height / 2 - offsetY; + + ctx.translate(centerX, centerY); + ctx.rotate(layer.rotation * Math.PI / 180); + + const scaleH = layer.flipH ? -1 : 1; + const scaleV = layer.flipV ? -1 : 1; + if (layer.flipH || layer.flipV) { + ctx.scale(scaleH, scaleV); + } + + ctx.imageSmoothingEnabled = true; + ctx.imageSmoothingQuality = 'high'; + ctx.drawImage( + layer.image, + -layer.width / 2, -layer.height / 2, + layer.width, layer.height + ); + ctx.restore(); + } + + private _drawLayers(ctx: CanvasRenderingContext2D, layers: Layer[], options: { offsetX?: number, offsetY?: number } = {}): void { + const sortedLayers = [...layers].sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); + sortedLayers.forEach(layer => this._drawLayer(ctx, layer, options)); + } + + public drawLayersToContext(ctx: CanvasRenderingContext2D, layers: Layer[], options: { offsetX?: number, offsetY?: number } = {}): void { + this._drawLayers(ctx, layers, options); + } + async mirrorHorizontal(): Promise { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; this.canvas.canvasSelection.selectedLayers.forEach((layer: Layer) => { @@ -376,19 +416,15 @@ export class CanvasLayers { tempCanvas.width = layer.width; tempCanvas.height = layer.height; - tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height); + // We need to draw the layer relative to the new canvas, so we "move" it to 0,0 + // by creating a temporary layer object for drawing. + const layerToDraw = { + ...layer, + x: 0, + y: 0, + }; - tempCtx.save(); - tempCtx.translate(layer.width / 2, layer.height / 2); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage( - layer.image, - -layer.width / 2, - -layer.height / 2, - layer.width, - layer.height - ); - tempCtx.restore(); + this._drawLayer(tempCtx, layerToDraw); const dataUrl = tempCanvas.toDataURL('image/png'); if (!dataUrl.startsWith('data:image/png;base64,')) { @@ -657,27 +693,7 @@ export class CanvasLayers { return; } - const sortedLayers = [...this.canvas.layers].sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - - sortedLayers.forEach((layer: Layer) => { - if (!layer.image) return; - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage( - layer.image, - -layer.width / 2, - -layer.height / 2, - layer.width, - layer.height - ); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.layers); const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height); const data = imageData.data; @@ -754,27 +770,7 @@ export class CanvasLayers { return; } - const sortedLayers = [...this.canvas.layers].sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - - sortedLayers.forEach((layer: Layer) => { - if (!layer.image) return; - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - tempCtx.drawImage( - layer.image, - -layer.width / 2, - -layer.height / 2, - layer.width, - layer.height - ); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.layers); tempCanvas.toBlob((blob) => { if (blob) { @@ -843,33 +839,7 @@ export class CanvasLayers { tempCtx.translate(-minX, -minY); - const sortedSelection = [...this.canvas.canvasSelection.selectedLayers].sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - - sortedSelection.forEach((layer: Layer) => { - if (!layer.image) return; - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - - const scaleH = layer.flipH ? -1 : 1; - const scaleV = layer.flipV ? -1 : 1; - if (layer.flipH || layer.flipV) { - tempCtx.scale(scaleH, scaleV); - } - - tempCtx.drawImage( - layer.image, - -layer.width / 2, -layer.height / 2, - layer.width, layer.height - ); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.canvasSelection.selectedLayers); tempCanvas.toBlob((blob) => { resolve(blob); @@ -933,33 +903,7 @@ export class CanvasLayers { tempCtx.translate(-minX, -minY); - const sortedSelection = [...this.canvas.canvasSelection.selectedLayers].sort((a: Layer, b: Layer) => a.zIndex - b.zIndex); - - sortedSelection.forEach((layer: Layer) => { - if (!layer.image) return; - - tempCtx.save(); - tempCtx.globalCompositeOperation = layer.blendMode as any || 'normal'; - tempCtx.globalAlpha = layer.opacity !== undefined ? layer.opacity : 1; - - const centerX = layer.x + layer.width / 2; - const centerY = layer.y + layer.height / 2; - tempCtx.translate(centerX, centerY); - tempCtx.rotate(layer.rotation * Math.PI / 180); - - const scaleH = layer.flipH ? -1 : 1; - const scaleV = layer.flipV ? -1 : 1; - if (layer.flipH || layer.flipV) { - tempCtx.scale(scaleH, scaleV); - } - - tempCtx.drawImage( - layer.image, - -layer.width / 2, -layer.height / 2, - layer.width, layer.height - ); - tempCtx.restore(); - }); + this._drawLayers(tempCtx, this.canvas.canvasSelection.selectedLayers); const fusedImage = new Image(); fusedImage.src = tempCanvas.toDataURL(); @@ -1006,7 +950,7 @@ export class CanvasLayers { } log.info("Layers fused successfully", { - originalLayerCount: sortedSelection.length, + originalLayerCount: this.canvas.canvasSelection.selectedLayers.length, fusedDimensions: { width: fusedWidth, height: fusedHeight }, fusedPosition: { x: minX, y: minY } }); diff --git a/src/CanvasState.ts b/src/CanvasState.ts index f1ec070..cdbd1ea 100644 --- a/src/CanvasState.ts +++ b/src/CanvasState.ts @@ -297,13 +297,14 @@ export class CanvasState { delete (newLayer as any).image; if (layer.image instanceof HTMLImageElement) { - log.debug(`Layer ${index}: Using imageId instead of serializing image.`); - if (!layer.imageId) { + if (layer.imageId) { + newLayer.imageId = layer.imageId; + } else { + log.debug(`Layer ${index}: No imageId found, generating new one and saving image.`); newLayer.imageId = generateUUID(); const imageBitmap = await createImageBitmap(layer.image); await saveImage(newLayer.imageId, imageBitmap); } - newLayer.imageId = layer.imageId; } else if (!layer.imageId) { log.error(`Layer ${index}: No image or imageId found, skipping layer.`); return null; diff --git a/src/CanvasView.ts b/src/CanvasView.ts index 3ad4878..6629d58 100644 --- a/src/CanvasView.ts +++ b/src/CanvasView.ts @@ -363,7 +363,7 @@ async function createCanvasWidget(node: ComfyNode, widget: any, app: ComfyApp): const mattedImage = new Image(); mattedImage.src = result.matted_image; await mattedImage.decode(); - const newLayer = {...selectedLayer, image: mattedImage} as Layer; + const newLayer = {...selectedLayer, image: mattedImage, flipH: false, flipV: false} as Layer; delete (newLayer as any).imageId; canvas.layers[selectedLayerIndex] = newLayer; canvas.canvasSelection.updateSelection([newLayer]);