Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active August 29, 2015 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nitaku/8d945de79daa48768fee to your computer and use it in GitHub Desktop.
Save nitaku/8d945de79daa48768fee to your computer and use it in GitHub Desktop.
Bilinear interpolation
`// noprotect`
### BEGIN ###
hcl_linear_rainbow = () ->
# H and L are linear, C is quadratic
domain = [0,1]
hue_range = [340, 340-480]
chroma_range = [0, 40]
luminance_range = [0, 100]
scale = (x) ->
ext = domain[1]-domain[0]
xn = (x-domain[0]) / ext
return d3.hcl(hue_range[0] + (hue_range[1]-hue_range[0])*xn, chroma_range[0] + (chroma_range[1]-chroma_range[0]) * (1 - Math.pow(1 - 2*xn, 2) ), luminance_range[0] + (luminance_range[1]-luminance_range[0]) *xn)
scale.domain = (x) ->
return domain if(!arguments.length)
domain = x
return scale
scale.hue_range = (x) ->
return hue_range if(!arguments.length)
hue_range = x
return scale
scale.chroma_range = (x) ->
return chroma_range if(!arguments.length)
chroma_range = x
return scale
scale.luminance_range = (x) ->
return luminance_range if(!arguments.length)
luminance_range = x
return scale
return scale
### END ###
canvas = d3.select('canvas')
width = canvas.node().getBoundingClientRect().width
height = canvas.node().getBoundingClientRect().height
side = Math.min(width, height) - 20
ctx = canvas.node().getContext('2d')
image = ctx.createImageData(side, side)
F00 = Math.random()
F10 = Math.random()
F01 = Math.random()
F11 = Math.random()
### Bilinear interpolation ###
### F(x,y) = b1 + b2*x + b3*y + b4*x*y ###
b1 = F00
b2 = F10-F00
b3 = F01-F00
b4 = F00-F10-F01+F11
### define a default cubehelix-style hcl linear rainbow scale ###
colorize = hcl_linear_rainbow()
console.debug 'Coloring...'
for pixel_x in [0...side]
for pixel_y in [0...side]
pixel_i = (pixel_y*side + pixel_x)*4
[r,g,b,a] = [pixel_i+0, pixel_i+1, pixel_i+2, pixel_i+3]
[x,y] = [pixel_x/side, pixel_y/side]
Fxy = b1 + b2*x + b3*y + b4*x*y
color = d3.rgb colorize(Fxy)
image.data[r] = color.r
image.data[g] = color.g
image.data[b] = color.b
image.data[a] = 255
ctx.putImageData(image,(width-side)/2,(height-side)/2)
### draw labels ###
format = d3.format('%')
svg = d3.select('svg')
vis = svg.append('g')
.attr
transform: "translate(#{width/2},#{height/2})"
vis.append('text')
.text(format(F00))
.style('text-anchor', 'end')
.attr
class: 'label'
dx: '-4px'
dy: '0.85em'
x: -side/2
y: -side/2
vis.append('text')
.text(format(F01))
.style('text-anchor', 'end')
.attr
class: 'label'
dx: '-4px'
x: -side/2
y: side/2
vis.append('text')
.text(format(F10))
.style('text-anchor', 'start')
.attr
class: 'label'
dx: '4px'
dy: '0.85em'
x: side/2
y: -side/2
vis.append('text')
.text(format(F11))
.style('text-anchor', 'start')
.attr
class: 'label'
dx: '4px'
x: side/2
y: side/2
html, body {
padding: 0;
margin: 0;
}
canvas {
position: absolute;
top: 0;
left: 0;
background: #222;
}
svg {
position: absolute;
top: 0;
left: 0;
}
.label {
fill: white;
font-family: sans-serif;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="Bilinear interpolation" />
<title>Bilinear interpolation</title>
<link rel="stylesheet" href="index.css">
<script src="http://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<canvas width="960" height="500"></canvas>
<svg width="960" height="500"></svg>
<script src="index.js"></script>
</body>
</html>
(function() {
// noprotect;
/* BEGIN
*/
var F00, F01, F10, F11, Fxy, a, b, b1, b2, b3, b4, canvas, color, colorize, ctx, format, g, hcl_linear_rainbow, height, image, pixel_i, pixel_x, pixel_y, r, side, svg, vis, width, x, y, _i, _j, _ref, _ref1;
hcl_linear_rainbow = function() {
var chroma_range, domain, hue_range, luminance_range, scale;
domain = [0, 1];
hue_range = [340, 340 - 480];
chroma_range = [0, 40];
luminance_range = [0, 100];
scale = function(x) {
var ext, xn;
ext = domain[1] - domain[0];
xn = (x - domain[0]) / ext;
return d3.hcl(hue_range[0] + (hue_range[1] - hue_range[0]) * xn, chroma_range[0] + (chroma_range[1] - chroma_range[0]) * (1 - Math.pow(1 - 2 * xn, 2)), luminance_range[0] + (luminance_range[1] - luminance_range[0]) * xn);
};
scale.domain = function(x) {
if (!arguments.length) {
return domain;
}
domain = x;
return scale;
};
scale.hue_range = function(x) {
if (!arguments.length) {
return hue_range;
}
hue_range = x;
return scale;
};
scale.chroma_range = function(x) {
if (!arguments.length) {
return chroma_range;
}
chroma_range = x;
return scale;
};
scale.luminance_range = function(x) {
if (!arguments.length) {
return luminance_range;
}
luminance_range = x;
return scale;
};
return scale;
};
/* END
*/
canvas = d3.select('canvas');
width = canvas.node().getBoundingClientRect().width;
height = canvas.node().getBoundingClientRect().height;
side = Math.min(width, height) - 20;
ctx = canvas.node().getContext('2d');
image = ctx.createImageData(side, side);
F00 = Math.random();
F10 = Math.random();
F01 = Math.random();
F11 = Math.random();
/* Bilinear interpolation
*/
/* F(x,y) = b1 + b2*x + b3*y + b4*x*y
*/
b1 = F00;
b2 = F10 - F00;
b3 = F01 - F00;
b4 = F00 - F10 - F01 + F11;
/* define a default cubehelix-style hcl linear rainbow scale
*/
colorize = hcl_linear_rainbow();
console.debug('Coloring...');
for (pixel_x = _i = 0; 0 <= side ? _i < side : _i > side; pixel_x = 0 <= side ? ++_i : --_i) {
for (pixel_y = _j = 0; 0 <= side ? _j < side : _j > side; pixel_y = 0 <= side ? ++_j : --_j) {
pixel_i = (pixel_y * side + pixel_x) * 4;
_ref = [pixel_i + 0, pixel_i + 1, pixel_i + 2, pixel_i + 3], r = _ref[0], g = _ref[1], b = _ref[2], a = _ref[3];
_ref1 = [pixel_x / side, pixel_y / side], x = _ref1[0], y = _ref1[1];
Fxy = b1 + b2 * x + b3 * y + b4 * x * y;
color = d3.rgb(colorize(Fxy));
image.data[r] = color.r;
image.data[g] = color.g;
image.data[b] = color.b;
image.data[a] = 255;
}
}
ctx.putImageData(image, (width - side) / 2, (height - side) / 2);
/* draw labels
*/
format = d3.format('%');
svg = d3.select('svg');
vis = svg.append('g').attr({
transform: "translate(" + (width / 2) + "," + (height / 2) + ")"
});
vis.append('text').text(format(F00)).style('text-anchor', 'end').attr({
"class": 'label',
dx: '-4px',
dy: '0.85em',
x: -side / 2,
y: -side / 2
});
vis.append('text').text(format(F01)).style('text-anchor', 'end').attr({
"class": 'label',
dx: '-4px',
x: -side / 2,
y: side / 2
});
vis.append('text').text(format(F10)).style('text-anchor', 'start').attr({
"class": 'label',
dx: '4px',
dy: '0.85em',
x: side / 2,
y: -side / 2
});
vis.append('text').text(format(F11)).style('text-anchor', 'start').attr({
"class": 'label',
dx: '4px',
x: side / 2,
y: side / 2
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment