Skip to content

Commit ca99b4e

Browse files
committed
Project 19 complete
1 parent c2489d9 commit ca99b4e

File tree

3 files changed

+201
-4
lines changed

3 files changed

+201
-4
lines changed

19 - Webcam Fun/index.html

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<!DOCTYPE html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="UTF-8">
56
<title>Get User Media Code Along!</title>
67
<link rel="stylesheet" href="style.css">
78
</head>
9+
810
<body>
911

1012
<div class="photobooth">
1113
<div class="controls">
1214
<button onClick="takePhoto()">Take Photo</button>
13-
<!-- <div class="rgb">
15+
<div class="rgb">
1416
<label for="rmin">Red Min:</label>
1517
<input type="range" min=0 max=255 name="rmin">
1618
<label for="rmax">Red Max:</label>
@@ -29,7 +31,7 @@
2931
<input type="range" min=0 max=255 name="bmin">
3032
<label for="bmax">Blue Max:</label>
3133
<input type="range" min=0 max=255 name="bmax">
32-
</div> -->
34+
</div>
3335
</div>
3436

3537
<canvas class="photo"></canvas>
@@ -39,7 +41,8 @@
3941

4042
<audio class="snap" src="https://wesbos.com/demos/photobooth/snap.mp3" hidden></audio>
4143

42-
<script src="scripts.js"></script>
44+
<script src="typescripts.js"></script>
4345

4446
</body>
45-
</html>
47+
48+
</html>

19 - Webcam Fun/typescripts.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
var video = document.querySelector('.player');
2+
var canvas = document.querySelector('.photo');
3+
var ctx = canvas.getContext('2d');
4+
var strip = document.querySelector('.strip');
5+
var snap = document.querySelector('.snap');
6+
function redEffect(pixels) {
7+
for (var i = 0; i < pixels.data.length; i += 4) {
8+
pixels.data[i + 0] += 100;
9+
pixels.data[i + 1] += -50;
10+
pixels.data[i + 2] *= 0.5;
11+
}
12+
return pixels;
13+
}
14+
function rgbSplit(pixels) {
15+
for (var i = 0; i < pixels.data.length; i += 4) {
16+
pixels.data[i - 150] = pixels.data[i + 0];
17+
pixels.data[i + 100] = pixels.data[i + 1];
18+
pixels.data[i - 150] = pixels.data[i + 2];
19+
}
20+
return pixels;
21+
}
22+
function greenScreen(pixels) {
23+
var levels = {};
24+
var inputs = document.querySelectorAll('.rgb input');
25+
if (!inputs)
26+
return pixels;
27+
inputs.forEach(function (input) { return levels[input.name] = Number(input.value); });
28+
for (var i = 0; i < pixels.data.length; i = i + 4) {
29+
var red = pixels.data[i + 0];
30+
var green = pixels.data[i + 1];
31+
var blue = pixels.data[i + 2];
32+
if (red >= levels.rmin
33+
&& green >= levels.gmin
34+
&& blue >= levels.bmin
35+
&& red <= levels.rmax
36+
&& green <= levels.gmax
37+
&& blue <= levels.bmax) {
38+
pixels.data[i + 3] = 0;
39+
}
40+
}
41+
return pixels;
42+
}
43+
function paintToCanvas() {
44+
var width = video.videoWidth;
45+
var height = video.videoHeight;
46+
canvas.width = width;
47+
canvas.height = height;
48+
function paintVideoLoop() {
49+
if (!ctx)
50+
return;
51+
ctx.drawImage(video, 0, 0, width, height);
52+
var pixels = ctx.getImageData(0, 0, width, height);
53+
pixels = greenScreen(pixels);
54+
ctx.putImageData(pixels, 0, 0);
55+
requestAnimationFrame(paintVideoLoop);
56+
}
57+
paintVideoLoop();
58+
}
59+
function getVideo() {
60+
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
61+
.then(function (localMediaStream) {
62+
video.srcObject = localMediaStream;
63+
video.onloadedmetadata = function () {
64+
video.play();
65+
paintToCanvas();
66+
};
67+
})
68+
.catch(function (err) { return console.error("\uD83D\uDE2C I'm gonna need your webcam for this...", err); });
69+
}
70+
getVideo();
71+
function takePhoto() {
72+
snap.currentTime = 0;
73+
snap.play();
74+
var data = canvas.toDataURL('image/jpeg');
75+
var link = document.createElement('a');
76+
link.href = data;
77+
link.setAttribute('download', 'handsome');
78+
link.innerHTML = "<img src=\"" + data + "\" alt=\"Photo booth photo\" />";
79+
strip.insertBefore(link, strip.firstChild);
80+
}

