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"
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 (