-
37dist/gammacorrection.html
-
BINdist/gammacorrection.png
-
BINdist/grayscale-finished.png
-
45dist/grayscale.html
-
BINdist/quantise-color-poster-finished.png
-
BINdist/quantise-grayscale-poster-finished.png
-
BINdist/quantise-hist-finished.png
-
BINdist/quantise.jpg
-
45dist/quantisecolor.html
-
45dist/quantisegrayscale.html
-
18src/03/gammacorrection.ts
-
16src/03/grayscale.ts
-
17src/03/quantisecolor.ts
-
17src/03/quantisegrayscale.ts
-
49src/03/setup-gammacorrection.ts
-
38src/03/setup-grayscale.ts
-
38src/03/setup-quantisecolor.ts
-
38src/03/setup-quantisegrayscale.ts
@ -0,0 +1,37 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - Color - Gamma Correction</title> |
||||
|
<script type="text/javascript" src="gammacorrection.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Gamma Correction</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<figure class="figure mx-auto d-block"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="800" height="400"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
<div class="form-group text-left"> |
||||
|
<label for="gammaslider">Gamma</label> |
||||
|
<input class="form-control-range" type="range" id="gammaslider" min="1" max="5" step="0.1"> |
||||
|
</div> |
||||
|
Determine the color of each pixel after the gamma correction |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
After Width: 800 | Height: 400 | Size: 8.4 KiB |
After Width: 512 | Height: 384 | Size: 233 KiB |
@ -0,0 +1,45 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - Color - XYZ</title> |
||||
|
<script type="text/javascript" src="grayscale.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Grayscale</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Create a grayscale version by converting the RBG values to XYZ and use the Y value. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<img class="figure-img mx-auto d-block" src="grayscale-finished.png"> |
||||
|
<figcaption class="figure-caption text-center">Reference image</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Original |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
After Width: 512 | Height: 384 | Size: 37 KiB |
After Width: 512 | Height: 384 | Size: 15 KiB |
After Width: 396 | Height: 396 | Size: 28 KiB |
After Width: 1024 | Height: 768 | Size: 228 KiB |
@ -0,0 +1,45 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - Color - XYZ</title> |
||||
|
<script type="text/javascript" src="quantisecolor.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Posterise Color</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Quantise the image to 4 brightness values per color channel. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<img class="figure-img mx-auto d-block" src="quantise-color-poster-finished.png"> |
||||
|
<figcaption class="figure-caption text-center">Reference image</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Original |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,45 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
|
||||
|
<html lang="en"> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<title>Graphische Datenverarbeitung - Color - XYZ</title> |
||||
|
<script type="text/javascript" src="quantisegrayscale.bundle.js"></script> |
||||
|
<link rel="icon" type="image/png" href="ai-logo.png"> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<nav class="navbar navbar-light bg-light"> |
||||
|
<div class="container"> |
||||
|
<a class="navbar-brand" href="/index.html"> |
||||
|
<img src="ai-logo.png" width="30" height="30" class="d-inline-block align-top" alt=""> |
||||
|
Graphische Datenverarbeitung |
||||
|
</a> |
||||
|
<div class="navbar-brand">Posterise Black and White</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
<br> |
||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="result" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Quantise the image to 4 brightness values. |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<img class="figure-img mx-auto d-block" src="quantise-grayscale-poster-finished.png"> |
||||
|
<figcaption class="figure-caption text-center">Reference image</figcaption> |
||||
|
</figure> |
||||
|
<figure class="figure col-sm-6"> |
||||
|
<canvas id="original" class="figure-img mx-auto d-block" width="512" height="384"></canvas> |
||||
|
<figcaption class="figure-caption text-center"> |
||||
|
Original |
||||
|
</figcaption> |
||||
|
</figure> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -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.
|
||||
|
} |
@ -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.
|
||||
|
} |
@ -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:
|
||||
|
} |
@ -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.
|
||||
|
} |
@ -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); |
||||
|
} |
@ -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"; |
||||
|
}); |
@ -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"; |
||||
|
}); |
@ -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"; |
||||
|
}); |