diff --git a/README.md b/README.md index 9a700ae..adb15c0 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,4 @@ Go+Wasm image palette converter -Build with: - -```bash -GOOS=js GOARCH=wasm go build -o dist/main.wasm . -``` - -Access with: - -``` -cd dist -npx http-server -``` - -A version is also available on IPFS: - -``` -/ipfs/Qmdnx5vkt8qietF5BkEDTwxZUFKkh5g7FwYv1CgXYhQV1o -``` - -You can access it directly [here](https://ipfs.io/ipfs/Qmdnx5vkt8qietF5BkEDTwxZUFKkh5g7FwYv1CgXYhQV1o/). +You can access it directly [here](http://paletteswitcher.bruyant.xyz), preferably using [IPFS](https://ipfs.io/). diff --git a/client/public/index.html b/client/public/index.html index a8aa323..806aa39 100644 --- a/client/public/index.html +++ b/client/public/index.html @@ -5,10 +5,7 @@ - + (); const [appState, setAppState] = React.useState(AppState.NO_IMAGE); - const handleImageSubmit = async (data: Blob) => { + const handleImageSubmit = async (data: Blob, palette: Palette) => { setBaseImage(data); setAppState(AppState.IMAGE_LOADED); try { const imageArray = new Uint8ClampedArray(await data.arrayBuffer()); - const ditheredImage = await new Ditherer().dither(imageArray); + const ditheredImage = await new Ditherer().dither(imageArray, palette); setDitheredImage(new Blob([ditheredImage], { type: "image/png" })); setAppState(AppState.IMAGE_PROCESSED); } catch (e) { @@ -34,20 +35,19 @@ function App() { return (
-
-
+
+

Go+Wasm image dithering tool

-

- Load an image, click Go and wait (potentially for a while) for the - image to be processed using the Floyd-Steinberg algorithm. + Load an image, select a palette, click Go and wait for the image to + be processed using the Floyd-Steinberg algorithm.

- WebAssembly might run out of memory when processing larger images. + The preview image is scaled using the nearest-neighbor algorithm, + which might cause artifacts in some cases. Download the image for + the best experience.

diff --git a/client/src/ImageInput.tsx b/client/src/ImageInput.tsx index abe2c6c..f0d2997 100644 --- a/client/src/ImageInput.tsx +++ b/client/src/ImageInput.tsx @@ -1,11 +1,13 @@ import React, { FormEventHandler } from "react"; +import Palette, { palettes } from "./Palette"; interface Props { - onImageSubmit: (image: Blob) => void; + onImageSubmit: (image: Blob, palette: Palette) => void; } function ImageInput({ onImageSubmit }: Props) { const fileInputRef = React.useRef(null); + const [paletteIndex, setPaletteIndex] = React.useState(0); const handleSubmit: FormEventHandler = (e) => { e.preventDefault(); @@ -17,7 +19,11 @@ function ImageInput({ onImageSubmit }: Props) { return; } - onImageSubmit(fileInputRef.current.files[0]); + onImageSubmit(fileInputRef.current.files[0], palettes[paletteIndex]); + }; + + const handlePaletteChange = (event: React.ChangeEvent) => { + setPaletteIndex(parseInt(event.target.value)); }; return ( @@ -34,12 +40,20 @@ function ImageInput({ onImageSubmit }: Props) { className="block w-full mt-1 text-sm text-nord-0 file:mr-4 file:py-2 file:px-4 file:border-0 file:text-sm file:font-semibold file:bg-nord-4 file:text-nord-0 hover:file:bg-nord-5" /> - {/*