在OpenLayers 5中对OSM源使用栅格操作

时间:2019-05-01 12:57:07

标签: raster operation openlayers-5

      var osmSource = new ol.source.OSM({
        transition: 0
      });
      var rasterSource = new ol.source.Raster({
          sources: [osmSource],
          operation: function(pixels,data) {
                var pixel = pixels[0];

                var r = pixel[0];
                var g = pixel[1];
                var b = pixel[2];

                // CIE luminance for the RGB
                var v = 0.2126 * r + 0.7152 * g + 0.0722 * b;

                pixel[0] = v; // Red
                pixel[1] = v; // Green
                pixel[2] = v; // Blue
                //pixel[3] = 255;

                return pixel;
            }
      });
      var mapLayer = new ol.layer.Image({
          source: rasterSource
      });

      var map = new ol.Map({
        layers: [mapLayer],
        target: 'map',
        view: new ol.View({
          center: [1331819, 7906244],
          zoom: 12
        })
      });
 <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>

我正在尝试处理从图块源(在本例中为OSM)加载的图块中的像素的颜色,并实现了一个简单的测试用例,可以转换为灰度图,但是对我来说,它实际上并不起作用。

我已经阅读了OpenLayers v5.3的示例,该示例使用Raster源执行逐像素操作。

  var osmSource = new ol.source.OSM();
  var rasterSource = new ol.source.Raster({
      sources: [osmSource],
      operation: function(pixels,data) {
            var pixel = pixels[0];

            var r = pixel[0];
            var g = pixel[1];
            var b = pixel[2];

            // CIE luminance for the RGB
            var v = 0.2126 * r + 0.7152 * g + 0.0722 * b;

            pixel[0] = v; // Red
            pixel[1] = v; // Green
            pixel[2] = v; // Blue
            //pixel[3] = 255;

            return pixel;
        }
  });
  var mapLayer = new ol.layer.Image({
      source: rasterSource
  });

  var map = new ol.Map({
    layers: [mapLayer],
    target: 'map',
    view: new ol.View({
      center: [1331819, 7906244],
      zoom: 12
    })
  });

是的,我可以得到灰度图块,但有时它们似乎是中间版本。有时候,加载的图块是完全白色的,有时是介于白色和最终图像之间的图像,放大时,有时您只是获得了先前缩放级别的调整大小版本。

这是我的完整示例:

https://apertum.se/iairvirodvlp/maptest_grey.htm

1 个答案:

答案 0 :(得分:0)

我看不到您的演示有任何重大问题,但是光栅操作将夸大OSM源服务器缓慢加载时经常发生的OSM源加载缓慢的影响。实现灰度的一种更有效的方法是在普通图块图层的后合成事件时在画布上使用全局合成操作

osmLayer.on('postcompose', function (evt) {
    evt.context.globalCompositeOperation = 'color';
    evt.context.fillStyle = '#888';
    evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
    evt.context.globalCompositeOperation = 'source-over';
});

      var osmSource = new ol.source.OSM({
          transition: 0
      });
      var mapLayer = new ol.layer.Tile({
          source: osmSource
      });

      mapLayer.on('postcompose', function (evt) {
          evt.context.globalCompositeOperation = 'color';
          // check browser supports globalCompositeOperation
          if (evt.context.globalCompositeOperation == 'color') {
              evt.context.fillStyle = 'rgba(255,255,255,' + grayInput.value/100 + ')';
              evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
          }
          evt.context.globalCompositeOperation = 'overlay';
          // check browser supports globalCompositeOperation
          if (evt.context.globalCompositeOperation == 'overlay') {
              evt.context.fillStyle = 'rgb(' + [background,background,background].toString() + ')';
              evt.context.fillRect(0, 0, evt.context.canvas.width, evt.context.canvas.height);
          }
          evt.context.globalCompositeOperation = 'source-over';
      });

      var intensityInput = document.getElementById('intensity');
      var background = 255 - intensityInput.value;

      intensityInput.onchange = function() {
          background = 255 - intensityInput.value;
          map.render();
      };

      var grayInput = document.getElementById('gray');

      grayInput.onchange = function() {
          map.render();
      };

      var map = new ol.Map({
        layers: [mapLayer],
        target: 'map',
        view: new ol.View({
          center: [1331819, 7906244],
          zoom: 12
        })
      });
html, body, .map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}
.map {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 80%;
}
 <link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div id="map" class="map"></div>
<b>Gray:</b><input id="gray" type="range" min="0" max="100" step="1" value="50">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<b>Intensity:</b><input id="intensity" type="range" min="0" max="255" step="1" value="128">