Reputation: 11
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>
I'm trying to manipulate the color of pixels in tiles loaded from a tile source (in this case OSM) and implemented a simple test case with a conversion to a gray scale map, but for me it doesn't really work.
I have read the examples for OpenLayers v5.3 for using the Raster source to perform pixel wise operations.
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
})
});
Yes, I can get gray scale tiles, but sometimes they seem to be an intermediate version or something. Sometimes the loaded tiles are completely white, sometimes something in between white and the final image and when you zoom in, sometimes you just get the resized version of the previous zoom level.
Here is my full example:
https://apertum.se/iairvirodvlp/maptest_grey.htm
Upvotes: 0
Views: 1388
Reputation: 17962
I cannot see any major problem with your demo, but the raster operation is going to exaggerate the effect of slow loading OSM sources which happens frequently when the OSM tile servers are busy. A much more efficient way of achieving grayscale is to use a global composite operation on the canvas at the postcompose event of a normal tile layer
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">
<b>Intensity:</b><input id="intensity" type="range" min="0" max="255" step="1" value="128">
Upvotes: 1