From e4bbafeae67efc5a50af21ddd94f0f6865ed94d9 Mon Sep 17 00:00:00 2001 From: Michael Chung Date: Mon, 21 Apr 2025 16:58:02 -0400 Subject: [PATCH] Used Aspect Ratio to fix. Prompt box handles both web and desktop. --- .../RenderingPrimitives/RealTimeDrawEngine.ts | 64 +++++-- .../editor2d/src/components/PromptBox.tsx | 160 +++++++++++------- 2 files changed, 150 insertions(+), 74 deletions(-) diff --git a/frontend/apps/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts b/frontend/apps/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts index d3f31b3869..0198aafcd5 100644 --- a/frontend/apps/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts +++ b/frontend/apps/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts @@ -520,24 +520,47 @@ export class RealTimeDrawEngine { if (!this.captureCanvas) { return; } - const scaleFactor = 1; + const scaleFactor = 0.9; // Store old values for calculating delta const oldPositionX = this.positionX; const oldPositionY = this.positionY; - // If width/height aren't provided, use window dimensions + const oldWidth = this.width; + const oldHeight = this.height; + + // Original aspect ratio + const originalAspectRatio = oldWidth / oldHeight; + + // Calculate new dimensions based on window size + let newWidth: number; + let newHeight: number; + if (width === undefined) { - this.width = window.innerWidth * scaleFactor; // Using 80% of window width + newWidth = window.innerWidth * scaleFactor; } else { - this.width = width * scaleFactor; + newWidth = width * scaleFactor; } if (height === undefined) { - this.height = window.innerHeight * scaleFactor; // Using 80% of window height + newHeight = window.innerHeight * scaleFactor; } else { - this.height = height * scaleFactor; + newHeight = height * scaleFactor; } + // Preserve aspect ratio + const newAspectRatio = newWidth / newHeight; + + if (newAspectRatio > originalAspectRatio) { + // Width is constraining factor + newWidth = newHeight * originalAspectRatio; + } else { + // Height is constraining factor + newHeight = newWidth / originalAspectRatio; + } + + this.width = newWidth; + this.height = newHeight; + console.log("New dimensions:", this.width, this.height); // Calculate new position to center the canvas in the window @@ -553,9 +576,12 @@ export class RealTimeDrawEngine { }); this.captureCanvas.size({ width: this.width, height: this.height }); - // Calculate the change in position - const deltaX = this.positionX - oldPositionX; - const deltaY = this.positionY - oldPositionY; + // Calculate scale factors to maintain proportions + const scaleX = this.width / oldWidth; + const scaleY = this.height / oldHeight; + + // Use a uniform scale factor to preserve aspect ratio + const uniformScale = Math.min(scaleX, scaleY); // Update all children except the capture canvas var children = this.mediaLayerRef.getChildren(); @@ -566,11 +592,27 @@ export class RealTimeDrawEngine { if (node.name() === "CaptureCanvas") { continue; } + const pos = node.getPosition(); + const oldScale = node.scale(); + + // Apply both position shift and scaling to maintain relative positioning node.setPosition({ - x: pos.x + deltaX, - y: pos.y + deltaY, + x: (pos.x - oldPositionX) * uniformScale + this.positionX, + y: (pos.y - oldPositionY) * uniformScale + this.positionY, }); + + // Update scale proportionally if the node has a scale property + if ( + oldScale && + typeof oldScale.x === "number" && + typeof oldScale.y === "number" + ) { + node.scale({ + x: oldScale.x * uniformScale, + y: oldScale.y * uniformScale, + }); + } } this.mediaLayerRef.batchDraw(); diff --git a/frontend/apps/editor2d/src/components/PromptBox.tsx b/frontend/apps/editor2d/src/components/PromptBox.tsx index 46908dfff2..a3fa06da5e 100644 --- a/frontend/apps/editor2d/src/components/PromptBox.tsx +++ b/frontend/apps/editor2d/src/components/PromptBox.tsx @@ -177,7 +177,100 @@ export const PromptBox = () => { const handleChange = (e: React.ChangeEvent) => { setPrompt(e.target.value); }; + const handleTauriEnqueue = async () => { + const api = new Api(); + let image = getCanvasRenderBitmap(); + if (image === undefined) { + return; + } + const base64Bitmap = await EncodeImageBitmapToBase64(image); + const byteString = atob(base64Bitmap); + const mimeString = "image/png"; + + const ab = new ArrayBuffer(byteString.length); + const ia = new Uint8Array(ab); + + for (let i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + const uuid = crypto.randomUUID(); // Generate a new UUID + const file = new File([ab], `${uuid}.png`, { type: mimeString }); + + const snapshotMediaToken = await api.uploadSceneSnapshot({ + screenshot: file, + }); + + if (snapshotMediaToken.data === undefined) { + toast.error("Error: Unable to upload scene snapshot Please try again."); + return; + } + console.log("useSystemPrompt", useSystemPrompt); + console.log("Snapshot media token:", snapshotMediaToken.data); + + const generateResponse = await invoke("sora_image_generation_command", { + snapshot_media_token: snapshotMediaToken.data, + disable_system_prompt: !useSystemPrompt, + prompt: prompt, + maybe_additional_images: referenceImages.map((image) => image.mediaToken), + maybe_number_of_samples: 1, + }); + toast.success("Please wait while we process your image."); + }; + + const handleWebEnqueue = async () => { + const api = new Api(); + let image = getCanvasRenderBitmap(); + if (image === undefined) { + toast.error( + "Error: Unable to generate image. Please check the input and try again.", + ); + return; + } + const base64Bitmap = await EncodeImageBitmapToBase64(image); + + const byteString = atob(base64Bitmap); + const mimeString = "image/png"; + + const ab = new ArrayBuffer(byteString.length); + const ia = new Uint8Array(ab); + + for (let i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + + const uuid = crypto.randomUUID(); // Generate a new UUID + const file = new File([ab], `${uuid}.png`, { type: mimeString }); + + const snapshotMediaToken = await api.uploadSceneSnapshot({ + screenshot: file, + }); + + if (snapshotMediaToken.data === undefined) { + toast.error("Error: Unable to upload scene snapshot Please try again."); + return; + } + console.log("useSystemPrompt", useSystemPrompt); + console.log("Snapshot media token:", snapshotMediaToken.data); + + const response = await api.enqueueImageGeneration({ + disableSystemPrompt: !useSystemPrompt, + prompt: prompt, + snapshotMediaToken: snapshotMediaToken.data, + additionalImages: referenceImages.map((image) => image.mediaToken), + }); + + if (response.success === true) { + toast.success("Please wait while we process your image."); + if (response.data) { + addJobToken(response.data); + } + return; + } else { + toast.error("Failed to enqueue image generation. Please try again."); + } + }; const handleEnqueue = async () => { if (!prompt.trim()) return; @@ -191,69 +284,10 @@ export const PromptBox = () => { referenceImages, ); - if (isDesktopApp) { - let image = getCanvasRenderBitmap(); - if (image === undefined) { - return; - } - const base64Bitmap = await EncodeImageBitmapToBase64(image); - const generateResponse = await invoke("image_generation_command", { - image: base64Bitmap, - prompt: prompt, - }); - await new Promise((resolve) => setTimeout(resolve, 2000)); - } - - if (!isDesktopApp) { - const api = new Api(); - let image = getCanvasRenderBitmap(); - if (image === undefined) { - toast.error( - "Error: Unable to generate image. Please check the input and try again.", - ); - return; - } - const base64Bitmap = await EncodeImageBitmapToBase64(image); - const byteString = atob(base64Bitmap); - const mimeString = "image/png"; - const ab = new ArrayBuffer(byteString.length); - const ia = new Uint8Array(ab); - - for (let i = 0; i < byteString.length; i++) { - ia[i] = byteString.charCodeAt(i); - } - - const uuid = crypto.randomUUID(); // Generate a new UUID - const file = new File([ab], `${uuid}.png`, { type: mimeString }); - - const snapshotMediaToken = await api.uploadSceneSnapshot({ - screenshot: file, - }); - - if (snapshotMediaToken.data === undefined) { - toast.error( - "Error: Unable to upload scene snapshot Please try again.", - ); - return; - } - console.log("useSystemPrompt", useSystemPrompt); - console.log("Snapshot media token:", snapshotMediaToken.data); - const response = await api.enqueueImageGeneration({ - disableSystemPrompt: !useSystemPrompt, - prompt: prompt, - snapshotMediaToken: snapshotMediaToken.data, - additionalImages: referenceImages.map((image) => image.mediaToken), - }); - - if (response.success === true) { - toast.success("Please wait while we process your image."); - if (response.data) { - addJobToken(response.data); - } - return; - } else { - toast.error("Failed to enqueue image generation. Please try again."); - } + if (isDesktopApp == true) { + handleTauriEnqueue(); + } else { + handleWebEnqueue(); } } catch (error) { console.error("Error during image generation:", error);