zoukankan      html  css  js  c++  java
  • 前端处理图片高斯模糊

    得到一个需求,要求书籍封面的背景和书籍封面的颜色有一定的一致性,也就是如下这种情况:

    这种情况,我们解决的思路就是:利用canvas的图像高斯模糊算法,通过高斯模糊书籍封面,获得一张背景图像,结果就是这样:

    我们需要依次解决以下两个问题:

    1.基于canvas的高斯模糊算法

    2.书籍封面是取自阿里大数据服务器的,canvas不支持非本地图片的drawImage和getImageData

    针对第一个问题。高斯模糊算法网上有,这就是算法源码:

      1 function stackBlurCanvasRGBA( canvas, top_x, top_y, width, height, radius )
      2 {
      3     if ( isNaN(radius) || radius < 1 ) return;
      4     radius |= 0;
      5 
      6     if (typeof(canvas) == "string")
      7         var canvas  = document.getElementById( canvas );
      8     else if (!canvas instanceof HTMLCanvasElement)
      9         return;
     10 
     11     var context = canvas.getContext("2d");
     12     var imageData;
     13     try {
     14         try {
     15             imageData = context.getImageData( top_x, top_y, width, height );
     16         } catch(e) {
     17 
     18             // NOTE: this part is supposedly only needed if you want to work with local files
     19             // so it might be okay to remove the whole try/catch block and just use
     20             // imageData = context.getImageData( top_x, top_y, width, height );
     21             try {
     22                 netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
     23                 imageData = context.getImageData( top_x, top_y, width, height );
     24             } catch(e) {
     25                 //alert("Cannot access local image");
     26                 throw new Error("unable to access local image data: " + e);
     27                 return;
     28             }
     29         }
     30     } catch(e) {
     31         //alert("Cannot access image");
     32         throw new Error("unable to access image data: " + e);
     33     }
     34 
     35     var pixels = imageData.data;
     36 
     37     var x, y, i, p, yp, yi, yw, r_sum, g_sum, b_sum, a_sum,
     38         r_out_sum, g_out_sum, b_out_sum, a_out_sum,
     39         r_in_sum, g_in_sum, b_in_sum, a_in_sum,
     40         pr, pg, pb, pa, rbs;
     41 
     42     var div = radius + radius + 1;
     43     var w4 = width << 2;
     44     var widthMinus1  = width - 1;
     45     var heightMinus1 = height - 1;
     46     var radiusPlus1  = radius + 1;
     47     var sumFactor = radiusPlus1 * ( radiusPlus1 + 1 ) / 2;
     48 
     49     var stackStart = new BlurStack();
     50     var stack = stackStart;
     51     for ( i = 1; i < div; i++ )
     52     {
     53         stack = stack.next = new BlurStack();
     54         if ( i == radiusPlus1 ) var stackEnd = stack;
     55     }
     56     stack.next = stackStart;
     57     var stackIn = null;
     58     var stackOut = null;
     59 
     60     yw = yi = 0;
     61 
     62     var mul_sum = mul_table[radius];
     63     var shg_sum = shg_table[radius];
     64 
     65     for ( y = 0; y < height; y++ )
     66     {
     67         r_in_sum = g_in_sum = b_in_sum = a_in_sum = r_sum = g_sum = b_sum = a_sum = 0;
     68 
     69         r_out_sum = radiusPlus1 * ( pr = pixels[yi] );
     70         g_out_sum = radiusPlus1 * ( pg = pixels[yi+1] );
     71         b_out_sum = radiusPlus1 * ( pb = pixels[yi+2] );
     72         a_out_sum = radiusPlus1 * ( pa = pixels[yi+3] );
     73 
     74         r_sum += sumFactor * pr;
     75         g_sum += sumFactor * pg;
     76         b_sum += sumFactor * pb;
     77         a_sum += sumFactor * pa;
     78 
     79         stack = stackStart;
     80 
     81         for ( i = 0; i < radiusPlus1; i++ )
     82         {
     83             stack.r = pr;
     84             stack.g = pg;
     85             stack.b = pb;
     86             stack.a = pa;
     87             stack = stack.next;
     88         }
     89 
     90         for ( i = 1; i < radiusPlus1; i++ )
     91         {
     92             p = yi + (( widthMinus1 < i ? widthMinus1 : i ) << 2 );
     93             r_sum += ( stack.r = ( pr = pixels[p])) * ( rbs = radiusPlus1 - i );
     94             g_sum += ( stack.g = ( pg = pixels[p+1])) * rbs;
     95             b_sum += ( stack.b = ( pb = pixels[p+2])) * rbs;
     96             a_sum += ( stack.a = ( pa = pixels[p+3])) * rbs;
     97 
     98             r_in_sum += pr;
     99             g_in_sum += pg;
    100             b_in_sum += pb;
    101             a_in_sum += pa;
    102 
    103             stack = stack.next;
    104         }
    105 
    106 
    107         stackIn = stackStart;
    108         stackOut = stackEnd;
    109         for ( x = 0; x < width; x++ )
    110         {
    111             pixels[yi+3] = pa = (a_sum * mul_sum) >> shg_sum;
    112             if ( pa != 0 )
    113             {
    114                 pa = 255 / pa;
    115                 pixels[yi]   = ((r_sum * mul_sum) >> shg_sum) * pa;
    116                 pixels[yi+1] = ((g_sum * mul_sum) >> shg_sum) * pa;
    117                 pixels[yi+2] = ((b_sum * mul_sum) >> shg_sum) * pa;
    118             } else {
    119                 pixels[yi] = pixels[yi+1] = pixels[yi+2] = 0;
    120             }
    121 
    122             r_sum -= r_out_sum;
    123             g_sum -= g_out_sum;
    124             b_sum -= b_out_sum;
    125             a_sum -= a_out_sum;
    126 
    127             r_out_sum -= stackIn.r;
    128             g_out_sum -= stackIn.g;
    129             b_out_sum -= stackIn.b;
    130             a_out_sum -= stackIn.a;
    131 
    132             p =  ( yw + ( ( p = x + radius + 1 ) < widthMinus1 ? p : widthMinus1 ) ) << 2;
    133 
    134             r_in_sum += ( stackIn.r = pixels[p]);
    135             g_in_sum += ( stackIn.g = pixels[p+1]);
    136             b_in_sum += ( stackIn.b = pixels[p+2]);
    137             a_in_sum += ( stackIn.a = pixels[p+3]);
    138 
    139             r_sum += r_in_sum;
    140             g_sum += g_in_sum;
    141             b_sum += b_in_sum;
    142             a_sum += a_in_sum;
    143 
    144             stackIn = stackIn.next;
    145 
    146             r_out_sum += ( pr = stackOut.r );
    147             g_out_sum += ( pg = stackOut.g );
    148             b_out_sum += ( pb = stackOut.b );
    149             a_out_sum += ( pa = stackOut.a );
    150 
    151             r_in_sum -= pr;
    152             g_in_sum -= pg;
    153             b_in_sum -= pb;
    154             a_in_sum -= pa;
    155 
    156             stackOut = stackOut.next;
    157 
    158             yi += 4;
    159         }
    160         yw += width;
    161     }
    162 
    163 
    164     for ( x = 0; x < width; x++ )
    165     {
    166         g_in_sum = b_in_sum = a_in_sum = r_in_sum = g_sum = b_sum = a_sum = r_sum = 0;
    167 
    168         yi = x << 2;
    169         r_out_sum = radiusPlus1 * ( pr = pixels[yi]);
    170         g_out_sum = radiusPlus1 * ( pg = pixels[yi+1]);
    171         b_out_sum = radiusPlus1 * ( pb = pixels[yi+2]);
    172         a_out_sum = radiusPlus1 * ( pa = pixels[yi+3]);
    173 
    174         r_sum += sumFactor * pr;
    175         g_sum += sumFactor * pg;
    176         b_sum += sumFactor * pb;
    177         a_sum += sumFactor * pa;
    178 
    179         stack = stackStart;
    180 
    181         for ( i = 0; i < radiusPlus1; i++ )
    182         {
    183             stack.r = pr;
    184             stack.g = pg;
    185             stack.b = pb;
    186             stack.a = pa;
    187             stack = stack.next;
    188         }
    189 
    190         yp = width;
    191 
    192         for ( i = 1; i <= radius; i++ )
    193         {
    194             yi = ( yp + x ) << 2;
    195 
    196             r_sum += ( stack.r = ( pr = pixels[yi])) * ( rbs = radiusPlus1 - i );
    197             g_sum += ( stack.g = ( pg = pixels[yi+1])) * rbs;
    198             b_sum += ( stack.b = ( pb = pixels[yi+2])) * rbs;
    199             a_sum += ( stack.a = ( pa = pixels[yi+3])) * rbs;
    200 
    201             r_in_sum += pr;
    202             g_in_sum += pg;
    203             b_in_sum += pb;
    204             a_in_sum += pa;
    205 
    206             stack = stack.next;
    207 
    208             if( i < heightMinus1 )
    209             {
    210                 yp += width;
    211             }
    212         }
    213 
    214         yi = x;
    215         stackIn = stackStart;
    216         stackOut = stackEnd;
    217         for ( y = 0; y < height; y++ )
    218         {
    219             p = yi << 2;
    220             pixels[p+3] = pa = (a_sum * mul_sum) >> shg_sum;
    221             if ( pa > 0 )
    222             {
    223                 pa = 255 / pa;
    224                 pixels[p]   = ((r_sum * mul_sum) >> shg_sum ) * pa;
    225                 pixels[p+1] = ((g_sum * mul_sum) >> shg_sum ) * pa;
    226                 pixels[p+2] = ((b_sum * mul_sum) >> shg_sum ) * pa;
    227             } else {
    228                 pixels[p] = pixels[p+1] = pixels[p+2] = 0;
    229             }
    230 
    231             r_sum -= r_out_sum;
    232             g_sum -= g_out_sum;
    233             b_sum -= b_out_sum;
    234             a_sum -= a_out_sum;
    235 
    236             r_out_sum -= stackIn.r;
    237             g_out_sum -= stackIn.g;
    238             b_out_sum -= stackIn.b;
    239             a_out_sum -= stackIn.a;
    240 
    241             p = ( x + (( ( p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1 ) * width )) << 2;
    242 
    243             r_sum += ( r_in_sum += ( stackIn.r = pixels[p]));
    244             g_sum += ( g_in_sum += ( stackIn.g = pixels[p+1]));
    245             b_sum += ( b_in_sum += ( stackIn.b = pixels[p+2]));
    246             a_sum += ( a_in_sum += ( stackIn.a = pixels[p+3]));
    247 
    248             stackIn = stackIn.next;
    249 
    250             r_out_sum += ( pr = stackOut.r );
    251             g_out_sum += ( pg = stackOut.g );
    252             b_out_sum += ( pb = stackOut.b );
    253             a_out_sum += ( pa = stackOut.a );
    254 
    255             r_in_sum -= pr;
    256             g_in_sum -= pg;
    257             b_in_sum -= pb;
    258             a_in_sum -= pa;
    259 
    260             stackOut = stackOut.next;
    261 
    262             yi += width;
    263         }
    264     }
    265 
    266     context.putImageData( imageData, top_x, top_y );
    267 
    268 }
    View Code

    而第二个问题也很简单,canvas虽然不支持处理外域图片,但是可以接收图像的base64
    把图片处理成base64,后端服务器语言只需调用一个函数就能做到,但是大规模字符串传递会影响服务器效率,所以,将图片转换成base64只能通过前端解决

    由于只考虑谷歌浏览器,所以这方面的转换十分简单,

    XMLHttpRequest 2.0 可以设置responseType, 我们将其设置为 blob

    然后将blob转换成base64

    代码如下:

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     5     <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
     6     <meta name="apple-mobile-web-app-capable" content="yes">
     7     <meta name="format-detection" content="telephone=no">
     8     <title>Examples</title>
     9     <meta name="description" content="">
    10     <meta name="keywords" content="">
    11     <link href="" rel="stylesheet">
    12     <style>
    13         .hero {
    14             padding: 3em 0;
    15             position: relative;
    16         }
    17         .hero__background {
    18             position: absolute;
    19             top: 0;
    20             left: 0;
    21             width: 100%;
    22             height: 200px;
    23             z-index: 1;
    24         }
    25         .hero__title {
    26             position: relative;
    27             z-index: 2;
    28             color: #fff;
    29             text-align: center;
    30         }
    31 
    32     </style>
    33 
    34 <body>
    35 <div class="hero">
    36     <canvas class="hero__background" id="heroCanvas" width="200" height="200" data-canvas></canvas>
    37     <!--<h1 class="hero__title"></h1>-->
    38 </div>
    39 
    40 <!-- Our image to be blurred http://oss-asq-img.11222.cn/cover/raw/2013081212197381.jpg-->
    41 
    42 <img id="img" data-canvas-image  style="top:200px; position:relative; ">
    43 <canvas id="mc" style="height:200px; 320px;"></canvas>
    44 <div id="add" style="height:300px; 400px;">
    45   
    46 </div>
    47 </body>
    48 <script type="text/javascript" src="js/stackBoxBlur.js"></script>
    49 <script type="text/javascript">
    50 
    51        
    52 </script>
    53 <script>
    54      function ajax(url,method,funcs){
    55         var xhr=new XMLHttpRequest();
    56         xhr.open(method,url,true);
    57         xhr.responseType='blob';
    58         xhr.onload=function(e){
    59            if(this.status==200){
    60                funcs(this.response); 
    61            } 
    62         }
    63         xhr.send(null);
    64      }
    65      var url='http://xxxxxxxxxxx/demo/abc.jpg';
    66      ajax(url,'get',function(x){
    67           var bb=new Blob([x],{type:'image/jpeg'});
    68           var ak=btoa(bb);     
    69            var reader = new window.FileReader();
    70           reader.readAsDataURL(x); 
    71           reader.onloadend = function() {
    72                 ak = this.result;                
    73                 document.querySelector('#img').src=ak;
    74                  var BLUR_RADIUS = 100;
    75                  var canvas = document.querySelector('[data-canvas]');
    76                  var canvasContext = canvas.getContext('2d');
    77                  var image = new Image();
    78                  image.src = ak;
    79                  image.crossOrigin = "Anonymous";
    80                  var drawBlur = function() {
    81                         var w = canvas.width;
    82                         var h = canvas.height;
    83                         canvasContext.drawImage(image, 0, 0, w, h);
    84                         stackBlurCanvasRGBA('heroCanvas', 0, 0, w, h, BLUR_RADIUS);
    85                   };
    86                   image.onload = function() {
    87                       drawBlur();
    88                    }
    89      }
    90 });
    91     
    92 </script>
    93 </html>
    View Code

    问题解决

  • 相关阅读:
    MFC中 CListCtrl控件的使用及定位、选中
    在VC++6.0中,编译,调试都能通过,但运行到某一步的时候就报错的可能原因。
    存储IplImage结构体到STL中的vector中的问题
    VS工程,换电脑后出现的问题
    What is a Full Stack developer?
    [MB855]变砖解决
    ERP 开发过程中涉及到的算法 库存,工程,生产计划,固定资产计算方法
    定义枚举类型带有byte 的作用
    构造函数带有this和base的作用
    创建一个简单的WCF程序(转载)
  • 原文地址:https://www.cnblogs.com/JhoneLee/p/4317550.html
Copyright © 2011-2022 走看看