Skip to content

Commit 0cbc3c3

Browse files
committed
Day 19 complete
1 parent e60b330 commit 0cbc3c3

File tree

2 files changed

+169
-3
lines changed

2 files changed

+169
-3
lines changed

19 - Webcam Fun/index.html

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@
99

1010
<div class="photobooth">
1111
<div class="controls">
12-
<button onClick="takePhoto()">Take Photo</button>
13-
<!-- <div class="rgb">
12+
<button id="TakePhoto">Take Photo</button>
13+
<button id="RedEffect">Red Effect</button>
14+
<button id="SplitEffect">Split Effect</button>
15+
<button id="GreenscreenEffect">Greenscreen Effect</button>
16+
<button id="MyEffect">My Effect</button>
17+
<button id="ClearEffect">Clear Effect</button>
18+
<div class="rgb">
1419
<label for="rmin">Red Min:</label>
1520
<input type="range" min=0 max=255 name="rmin">
1621
<label for="rmax">Red Max:</label>
@@ -29,7 +34,7 @@
2934
<input type="range" min=0 max=255 name="bmin">
3035
<label for="bmax">Blue Max:</label>
3136
<input type="range" min=0 max=255 name="bmax">
32-
</div> -->
37+
</div>
3338
</div>
3439

3540
<canvas class="photo"></canvas>

19 - Webcam Fun/scripts.js

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,164 @@ const canvas = document.querySelector('.photo');
33
const ctx = canvas.getContext('2d');
44
const strip = document.querySelector('.strip');
55
const snap = document.querySelector('.snap');
6+
const rgb = document.querySelector('.rgb');
7+
const booth = document.querySelector('.photobooth');
8+
9+
let videoFilter = noFilter;
10+
const ghostingValue = 1.0;
11+
12+
function getVideo() {
13+
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
14+
.then(stream => {
15+
video.src = window.URL.createObjectURL(stream);
16+
video.play();
17+
})
18+
.catch(error => console.error("Oh snap!", error));
19+
}
20+
21+
function paintToCanavas() {
22+
const width = video.videoWidth;
23+
const height = video.videoHeight;
24+
canvas.width = width;
25+
canvas.height = height;
26+
27+
return setInterval(() => {
28+
ctx.drawImage(video, 0, 0, width, height);
29+
// take the pixels out
30+
let pixels = ctx.getImageData(0, 0, width, height);
31+
// mess with them
32+
pixels = videoFilter(pixels);
33+
ctx.globalAlpha = ghostingValue;
34+
// put them back
35+
ctx.putImageData(pixels, 0, 0);
36+
}, 16);
37+
}
38+
39+
function takePhoto() {
40+
// played the sound
41+
snap.currentTime = 0;
42+
snap.play();
43+
44+
// take the data out of the canvas
45+
const dataURI = canvas.toDataURL('image/jpeg');
46+
const link = document.createElement('a');
47+
link.href = dataURI;
48+
link.setAttribute('download', 'handsome');
49+
link.innerHTML = `<img src="${dataURI}" alt="Video still" />`;
50+
strip.insertBefore(link, strip.firsChild);
51+
}
52+
53+
function noFilter(pixels) { return me(pixels); }
54+
me = i => i;
55+
plus = x => i => i + x;
56+
minus = x => i => i - x;
57+
multiply = x => i => i * x;
58+
divide = x => i => i / x;
59+
redIndex = me;
60+
greenIndex = plus(1);
61+
blueIndex = plus(2);
62+
alphaIndex = plus(3);
63+
/**
64+
* pixels - our pixels for the video filter effect
65+
* all other params are functions
66+
* params beginning with r deal with the Red channel
67+
* params beginning with g deal with the Green channel
68+
* params beginning with g deal with the Blue channel
69+
* params beginning with a deal with the Alpha channel
70+
* params ending in i take the iterator from the for loop as a param and return
71+
* an index number for use in the pixel data array
72+
* params ending in t are transformation functions meant to consume a value from
73+
* the pixel data array and transform it into some new value
74+
* the middle letter for the 3 letter params deal with direction
75+
* r for Right and l for Left
76+
* the line for the Red channel can be read as:
77+
* Choose a value from the pixel data array using the index from our Red Right
78+
* Index function
79+
* Calcualte a new value from the selected value using the Red Transformation
80+
* function
81+
* Store the newly calculated value in our pixel data array at the index
82+
* indicated by our Red Left Index function
83+
*/
84+
function simpleFilter(pixels, rli, rri, rt, gli, gri, gt, bli, bri, bt, ali, ari, at) {
85+
for(let i = 0; i < pixels.data.length; i+=4) {
86+
pixels.data[rli(i)] = rt(pixels.data[rri(i)]); // Red
87+
pixels.data[gli(i)] = gt(pixels.data[gri(i)]); // Green
88+
pixels.data[bli(i)] = bt(pixels.data[bri(i)]); // Blue
89+
pixels.data[ali(i)] = at(pixels.data[ari(i)]); // Alpha
90+
}
91+
return pixels;
92+
}
93+
94+
function redEffect(pixels) {
95+
return simpleFilter(
96+
pixels,
97+
redIndex, redIndex, plus(200),
98+
greenIndex, greenIndex, minus(50),
99+
blueIndex, blueIndex, multiply(0.5),
100+
alphaIndex, alphaIndex, me
101+
);
102+
}
103+
function rgbSplit(pixels) {
104+
return simpleFilter(
105+
pixels,
106+
minus(150), redIndex, me,
107+
plus(500), greenIndex, me,
108+
minus(550), blueIndex, me,
109+
alphaIndex, alphaIndex, me
110+
);
111+
}
112+
function myFilter(pixels) {
113+
return simpleFilter(
114+
pixels,
115+
redIndex, greenIndex, me,
116+
greenIndex, blueIndex, me,
117+
blueIndex, redIndex, me,
118+
alphaIndex, alphaIndex, me
119+
);
120+
}
121+
function greenScreen(pixels) {
122+
const levels = {};
123+
124+
rgb.querySelectorAll('input').forEach((input) => {
125+
levels[input.name] = input.value;
126+
});
127+
128+
for (i = 0; i < pixels.data.length; i = i + 4) {
129+
red = pixels.data[i + 0];
130+
green = pixels.data[i + 1];
131+
blue = pixels.data[i + 2];
132+
alpha = pixels.data[i + 3];
133+
134+
if (red >= levels.rmin
135+
&& green >= levels.gmin
136+
&& blue >= levels.bmin
137+
&& red <= levels.rmax
138+
&& green <= levels.gmax
139+
&& blue <= levels.bmax) {
140+
// take it out!
141+
pixels.data[i + 3] = 0;
142+
}
143+
}
144+
145+
return pixels;
146+
}
147+
148+
function handleButtons(event) {
149+
if (event.target.matches('#TakePhoto')) {
150+
takePhoto();
151+
} else if (event.target.matches('#RedEffect')) {
152+
videoFilter = redEffect;
153+
} else if (event.target.matches('#SplitEffect')) {
154+
videoFilter = rgbSplit;
155+
} else if (event.target.matches('#GreenscreenEffect')) {
156+
videoFilter = greenScreen;
157+
} else if (event.target.matches('#ClearEffect')) {
158+
videoFilter = noFilter;
159+
} else if (event.target.matches('#MyEffect')) {
160+
videoFilter = myFilter;
161+
} // else do nothing
162+
}
163+
164+
getVideo();
165+
video.addEventListener('canplay', paintToCanavas);
166+
booth.addEventListener('click', handleButtons);

0 commit comments

Comments
 (0)