Skip to content

Commit 3abbcde

Browse files
committed
proj 19: work on image mirroring (flipping horizontally).
1 parent 8ac28d9 commit 3abbcde

File tree

5 files changed

+145
-75
lines changed

5 files changed

+145
-75
lines changed

19--Webcam_Fun/index-jds.html

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ <h1>webcam fun</h1>
2323
<legend>cam</legend>
2424
<button class="btn_on status success">On</button>
2525
<button class="btn_off status error disabled" disabled>Off</button>
26+
27+
<!-- convert on/off buttons into checkbox toggle -->
28+
<!-- <label class="" for="cam">
29+
<input type="checkbox" id="cam" class="">
30+
<span class="label">On?</span>
31+
</label> -->
32+
33+
<!-- add checkbox toggle for mirror effect -->
34+
<label class="" for="mirror">
35+
<input type="checkbox" id="mirror" class="">
36+
<span class="label">Mirror?</span>
37+
</label>
38+
2639
<button class="btn_clear disabled" disabled>Clear</button>
2740
</fieldset>
2841
<fieldset id="ctrl_fx">
@@ -152,7 +165,7 @@ <h1>webcam fun</h1>
152165
<tr>
153166
<td>
154167
<label>
155-
<span>saturate:</span>
168+
<span>saturate: <code class="value">0</code></span>
156169
<input id="saturate" type="range" class="input-range" value=100 min=0 max=200>
157170
</label>
158171
</td>
@@ -167,8 +180,8 @@ <h1>webcam fun</h1>
167180
<tr>
168181
<td>
169182
<label>
170-
<span>pixelate:</span>
171-
<input id="pixelate" type="range" class="input-range" value=0 min=-100 max=100>
183+
<span>pixelate: <code class="value">0</code></span>
184+
<input id="pixelate" type="range" class="input-range" value=0 min=1 max=10>
172185
</label>
173186
</td>
174187
</tr>
@@ -203,6 +216,7 @@ <h1>webcam fun</h1>
203216
<script src="js/utils.js"></script>
204217
<script src="js/scripts.js"></script>
205218
<script src="js/fx.js"></script>
219+
<script src="js/mirror.js"></script>
206220
<!-- <script src="scripts-FINISHED.js"></script> -->
207221

208222
</body>

19--Webcam_Fun/js/fx.js

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ console.log('fx.js READY!');
66
* @param {big array} data - The pixels.
77
* @return {big array} The modified pixels.
88
*/
9-
function fFxChromaKey(data) {
9+
function fFxChromaKey(uint8) {
1010
// console.log('START fFxChromaKey');
1111
// create empty array of min & max values
1212
const levels = {};
@@ -16,12 +16,12 @@ function fFxChromaKey(data) {
1616
});
1717
// console.log(levels);
1818
// debugger;
19-
for (let i = 0; i < data.data.length; i+=4) {
19+
for (let i = 0; i < uint8.data.length; i+=4) {
2020
// put values into vars
21-
red = data.data[i+0]; // r
22-
green = data.data[i+1]; // g
23-
blue = data.data[i+2]; // b
24-
alpha = data.data[i+3]; // a
21+
red = uint8.data[i+0]; // r
22+
green = uint8.data[i+1]; // g
23+
blue = uint8.data[i+2]; // b
24+
alpha = uint8.data[i+3]; // a
2525

2626
// check if values are within ranges
2727
if (red >= levels.rmin
@@ -31,10 +31,10 @@ function fFxChromaKey(data) {
3131
&& blue >= levels.bmin
3232
&& blue <= levels.bmax) {
3333
// take it out!
34-
data.data[i + 3] = 0;
34+
uint8.data[i + 3] = 0;
3535
}
3636
}
37-
return data;
37+
return uint8;
3838
}
3939

4040
/**
@@ -45,14 +45,14 @@ function fFxChromaKey(data) {
4545
* @param {array} nums - Integers used to shift each R, G, and B value.
4646
* @return {big array} The modified pixels.
4747
*/
48-
function fFxChannelSplit(data,nums) {
48+
function fFxChannelSplit(uint8,nums) {
4949
// console.log('START fFxChannelSplit');
50-
for (let i = 0; i < data.data.length; i+=4) {
51-
data.data[i+nums[0]] = data.data[i+0]; // r
52-
data.data[i+nums[1]] = data.data[i+1]; // g
53-
data.data[i+nums[2]] = data.data[i+2]; // b
50+
for (let i = 0; i < uint8.data.length; i+=4) {
51+
uint8.data[i+nums[0]] = uint8.data[i+0]; // r
52+
uint8.data[i+nums[1]] = uint8.data[i+1]; // g
53+
uint8.data[i+nums[2]] = uint8.data[i+2]; // b
5454
}
55-
return data;
55+
return uint8;
5656
}
5757

5858
/**
@@ -62,27 +62,27 @@ function fFxChannelSplit(data,nums) {
6262
* @param {array} nums - Integers used to shift each R, G, and B value.
6363
* @return {big array} The modified pixels.
6464
*/
65-
function fFxColorize(data,nums) {
65+
function fFxColorize(uint8,nums) {
6666
// console.log('START fFxRGB',nums);
67-
for (let i = 0; i < data.data.length; i+=4) {
68-
data.data[i+0] += nums[0]; // r
69-
data.data[i+1] += nums[1]; // g
70-
data.data[i+2] += nums[2]; // b
67+
for (let i = 0; i < uint8.data.length; i+=4) {
68+
uint8.data[i+0] += nums[0]; // r
69+
uint8.data[i+1] += nums[1]; // g
70+
uint8.data[i+2] += nums[2]; // b
7171
}
72-
return data;
72+
return uint8;
7373
}
7474

7575
/**
7676
* [fFxPixelate description]
7777
* @param {big array} data - The pixels.
78-
* @param {number} resolution - Resolution of the pixels: 1 = 1:1, 2 = 1:2, 3 = 1:3, etc.
78+
* @param {number} res - Resolution of the pixels: 1 = 1:1, 2 = 1:2, 3 = 1:3, etc.
7979
* @return {big array} The modified pixels.
8080
*/
81-
function fFxPixelate(data,resolution) {
82-
// console.log('START fFxPixelate',resolution);
83-
for (let i = 0; i < data.data.length; i+=4) {
81+
function fFxPixelate(uint8,res) {
82+
// console.log('START fFxPixelate',res);
83+
for (let i = 0; i < uint8.data.length; i+=4) {
8484
}
85-
return data;
85+
return uint8;
8686
}
8787

8888
/**
@@ -91,27 +91,15 @@ function fFxPixelate(data,resolution) {
9191
* @param {number} saturation - How saturated the video should be: 0 = monochrome, 100 = normal color, 200 = super color.
9292
* @return {big array} The modified pixels.
9393
*/
94-
function fFxSaturate(data,nums) {
94+
function fFxSaturate(uint8,nums) {
9595
// console.log('START fFxSaturate',nums);
96-
for (let i = 0; i < data.data.length; i+=4) {
96+
for (let i = 0; i < uint8.data.length; i+=4) {
9797
/* add color values together to get average */
98-
const avg = (data.data[i+0] + data.data[i+1] + data.data[i+2])/3;
98+
const avg = (uint8.data[i+0] + uint8.data[i+1] + uint8.data[i+2])/3;
9999
/* apply average to R,G, and B values of each pixel */
100-
data.data[i+0] = (avg*nums[0])+(data.data[i+0]*nums[1]); // r
101-
data.data[i+1] = (avg*nums[0])+(data.data[i+1]*nums[1]); // g
102-
data.data[i+2] = (avg*nums[0])+(data.data[i+2]*nums[1]); // b
100+
uint8.data[i+0] = (avg*nums[0])+(uint8.data[i+0]*nums[1]); // r
101+
uint8.data[i+1] = (avg*nums[0])+(uint8.data[i+1]*nums[1]); // g
102+
uint8.data[i+2] = (avg*nums[0])+(uint8.data[i+2]*nums[1]); // b
103103
}
104-
return data;
105-
}
106-
107-
/**
108-
* [fFxMirror description]
109-
* @param {big array} data - The pixels.
110-
* @return {big array} The modified pixels.
111-
*/
112-
function fFxMirror(data) {
113-
// console.log('START fFxMirror');
114-
for (let i = 0; i < data.data.length; i+=4) {
115-
}
116-
return data;
104+
return uint8;
117105
}

19--Webcam_Fun/js/mirror.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* [fMirror description]
3+
* @param {big array} data - The pixels.
4+
* @return {big array} The modified pixels.
5+
*/
6+
function fMirror(context) {
7+
console.group('START fMirror: ',context);
8+
9+
context.drawImage(video,0,0,vWidth,vHeight);
10+
let pixels = context.getImageData(0,0,vWidth,vHeight);
11+
console.log('pixels:', pixels);
12+
13+
/**
14+
* in retrospect, reversing the array does not work b/c the RGBA sequence
15+
* values get applies backwards as ABGR. in order to preserve the color and transparency while reversing the image, I will need to reverse the values in blocks of 4...
16+
*/
17+
18+
// pixels.data = pixels.data.map((px)=>{
19+
// console.log('test',index);
20+
// });
21+
// debugger;
22+
23+
// for (let i = 0; i < pixels.data.length; i+=4) {
24+
// var sub = pixels.data.subarray(0,4);
25+
// console.log('sub: ', sub);
26+
// console.log('pixels.data:', pixels.data);
27+
// debugger;
28+
// }
29+
console.groupEnd();
30+
return pixels;
31+
}

19--Webcam_Fun/js/scripts.js

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ctx = canvas.getContext('2d');
1111
const strip = document.querySelector('.strip');
1212
const snapSound = document.querySelector('.sound-snap');
1313
const snapLimit = document.querySelector('#limit');
14+
const mirror = document.querySelector('#mirror');
1415
const alertAllMsg = document.querySelectorAll('.alert');
1516
const alertMsgCam = document.querySelector('#msg_cam');
1617
const alertMsgFx = document.querySelector('#msg_fx');
@@ -46,6 +47,10 @@ const rgbMax = document.querySelector('.max .rgb');
4647
const ctrlSaturate = document.querySelector('#ctrl_fx_saturate');
4748
const inputSaturate = document.querySelector('#saturate');
4849

50+
/* video resolution controls */
51+
const ctrlPixelate = document.querySelector('#ctrl_fx_pixelate');
52+
const inputPixelate = document.querySelector('#pixelate');
53+
4954
/* buttons */
5055
const btnAllApply = document.querySelectorAll('.btn_apply');
5156
const btnAllClear = document.querySelectorAll('.btn_clear');
@@ -263,14 +268,18 @@ if (navigator.mediaDevices) {
263268

264269
const vWidth = video.videoWidth;
265270
const vHeight = video.videoHeight;
266-
// console.log('vWidth:'+vWidth,'vHeight:'+vHeight);
271+
console.log('vWidth:'+vWidth+' / vHeight:'+vHeight);
267272

268-
const ratio = vWidth/vHeight;
269-
// console.log('ratio: ', ratio);
273+
const vRatio = vWidth/vHeight;
274+
console.log('vRatio: ', vRatio);
270275

271276
const wWidth = window.innerWidth;
272-
const wHeight = window.innerHeight;
273-
// console.log('wWidth:'+wWidth,'wHeight:'+wHeight);
277+
const wHeight = wWidth*vRatio;
278+
// const wHeight = window.innerHeight;
279+
console.log('wWidth:'+wWidth+' / wHeight:'+wHeight);
280+
281+
const wRatio = wWidth/wHeight;
282+
console.log('wRatio: ', wRatio);
274283

275284
/* set canvas to W&H of window */
276285
// canvas.width = wWidth;
@@ -304,8 +313,12 @@ if (navigator.mediaDevices) {
304313
for (var i = 0; i < randoms.length; i++) {
305314
randoms[i] *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
306315
}
316+
console.group('randoms: ', randoms);
307317
// console.log('randoms: ', randoms);
318+
console.groupEnd();
308319

320+
/* values for F/X function */
321+
console.group('selectSplit.value: ', selectSplit.value);
309322
let intsSplit = [];
310323
if (selectSplit.value === 'stereo') {
311324
// expression
@@ -321,6 +334,10 @@ if (navigator.mediaDevices) {
321334
intsSplit = randoms;
322335
}
323336
// console.log('intsSplit: ', intsSplit);
337+
console.groupEnd();
338+
339+
/* values for F/X function */
340+
console.group('selectColorize.value: ', selectColorize.value);
324341
let intsColorize = [];
325342
if (selectColorize.value === 'red') {
326343
intsColorize = [150, -50, -50];
@@ -332,15 +349,23 @@ if (navigator.mediaDevices) {
332349
intsColorize = randoms;
333350
}
334351
// console.log('intsColorize: ', intsColorize);
352+
console.groupEnd();
335353

354+
/* values for F/X function */
336355
const inputSaturateVal = parseInt(inputSaturate.value);
337-
console.log('inputSaturateVal: ', inputSaturateVal);
356+
console.group('inputSaturateVal: ', inputSaturateVal);
338357
let intsSaturate = [0.5,0.5];
339-
console.log('intsSaturate: ', intsSaturate);
358+
// console.log('intsSaturate: ', intsSaturate);
340359
intsSaturate = [(100-inputSaturateVal)/100,inputSaturateVal/100];
341360
console.log('intsSaturate: ', intsSaturate);
361+
console.groupEnd();
342362

343-
let intPixelate = 0;
363+
/* values for F/X function */
364+
const inputPixelateVal = parseInt(inputPixelate.value);
365+
console.group('inputPixelateVal: ', inputPixelateVal);
366+
let intPixelate = 2;
367+
console.log('intPixelate: ', intPixelate);
368+
console.groupEnd();
344369

345370
// console.log('selectFx.value: ',selectFx.value);
346371
// const effect = selectFx.value | '';
@@ -373,13 +398,6 @@ if (navigator.mediaDevices) {
373398
ctx.drawImage(video,positionX,positionY,vWidth,vHeight);
374399
let pixels = ctx.getImageData(positionX,positionY,vWidth,vHeight);
375400
// console.log(pixels);
376-
let pixNums = pixels.data;
377-
// console.log(pixNums);
378-
pixNums = pixNums.reverse();
379-
// console.log(pixNums);
380-
pixels.data = pixNums;
381-
// console.log(pixels);
382-
// debugger;
383401

384402
/* manipulate pixels */
385403
switch(fx) {
@@ -552,6 +570,15 @@ if (navigator.mediaDevices) {
552570
toggleFxControls();
553571
});
554572

573+
let flagMirror = mirror.checked;
574+
console.log('flagMirror: ', flagMirror);
575+
/* listen for change on master F/X select/option */
576+
mirror.addEventListener('change',(e)=>{
577+
flagMirror = !flagMirror;
578+
console.log('mirror: ',flagMirror);
579+
fMirror(flagMirror);
580+
});
581+
555582
/* listen for change on deeper F/X select/option */
556583
inputAllSelect.forEach(btn => {
557584
btn.addEventListener('change',(e)=>{
@@ -574,17 +601,17 @@ if (navigator.mediaDevices) {
574601

575602
let flagSaturate = false;
576603
inputSaturate.addEventListener('change',startStream);
577-
inputSaturate.addEventListener('mousedown',(e)=>{
578-
flagSaturate = true;
579-
});
580-
inputSaturate.addEventListener('mousemove',(e)=>{
581-
if (flagSaturate) {
582-
startStream();
583-
}
584-
});
585-
inputSaturate.addEventListener('mouseup',(e)=>{
586-
flagSaturate = false;
587-
});
604+
// inputSaturate.addEventListener('mousedown',(e)=>{
605+
// flagSaturate = true;
606+
// });
607+
// inputSaturate.addEventListener('mousemove',(e)=>{
608+
// if (flagSaturate) {
609+
// startStream();
610+
// }
611+
// });
612+
// inputSaturate.addEventListener('mouseup',(e)=>{
613+
// flagSaturate = false;
614+
// });
588615

589616
/* listen for click on all "apply" buttons */
590617
btnAllApply.forEach(btn => {
@@ -604,6 +631,6 @@ window.addEventListener('resize', fMediaQueries);
604631

605632
/* fake UI clicks to open controls */
606633
startStream();
607-
// selectFx.selectedIndex = 4;
608-
// toggleFxControls();
634+
selectFx.selectedIndex = 4;
635+
toggleFxControls();
609636

19--Webcam_Fun/js/utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
/* utils.js */
22
console.log('utils.js READY!');
3+
Array.prototype.move = function (old_index, new_index) {
4+
if (new_index >= this.length) {
5+
var k = new_index - this.length;
6+
while ((k--) + 1) {
7+
this.push(undefined);
8+
}
9+
}
10+
this.splice(new_index, 0, this.splice(old_index, 1)[0]);
11+
return this; // for testing purposes
12+
};
313

414
/* toggle button enable/disable */
515
function toggleButton(el,state) {

0 commit comments

Comments
 (0)