+
+
+
+ Quantise the image to 4 brightness values.
+
+
+
+
+ Reference image
+
+
+
+
+ Original
+
+
+
+
+
+
+
diff --git a/src/03/gammacorrection.ts b/src/03/gammacorrection.ts
new file mode 100644
index 0000000..4443a90
--- /dev/null
+++ b/src/03/gammacorrection.ts
@@ -0,0 +1,18 @@
+/**
+ * Conducts a gamma adjustment with a given gamma value on the pixel
+ * (x, y). The original color information can be read from the source image.
+ * The adjusted color is to be saved in the dest array.
+ * @param {number} gamma The gamma factor to adjust the brightness
+ * @param {Uint8ClampedArray} source The original pixel data
+ * @param {Uint8ClampedArray} dest The array to save the adjusted color data to
+ * @param {number} x The x coordinate of the pixel to adjust
+ * @param {number} y The y coordinate of the pixel to adjust
+ * @param {number} width The width of the image in pixels
+ * @param {number} height The height of the image in pixels
+ */
+export function gammaAdjust(gamma: number, source: Uint8ClampedArray,
+ dest: Uint8ClampedArray, x: number, y: number,
+ width: number, height: number) {
+
+ // TODO: Perform a gamma correction with the given gamma value on the current pixel at position (x, y) in the source array, and store the result in the dest array.
+}
diff --git a/src/03/grayscale.ts b/src/03/grayscale.ts
new file mode 100644
index 0000000..f11d074
--- /dev/null
+++ b/src/03/grayscale.ts
@@ -0,0 +1,16 @@
+/**
+ * Convert the color information of the pixel at (x, y) to grayscale by using the
+ * Y coordinate of the XYZ color space.
+ *
+ * @param x The x coordinate of the pixel to convert
+ * @param y The y coordinate of the pixel to convert
+ * @param source The source image data
+ * @param target The image data to save the converted color information to
+ * @param width The width of the canvas
+ * @param height The height of the canvas
+ */
+export function grayscale(x: number, y: number, source: Uint8ClampedArray, target: Uint8ClampedArray, width: number, height: number) {
+
+ // TODO: Convert the pixel at position (x, y) in the source array from RGB to XYZ.
+ // TODO: Set the RGBA values in the target array according to the Y component of the source pixel in XYZ space.
+}
diff --git a/src/03/quantisecolor.ts b/src/03/quantisecolor.ts
new file mode 100644
index 0000000..0273860
--- /dev/null
+++ b/src/03/quantisecolor.ts
@@ -0,0 +1,17 @@
+/**
+ * Posterise the source image and save the result in the target image.
+ * Restrict each color channel to four equidistant values.
+ *
+ * @param x The x coordinate of the pixel to posterise
+ * @param y The y coordinate of the pixel to posterise
+ * @param source The source image data
+ * @param target The image data to save the converted color information to
+ * @param width The width of the canvas
+ * @param height The height of the canvas
+ */
+export function quantiseColor(x: number, y: number, source: Uint8ClampedArray, target: Uint8ClampedArray, width: number, height: number) {
+
+ // TODO: Limit the brightness of each color channel to the set of 4 different values 0, 85, 170, 255.
+ // TODO: Set the RGBA values in the target array accordingly.
+ // TODO:
+}
diff --git a/src/03/quantisegrayscale.ts b/src/03/quantisegrayscale.ts
new file mode 100644
index 0000000..d3c1c2f
--- /dev/null
+++ b/src/03/quantisegrayscale.ts
@@ -0,0 +1,17 @@
+/**
+ * Posterise the source image and save the result in the target image.
+ * Restrict the amount of used brightness levels to four equidistant values.
+ *
+ * @param x The x coordinate of the pixel to posterise
+ * @param y The y coordinate of the pixel to posterise
+ * @param source The source image data
+ * @param target The image data to save the converted color information to
+ * @param width The width of the canvas
+ * @param height The height of the canvas
+ */
+export function quantisegrayscale(x: number, y: number, source: Uint8ClampedArray, target: Uint8ClampedArray, width: number, height: number) {
+
+ // TODO: Convert the pixel at position (x, y) in the source array from RGB to XYZ. Limit the
+ // TODO: Limit the brightness to the set of 4 different values 0, 85, 170, 255.
+ // TODO: Set the RGBA values in the target array to this brightness.
+}
diff --git a/src/03/setup-gammacorrection.ts b/src/03/setup-gammacorrection.ts
new file mode 100644
index 0000000..5c2ff8a
--- /dev/null
+++ b/src/03/setup-gammacorrection.ts
@@ -0,0 +1,49 @@
+import 'bootstrap';
+import 'bootstrap/scss/bootstrap.scss';
+import { gammaAdjust } from './gammacorrection';
+
+let gammaImageData: ImageData;
+let gammaCtx: CanvasRenderingContext2D;
+let gamma = 1;
+
+window.addEventListener('load', () => {
+
+ const gammaSlider =
+ document.getElementById("gammaslider") as HTMLInputElement;
+ const gammaCanvas = document.getElementById("result") as HTMLCanvasElement;
+ if (gammaCanvas === null)
+ return;
+ gammaCtx = gammaCanvas.getContext("2d");
+
+ const gammaImg = new Image();
+ gammaImg.onload = () => {
+ gammaCtx.drawImage(gammaImg, 0, 0);
+ gammaImageData = gammaCtx.getImageData(
+ 0, 0, gammaImg.width, gammaImg.height);
+ gammaAdjustImage();
+ };
+ gammaImg.src = "gammacorrection.png";
+
+ gammaSlider.addEventListener('change', e => {
+ gamma = Number(gammaSlider.value);
+ gammaAdjustImage();
+ });
+ gamma = Number(gammaSlider.value);
+});
+
+function gammaAdjustImage() {
+ const imageData = gammaCtx.getImageData(
+ 0, 0,
+ gammaImageData.width, gammaImageData.height
+ );
+ for (let width = 0; width < gammaImageData.width; width++) {
+ for (let height = 0; height < gammaImageData.height; height++) {
+ gammaAdjust(gamma,
+ gammaImageData.data, imageData.data,
+ width, height,
+ gammaImageData.width, gammaImageData.height
+ );
+ }
+ }
+ gammaCtx.putImageData(imageData, 0, 0);
+}
diff --git a/src/03/setup-grayscale.ts b/src/03/setup-grayscale.ts
new file mode 100644
index 0000000..db9c56d
--- /dev/null
+++ b/src/03/setup-grayscale.ts
@@ -0,0 +1,38 @@
+import 'bootstrap';
+import 'bootstrap/scss/bootstrap.scss';
+
+import { grayscale } from './grayscale';
+
+function quantise(evt: Event) {
+
+ const originalCanvas = document.getElementById("original") as HTMLCanvasElement;
+ if (originalCanvas === null)
+ return;
+ const original = originalCanvas.getContext("2d");
+ original.drawImage(evt.target as HTMLImageElement, 0, 0, 512, 384);
+ const originalData = original.getImageData(0, 0, originalCanvas.width, originalCanvas.height);
+
+ const grayscaleCanvas = document.getElementById("result") as HTMLCanvasElement;
+ const grayscaleContext = grayscaleCanvas.getContext("2d");
+ var pixel = grayscaleContext.createImageData(1, 1);
+ const grayscaleData = grayscaleContext.getImageData(0, 0, grayscaleCanvas.width, grayscaleCanvas.height);
+
+ for (let y = 0; y < grayscaleCanvas.height; y++) {
+ for (let x = 0; x < grayscaleCanvas.width; x++) {
+ grayscale(x, y, originalData.data, grayscaleData.data, grayscaleCanvas.width, grayscaleCanvas.height);
+
+ // update pixel in HTML context2d
+ for (let i = 0; i < 4; i ++)
+ pixel.data[i] =
+ grayscaleData.data[(x + y * grayscaleCanvas.width) * 4 + i];
+ grayscaleContext.putImageData(pixel, x, y);
+ }
+ }
+}
+
+window.addEventListener('load', () => {
+
+ const squirrel = new Image();
+ squirrel.onload = quantise;
+ squirrel.src = "quantise.jpg";
+});
diff --git a/src/03/setup-quantisecolor.ts b/src/03/setup-quantisecolor.ts
new file mode 100644
index 0000000..a6034cf
--- /dev/null
+++ b/src/03/setup-quantisecolor.ts
@@ -0,0 +1,38 @@
+import 'bootstrap';
+import 'bootstrap/scss/bootstrap.scss';
+
+import { quantiseColor } from './quantisecolor';
+
+function quantise(evt: Event) {
+
+ const originalCanvas = document.getElementById("original") as HTMLCanvasElement;
+ if (originalCanvas === null)
+ return;
+ const original = originalCanvas.getContext("2d");
+ original.drawImage(evt.target as HTMLImageElement, 0, 0, 512, 384);
+ const originalData = original.getImageData(0, 0, originalCanvas.width, originalCanvas.height);
+
+ const colorCanvas = document.getElementById("result") as HTMLCanvasElement;
+ const color = colorCanvas.getContext("2d");
+ var pixel = color.createImageData(1, 1);
+ const colorData = color.getImageData(0, 0, colorCanvas.width, colorCanvas.height);
+
+ for (let y = 0; y < colorCanvas.height; y++) {
+ for (let x = 0; x < colorCanvas.width; x++) {
+ quantiseColor(x, y, originalData.data, colorData.data, colorCanvas.width, colorCanvas.height);
+
+ // update pixel in HTML context2d
+ for (let i = 0; i < 4; i ++)
+ pixel.data[i] =
+ colorData.data[(x + y * colorCanvas.width) * 4 + i];
+ color.putImageData(pixel, x, y);
+ }
+ }
+}
+
+window.addEventListener('load', () => {
+
+ const squirrel = new Image();
+ squirrel.onload = quantise;
+ squirrel.src = "quantise.jpg";
+});
diff --git a/src/03/setup-quantisegrayscale.ts b/src/03/setup-quantisegrayscale.ts
new file mode 100644
index 0000000..f68be68
--- /dev/null
+++ b/src/03/setup-quantisegrayscale.ts
@@ -0,0 +1,38 @@
+import 'bootstrap';
+import 'bootstrap/scss/bootstrap.scss';
+
+import { quantisegrayscale } from './quantisegrayscale';
+
+function quantise(evt: Event) {
+
+ const originalCanvas = document.getElementById("original") as HTMLCanvasElement;
+ if (originalCanvas === null)
+ return;
+ const original = originalCanvas.getContext("2d");
+ original.drawImage(evt.target as HTMLImageElement, 0, 0, 512, 384);
+ const originalData = original.getImageData(0, 0, originalCanvas.width, originalCanvas.height);
+
+ const grayscaleCanvas = document.getElementById("result") as HTMLCanvasElement;
+ const grayscale = grayscaleCanvas.getContext("2d");
+ var pixel = grayscale.createImageData(1, 1);
+ const grayscaleData = grayscale.getImageData(0, 0, grayscaleCanvas.width, grayscaleCanvas.height);
+
+ for (let y = 0; y < grayscaleCanvas.height; y++) {
+ for (let x = 0; x < grayscaleCanvas.width; x++) {
+ quantisegrayscale(x, y, originalData.data, grayscaleData.data, grayscaleCanvas.width, grayscaleCanvas.height);
+
+ // update pixel in HTML context2d
+ for (let i = 0; i < 4; i ++)
+ pixel.data[i] =
+ grayscaleData.data[(x + y * grayscaleCanvas.width) * 4 + i];
+ grayscale.putImageData(pixel, x, y);
+ }
+ }
+}
+
+window.addEventListener('load', () => {
+
+ const squirrel = new Image();
+ squirrel.onload = quantise;
+ squirrel.src = "quantise.jpg";
+});