diff --git a/js/CanvasLayers.js b/js/CanvasLayers.js index c3fd080..ecd7acd 100644 --- a/js/CanvasLayers.js +++ b/js/CanvasLayers.js @@ -306,52 +306,18 @@ export class CanvasLayers { async mirrorHorizontal() { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; - const promises = this.canvas.canvasSelection.selectedLayers.map((layer) => { - return new Promise(resolve => { - const tempCanvas = document.createElement('canvas'); - const tempCtx = tempCanvas.getContext('2d'); - if (!tempCtx) - return; - tempCanvas.width = layer.image.width; - tempCanvas.height = layer.image.height; - tempCtx.translate(tempCanvas.width, 0); - tempCtx.scale(-1, 1); - tempCtx.drawImage(layer.image, 0, 0); - const newImage = new Image(); - newImage.onload = () => { - layer.image = newImage; - resolve(); - }; - newImage.src = tempCanvas.toDataURL(); - }); + this.canvas.canvasSelection.selectedLayers.forEach((layer) => { + layer.flipH = !layer.flipH; }); - await Promise.all(promises); this.canvas.render(); this.canvas.requestSaveState(); } async mirrorVertical() { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; - const promises = this.canvas.canvasSelection.selectedLayers.map((layer) => { - return new Promise(resolve => { - const tempCanvas = document.createElement('canvas'); - const tempCtx = tempCanvas.getContext('2d'); - if (!tempCtx) - return; - tempCanvas.width = layer.image.width; - tempCanvas.height = layer.image.height; - tempCtx.translate(0, tempCanvas.height); - tempCtx.scale(1, -1); - tempCtx.drawImage(layer.image, 0, 0); - const newImage = new Image(); - newImage.onload = () => { - layer.image = newImage; - resolve(); - }; - newImage.src = tempCanvas.toDataURL(); - }); + this.canvas.canvasSelection.selectedLayers.forEach((layer) => { + layer.flipV = !layer.flipV; }); - await Promise.all(promises); this.canvas.render(); this.canvas.requestSaveState(); } @@ -759,6 +725,11 @@ export class CanvasLayers { 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(); }); @@ -824,6 +795,11 @@ export class CanvasLayers { 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(); }); diff --git a/js/CanvasRenderer.js b/js/CanvasRenderer.js index 71332cd..b5acdc7 100644 --- a/js/CanvasRenderer.js +++ b/js/CanvasRenderer.js @@ -58,6 +58,11 @@ export class CanvasRenderer { const centerY = layer.y + layer.height / 2; 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); diff --git a/js/utils/CommonUtils.js b/js/utils/CommonUtils.js index af632b1..52e99bf 100644 --- a/js/utils/CommonUtils.js +++ b/js/utils/CommonUtils.js @@ -111,7 +111,9 @@ export function getStateSignature(layers) { rotation: Math.round((layer.rotation || 0) * 100) / 100, zIndex: layer.zIndex, blendMode: layer.blendMode || 'normal', - opacity: layer.opacity !== undefined ? Math.round(layer.opacity * 100) / 100 : 1 + opacity: layer.opacity !== undefined ? Math.round(layer.opacity * 100) / 100 : 1, + flipH: !!layer.flipH, + flipV: !!layer.flipV }; if (layer.imageId) { sig.imageId = layer.imageId; diff --git a/src/CanvasLayers.ts b/src/CanvasLayers.ts index 873d163..97a7ea6 100644 --- a/src/CanvasLayers.ts +++ b/src/CanvasLayers.ts @@ -351,58 +351,18 @@ export class CanvasLayers { async mirrorHorizontal(): Promise { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; - - const promises = this.canvas.canvasSelection.selectedLayers.map((layer: Layer) => { - return new Promise(resolve => { - const tempCanvas = document.createElement('canvas'); - const tempCtx = tempCanvas.getContext('2d'); - if (!tempCtx) return; - tempCanvas.width = layer.image.width; - tempCanvas.height = layer.image.height; - - tempCtx.translate(tempCanvas.width, 0); - tempCtx.scale(-1, 1); - tempCtx.drawImage(layer.image, 0, 0); - - const newImage = new Image(); - newImage.onload = () => { - layer.image = newImage; - resolve(); - }; - newImage.src = tempCanvas.toDataURL(); - }); + this.canvas.canvasSelection.selectedLayers.forEach((layer: Layer) => { + layer.flipH = !layer.flipH; }); - - await Promise.all(promises); this.canvas.render(); this.canvas.requestSaveState(); } async mirrorVertical(): Promise { if (this.canvas.canvasSelection.selectedLayers.length === 0) return; - - const promises = this.canvas.canvasSelection.selectedLayers.map((layer: Layer) => { - return new Promise(resolve => { - const tempCanvas = document.createElement('canvas'); - const tempCtx = tempCanvas.getContext('2d'); - if (!tempCtx) return; - tempCanvas.width = layer.image.width; - tempCanvas.height = layer.image.height; - - tempCtx.translate(0, tempCanvas.height); - tempCtx.scale(1, -1); - tempCtx.drawImage(layer.image, 0, 0); - - const newImage = new Image(); - newImage.onload = () => { - layer.image = newImage; - resolve(); - }; - newImage.src = tempCanvas.toDataURL(); - }); + this.canvas.canvasSelection.selectedLayers.forEach((layer: Layer) => { + layer.flipV = !layer.flipV; }); - - await Promise.all(promises); this.canvas.render(); this.canvas.requestSaveState(); } @@ -896,6 +856,13 @@ export class CanvasLayers { 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, @@ -979,6 +946,13 @@ export class CanvasLayers { 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, diff --git a/src/CanvasRenderer.ts b/src/CanvasRenderer.ts index 0d78cf2..c14fc4a 100644 --- a/src/CanvasRenderer.ts +++ b/src/CanvasRenderer.ts @@ -71,6 +71,13 @@ export class CanvasRenderer { const centerY = layer.y + layer.height / 2; 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( diff --git a/src/types.ts b/src/types.ts index 8561258..3cb8a90 100644 --- a/src/types.ts +++ b/src/types.ts @@ -17,6 +17,8 @@ export interface Layer { blendMode: string; opacity: number; mask?: Float32Array; + flipH?: boolean; + flipV?: boolean; } export interface ComfyNode { diff --git a/src/utils/CommonUtils.ts b/src/utils/CommonUtils.ts index 8d2cff8..dd551aa 100644 --- a/src/utils/CommonUtils.ts +++ b/src/utils/CommonUtils.ts @@ -136,7 +136,9 @@ export function getStateSignature(layers: Layer[]): string { rotation: Math.round((layer.rotation || 0) * 100) / 100, zIndex: layer.zIndex, blendMode: layer.blendMode || 'normal', - opacity: layer.opacity !== undefined ? Math.round(layer.opacity * 100) / 100 : 1 + opacity: layer.opacity !== undefined ? Math.round(layer.opacity * 100) / 100 : 1, + flipH: !!layer.flipH, + flipV: !!layer.flipV }; if (layer.imageId) {