From b6537cce6aa34eb33c052d7ec2cbbf804be08fba Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Wed, 28 Jun 2023 11:47:41 -0400 Subject: added files --- .../generativeFillUtils/GenerativeFillMathHelpers.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts (limited to 'src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts') diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts new file mode 100644 index 000000000..027b99a52 --- /dev/null +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts @@ -0,0 +1,11 @@ +import { Point } from "./generativeFillInterfaces"; + +export class GenerativeFillMathHelpers { + // math helpers + static distanceBetween = (p1: Point, p2: Point) => { + return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); + }; + static angleBetween = (p1: Point, p2: Point) => { + return Math.atan2(p2.x - p1.x, p2.y - p1.y); + }; +} -- cgit v1.2.3-70-g09d2 From 16d8c1f7af7989afd13201c1813163bc82d84622 Mon Sep 17 00:00:00 2001 From: Sophie Zhang Date: Fri, 18 Aug 2023 18:43:23 -0400 Subject: cleanup --- .../views/nodes/generativeFill/GenerativeFill.tsx | 49 ++++++++++------------ .../nodes/generativeFill/GenerativeFillButtons.tsx | 38 +++++++++++------ .../generativeFillUtils/BrushHandler.ts | 19 --------- .../GenerativeFillMathHelpers.ts | 15 ++++--- .../generativeFillUtils/ImageHandler.ts | 21 ++++++++-- .../generativeFillUtils/generativeFillConstants.ts | 1 - .../generativeFillInterfaces.ts | 1 - 7 files changed, 71 insertions(+), 73 deletions(-) (limited to 'src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts') diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx index 547a76348..998961f20 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx @@ -3,12 +3,12 @@ import React = require('react'); import { useEffect, useRef, useState } from 'react'; import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler'; import { BrushHandler } from './generativeFillUtils/BrushHandler'; -import { Box, Checkbox, FormControlLabel, IconButton, Slider, TextField } from '@mui/material'; +import { IconButton } from 'browndash-components'; +import { Checkbox, FormControlLabel, Slider, TextField } from '@mui/material'; import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; import { PointerHandler } from './generativeFillUtils/PointerHandler'; -import { BsEraser, BsX } from 'react-icons/bs'; -import { CiUndo, CiRedo } from 'react-icons/ci'; +import { IoMdUndo, IoMdRedo } from 'react-icons/io'; import { MainView } from '../../MainView'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { Networking } from '../../../Network'; @@ -19,6 +19,7 @@ import { CollectionDockingView } from '../../collections/CollectionDockingView'; import { OpenWhereMod } from '../DocumentView'; import Buttons from './GenerativeFillButtons'; import { List } from '../../../../fields/List'; +import { CgClose } from 'react-icons/cg'; enum BrushStyle { ADD, @@ -432,9 +433,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD sx={{ whiteSpace: 'nowrap' }} /> - - - + } onClick={handleViewClose} /> {/* Main canvas for editing */} @@ -459,40 +458,34 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD {/* Icons */}
- { - setBrushStyle(BrushStyle.ADD); - }}> - - {/* Undo and Redo */} { e.stopPropagation(); handleUndo(); }} onPointerUp={e => { e.stopPropagation(); - }}> - - + }} + color={activeColor} + tooltip="Undo" + icon={} + /> { e.stopPropagation(); handleRedo(); }} onPointerUp={e => { e.stopPropagation(); - }}> - - - + }} + color={activeColor} + tooltip="Redo" + icon={} + /> +
e.stopPropagation()} style={{ height: 225, width: '100%', display: 'flex', justifyContent: 'center', cursor: 'pointer' }}> { setCursorData(prev => ({ ...prev, width: val as number })); }} /> - +
{/* Edits thumbnails*/}
diff --git a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx index 398ba5333..0dfcebea3 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx @@ -1,7 +1,8 @@ -import { Button } from '@mui/material'; -import { Oval } from 'react-loader-spinner'; import './GenerativeFillButtons.scss'; import React = require('react'); +import ReactLoading from 'react-loading'; +import { activeColor } from './generativeFillUtils/generativeFillConstants'; +import { Button, Type } from 'browndash-components'; interface ButtonContainerProps { getEdit: () => Promise; @@ -12,17 +13,28 @@ interface ButtonContainerProps { const Buttons = ({ loading, getEdit, onReset }: ButtonContainerProps) => { return (
- - +
); }; diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts index ace7ebcae..f4ec70fbc 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts @@ -3,16 +3,6 @@ import { eraserColor } from './generativeFillConstants'; import { Point } from './generativeFillInterfaces'; export class BrushHandler { - static brushCircle = (x: number, y: number, brushRadius: number, ctx: CanvasRenderingContext2D) => { - ctx.globalCompositeOperation = 'destination-out'; - ctx.shadowColor = '#ffffffeb'; - ctx.shadowBlur = 5; - ctx.beginPath(); - ctx.arc(x, y, brushRadius, 0, 2 * Math.PI); - ctx.fill(); - ctx.closePath(); - }; - static brushCircleOverlay = (x: number, y: number, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string, erase: boolean) => { ctx.globalCompositeOperation = 'destination-out'; ctx.fillStyle = fillColor; @@ -24,15 +14,6 @@ export class BrushHandler { ctx.closePath(); }; - static createBrushPath = (startPoint: Point, endPoint: Point, brushRadius: number, ctx: CanvasRenderingContext2D) => { - const dist = GenerativeFillMathHelpers.distanceBetween(startPoint, endPoint); - - for (let i = 0; i < dist; i += 5) { - const s = i / dist; - BrushHandler.brushCircle(startPoint.x * (1 - s) + endPoint.x * s, startPoint.y * (1 - s) + endPoint.y * s, brushRadius, ctx); - } - }; - static createBrushPathOverlay = (startPoint: Point, endPoint: Point, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string, erase: boolean) => { const dist = GenerativeFillMathHelpers.distanceBetween(startPoint, endPoint); diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts index 027b99a52..97e03ff20 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts @@ -1,11 +1,10 @@ -import { Point } from "./generativeFillInterfaces"; +import { Point } from './generativeFillInterfaces'; export class GenerativeFillMathHelpers { - // math helpers - static distanceBetween = (p1: Point, p2: Point) => { - return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); - }; - static angleBetween = (p1: Point, p2: Point) => { - return Math.atan2(p2.x - p1.x, p2.y - p1.y); - }; + static distanceBetween = (p1: Point, p2: Point) => { + return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); + }; + static angleBetween = (p1: Point, p2: Point) => { + return Math.atan2(p2.x - p1.x, p2.y - p1.y); + }; } diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts index 4ff70c86c..c6ecedb6b 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts @@ -12,6 +12,11 @@ export interface APIError { } export class ImageUtility { + /** + * + * @param canvas Canvas to convert + * @returns Blob of canvas + */ static canvasToBlob = (canvas: HTMLCanvasElement): Promise => { return new Promise(resolve => { canvas.toBlob(blob => { @@ -45,6 +50,7 @@ export class ImageUtility { } }; + // converts an image to a canvas data url static convertImgToCanvasUrl = async (imageSrc: string, width: number, height: number): Promise => { return new Promise((resolve, reject) => { const img = new Image(); @@ -62,6 +68,7 @@ export class ImageUtility { }); }; + // calls the openai api to get image edits static getEdit = async (imgBlob: Blob, maskBlob: Blob, prompt: string, n?: number): Promise => { const apiUrl = 'https://api.openai.com/v1/images/edits'; const fd = new FormData(); @@ -92,6 +99,7 @@ export class ImageUtility { } }; + // mock api call static mockGetEdit = async (mockSrc: string): Promise => { return { status: 'success', @@ -99,6 +107,7 @@ export class ImageUtility { }; }; + // Gets the canvas rendering context of a canvas static getCanvasContext = (canvasRef: RefObject): CanvasRenderingContext2D | null => { if (!canvasRef.current) return null; const ctx = canvasRef.current.getContext('2d'); @@ -106,6 +115,7 @@ export class ImageUtility { return ctx; }; + // Helper for downloading the canvas (for debugging) static downloadCanvas = (canvas: HTMLCanvasElement) => { const url = canvas.toDataURL(); const downloadLink = document.createElement('a'); @@ -116,6 +126,7 @@ export class ImageUtility { downloadLink.remove(); }; + // Download the canvas (for debugging) static downloadImageCanvas = (imgUrl: string) => { const img = new Image(); img.src = imgUrl; @@ -130,12 +141,14 @@ export class ImageUtility { }; }; + // Clears the canvas static clearCanvas = (canvasRef: React.RefObject) => { const ctx = this.getCanvasContext(canvasRef); if (!ctx || !canvasRef.current) return; ctx.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height); }; + // Draws the image to the current canvas static drawImgToCanvas = (img: HTMLImageElement, canvasRef: React.RefObject, width: number, height: number) => { const drawImg = (img: HTMLImageElement) => { const ctx = this.getCanvasContext(canvasRef); @@ -154,7 +167,7 @@ export class ImageUtility { } }; - // The image must be loaded! + // Gets the image mask for the openai endpoint static getCanvasMask = (srcCanvas: HTMLCanvasElement, paddedCanvas: HTMLCanvasElement): HTMLCanvasElement | undefined => { const canvas = document.createElement('canvas'); canvas.width = canvasSize; @@ -162,8 +175,6 @@ export class ImageUtility { const ctx = canvas.getContext('2d'); if (!ctx) return; ctx?.clearRect(0, 0, canvasSize, canvasSize); - // ctx.fillStyle = bgColor; - // ctx.fillRect(0, 0, canvasSize, canvasSize); ctx.drawImage(paddedCanvas, 0, 0); // extract and set padding data @@ -181,6 +192,7 @@ export class ImageUtility { return canvas; }; + // Fills in the blank areas of the image with an image reflection (to fill in a square-shaped canvas) static drawHorizontalReflection = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, xOffset: number) => { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data; @@ -209,6 +221,7 @@ export class ImageUtility { ctx.putImageData(imageData, 0, 0); }; + // Fills in the blank areas of the image with an image reflection (to fill in a square-shaped canvas) static drawVerticalReflection = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, yOffset: number) => { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); const data = imageData.data; @@ -237,7 +250,7 @@ export class ImageUtility { ctx.putImageData(imageData, 0, 0); }; - // The image must be loaded! + // Gets the unaltered (besides filling in padding) version of the image for the api call static getCanvasImg = (img: HTMLImageElement): HTMLCanvasElement | undefined => { const canvas = document.createElement('canvas'); canvas.width = canvasSize; diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillConstants.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillConstants.ts index 1fe151b46..dc94a9368 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillConstants.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillConstants.ts @@ -1,4 +1,3 @@ -// constants export const canvasSize = 512; export const freeformRenderSize = 300; export const offsetDistanceY = freeformRenderSize + 400; diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillInterfaces.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillInterfaces.ts index 83a21a1a5..1e7801056 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillInterfaces.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/generativeFillInterfaces.ts @@ -1,4 +1,3 @@ -// interfaces export interface CursorData { x: number; y: number; -- cgit v1.2.3-70-g09d2