19 - Webcam Fun/typescripts.ts

+114
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* JavaScript30 by Wes Bos, https://javascript30.com/
3+
* TypeScript implementation by Will Wager
4+
* Project: Webcam fun
5+
* Concepts: Accessing user media; Painting video to canvas; pixel manipulation
6+
* Key takeaways: Pixel manipulation is straightforward with the ImageData object and a canvas;
7+
* Create a download link with the download attribute
8+
* Sidenotes: Small update was required to get the media stream to work (video.srcObject)
9+
* Compilation command:
10+
* tsc --removeComments --strictNullChecks --noImplicitAny --target es5 typescripts.ts
11+
*/
12+
13+
interface GreenScreenConfig {
14+
[index: string]: number;
15+
}
16+
17+
const video = document.querySelector('.player') as HTMLVideoElement;
18+
const canvas = document.querySelector('.photo') as HTMLCanvasElement;
19+
const ctx = canvas.getContext('2d');
20+
const strip = document.querySelector('.strip')! as HTMLDivElement;
21+
const snap = document.querySelector('.snap') as HTMLAudioElement;
22+
23+
function redEffect(pixels: ImageData) {
24+
for (let i = 0; i < pixels.data.length; i += 4) {
25+
pixels.data[i + 0] += 100;
26+
pixels.data[i + 1] += -50;
27+
pixels.data[i + 2] *= 0.5;
28+
}
29+
return pixels;
30+
}
31+
32+
function rgbSplit(pixels: ImageData) {
33+
for (let i = 0; i < pixels.data.length; i += 4) {
34+
pixels.data[i - 150] = pixels.data[i + 0];
35+
pixels.data[i + 100] = pixels.data[i + 1];
36+
pixels.data[i - 150] = pixels.data[i + 2];
37+
}
38+
return pixels;
39+
}
40+
41+
function greenScreen(pixels: ImageData) {
42+
const levels: GreenScreenConfig = {};
43+
44+
const inputs = document.querySelectorAll('.rgb input');
45+
if (!inputs) return pixels;
46+
inputs.forEach((input: HTMLInputElement) => levels[input.name] = Number(input.value));
47+
48+
for (let i = 0; i < pixels.data.length; i = i + 4) {
49+
const red = pixels.data[i + 0];
50+
const green = pixels.data[i + 1];
51+
const blue = pixels.data[i + 2];
52+
53+
if (
54+
red >= levels.rmin
55+
&& green >= levels.gmin
56+
&& blue >= levels.bmin
57+
&& red <= levels.rmax
58+
&& green <= levels.gmax
59+
&& blue <= levels.bmax
60+
) {
61+
pixels.data[i + 3] = 0;
62+
}
63+
}
64+
65+
return pixels;
66+
}
67+
68+
function paintToCanvas() {
69+
const width = video.videoWidth;
70+
const height = video.videoHeight;
71+
72+
canvas.width = width;
73+
canvas.height = height;
74+
75+
function paintVideoLoop() {
76+
if (!ctx) return;
77+
ctx.drawImage(video, 0, 0, width, height)
78+
let pixels = ctx.getImageData(0, 0, width, height);
79+
80+
// pixels = redEffect(pixels);
81+
// pixels = rgbSplit(pixels);
82+
// ctx.globalAlpha = 0.1;
83+
pixels = greenScreen(pixels);
84+
ctx.putImageData(pixels, 0, 0);
85+
requestAnimationFrame(paintVideoLoop);
86+
}
87+
paintVideoLoop();
88+
}
89+
90+
function getVideo() {
91+
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
92+
.then(localMediaStream => {
93+
video.srcObject = localMediaStream;
94+
video.onloadedmetadata = () => {
95+
video.play();
96+
paintToCanvas();
97+
};
98+
})
99+
.catch(err => console.error(`😬 I'm gonna need your webcam for this...`, err));
100+
}
101+
getVideo();
102+
103+
function takePhoto() {
104+
snap.currentTime = 0;
105+
snap.play();
106+
107+
const data = canvas.toDataURL('image/jpeg');
108+
const link = document.createElement('a');
109+
link.href = data;
110+
link.setAttribute('download', 'handsome');
111+
link.innerHTML = `<img src="${data}" alt="Photo booth photo" />`;
112+
strip.insertBefore(link, strip.firstChild);
113+
}
114+

0 commit comments

Comments
 (0)