Использование растровых операций с источником OSM в OpenLayers 5 - PullRequest
0 голосов
/ 01 мая 2019

      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 голосов
/ 01 мая 2019

Я не вижу каких-либо серьезных проблем с вашей демонстрацией, но растровая операция будет преувеличивать эффект медленной загрузки источников 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">
...