Files
clock4/brightness-curve.htm

188 lines
4.2 KiB
HTML

<!doctype html>
<canvas width=800 height=600 style='position:relative;'></canvas>
<br>
<textarea style="width:300px;height:100px" oninput='parse()'></textarea>
<span style='position:absolute;pointer-events:none;font-family:monospace;'></span>
<script>
pre = document.querySelector('textarea')
span = document.querySelector('span')
canvas = document.querySelector('canvas')
ctx = canvas.getContext('2d')
w = canvas.width; h = canvas.height;
gw = w-50; gh = h-50
gx=25; gy=25
b={x:0,y:0}
curve = [
[0, 0],
[0.4, 0.1],
[0.7, 0.3],
[0.9, 0.6],
[1.0, 1.0]
]
function line(x1,y1,x2,y2){
ctx.beginPath()
ctx.moveTo(gx + x1*gw, gy+ gh-y1*gh)
ctx.lineTo(gx + x2*gw, gy+ gh-y2*gh)
ctx.stroke()
}
function circle(x,y) {
ctx.beginPath();
ctx.arc(gx + x*gw, gy+ gh-y*gh, 5, 0, 2 * Math.PI);
ctx.stroke();
}
ctx.font = '18px Courier, monospace';
function draw(wb){
b=canvas.getBoundingClientRect()
ctx.clearRect(0,0,w,h)
ctx.fillStyle='rgba(1,1,1,0.05)'
ctx.fillRect(gx,gy,gw,gh)
line(0,0,0,1)
line(0,0,1,0)
ctx.fillStyle='black'
ctx.textAlign='center';
ctx.fillText('Input',gx+gw/2,gy+gh+18)
ctx.save()
ctx.translate(18,gy+gh/2)
ctx.rotate(-Math.PI/2)
ctx.fillText('Output',0,0)
ctx.restore()
for (let i=0;i<curve.length;i++) {
circle( curve[i][0], curve[i][1] )
if (i) line( curve[i-1][0], curve[i-1][1], curve[i][0], curve[i][1] )
}
if (wb) return;
s=""
for (let i=0;i<curve.length;i++)
s+= "BS"+(i+1)+" = "+ Math.round(curve[i][0]*4095)+ ',' + Math.round(curve[i][1]*4095)+"\n"
pre.value = s
}
function distance(x1,y1,x2,y2){
return Math.sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )
}
function nearestPoint(x,y){
let nearest = 0
let neardist = 999
for (let i=0;i<curve.length;i++) {
let d = distance( curve[i][0], curve[i][1], x, y )
if (d < neardist) {
nearest=i
neardist=d
}
}
return nearest
}
function clamp(x,y,i){
let step = 1/4095;
let minx = i>0? curve[i-1][0]+step:0;
let maxx = i<curve.length-1? curve[i+1][0]-step:1;
return [Math.min(maxx,Math.max(minx,x)),Math.min(1,Math.max(0,y))]
}
function highlight(e){
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
if (x<0.0 || x>1.0 || y<0.0 || y>1.0) {
span.textContent="";
} else {
let out = single(x)
span.textContent=Math.round(x*4095)+","+Math.round(out*4095);
span.style.left=e.pageX+"px"
span.style.top=((1-out)*gh+gy+b.y)+"px"
}
}
document.onmousemove=highlight
canvas.onmousedown=function(e){
e.preventDefault()
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
span.textContent="";
let i = nearestPoint(x,y)
curve[i] = clamp(x,y,i)
document.onmousemove=function(e){
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
curve[i] = clamp(x,y,i)
draw()
}
document.onmouseup=function(e){
document.onmousemove=highlight
document.onmouseup=null
}
draw()
}
touch={};
canvas.addEventListener("touchstart",function(e){
if (e.touches.length>1) return;
for (let t of e.changedTouches) {
let x = (t.pageX-gx-b.x)/gw
let y = 1-(t.pageY-gy-b.y)/gh
let i = nearestPoint(x,y)
curve[i] = clamp(x,y,i)
touch = {id:t.identifier,i}
}
e.preventDefault();
draw()
},true);
canvas.addEventListener("touchmove",function(e){
for (let t of e.changedTouches) {
if (touch.id == t.identifier) {
let x = (t.pageX-gx-b.x)/gw
let y = 1-(t.pageY-gy-b.y)/gh
curve[touch.i] = clamp(x,y,touch.i)
}
}
draw()
},true);
function parse(){
var lines = pre.value.split("\n");
for (let line of lines) {
let m = line.match(/^BS([1-5]) = (\d+),(\d+)$/)
if (!m || m[2]>4095 || m[3]>4095) continue;
curve[m[1]-1]=[m[2]/4095, m[3]/4095]
}
draw(1)
}
function single(inp){
let i;
for (i=1; i< curve.length-1; i++){
if (curve[i][0] > inp) break;
}
let factor = (inp - curve[i-1][0]) / (curve[i][0] - curve[i-1][0]);
let out = curve[i-1][1]*(1.0-factor) + curve[i][1]*factor;
if (out>1.0 || isNaN(out)) out=1.0;
else if (out<0.0) out=0.0;
return out
}
draw()
</script>