Grayscale Tile Layer implementation

There is way to shade all pixels in the newer version of Openlayers (tested on 6.0.1). Although it is not working fast enough in IE, all other browsers seem to cope with it pretty well.

In order to implement this we need to subscribe to layers postrender event and update imageData for each pixel.

 

  1. createBackgroundLayer: function () {
  2. var openStreetMapLayer = new ol.layer.Tile({
  3. //source: new ol.source.BingMaps({ key: '', imagerySet: 'Aerial' }),
  4. source: new ol.source.OSM(),
  5. legendConfig: {
  6. isBackgroundLayer: true,
  7. label: 'openStreetMap'
  8. }
  9. });
  10.  
  11. function shade(context) {
  12. var canvas = context.canvas;
  13. var width = canvas.width;
  14. var height = canvas.height;
  15.  
  16. var inputData = context.getImageData(0, 0, width, height).data;
  17.  
  18. var output = context.createImageData(width, height);
  19. var outputData = output.data;
  20.  
  21. for (var pixelY = 0; pixelY < height; ++pixelY) {
  22. var pixelsAbove = pixelY * width;
  23. for (var pixelX = 0; pixelX < width; ++pixelX) {
  24. var inputIndex = (pixelY * width + pixelX) * 4;
  25.  
  26. var r = inputData[inputIndex];
  27. var g = inputData[inputIndex + 1];
  28. var b = inputData[inputIndex + 2];
  29. var a = inputData[inputIndex + 3];
  30.  
  31. var v = 0.2126 * r + 0.7152 * g + 0.0722 * b;
  32. if (v === 0.0) v = 255.0;
  33.  
  34. var outputIndex = (pixelsAbove + pixelX) * 4;
  35. outputData[outputIndex] = v;
  36. outputData[outputIndex + 1] = v;
  37. outputData[outputIndex + 2] = v;
  38. outputData[outputIndex + 3] = 255;
  39. }
  40. }
  41. context.putImageData(output, 0, 0);
  42. }
  43.  
  44. openStreetMapLayer.on('postrender', function (event) {
  45. shade(event.context);
  46. });
  47.  
  48. return openStreetMapLayer;
  49. },