+
);
diff --git a/client/src/Palette.ts b/client/src/Palette.ts
new file mode 100644
index 0000000..030b8f6
--- /dev/null
+++ b/client/src/Palette.ts
@@ -0,0 +1,68 @@
+class Palette {
+ colors: string[];
+ label: string;
+
+ constructor(label: string, colors: string[]) {
+ this.label = label;
+ this.colors = colors;
+ }
+}
+
+const nord = new Palette("Nord", [
+ "2e3440",
+ "3b4252",
+ "434c5e",
+ "4c566a",
+ "d8dee9",
+ "e5e9f0",
+ "eceff4",
+ "8fbcbb",
+ "88c0d0",
+ "81a1c1",
+ "5e81ac",
+ "bf616a",
+ "d08770",
+ "ebcb8b",
+ "a3be8c",
+ "b48ead",
+]);
+
+const monokai = new Palette("Monokai", [
+ "2e2e2e",
+ "797979",
+ "d6d6d6",
+ "e5b567",
+ "b4d273",
+ "e87d3e",
+ "9e86c8",
+ "b05279",
+ "6c99bb",
+]);
+
+const grayScale1bit = new Palette("Gray Scale 1 bit (Black & White)", [
+ "000000",
+ "ffffff",
+]);
+
+const grayScale2bits = new Palette("Gray Scale 2 bits", [
+ "000000",
+ "676767",
+ "b6b6b6",
+ "ffffff",
+]);
+
+let grayColors: string[] = [];
+for (let i = 0; i < 256; i++) {
+ const hexValue = i.toString(16).padStart(2, "0");
+ grayColors.push(`${hexValue}${hexValue}${hexValue}`);
+}
+const grayScale8bits = new Palette("Gray Scale 8 bits", grayColors);
+
+export const palettes = [
+ nord,
+ monokai,
+ grayScale1bit,
+ grayScale2bits,
+ grayScale8bits,
+];
+export default Palette;
diff --git a/client/src/lib/Ditherer.ts b/client/src/lib/Ditherer.ts
index b62b124..e6819bc 100644
--- a/client/src/lib/Ditherer.ts
+++ b/client/src/lib/Ditherer.ts
@@ -1,9 +1,14 @@
+import Palette from "../Palette";
+
class Ditherer {
- async dither(image: Uint8ClampedArray): Promise
{
+ async dither(
+ image: Uint8ClampedArray,
+ palette: Palette
+ ): Promise {
const worker: any = await wasmWorker("./main.wasm");
let output: Uint8ClampedArray;
try {
- output = await worker.dither(image);
+ output = await worker.dither(image, palette.colors);
} finally {
worker.terminate();
}
diff --git a/src/wasm.go b/src/wasm.go
index f65962e..2a17192 100644
--- a/src/wasm.go
+++ b/src/wasm.go
@@ -15,25 +15,6 @@ import (
"github.com/makeworld-the-better-one/dither/v2"
)
-var nordPalette, _ = buildPalette([]string{
- "2e3440",
- "3b4252",
- "434c5e",
- "4c566a",
- "d8dee9",
- "e5e9f0",
- "eceff4",
- "8fbcbb",
- "88c0d0",
- "81a1c1",
- "5e81ac",
- "bf616a",
- "d08770",
- "ebcb8b",
- "a3be8c",
- "b48ead",
-})
-
func buildPalette(pal []string) (color.Palette, error) {
var palette = make(color.Palette, len(pal))
@@ -53,9 +34,9 @@ func buildPalette(pal []string) (color.Palette, error) {
return palette, nil
}
-func ditherImage(img image.Image) image.Image {
+func ditherImage(img image.Image, palette color.Palette) image.Image {
// Build ditherer
- ditherer := dither.NewDitherer(nordPalette)
+ ditherer := dither.NewDitherer(palette)
ditherer.Matrix = dither.FloydSteinberg
dst := ditherer.Dither(img)
@@ -79,9 +60,9 @@ func Dither() js.Func {
imageBytes := make([]byte, args[0].Length())
js.CopyBytesToGo(imageBytes, args[0])
- handler := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
- resolve := args[0]
- reject := args[1]
+ handler := js.FuncOf(func(promiseThis js.Value, promiseArgs []js.Value) interface{} {
+ resolve := promiseArgs[0]
+ reject := promiseArgs[1]
go func() {
errorConstructor := js.Global().Get("Error")
@@ -94,10 +75,21 @@ func Dither() js.Func {
reject.Invoke(errorObject)
}
+ // Build palette
+ colors := make([]string, args[1].Length())
+ for i := 0; i < args[1].Length(); i++ {
+ colors[i] = args[1].Index(i).String()
+ }
+ palette, err := buildPalette(colors)
+ if err != nil {
+ errorObject := errorConstructor.New(err.Error())
+ reject.Invoke(errorObject)
+ }
+
// Perform dithering
log.Println("Dithering image...")
t1 := time.Now()
- ditheredImage := ditherImage(img)
+ ditheredImage := ditherImage(img, palette)
t2 := time.Now()
log.Printf("Image dithered in %v\n", t2.Sub(t1))