block by nitaku 8d945de79daa48768fee

Bilinear interpolation

Full Screen

-

index.js

(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);

index.html

<!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="//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>

index.coffee

`// 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

index.css

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;
}