initial commit
This commit is contained in:
commit
38d90de7b3
|
@ -0,0 +1,624 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script type = "text/javascript">
|
||||
var framecount=0;
|
||||
var buf = new Uint8ClampedArray(768);
|
||||
var framebuffer1 = "";
|
||||
var starttime = new Date().getTime();
|
||||
var currentfps = 25;
|
||||
var fpsms = 1000/currentfps;
|
||||
var videocontrast=0;
|
||||
|
||||
var sat_r=256;
|
||||
var sat_g=256;
|
||||
var sat_b=256;
|
||||
|
||||
var vf_size_x = 480;
|
||||
var vf_size_y = 360;
|
||||
var vf_pos_x = 0;
|
||||
var vf_pos_y = 0;
|
||||
|
||||
var v_size_x = 32;
|
||||
var v_size_y = 24;
|
||||
var v_pos_x = 0;
|
||||
var v_pos_y = 0;
|
||||
|
||||
var zoom=1;
|
||||
|
||||
var loop_video=0;
|
||||
var mute_video=0;
|
||||
|
||||
function contrastImage(imgData, contrast){ //input range [-100..100]
|
||||
var d = imgData.data;
|
||||
contrast = (contrast/100) + 1; //convert to decimal & shift range: [0..2]
|
||||
var intercept = 128 * (1 - contrast);
|
||||
for(var i=0;i<d.length;i+=4){ //r,g,b,a
|
||||
d[i] = d[i]*contrast + intercept;
|
||||
d[i+1] = d[i+1]*contrast + intercept;
|
||||
d[i+2] = d[i+2]*contrast + intercept;
|
||||
}
|
||||
return imgData;
|
||||
}
|
||||
|
||||
var loc = window.location, new_uri;
|
||||
new_uri = "ws://" + loc.host + "/ws";
|
||||
var ws = new WebSocket(new_uri);
|
||||
|
||||
ws.onopen = function() {
|
||||
console.log("WS BINARY TYPE: "+ws.binaryType);
|
||||
};
|
||||
|
||||
ws.onmessage = function(evt) {
|
||||
/* INCOMING MESSAGE */
|
||||
};
|
||||
|
||||
let processor = {
|
||||
timerCallback: function() {
|
||||
var timenow = new Date().getTime();
|
||||
var timediff = timenow-starttime;
|
||||
|
||||
|
||||
if (this.video.paused || this.video.ended) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (timediff>fpsms) {
|
||||
starttime=timenow;
|
||||
//console.log("timediff: "+timediff);
|
||||
this.computeFrame();
|
||||
}
|
||||
|
||||
|
||||
let self = this;
|
||||
setTimeout(function () {
|
||||
self.timerCallback();
|
||||
}, 0);
|
||||
},
|
||||
|
||||
doLoad: function() {
|
||||
console.log("doLoad");
|
||||
document.querySelector('input').addEventListener('change', processor.extractFrames, false);
|
||||
this.video = document.getElementById("video");
|
||||
this.c1 = document.getElementById("c1");
|
||||
this.ctx1 = this.c1.getContext("2d");
|
||||
this.matrix = document.getElementById("matrix");
|
||||
|
||||
let self = this;
|
||||
|
||||
/* CREATE PIXEL NODES */
|
||||
for (var i=0; i<768; i++) {
|
||||
var px = document.createElement("div");
|
||||
px.className = "px";
|
||||
matrix.appendChild(px);
|
||||
}
|
||||
|
||||
this.video.addEventListener("play", function() {
|
||||
self.width = self.video.videoWidth / 10;
|
||||
self.height = self.video.videoHeight / 10;
|
||||
self.timerCallback();
|
||||
}, false);
|
||||
},
|
||||
|
||||
readURL: function(input) {
|
||||
console.log("readURL");
|
||||
var video = document.getElementById("video");
|
||||
var matrix = document.getElementById("matrix");
|
||||
|
||||
|
||||
video.pause();
|
||||
if (input.files && input.files[0]) {
|
||||
var file = input.files[0];
|
||||
var url = URL.createObjectURL(file);
|
||||
console.log(url);
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
video.src = url;
|
||||
video.load();
|
||||
|
||||
video.addEventListener('loadeddata', function() {
|
||||
|
||||
var xratio = video.videoWidth/480;
|
||||
var yratio = video.videoHeight/360;
|
||||
|
||||
console.log(video.videoWidth);
|
||||
|
||||
var video_container = document.getElementById("video_container");
|
||||
var video_frame = document.getElementById("vidframe");
|
||||
|
||||
var vidframe_offset_x = video_frame.offsetLeft-video_container.offsetLeft;
|
||||
var vidframe_offset_y = video_frame.offsetTop-video_container.offsetTop;
|
||||
|
||||
v_pos_x=Math.floor(vidframe_offset_x*xratio);
|
||||
v_pos_y=Math.floor(vidframe_offset_y*yratio);
|
||||
v_size_x = Math.floor((480/zoom)*xratio);
|
||||
v_size_y = Math.floor((360/zoom)*yratio);
|
||||
|
||||
console.log("vpx: "+v_pos_x+" --- vpy: "+v_pos_y);
|
||||
|
||||
/*
|
||||
v_size_x = Math.floor((480/zoom)*xratio);
|
||||
v_size_y = Math.floor((360/zoom)*yratio);
|
||||
|
||||
v_pos_x=Math.floor(vf_pos_x*10*xratio);
|
||||
v_pos_y=Math.floor(vf_pos_y*10*yratio);
|
||||
*/
|
||||
|
||||
console.log("V z "+zoom+" "+xratio+" "+v_pos_x+" "+v_pos_y+" "+v_size_x+" "+v_size_y);
|
||||
video.controls = false;
|
||||
video.play();
|
||||
}, false);
|
||||
|
||||
//video.controls = true;
|
||||
|
||||
console.log(video);
|
||||
console.log("loaded height "+video.videoHeight);
|
||||
|
||||
}
|
||||
reader.readAsDataURL(file);
|
||||
|
||||
|
||||
for (let i = 0; i < 768; i+=1) {
|
||||
matrix.childNodes[i].style.backgroundColor = "rgb(0,0,0)";
|
||||
buf[i]=0;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computeFrame: function() {
|
||||
framebuffer1="";
|
||||
this.ctx1 = this.c1.getContext("2d");
|
||||
|
||||
var ratio = this.video.videoHeight/this.video.videoWidth;
|
||||
this.width = 32;
|
||||
this.cw = Math.round(32*ratio);
|
||||
|
||||
if (this.cw%2!=0) this.cw+=1;
|
||||
//if (zoom>1) this.cw = 24;
|
||||
|
||||
this.height = this.cw;
|
||||
|
||||
this.offsety = Math.floor((24-this.cw)*.5)*32;
|
||||
|
||||
this.ctx1.drawImage(this.video, v_pos_x, v_pos_y, v_size_x, v_size_y, 0, 0, this.width, this.height);
|
||||
//let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
|
||||
let frame = contrastImage(this.ctx1.getImageData(0, 0, this.width, this.height),videocontrast);
|
||||
let l = frame.data.length / 4;
|
||||
|
||||
for (let i = 0; i < 768; i+=1) {
|
||||
buf[i]=0;
|
||||
}
|
||||
|
||||
for (let i = 0; i < l; i+=1) {
|
||||
var true_r = Math.floor((frame.data[i * 4 + 0] / 32 * (sat_r/256)));
|
||||
var true_g = Math.floor((frame.data[i * 4 + 1] / 32 * (sat_g/256)));
|
||||
var true_b = Math.floor((frame.data[i * 4 + 2] / 64 * (sat_b/256)));
|
||||
|
||||
let r = (true_r << 5);
|
||||
let g = (true_g << 2); //0 << 2;
|
||||
let b = true_b;
|
||||
|
||||
var px_r = true_r * 32;
|
||||
var px_g = true_g * 32;
|
||||
var px_b = true_b * 64;
|
||||
|
||||
if (i+this.offsety<768) {
|
||||
matrix.childNodes[i+this.offsety].style.backgroundColor = "rgb("+px_r+","+px_g+","+px_b+")";
|
||||
|
||||
var py = Math.floor((i+this.offsety)/32);
|
||||
var pii = (i+this.offsety)-(py*32);
|
||||
//var pii = (i+this.offsety);
|
||||
if (py%2==0) {
|
||||
//buf[py*32+31-pii]=r+g+b;
|
||||
buf[py*32+pii]=r+g+b;
|
||||
} else {
|
||||
//buf[py*32+pii]=r+g+b;
|
||||
buf[py*32+31-pii]=r+g+b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ws.send(buf.buffer);
|
||||
|
||||
framecount+=1;
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
processor.doLoad();
|
||||
|
||||
var slider_r = document.getElementById("rgb_r");
|
||||
var slider_g = document.getElementById("rgb_g");
|
||||
var slider_b = document.getElementById("rgb_b");
|
||||
|
||||
var slider_zoom = document.getElementById("zoom");
|
||||
var contrast_slider = document.getElementById("video_contrast");
|
||||
|
||||
var slider_offsetx = document.getElementById("vf_offset_x");
|
||||
var slider_offsety = document.getElementById("vf_offset_y");
|
||||
|
||||
slider_offsetx.value=0;
|
||||
slider_offsety.value=0;
|
||||
slider_zoom.value=1;
|
||||
slider_r.value=8;
|
||||
slider_g.value=8;
|
||||
slider_b.value=8;
|
||||
|
||||
var playvid = document.getElementById("playvid");
|
||||
var loopvid = document.getElementById("loopvid");
|
||||
var mutevid = document.getElementById("mutevid");
|
||||
|
||||
var myVideo = document.getElementById("video");
|
||||
var viframe = document.getElementById("vidframe");
|
||||
|
||||
var v_progress = document.getElementById("v_progress");
|
||||
var v_volume = document.getElementById("v_volume");
|
||||
|
||||
var docbody = document.getElementById("body");
|
||||
var fullvid = document.getElementById("fullvid");
|
||||
|
||||
|
||||
|
||||
docbody.onresize = function() {
|
||||
var vidc = document.getElementById("video_container");
|
||||
var vidfr = document.getElementById("vidframe");
|
||||
|
||||
console.log("newx "+vidc.offsetLeft);
|
||||
|
||||
vidfr.style.top = (parseInt(vidc.offsetTop)+parseInt(slider_offsety.value))+"px";
|
||||
vidfr.style.left = (parseInt(vidc.offsetLeft)+parseInt(slider_offsetx.value))+"px";
|
||||
|
||||
console.log("vidframe x: "+vidfr.offsetLeft);
|
||||
console.log("slider x: "+slider_offsetx.value);
|
||||
//console.log("vidcontainer x: "+vidc.offsetLeft+" "+slider_offsetx.value);
|
||||
}
|
||||
|
||||
v_progress.oninput = function() {
|
||||
var skipto = Math.floor((v_progress.value/100)*myVideo.duration);
|
||||
myVideo.currentTime = skipto;
|
||||
processor.computeFrame();
|
||||
};
|
||||
|
||||
v_volume.oninput = function() {
|
||||
myVideo.volume = v_volume.value*.01;
|
||||
if (v_volume.value==0) {
|
||||
mutevid.className = "muteactive";
|
||||
} else {
|
||||
mutevid.className = "";
|
||||
}
|
||||
};
|
||||
|
||||
function togglePlay() {
|
||||
if (myVideo.paused) {
|
||||
myVideo.play();
|
||||
playvid.innerHTML = "⏸";
|
||||
} else {
|
||||
myVideo.pause();
|
||||
playvid.innerHTML = "▶";
|
||||
}
|
||||
};
|
||||
|
||||
myVideo.onended = function() {
|
||||
console.log("The video has ended");
|
||||
playvid.innerHTML = "▶";
|
||||
};
|
||||
|
||||
myVideo.onplay = function() {
|
||||
console.log("The video has started");
|
||||
playvid.innerHTML = "⏸";
|
||||
};
|
||||
|
||||
myVideo.ontimeupdate = function(){
|
||||
var percentage = Math.floor(( myVideo.currentTime / myVideo.duration ) * 100);
|
||||
//console.log("percent: "+percentage);
|
||||
v_progress.value = percentage;
|
||||
};
|
||||
|
||||
slider_r.oninput = function() {
|
||||
sat_r=this.value*32;
|
||||
this.style.backgroundColor = "rgb("+sat_r+",0,0)";
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
slider_g.oninput = function() {
|
||||
sat_g=this.value*32;
|
||||
this.style.backgroundColor = "rgb(0,"+sat_g+",0)";
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
slider_b.oninput = function() {
|
||||
sat_b=this.value*64;
|
||||
this.style.backgroundColor = "rgb(0,0,"+sat_b+")";
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
slider_zoom.oninput = function() {
|
||||
zoom=this.value*.1;
|
||||
makeZoom();
|
||||
}
|
||||
|
||||
contrast_slider.oninput = function() {
|
||||
videocontrast=this.value;
|
||||
}
|
||||
|
||||
slider_offsetx.oninput = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
var vidframe = document.getElementById("vidframe");
|
||||
|
||||
vf_pos_x=this.value;
|
||||
vidframe.style.marginLeft = ((vf_pos_x*10)-2)+"px";
|
||||
|
||||
var xratio = tempvideo.videoWidth/480;
|
||||
v_pos_x=Math.floor(vf_pos_x*10*xratio);
|
||||
console.log("xratio: "+xratio);
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
slider_offsety.oninput = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
var vidframe = document.getElementById("vidframe");
|
||||
|
||||
vf_pos_y=this.value;
|
||||
vidframe.style.marginTop = ((vf_pos_y*10)-2)+"px";
|
||||
|
||||
var yratio = tempvideo.videoHeight/360;
|
||||
v_pos_y=Math.floor(vf_pos_y*10*yratio);
|
||||
console.log("yratio: "+yratio);
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
playvid.onclick = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
console.log("aka");
|
||||
//tempvideo.play();
|
||||
togglePlay();
|
||||
}
|
||||
|
||||
fullvid.onclick = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
tempvideo.requestFullscreen();
|
||||
}
|
||||
|
||||
loopvid.onclick = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
var loopvid = document.getElementById("loopvid");
|
||||
if (loop_video==0) {
|
||||
tempvideo.loop = true;
|
||||
loop_video=1;
|
||||
loopvid.classList.add("loopactive");
|
||||
} else {
|
||||
tempvideo.loop = false;
|
||||
loop_video=0;
|
||||
loopvid.classList.remove("loopactive");
|
||||
}
|
||||
}
|
||||
|
||||
mutevid.onclick = function() {
|
||||
var tempvideo = document.getElementById("video");
|
||||
if (mute_video==1) {
|
||||
tempvideo.volume = .5;
|
||||
mute_video=0;
|
||||
this.classList.remove("muteactive");
|
||||
v_volume.value=50;
|
||||
} else {
|
||||
tempvideo.volume = 0;
|
||||
mute_video=1;
|
||||
this.classList.add("muteactive");
|
||||
v_volume.value=0;
|
||||
}
|
||||
}
|
||||
|
||||
function doZoom(event) {
|
||||
event.preventDefault();
|
||||
console.log(event.deltaY);
|
||||
if (zoom-event.deltaY*.1>=1 && zoom-event.deltaY*.1<=10) {
|
||||
zoom-=event.deltaY*.1;
|
||||
makeZoom();
|
||||
}
|
||||
}
|
||||
|
||||
function makeZoom(event) {
|
||||
var tempvideo = document.getElementById("video");
|
||||
var xratio = tempvideo.videoWidth/480;
|
||||
var yratio = tempvideo.videoHeight/360;
|
||||
|
||||
vf_size_x = Math.floor(480/zoom);
|
||||
console.log("vf_Sx: "+vf_size_x);
|
||||
console.log("vf_Px: "+vf_pos_x);
|
||||
vf_size_y = Math.floor(360/zoom);
|
||||
v_size_x = Math.floor((480/zoom)*xratio);
|
||||
v_size_y = Math.floor((360/zoom)*yratio);
|
||||
|
||||
var vidframe = document.getElementById("vidframe");
|
||||
vidframe.style.width = vf_size_x+"px";
|
||||
vidframe.style.height = vf_size_y+"px";
|
||||
processor.computeFrame();
|
||||
}
|
||||
|
||||
video.onwheel = doZoom;
|
||||
viframe.onwheel = doZoom;
|
||||
|
||||
dragElement(document.getElementById("vidframe"));
|
||||
|
||||
function dragElement(elmnt) {
|
||||
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, vftop = 0, vfleft = 0;
|
||||
if (document.getElementById(elmnt.id + "header")) {
|
||||
// if present, the header is where you move the DIV from:
|
||||
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
|
||||
} else {
|
||||
// otherwise, move the DIV from anywhere inside the DIV:
|
||||
elmnt.onmousedown = dragMouseDown;
|
||||
}
|
||||
|
||||
function dragMouseDown(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
// get the mouse cursor position at startup:
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
document.onmouseup = closeDragElement;
|
||||
// call a function whenever the cursor moves:
|
||||
document.onmousemove = elementDrag;
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
// calculate the new cursor position:
|
||||
pos1 = pos3 - e.clientX;
|
||||
pos2 = pos4 - e.clientY;
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
// set the element's new position:
|
||||
|
||||
var video_container = document.getElementById("video_container");
|
||||
var video_frame = document.getElementById("vidframe");
|
||||
|
||||
var vf_rightbound = elmnt.offsetLeft-pos1-video_container.offsetLeft+video_frame.offsetWidth;
|
||||
var vf_bottombound = elmnt.offsetTop-pos2-video_container.offsetTop+video_frame.offsetHeight;
|
||||
|
||||
//console.log("vf_right: "+vf_rightbound+" --- vf_bottom: "+vf_bottombound);
|
||||
|
||||
if (vf_rightbound<480 && (elmnt.offsetLeft - pos1)>=video_container.offsetLeft && vf_bottombound<360 && (elmnt.offsetTop - pos2)>=video_container.offsetTop) {
|
||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
||||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
||||
|
||||
/* UPDATE FRAME INFO */
|
||||
|
||||
var tempvideo = document.getElementById("video");
|
||||
|
||||
var yratio = tempvideo.videoHeight/360;
|
||||
var xratio = tempvideo.videoWidth/480;
|
||||
|
||||
var tvf_pos_x=elmnt.offsetLeft-video_container.offsetLeft;
|
||||
var tvf_pos_y=elmnt.offsetTop-video_container.offsetTop;
|
||||
|
||||
vf_pos_x=tvf_pos_x;
|
||||
vf_pos_y=tvf_pos_y;
|
||||
|
||||
v_pos_x=Math.floor(tvf_pos_x*xratio);
|
||||
v_pos_y=Math.floor(tvf_pos_y*yratio);
|
||||
|
||||
|
||||
var slide_offsetx = document.getElementById("vf_offset_x");
|
||||
var slide_offsety = document.getElementById("vf_offset_y");
|
||||
|
||||
slide_offsetx.value = tvf_pos_x;
|
||||
slide_offsety.value = tvf_pos_y;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function closeDragElement() {
|
||||
// stop moving when mouse button is released:
|
||||
document.onmouseup = null;
|
||||
document.onmousemove = null;
|
||||
|
||||
var video_container = document.getElementById("video_container");
|
||||
//console.log(video_container);
|
||||
|
||||
var video_frame = document.getElementById("vidframe");
|
||||
//console.log(video_frame);
|
||||
|
||||
|
||||
processor.computeFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
body { background:#333; font-family:sans-serif; margin:0px; padding:20px; color:#f7f7f7; }
|
||||
#c2 { background-repeat: no-repeat; }
|
||||
#matrix { float:none; clear:both; width:320px; height:240px; }
|
||||
.px { float:left; width:9px; height:9px; margin:0px; padding:0px; display:block; border:0px; border-left:1px solid #222; border-top:1px solid #222; }
|
||||
#video_container { width:480px; height:360px; margin-bottom:10px; }
|
||||
#video { width:100%; height:100%; outline:0; }
|
||||
#c1 { float:left; display:none; }
|
||||
|
||||
/* slider */
|
||||
.slidecontainer { width: 482px; float:right; margin-bottom:20px; }
|
||||
.slidecontainer span { margin-bottom:10px; display:block; font-weight:bold; }
|
||||
.slider { -webkit-appearance: none; width: 100%; height: 9px; border-radius: 5px; background: #444; outline: 0px!important; -webkit-transition: .2s; transition: opacity .2s; margin-bottom:10px; }
|
||||
.slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 25px; height: 25px; border-radius: 50%; background: #00f; cursor: pointer; outline:0px!important; }
|
||||
.slider::-moz-range-thumb { width: 11px; height: 11px; border-radius: 50%; border:0px; background: #fff; cursor: pointer; outline:0px!important; }
|
||||
|
||||
.slider.red { background:#e00; }
|
||||
.slider.green { background:#0a0; }
|
||||
.slider.blue { background:#00b; }
|
||||
.slider.white { background:#555; }
|
||||
.slider.grey { background:#222; }
|
||||
.slider.grey:hover::-moz-range-thumb { background:#098; }
|
||||
.slider.grey::-moz-range-thumb:hover { background:#098; }
|
||||
|
||||
#vidframe { position:absolute; width:480px; height:360px; border:1px solid rgba(255,255,255,.5); margin-top:0px; margin-left:0px; cursor:grab; }
|
||||
#playvid { display:block; background:#222; padding:5px; width:20px; text-align:center; cursor:pointer; height:22px; margin-left:0px; margin-bottom:10px; float:left; }
|
||||
#playvid:hover { background:#089; }
|
||||
#outputleft { float:left; width:340px; }
|
||||
#outputleft span { margin-bottom:10px; display:block; font-weight:bold; }
|
||||
#inputright { float:right; width:500px; }
|
||||
|
||||
#v_progress { float:left; width:250px; margin-top:12px; margin-left:10px; }
|
||||
#v_volume { float:left; width:100px; margin-top:12px; margin-left:10px; }
|
||||
#fullvid { float:right; margin-top:7px; text-align:center; background:#222; cursor:pointer; }
|
||||
#mutevid { float:left; margin-top:7px; text-align:center; margin-left:15px; cursor:pointer; }
|
||||
#loopvid { float:left; margin-top:7px; margin-left:10px; text-align:center; cursor:pointer; }
|
||||
.loopactive { color:#089; }
|
||||
.muteactive { color:rgba(255,255,255,.1); }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body id="body">
|
||||
<div id="outputleft">
|
||||
<span>Matrix Output</span>
|
||||
<div id="matrix"></div>
|
||||
</div>
|
||||
<div id="inputright">
|
||||
<div class="slidecontainer">
|
||||
<span>Video Input & Controls</span>
|
||||
<div id="video_container">
|
||||
<div id="vidframe"></div>
|
||||
<video id="video" src="input.mp4" />
|
||||
</div>
|
||||
<div id="playvid">▶</div>
|
||||
<input type="range" min="0" max="100" value="0" class="slider grey" id="v_progress">
|
||||
<div id="loopvid">↻</div>
|
||||
<div id="mutevid">🔊</div>
|
||||
<input type="range" min="0" max="100" value="50" class="slider grey" id="v_volume">
|
||||
|
||||
<div id="fullvid">⛶</div>
|
||||
<br/>
|
||||
<input type="file" accept="video/*" style="margin-top:30px; float:none; clear:both; display:block; max-width:100%;" onchange="processor.readURL(this);" />
|
||||
<div style="clear:both"></div>
|
||||
<br/>
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<span>Channel Saturation</span>
|
||||
<input type="range" min="1" max="8" value="8" class="slider red" id="rgb_r">
|
||||
<input type="range" min="1" max="8" value="8" class="slider green" id="rgb_g">
|
||||
<input type="range" min="1" max="4" value="4" class="slider blue" id="rgb_b">
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<span>Contrast</span>
|
||||
<input type="range" min="-100" max="200" value="0" class="slider white" id="video_contrast">
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<span>Zoom</span>
|
||||
<input type="range" min="10" max="100" value="1" class="slider white" id="zoom">
|
||||
</div>
|
||||
<div class="slidecontainer">
|
||||
<span>Offset</span>
|
||||
<input type="range" min="0" max="480" value="0" class="slider white" id="vf_offset_x">
|
||||
<input type="range" min="0" max="360" value="0" class="slider white" id="vf_offset_y">
|
||||
</div>
|
||||
|
||||
<canvas id="c1" width="320" height="240"></canvas>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,532 @@
|
|||
/* TETRIS */
|
||||
|
||||
uint8_t last_leds[768*3];
|
||||
int last_led_count = 768;
|
||||
|
||||
|
||||
// First dimension: which shape
|
||||
// Second dimension: which rotation, + color
|
||||
// Third & fourth dimensions: rows and columns of shape
|
||||
bool shapetypes[7][5][4][4] = {
|
||||
{
|
||||
// Line of four
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 1 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 1 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 }
|
||||
},
|
||||
{
|
||||
{1}, {1}, {0}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
// S-shape (orientation 1)
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{0}, {0}, {1}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
// S-shape (orientation 2)
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{1}, {0}, {0}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
// T-piece
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 1, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 1, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{1}, {1}, {1}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
// L-piece (orientation 1)
|
||||
{
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 1, 1, 1, 0 },
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 1, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{0}, {1}, {0}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
// L-piece (orientation 2)
|
||||
{
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 1, 1 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 1 },
|
||||
{ 0, 0, 0, 1 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{0}, {1}, {1}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
{
|
||||
// Cube
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 1, 1, 0 },
|
||||
{ 0, 0, 0, 0 }
|
||||
},
|
||||
{
|
||||
{1}, {0}, {1}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
/* SOMEBRICKS: Position, Type and Rotation of current piece (array index = player) */
|
||||
/* number of players */
|
||||
int players=2;
|
||||
|
||||
/* field position */
|
||||
int p_field_pos[2][2] = {{2,2},{20,2}};
|
||||
|
||||
/* set players current shape xy-position */
|
||||
int set_x[2]={3,3};
|
||||
int set_y[2]={0,0};
|
||||
|
||||
/* set players current shapetype & rotation */
|
||||
int current_btype[2]={0,1};
|
||||
int current_brot[2]={0,0};
|
||||
|
||||
|
||||
/* Somebricks Functions */
|
||||
|
||||
void init_lights() {
|
||||
int arrsize = last_led_count*3;
|
||||
|
||||
int i;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
int idx = 0;
|
||||
|
||||
for (int led=0;led<last_led_count;led++) {
|
||||
x = lookup[led][0];
|
||||
y = lookup[led][1];
|
||||
|
||||
last_leds[idx] = 0;
|
||||
last_leds[idx+1] = 0;
|
||||
last_leds[idx+2] = 0;
|
||||
|
||||
idx+=3;
|
||||
}
|
||||
}
|
||||
|
||||
void update_stones() {
|
||||
/* Position in grid */
|
||||
int field_x;
|
||||
int field_y;
|
||||
|
||||
int light_i;
|
||||
|
||||
/* Walk piece-array, draw pixels */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
/* Check active pixels */
|
||||
for (int p=0; p<players; p++) {
|
||||
if (shapetypes[current_btype[p]][current_brot[p]][i][j] == 1) {
|
||||
/* set xy for current active pixel */
|
||||
field_x=p_field_pos[p][0]+set_x[p]+j;
|
||||
field_y=p_field_pos[p][1]+set_y[p]+i;
|
||||
|
||||
/* check boundaries */
|
||||
if (field_x<32 && field_x>=0 && field_y<24 && field_y>=0) {
|
||||
light_i = lookup_yx[field_y][field_x];
|
||||
|
||||
/* set rgb of pieces separately */
|
||||
if (shapetypes[current_btype[p]][4][0][0]==1) { last_leds[light_i*3] = 100; } else { last_leds[light_i*3] = 0; }
|
||||
if (shapetypes[current_btype[p]][4][1][0]==1) { last_leds[light_i*3+1] = 100; } else { last_leds[light_i*3+1] = 0; }
|
||||
if (shapetypes[current_btype[p]][4][2][0]==1) { last_leds[light_i*3+2] = 100; } else { last_leds[light_i*3+2] = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void clear_lines(int player_id) {
|
||||
int stones_in_line;
|
||||
int pixel_value;
|
||||
int light_int;
|
||||
int light_int_old;
|
||||
|
||||
int field_newx;
|
||||
int field_newy;
|
||||
|
||||
for (int j=p_field_pos[player_id][1]+19; j>p_field_pos[player_id][1]; j--) {
|
||||
/* Count stones in line */
|
||||
stones_in_line=0;
|
||||
for (int i=p_field_pos[player_id][0]; i<p_field_pos[player_id][0]+10; i++) {
|
||||
light_int = lookup_yx[j][i];
|
||||
|
||||
pixel_value=last_leds[light_int*3+0]+last_leds[light_int*3+1]+last_leds[light_int*3+2];
|
||||
if (pixel_value>99) {
|
||||
stones_in_line++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found complete line */
|
||||
if (stones_in_line==10) {
|
||||
/* Move down everything by 1 line */
|
||||
for (int y=j; y>p_field_pos[player_id][1]; y--) {
|
||||
for (int x=p_field_pos[player_id][0]; x<10+p_field_pos[player_id][0]; x++) {
|
||||
light_int = lookup_yx[y][x];
|
||||
if ((y-1)>=0) {
|
||||
light_int_old = lookup_yx[y-1][x];
|
||||
|
||||
last_leds[light_int*3+0]=last_leds[(light_int_old)*3+0];
|
||||
last_leds[light_int*3+1]=last_leds[(light_int_old)*3+1];
|
||||
last_leds[light_int*3+2]=last_leds[(light_int_old)*3+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Set index to last line */
|
||||
j++;
|
||||
|
||||
/* Change Enemy Field - Move up everything by 1 line */
|
||||
for (int p=0; p<players; p++) {
|
||||
if (p != player_id) {
|
||||
|
||||
/* Remove current position */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
if (shapetypes[current_btype[p]][current_brot[p]][i][j] == 1) {
|
||||
field_newx=p_field_pos[p][0]+set_x[p]+j;
|
||||
field_newy=p_field_pos[p][1]+set_y[p]+i;
|
||||
|
||||
light_int = lookup_yx[field_newy][field_newx];
|
||||
|
||||
last_leds[light_int*3+0]=0;
|
||||
last_leds[light_int*3+1]=0;
|
||||
last_leds[light_int*3+2]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move all up */
|
||||
for (int y=p_field_pos[p][1]; y<p_field_pos[p][1]+19; y++) {
|
||||
for (int x=p_field_pos[p][0]; x<10+p_field_pos[p][0]; x++) {
|
||||
light_int = lookup_yx[y][x];
|
||||
if ((y+1)<p_field_pos[p][1]+20) {
|
||||
light_int_old = lookup_yx[y+1][x];
|
||||
|
||||
last_leds[light_int*3+0]=last_leds[(light_int_old)*3+0];
|
||||
last_leds[light_int*3+1]=last_leds[(light_int_old)*3+1];
|
||||
last_leds[light_int*3+2]=last_leds[(light_int_old)*3+2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a random line */
|
||||
for (int x=p_field_pos[p][0]; x<10+p_field_pos[p][0]; x++) {
|
||||
light_int = lookup_yx[p_field_pos[p][1]+19][x];
|
||||
|
||||
last_leds[light_int*3+1]=0;
|
||||
if (rand()%10<3) {
|
||||
last_leds[light_int*3]=0;
|
||||
} else {
|
||||
last_leds[light_int*3]=100;
|
||||
}
|
||||
last_leds[light_int*3+2]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update_stones();
|
||||
}
|
||||
|
||||
/* fix player_id's current stone in position, create new */
|
||||
void merge_stone(int player_id) {
|
||||
int field_newx;
|
||||
int field_newy;
|
||||
int light_int;
|
||||
|
||||
/* Place current position */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
if (shapetypes[current_btype[player_id]][current_brot[player_id]][i][j] == 1) {
|
||||
field_newx=p_field_pos[player_id][0]+set_x[player_id]+j;
|
||||
field_newy=p_field_pos[player_id][1]+set_y[player_id]+i;
|
||||
|
||||
light_int = lookup_yx[field_newy][field_newx];
|
||||
|
||||
if (shapetypes[current_btype[player_id]][4][0][0] == 1) { last_leds[light_int*3] = 100; } else { last_leds[light_int*3] = 0; }
|
||||
if (shapetypes[current_btype[player_id]][4][1][0] == 1) { last_leds[light_int*3+1] = 100; } else { last_leds[light_int*3+1] = 0; }
|
||||
if (shapetypes[current_btype[player_id]][4][2][0] == 1) { last_leds[light_int*3+2] = 100; } else { last_leds[light_int*3+2] = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (set_y[player_id]<1) {
|
||||
init_lights();
|
||||
}
|
||||
|
||||
/* set new piece position */
|
||||
set_y[player_id]=0;
|
||||
current_btype[player_id]=rand()%7;
|
||||
current_brot[player_id]=rand()%4;
|
||||
set_x[player_id]=3;
|
||||
clear_lines(player_id);
|
||||
}
|
||||
|
||||
/* check if player_id's next shapemove is possible */
|
||||
/* returns false when move is not possible */
|
||||
|
||||
bool check_movement(int player_id, int x, int y, int rot) {
|
||||
/* var for current pixel */
|
||||
int field_newx;
|
||||
int field_newy;
|
||||
int light_int;
|
||||
|
||||
/* XY Offset for 4x4 shape field */
|
||||
int temp_set_x=set_x[player_id]+x;
|
||||
int temp_set_y=set_y[player_id]+y;
|
||||
|
||||
/* current rotation */
|
||||
int temp_brot=(current_brot[player_id]+rot)%4;
|
||||
|
||||
int pixel_value;
|
||||
|
||||
/* Remove current shape position */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
/* player_id's current shape and current rotation */
|
||||
if (shapetypes[current_btype[player_id]][current_brot[player_id]][i][j] == 1) {
|
||||
field_newx=p_field_pos[player_id][0]+set_x[player_id]+j;
|
||||
field_newy=p_field_pos[player_id][1]+set_y[player_id]+i;
|
||||
|
||||
light_int = lookup_yx[field_newy][field_newx];
|
||||
|
||||
/* set pixels to 0 */
|
||||
last_leds[light_int*3+0]=0;
|
||||
last_leds[light_int*3+1]=0;
|
||||
last_leds[light_int*3+2]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check future position */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
if (shapetypes[current_btype[player_id]][temp_brot][i][j] == 1) {
|
||||
field_newx=p_field_pos[player_id][0]+temp_set_x+j;
|
||||
field_newy=p_field_pos[player_id][1]+temp_set_y+i;
|
||||
|
||||
if (field_newx>=0 && field_newx<32 && field_newy>=0 && field_newy<22) {
|
||||
|
||||
light_int = lookup_yx[field_newy][field_newx];
|
||||
|
||||
pixel_value=last_leds[light_int*3+0]+last_leds[light_int*3+1]+last_leds[light_int*3+2];
|
||||
|
||||
int p_min_x = p_field_pos[player_id][0];
|
||||
int p_min_y = p_field_pos[player_id][1];
|
||||
int p_max_x = p_field_pos[player_id][0]+9;
|
||||
int p_max_y = p_field_pos[player_id][1]+19;
|
||||
|
||||
/* collision */
|
||||
if (field_newx>p_max_x || field_newx<p_min_x || field_newy>p_max_y || field_newy<p_min_y || pixel_value > 99) {
|
||||
if (y==1) {
|
||||
merge_stone(player_id);
|
||||
}
|
||||
|
||||
update_stones();
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
/* piece at the lowest point -> merge */
|
||||
if (y==1) {
|
||||
merge_stone(player_id);
|
||||
}
|
||||
update_stones();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Place future position (eventually will not be reached) */
|
||||
for (int i=0; i<4; i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
if (shapetypes[current_btype[player_id]][temp_brot][i][j] == 1) {
|
||||
field_newx=p_field_pos[player_id][0]+temp_set_x+j;
|
||||
field_newy=p_field_pos[player_id][1]+temp_set_y+i;
|
||||
|
||||
light_int = lookup_yx[field_newy][field_newx];
|
||||
|
||||
if (shapetypes[current_btype[player_id]][4][0][0]==1) { last_leds[light_int*3] = 100; } else { last_leds[light_int*3] = 0; }
|
||||
if (shapetypes[current_btype[player_id]][4][1][0]==1) { last_leds[light_int*3+1] = 100; } else { last_leds[light_int*3+1] = 0; }
|
||||
if (shapetypes[current_btype[player_id]][4][2][0]==1) { last_leds[light_int*3+2] = 100; } else { last_leds[light_int*3+2] = 0; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_x[player_id] = temp_set_x;
|
||||
set_y[player_id] = temp_set_y;
|
||||
current_brot[player_id] = temp_brot;
|
||||
|
||||
update_stones();
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in New Issue