PaletteSwitcher/client/src/App.tsx

66 lines
2.1 KiB
TypeScript
Raw Normal View History

2021-12-11 15:51:45 +00:00
import React from "react";
2021-12-12 16:50:58 +00:00
import ImageInput from "./ImageInput";
import ImageOutput from "./ImageOutput";
2021-12-12 17:27:19 +00:00
import Ditherer from "./lib/Ditherer";
2021-12-12 16:50:58 +00:00
import ImagePreview from "./ImagePreview";
import Header from "./Header";
import Palette from "./Palette";
2021-12-12 16:50:58 +00:00
enum AppState {
NO_IMAGE,
IMAGE_LOADED,
IMAGE_PROCESSED,
}
function App() {
2021-12-13 12:54:54 +00:00
const [baseImage, setBaseImage] = React.useState<Blob>();
const [ditheredImage, setDitheredImage] = React.useState<Blob>();
2021-12-12 16:50:58 +00:00
const [appState, setAppState] = React.useState<AppState>(AppState.NO_IMAGE);
const handleImageSubmit = async (data: Blob, palette: Palette) => {
2021-12-12 16:50:58 +00:00
setBaseImage(data);
setAppState(AppState.IMAGE_LOADED);
2021-12-12 17:27:19 +00:00
try {
2021-12-13 12:54:54 +00:00
const imageArray = new Uint8ClampedArray(await data.arrayBuffer());
const ditheredImage = await new Ditherer().dither(imageArray, palette);
2021-12-13 12:54:54 +00:00
setDitheredImage(new Blob([ditheredImage], { type: "image/png" }));
2021-12-12 17:27:19 +00:00
setAppState(AppState.IMAGE_PROCESSED);
} catch (e) {
console.error(e);
window.alert("Something went wrong. Please try again.");
}
2021-12-11 15:19:48 +00:00
};
return (
2021-12-12 16:50:58 +00:00
<div className="bg-nord-6 text-nord-0 min-h-screen">
<Header />
<main className="container mx-auto pb-5">
<article className="text-xl leading-relaxed max-w-prose space-y-2 mx-auto pb-5 px-2">
2021-12-12 16:50:58 +00:00
<h1 className="text-3xl text-center pb-3">
Go+Wasm image dithering tool
</h1>
<p>
Load an image, select a palette, click Go and wait for the image to
be processed using the Floyd-Steinberg algorithm.
2021-12-12 16:50:58 +00:00
</p>
<p>
The preview image is scaled using the nearest-neighbor algorithm,
which might cause artifacts in some cases. Download the image for
the best experience.
2021-12-12 16:50:58 +00:00
</p>
</article>
<ImageInput onImageSubmit={handleImageSubmit}></ImageInput>
2021-12-13 12:54:54 +00:00
{appState === AppState.IMAGE_LOADED && baseImage && (
<ImagePreview imageData={baseImage} />
2021-12-12 16:50:58 +00:00
)}
2021-12-13 12:54:54 +00:00
{appState === AppState.IMAGE_PROCESSED && ditheredImage && (
<ImageOutput imageData={ditheredImage} />
2021-12-12 16:50:58 +00:00
)}
</main>
2021-12-11 15:19:48 +00:00
</div>
);
}
export default App;