七章-81-图像滤镜

2020-03-27  本文已影响0人  彩云飘过

本文基于腾讯课堂老胡的课《跟我学Openlayers--基础实例详解》做的学习笔记,使用的openlayers 5.3.x api。

源码 见 1081.html ,对应的 官网示例

image.png

核心技术点:
layer.on('postcompose', function(event) {})
绑定了layer的'postcompose'事件,并在渲染后进行图像的处理

image.png
<!DOCTYPE html>
<html>

<head>
 <title>图像滤镜</title>
 <link rel="stylesheet" href="../include/ol.css" type="text/css" />
 <script src="../include/ol.js"></script>
</head>
<style></style>

<body>
 <select id="kernel" name="kernel">
   <option>none</option>
   <option selected>sharpen锐化</option>
   <option value="sharpenless">sharpen less轻度锐化</option>
   <option>blur模糊</option>
   <option>shadow阴影</option>
   <option>emboss浮雕</option>
   <option value="edge">edge detect边缘查找</option>
 </select>
 <div id="map" class="map"></div>
 <div id="info">&nbsp;</div>
 <script>
   var key = 'As1HiMj1PvLPlqc_gtM7AqZfBL8ZL3VrjaS3zIb22Uvb9WKhuJObROC-qUpa81U5';

   var imagery = new ol.layer.Tile({
     source: new ol.source.OSM()
   });

   var map = new ol.Map({
     layers: [imagery],
     target: 'map',
     view: new ol.View({
       center: ol.proj.fromLonLat([-120, 50]),
       zoom: 6
     })
   });

   var 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) {
     var len = kernel.length;
     var normal = new Array(len);
     var 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;
   }

   var select = document.getElementById('kernel');
   var selectedKernel = normalize(kernels[select.value]);



   // map 和layers 都可以触发postcompose
   /**
    * 更新kernel并且在选项更改时重新归一化.
    */
   select.onchange = function () {
     selectedKernel = normalize(kernels[select.value]);
     map.render();//归一化之后,重新渲染地图
   };


   /**
    *在"postcompose" 触发之后应用滤镜.
    */
   imagery.on('postcompose', function (event) {
     convolve(event.context, selectedKernel);//卷积操作,应用滤镜效果
   });


   /**
    * Apply a convolution kernel to canvas.  This works for any size kernel, but
    * performance starts degrading above 3 x 3.
    * @param {CanvasRenderingContext2D} context Canvas 2d context.
    * @param {Array<number>} kernel Kernel.
    * 此处是卷积操作
    */
   function convolve(context, kernel) {
     var canvas = context.canvas;
     var width = canvas.width;
     var height = canvas.height;

     var size = Math.sqrt(kernel.length);
     var half = Math.floor(size / 2);

     var inputData = context.getImageData(0, 0, width, height).data;

     var output = context.createImageData(width, height);
     var outputData = output.data;

     for (var pixelY = 0; pixelY < height; ++pixelY) {
       var pixelsAbove = pixelY * width;
       for (var pixelX = 0; pixelX < width; ++pixelX) {
         var r = 0, g = 0, b = 0, a = 0;
         for (var kernelY = 0; kernelY < size; ++kernelY) {
           for (var kernelX = 0; kernelX < size; ++kernelX) {
             var weight = kernel[kernelY * size + kernelX];
             var neighborY = Math.min(
               height - 1, Math.max(0, pixelY + kernelY - half));
             var neighborX = Math.min(
               width - 1, Math.max(0, pixelX + kernelX - half));
             var inputIndex = (neighborY * width + neighborX) * 4;
             r += inputData[inputIndex] * weight;
             g += inputData[inputIndex + 1] * weight;
             b += inputData[inputIndex + 2] * weight;
             a += inputData[inputIndex + 3] * weight;
           }
         }
         var 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);
   }

 </script>
</body>

</html>
上一篇 下一篇

猜你喜欢

热点阅读