diff --git a/src/routes/dither/+page.svelte b/src/routes/dither/+page.svelte index 142e6b5..6d4542b 100644 --- a/src/routes/dither/+page.svelte +++ b/src/routes/dither/+page.svelte @@ -14,22 +14,37 @@ let offscreenCanvas: OffscreenCanvas; let ctx = $derived(canvas.getContext('2d')) let offscreenCtx: OffscreenCanvasRenderingContext2D; - let imgObjectUrl = $state('') + let selectedImage: HTMLImageElement | null = $state(null) let errorMessage = $state('') + let selectedAlgorithm = $state('atkinson') + + let maxImageWidth = $state(0) + let imageHeightRatio = $state(0) + let imageWidthPc = $state(100) onMount(() => { offscreenCanvas = new OffscreenCanvas(1000, 1000) offscreenCtx = offscreenCanvas.getContext('2d') }) - const doesCtxExist = () => { - if (!ctx) { - errorMessage = "Problem finding context for on-screen canvas" - return false + $effect(() => { + if (!selectedImage) { + console.log(`Selected Image is null, terminating effect...`) + return; } - return true; - } + maxImageWidth = selectedImage.width + imageHeightRatio = selectedImage.height / selectedImage.width + + ctx.clearRect(0, 0, canvas.width, canvas.height) + + canvas.width = maxImageWidth * (imageWidthPc/100) + canvas.height = imageHeightRatio * canvas.width + ctx.drawImage(selectedImage, 0, 0, canvas.width, canvas.height) + + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) + ctx.putImageData(DITHERING_ALGORITHMS[selectedAlgorithm](imageData), 0, 0) + }) const handleImageChange = async (event: any) => { const file = event.target.files[0]; @@ -38,18 +53,8 @@ return } - imgObjectUrl = URL.createObjectURL(file); - const image = await createImage(imgObjectUrl); - - // Change the sizes of canvases - canvas.width = image.width - canvas.height = image.height - - offscreenCanvas.height = image.height - offscreenCanvas.width = image.width - - // Now draw the images - drawImage(image) + const imgObjectUrl = URL.createObjectURL(file); + selectedImage = await createImage(imgObjectUrl); } async function createImage(objectUrl: string): Promise { @@ -63,30 +68,7 @@ }); } - const clearCanvases = () => { - ctx.clearRect(0, 0, canvas.width, canvas.height); - offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height); - } - - const drawImage = (theImage: HTMLImageElement) => { - if (!doesCtxExist()) return - clearCanvases() - ctx.drawImage(theImage, 0, 0, canvas.width, canvas.height); - offscreenCtx.drawImage(theImage, offscreenCanvas.width, offscreenCanvas.height) - } - - function applyDitheringAlgorithm(algorithm: (imageData: ImageData) => ImageData) { - return async () => { - const freshImage = await createImage(imgObjectUrl); - drawImage(freshImage) - const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); - const ditheredImageData = algorithm(imageData); - ctx.putImageData(ditheredImageData, 0, 0); - } - } - function saveImage() { - if (!canvas) return; const link = document.createElement('a'); link.download = 'dithered-image.png'; link.href = canvas.toDataURL(); @@ -95,7 +77,7 @@ - +

1: Select a file

@@ -108,9 +90,9 @@

2: Select a dithering algorithm

    - {#each Object.entries(DITHERING_ALGORITHMS) as [key, value]} + {#each Object.keys(DITHERING_ALGORITHMS) as key}
  • - +
  • {/each}
@@ -120,9 +102,20 @@ ctx = canvas.getContext('2d')}> +

+ 3: Remix +

+ +
+ +

{maxImageWidth * imageWidthPc / 100}

+

- 3: Save the file + 4: Save the file

diff --git a/src/routes/dither/ErrorMessage.svelte b/src/routes/dither/ErrorMessage.svelte index 1260cb5..502e4db 100644 --- a/src/routes/dither/ErrorMessage.svelte +++ b/src/routes/dither/ErrorMessage.svelte @@ -1,5 +1,8 @@ {#if errorMessage}