block by micahstubbs c8bbcfd20d979572d2a362f8951fbe6d

「鳴神忠右衛門 大谷門蔵」Histogram

Full Screen

woodblock print 100-7289 from the Ukiyo-e.org database and image similarity analysis engine developed by @jeresig

a shameless iteration on @mbostock‘s Mona Lisa Histogram

🙏 to @Milr0c for showing me how to preserve access to an individual character of a string that happens to be inside of an expression embedded within a template literal, like this:

  .attr('class', (d, i) => `histogram-area histogram-${'rgb'[i]}`);

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

canvas,
svg {
  position: absolute;
}

.brush .selection {
  stroke: #fff;
  stroke-opacity: 0.7;
  shape-rendering: crispEdges;
}

.histogram {
  pointer-events: none;
}

.histogram-panel {
  fill: #111;
  fill-opacity: 0.5;
  stroke: #000;
}

.histogram-area {
  mix-blend-mode: screen;
}

.histogram-area.histogram-r {
  fill: #f00;
}

.histogram-area.histogram-g {
  fill: #0f0;
}

.histogram-area.histogram-b {
  fill: #00f;
}

.histogram-line {
  fill: none;
  stroke: #000;
  stroke-width: 0.5px;
}

</style>
<canvas width="960" height="1452"></canvas>
<svg width="960" height="1452"></svg>
<script src="https://d3js.org/d3.v4.0.0-alpha.44.min.js"></script>
<script src="https://npmcdn.com/babel-core@5.8.34/browser.min.js"></script>
<script>

d3_color =
d3_dispatch =
d3_ease =
d3_interpolate =
d3_timer =
d3_selection =
d3_transition =
d3_drag = d3;

</script>
<script src="https://d3js.org/d3-brush.v0.1.min.js"></script>
<script lang='babel' type='text/babel'>
  const canvas = document.querySelector('canvas');
  const context = canvas.getContext('2d');
  const width = canvas.width;
  const height = canvas.height;

  const histomargin = { top: 10, right: 10, bottom: 0, left: width - 256 - 10 };
  const histowidth = width - histomargin.left - histomargin.right;
  const histoheight = 256;

  let r = d3.range(257).map(() => 0);
  let g = d3.range(257).map(() => 0);
  let b = d3.range(257).map(() => 0);
  let x = (d, i) => i;
  let y = d => histoheight - Math.round(d / n * 32 * histoheight);
  let n = 1;

  const area = d3.area()
    .curve(d3.curveStepBefore)
    .x(x)
    .y0(y(0))
    .y1(y);

  const line = d3.line()
    .curve(d3.curveStepBefore)
    .x(x)
    .y(y);

  const brush = d3_brush.brush()
    .on('start brush', brushed)
    .on('end', brushended);

  const svg = d3.select('svg');

  const histogram = svg.append('g')
    .attr('class', 'histogram')
    .attr('transform', `translate(${histomargin.left}, ${histomargin.top})`);

  histogram.append('rect')
    .attr('class', 'histogram-panel')
    .attr('x', -0.5)
    .attr('y', -0.5)
    .attr('width', histowidth + 1)
    .attr('height', histoheight + 1);

  const histoarea = histogram.selectAll('.histogram-area')
    .data([r, g, b])
    .enter().append('path')
      .attr('class', (d, i) => `histogram-area histogram-${'rgb'[i]}`);

  const histoline = histogram.selectAll('.histogram-line')
    .data([r, g, b])
    .enter().append('path')
      .attr('class', (d, i) => `histogram-line histogram-${'rgb'[i]}`)
      .attr('transform', 'translate(0.5,-0.5)');

  const image = new Image;
  image.src = '100-7289.jpg';
  image.onload = loaded;

  function loaded() {
    context.drawImage(this, 0, 0, width, height);

    svg.append('g')
      .attr('class', 'brush')
      .call(brush)
      .call(brush.move, [[260, 228], [656, 600]]);
  }

  function brushed() {
    const s = d3.event.selection;
    x = s[0][0];
    y = s[0][1];
    const w = s[1][0] - x;
    const h = s[1][1] - y;

    for (let i = 0; i < 256; ++i) {
      r[i] = g[i] = b[i] = 0;
    }

    n = w * h;
    if (n) {
      const data = context.getImageData(x, y, w, h).data;
      for (let i = 0; i < w; ++i) {
        for (let j = 0; j < h; ++j) {
          const k = j * w + i << 2;
          ++r[data[k]];
          ++g[data[k + 1]];
          ++b[data[k + 2]];
        }
      }
      histoarea.attr('d', area);
      histoline.attr('d', line);
    } else {
      histoarea.attr('d', null);
      histoline.attr('d', null);
    }
  }

  function brushended() {
    if (!d3.event.selection) {
      histoarea.attr('d', null);
      histoline.attr('d', null);
    }
  }
</script>