Color Manipulation——颜色操作


A raster source allows arbitrary manipulation of pixel values. In this example, RGB values on the input tile source are adjusted in a pixel-wise operation before being rendered with a second raster source. The raster operation takes pixels in in RGB space, converts them to HCL color space, adjusts the values based on the controls above, and then converts them back to RGB space for rendering.
栅格数据源允许对像素值的任意操作。在这个例子中,输入瓦片数据源的RGB值可以在用第二个栅格数据源渲染之前的逐像素操作中进行调整。栅格操作把RGB空间中的像素转换为HCL颜色空间,基于上面的控件进行调整,然后把它们在渲染之前转换回RGB空间进行渲染。

代码:
<!DOCTYPE html>
<html>
  <head>
    <title>Color Manipulation</title>
    <link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css">
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://openlayers.org/en/v4.2.0/build/ol.js"></script>
    <style>
      table.controls td {
        text-align: center;
        padding: 2px 5px;
        min-width: 60px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <table class="controls">
      <tr>
        <td>hue</td>
        <td><span id="hueOut"></span>°</td>
        <td><input id="hue" type="range" min="-180" max="180" value="0"/></td>
      </tr>
      <tr>
        <td>chroma</td>
        <td><span id="chromaOut"></span> %</td>
        <td><input id="chroma" type="range" min="0" max="100" value="100"/></td>
      </tr>
      <tr>
        <td>lightness</td>
        <td><span id="lightnessOut"></span> %</td>
        <td><input id="lightness" type="range" min="0" max="100" value="100"/></td>
      </tr>
    </table>
    <script>
      /**
       * Color manipulation functions below are adapted from
      * https://github.com/d3/d3-color.
       * 下面的颜色操作函数源自https://github.com/d3/d3-color
      */
      var Xn = 0.950470;
      var Yn = 1;
      var Zn = 1.088830;
      var t0 = 4 / 29;
      var t1 = 6 / 29;
      var t2 = 3 * t1 * t1;
      var t3 = t1 * t1 * t1;
      var twoPi = 2 * Math.PI;


      /**
       * Convert an RGB pixel into an HCL pixel.
       * 转换RGB像素为HCL像素
      * @param {Array.<number>} pixel A pixel in RGB space.
       * @return {Array.<number>} A pixel in HCL space.
       */
      function rgb2hcl(pixel) {
        var red = rgb2xyz(pixel[0]);
        var green = rgb2xyz(pixel[1]);
        var blue = rgb2xyz(pixel[2]);

        var x = xyz2lab(
            (0.4124564 * red + 0.3575761 * green + 0.1804375 * blue) / Xn);
        var y = xyz2lab(
            (0.2126729 * red + 0.7151522 * green + 0.0721750 * blue) / Yn);
        var z = xyz2lab(
            (0.0193339 * red + 0.1191920 * green + 0.9503041 * blue) / Zn);

        var l = 116 * y - 16;
        var a = 500 * (x - y);
        var b = 200 * (y - z);

        var c = Math.sqrt(a * a + b * b);
        var h = Math.atan2(b, a);
        if (h < 0) {
          h += twoPi;
        }

        pixel[0] = h;
        pixel[1] = c;
        pixel[2] = l;

        return pixel;
      }


      /**
       * Convert an HCL pixel into an RGB pixel.
       * 转换HCL像素为RGB像素
       * @param {Array.<number>} pixel A pixel in HCL space.
       * @return {Array.<number>} A pixel in RGB space.
       */
      function hcl2rgb(pixel) {
        var h = pixel[0];
        var c = pixel[1];
        var l = pixel[2];

        var a = Math.cos(h) * c;
        var b = Math.sin(h) * c;

        var y = (l + 16) / 116;
        var x = isNaN(a) ? y : y + a / 500;
        var z = isNaN(b) ? y : y - b / 200;

        y = Yn * lab2xyz(y);
        x = Xn * lab2xyz(x);
        z = Zn * lab2xyz(z);

        pixel[0] = xyz2rgb(3.2404542 * x - 1.5371385 * y - 0.4985314 * z);
        pixel[1] = xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z);
        pixel[2] = xyz2rgb(0.0556434 * x - 0.2040259 * y + 1.0572252 * z);

        return pixel;
      }

      function xyz2lab(t) {
        return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
      }

      function lab2xyz(t) {
        return t > t1 ? t * t * t : t2 * (t - t0);
      }

      function rgb2xyz(x) {
        return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
      }

      function xyz2rgb(x) {
        return 255 * (x <= 0.0031308 ?
            12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
      }

      var raster = new ol.source.Raster({
        sources: [new ol.source.Stamen({
          layer: 'watercolor'
        })],
        operation: function(pixels, data) {
          var hcl = rgb2hcl(pixels[0]);

          var h = hcl[0] + Math.PI * data.hue / 180;
          if (h < 0) {
            h += twoPi;
          } else if (h > twoPi) {
            h -= twoPi;
          }
          hcl[0] = h;

          hcl[1] *= (data.chroma / 100);
          hcl[2] *= (data.lightness / 100);

          return hcl2rgb(hcl);
        },
        lib: {
          rgb2hcl: rgb2hcl,
          hcl2rgb: hcl2rgb,
          rgb2xyz: rgb2xyz,
          lab2xyz: lab2xyz,
          xyz2lab: xyz2lab,
          xyz2rgb: xyz2rgb,
          Xn: Xn,
          Yn: Yn,
          Zn: Zn,
          t0: t0,
          t1: t1,
          t2: t2,
          t3: t3,
          twoPi: twoPi
        }
      });

      var controls = {};

      raster.on('beforeoperations', function(event) {
        var data = event.data;
        for (var id in controls) {
          data[id] = Number(controls[id].value);
        }
      });

      var map = new ol.Map({
        layers: [
          new ol.layer.Image({
            source: raster
          })
        ],
        target: 'map',
        view: new ol.View({
          center: [0, 2500000],
          zoom: 2,
          maxZoom: 18
        })
      });

      var controlIds = ['hue', 'chroma', 'lightness'];
      controlIds.forEach(function(id) {
        var control = document.getElementById(id);
        var output = document.getElementById(id + 'Out');
        control.addEventListener('input', function() {
          output.innerText = control.value;
          raster.changed();
        });
        output.innerText = control.value;
        controls[id] = control;
      });
    </script>
  </body>
</html>



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值