From b59fa868fa0b4f146278e3cbf1ef5afae7408a53 Mon Sep 17 00:00:00 2001 From: Alexandre BRUYANT Date: Mon, 13 Dec 2021 13:54:19 +0100 Subject: [PATCH 1/2] Dont launch browser on npm start --- client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/package.json b/client/package.json index 1bdd0ec..1256fac 100644 --- a/client/package.json +++ b/client/package.json @@ -24,7 +24,7 @@ "web-vitals": "^1.1.2" }, "scripts": { - "start": "react-scripts start", + "start": "BROWSER=none react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" -- 2.45.2 From 04209be0e85625b3f48971857caf4af89ed44831 Mon Sep 17 00:00:00 2001 From: Alexandre BRUYANT Date: Mon, 13 Dec 2021 13:54:54 +0100 Subject: [PATCH 2/2] Images are Blobs & revoke object URLs --- client/src/App.tsx | 19 ++++++++++--------- client/src/ImageInput.tsx | 14 ++------------ client/src/ImageOutput.tsx | 15 +++++++++++---- client/src/ImagePreview.tsx | 13 ++++++++++--- 4 files changed, 33 insertions(+), 28 deletions(-) diff --git a/client/src/App.tsx b/client/src/App.tsx index ab606ee..6567fe3 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -12,17 +12,18 @@ enum AppState { } function App() { - const [baseImage, setBaseImage] = React.useState(); - const [ditheredImage, setDitheredImage] = React.useState(); + const [baseImage, setBaseImage] = React.useState(); + const [ditheredImage, setDitheredImage] = React.useState(); const [appState, setAppState] = React.useState(AppState.NO_IMAGE); - const handleImageSubmit = async (data: Uint8ClampedArray) => { + const handleImageSubmit = async (data: Blob) => { setBaseImage(data); setAppState(AppState.IMAGE_LOADED); try { - const ditheredImage = await new Ditherer().dither(data); - setDitheredImage(ditheredImage); + const imageArray = new Uint8ClampedArray(await data.arrayBuffer()); + const ditheredImage = await new Ditherer().dither(imageArray); + setDitheredImage(new Blob([ditheredImage], { type: "image/png" })); setAppState(AppState.IMAGE_PROCESSED); } catch (e) { console.error(e); @@ -50,11 +51,11 @@ function App() {

- {appState === AppState.IMAGE_LOADED && ( - + {appState === AppState.IMAGE_LOADED && baseImage && ( + )} - {appState === AppState.IMAGE_PROCESSED && ( - + {appState === AppState.IMAGE_PROCESSED && ditheredImage && ( + )} diff --git a/client/src/ImageInput.tsx b/client/src/ImageInput.tsx index a2212bd..abe2c6c 100644 --- a/client/src/ImageInput.tsx +++ b/client/src/ImageInput.tsx @@ -1,11 +1,10 @@ import React, { FormEventHandler } from "react"; interface Props { - onImageSubmit: (image: Uint8ClampedArray) => void; + onImageSubmit: (image: Blob) => void; } function ImageInput({ onImageSubmit }: Props) { - let fileReader: FileReader; const fileInputRef = React.useRef(null); const handleSubmit: FormEventHandler = (e) => { @@ -18,16 +17,7 @@ function ImageInput({ onImageSubmit }: Props) { return; } - fileReader = new FileReader(); - fileReader.onloadend = handleFileRead; - fileReader.readAsArrayBuffer(fileInputRef.current.files[0]); - }; - - const handleFileRead: EventListener = (e) => { - if (fileReader.result) { - const image = new Uint8ClampedArray(fileReader.result as ArrayBuffer); - onImageSubmit(image); - } + onImageSubmit(fileInputRef.current.files[0]); }; return ( diff --git a/client/src/ImageOutput.tsx b/client/src/ImageOutput.tsx index 2759f54..f8ca746 100644 --- a/client/src/ImageOutput.tsx +++ b/client/src/ImageOutput.tsx @@ -1,16 +1,23 @@ import FileSaver from "file-saver"; +import { useEffect } from "react"; import "./ImageOutput.css"; interface OutputProps { - imageData: Uint8ClampedArray; + imageData: Blob; } function ImageOutput({ imageData }: OutputProps) { - const imageBlob = new Blob([imageData], { type: "image/png" }); - const imageUrl = URL.createObjectURL(imageBlob); + const imageUrl = URL.createObjectURL(imageData); + + useEffect(() => { + return () => { + URL.revokeObjectURL(imageUrl); + } + }, [imageUrl]); const handleClick = () => { - FileSaver.saveAs(imageBlob, "image.png"); + const extension = imageData.type.split("/")[1]; + FileSaver.saveAs(imageData, `image.${extension}`); }; return ( diff --git a/client/src/ImagePreview.tsx b/client/src/ImagePreview.tsx index a32c8d4..4a30230 100644 --- a/client/src/ImagePreview.tsx +++ b/client/src/ImagePreview.tsx @@ -1,10 +1,17 @@ +import { useEffect } from "react"; + interface ImagePreviewProps { - imageData: Uint8ClampedArray; + imageData: Blob; } function ImagePreview({ imageData }: ImagePreviewProps) { - const imageBlob = new Blob([imageData], { type: "image/png" }); - const imageUrl = URL.createObjectURL(imageBlob); + const imageUrl = URL.createObjectURL(imageData); + + useEffect(() => { + return () => { + URL.revokeObjectURL(imageUrl); + } + }, [imageUrl]); return (
-- 2.45.2