1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
| import Map from 'ol/Map.js'; import TileLayer from 'ol/layer/Tile.js'; import View from 'ol/View.js'; import XYZ from 'ol/source/XYZ.js'; import {fromLonLat} from 'ol/proj.js';
const key = 'Get your own API key at https://www.maptiler.com/cloud/'; const attributions = '<a href="https://www.maptiler.com/copyright/" target="_blank">© MapTiler</a> ' + '<a href="https://www.openstreetmap.org/copyright" target="_blank">© OpenStreetMap contributors</a>';
const imagery = new TileLayer({ source: new XYZ({ attributions: attributions, url: 'https://api.maptiler.com/tiles/satellite/{z}/{x}/{y}.jpg?key=' + key, maxZoom: 20, crossOrigin: '', }), });
const map = new Map({ layers: [imagery], target: 'map', view: new View({ center: fromLonLat([-120, 50]), zoom: 6, }), });
const kernels = { none: [0, 0, 0, 0, 1, 0, 0, 0, 0], sharpen: [0, -1, 0, -1, 5, -1, 0, -1, 0], sharpenless: [0, -1, 0, -1, 10, -1, 0, -1, 0], blur: [1, 1, 1, 1, 1, 1, 1, 1, 1], shadow: [1, 2, 1, 0, 1, 0, -1, -2, -1], emboss: [-2, 1, 0, -1, 1, 1, 0, 1, 2], edge: [0, 1, 0, 1, -4, 1, 0, 1, 0], };
function normalize(kernel) { const len = kernel.length; const normal = new Array(len); let i, sum = 0; for (i = 0; i < len; ++i) { sum += kernel[i]; } if (sum <= 0) { normal.normalized = false; sum = 1; } else { normal.normalized = true; } for (i = 0; i < len; ++i) { normal[i] = kernel[i] / sum; } return normal; }
const select = document.getElementById('kernel'); let selectedKernel = normalize(kernels[select.value]);
select.onchange = function () { selectedKernel = normalize(kernels[select.value]); map.render(); };
imagery.on('postrender', function (event) { convolve(event.context, selectedKernel); });
function convolve(context, kernel) { const canvas = context.canvas; const width = canvas.width; const height = canvas.height;
const size = Math.sqrt(kernel.length); const half = Math.floor(size / 2);
const inputData = context.getImageData(0, 0, width, height).data;
const output = context.createImageData(width, height); const outputData = output.data;
for (let pixelY = 0; pixelY < height; ++pixelY) { const pixelsAbove = pixelY * width; for (let pixelX = 0; pixelX < width; ++pixelX) { let r = 0, g = 0, b = 0, a = 0; for (let kernelY = 0; kernelY < size; ++kernelY) { for (let kernelX = 0; kernelX < size; ++kernelX) { const weight = kernel[kernelY * size + kernelX]; const neighborY = Math.min( height - 1, Math.max(0, pixelY + kernelY - half) ); const neighborX = Math.min( width - 1, Math.max(0, pixelX + kernelX - half) ); const inputIndex = (neighborY * width + neighborX) * 4; r += inputData[inputIndex] * weight; g += inputData[inputIndex + 1] * weight; b += inputData[inputIndex + 2] * weight; a += inputData[inputIndex + 3] * weight; } } const outputIndex = (pixelsAbove + pixelX) * 4; outputData[outputIndex] = r; outputData[outputIndex + 1] = g; outputData[outputIndex + 2] = b; outputData[outputIndex + 3] = kernel.normalized ? a : 255; } } context.putImageData(output, 0, 0); }
|