转《canvas实现滤镜效果》

[html] view plain copy
 
  1. <code class="language-html"><html>  
  2. <head>  
  3.     <style type="text/css">  
  4.   
  5.   
  6.   
  7.     form, input {width: 73px;height: 27px;}  
  8.     form {  
  9.         position: relative;  
  10.         float: left;  
  11.         margin: 0 10px 0 0;  
  12.     }  
  13.     #up-button{  
  14.         position: absolute;  
  15.         right: 0;  
  16.         top: 0;  
  17.         cursor: pointer;  
  18.         opacity: 0;  
  19.         filter: alpha(opacity=0);  
  20.         outline: none;  
  21.     }  
  22.     #button{  
  23.     }  
  24.     iframe {display: none;}  
  25. </style>  
  26.   
  27. </head>  
  28. <body>  
  29. <div class="bt">  
  30.     <form id="uf">  
  31.         <input type="file" name="file" id="up-button"/>  
  32.         <input type="button" id="button" value="upload"/>  
  33.         <input type="button" id="download" value="download"/>  
  34.     </form>  
  35.   
  36.     <span><input type="radio" value="spread" id="spread" name="filter"/><label for="spread">油画效果</label></span>  
  37.     <span><input type="radio" id="gray" name="filter"/><label for="gray">灰度效果</label></span>  
  38.     <span><input type="radio" id="comic" name="filter"/><label for="comic">连环画效果</label></span>  
  39.     <span><input type="radio" id="old" name="filter"/><label for="old">怀旧效果</label></span>  
  40.     <span><input type="radio" id="negatives" name="filter"/><label for="negatives">底片效果</label></span>  
  41.     <span><input type="radio" id="black" name="filter"/><label for="black">黑白效果</label></span>  
  42.     <span><input type="radio" id="cameo" name="filter"/><label for="cameo">浮雕效果</label></span>  
  43. </div>  
  44. <br>  
  45.   <canvas id="cv">fuck ie</canvas>  
  46.   <canvas id="myCanvas" >Gray Filter</canvas>  
  47.     
  48.   <script>  
  49.   
  50.   
  51.   /**  
  52.    * 获取mimeType  
  53.    * @param  {String} type the old mime-type  
  54.    * @return the new mime-type  
  55.    */  
  56.   var _fixType = function(type) {  
  57.       type = type.toLowerCase().replace(/jpg/i, 'jpeg');  
  58.       var r = type.match(/png|jpeg|bmp|gif/)[0];  
  59.       return 'image/' + r;  
  60.   };  
  61.   
  62.   /**  
  63.    * 在本地进行文件保存  
  64.    * @param  {String} data     要保存到本地的图片数据  
  65.    * @param  {String} filename 文件名  
  66.    */  
  67.   var saveFile = function(data, filename){  
  68.       var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');  
  69.       save_link.href = data;  
  70.       save_link.download = filename;  
  71.        
  72.       var event = document.createEvent('MouseEvents');  
  73.       event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);  
  74.       save_link.dispatchEvent(event);  
  75.   };  
  76.        
  77.   
  78.   document.getElementById("download").onclick=function()  
  79.   {  
  80.     //图片导出为 png 格式  
  81.       var type = 'png';  
  82.       var imgData = canvas.toDataURL(type);  
  83.       // 加工image data,替换mime type  
  84.       imgData = imgData.replace(_fixType(type),'image/octet-stream');    
  85.       // 下载后的问题名  
  86.       var filename = 'bloglaotou_' + (new Date()).getTime() + '.' + type;  
  87.       // download  
  88.       saveFile(imgData,filename);  
  89.            
  90.   
  91.   }  
  92. //  1.灰度效果  
  93. //计算公式 .299 * r + .587 * g + .114 * b;  
  94. // calculate gray scale value  
  95. function gray(canvasData)  
  96. {  
  97.  for ( var x = 0; x canvasData.width; x++) {  
  98.      for ( var y = 0; y canvasData.height; y++) {  
  99.   
  100.        // Index of the pixel in the array  
  101.        var idx = (x + y * canvasData.width) * 4;  
  102.        var r = canvasData.data[idx + 0];  
  103.        var g = canvasData.data[idx + 1];  
  104.        var b = canvasData.data[idx + 2];  
  105.        var gray = .299 * r + .587 * g + .114 * b;  
  106.               
  107.         // assign gray scale value  
  108.         canvasData.data[idx + 0] = gray; // Red channel  
  109.         canvasData.data[idx + 1] = gray; // Green channel  
  110.         canvasData.data[idx + 2] = gray; // Blue channel  
  111.         canvasData.data[idx + 3] = 255; // Alpha channel  
  112.         // add black border  
  113.         if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  114.         {  
  115.           canvasData.data[idx + 0] = 0;  
  116.           canvasData.data[idx + 1] = 0;  
  117.           canvasData.data[idx + 2] = 0;  
  118.         }  
  119.      }  
  120.  }  
  121.  return canvasData;  
  122. }  
  123.   
  124.   
  125.    
  126.   
  127.        
  128. //2.怀旧效果     
  129. function old(canvasData)  
  130. {  
  131. for ( var x = 0; x canvasData.width; x++) {  
  132.  for ( var y = 0; y canvasData.height; y++) {  
  133.   
  134.    // Index of the pixel in the array  
  135.    var idx = (x + y * canvasData.width) * 4;  
  136.    var r = canvasData.data[idx + 0];  
  137.    var g = canvasData.data[idx + 1];  
  138.    var b = canvasData.data[idx + 2];  
  139.   
  140.    var dr=.393*r+.769*g+.189*b;  
  141.    var dg=.349*r+.686*g+.168*b;  
  142.    var db=.272*r+.534*g+.131*b;  
  143.    var scale=Math.random()*0.5 + 0.5;  
  144.    var fr=scale*dr+(1-scale)*r;  
  145.    scale=Math.random()*0.5 + 0.5;  
  146.    var fg=scale*dg+(1-scale)*g;  
  147.    scale=Math.random()*0.5 + 0.5;  
  148.    var fb=scale*db+(1-scale)*b;  
  149.    canvasData.data[idx + 0] = fr; // Red channel  
  150.    canvasData.data[idx + 1] = fg; // Green channel  
  151.    canvasData.data[idx + 2] = fb; // Blue channel  
  152.    canvasData.data[idx + 3] = 255; // Alpha channel   
  153.    // add black border  
  154.    if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  155.    {  
  156.      canvasData.data[idx + 0] = 0;  
  157.      canvasData.data[idx + 1] = 0;  
  158.      canvasData.data[idx + 2] = 0;  
  159.    }  
  160.  }  
  161. }  
  162. return canvasData;  
  163. }  
  164.   
  165.   
  166.   
  167. //3 底片效果  
  168. //算法原理:将当前像素点的RGB值分别与255之差后的值作为当前点的RGB值,即  
  169. //R = 255 – R;G = 255 – G;B = 255 – B;  
  170. function negatives(canvasData)  
  171. {  
  172. for ( var x = 0; x canvasData.width; x++) {  
  173.  for ( var y = 0; y canvasData.height; y++) {  
  174.   
  175.    // Index of the pixel in the array  
  176.    var idx = (x + y * canvasData.width) * 4;  
  177.    var r = canvasData.data[idx + 0];  
  178.    var g = canvasData.data[idx + 1];  
  179.    var b = canvasData.data[idx + 2];  
  180.    var fr=255-r;  
  181.    var fg=255-g;  
  182.    var fb=255-b;  
  183.    canvasData.data[idx + 0] = fr; // Red channel  
  184.    canvasData.data[idx + 1] = fg; // Green channel  
  185.    canvasData.data[idx + 2] = fb; // Blue channel  
  186.    canvasData.data[idx + 3] = 255; // Alpha channel   
  187.    // add black border  
  188.    if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  189.    {  
  190.      canvasData.data[idx + 0] = 0;  
  191.      canvasData.data[idx + 1] = 0;  
  192.      canvasData.data[idx + 2] = 0;  
  193.    }  
  194.  }  
  195. }  
  196. return canvasData;  
  197. }  
  198.   
  199.    
  200.     
  201. //4 黑白效果  
  202. //求RGB平均值Avg = (R + G + B) / 3,如果Avg >= 100,则新的颜色值为R=G=B=255;  
  203. //如果Avg 100,则新的颜色值为R=G=B=0;255就是白色,0就是黑色;  
  204. //至于为什么用100作比较,这是一个经验值吧,设置为128也可以,可以根据效果来调整。  
  205. function black(canvasData)  
  206. {  
  207. for ( var x = 0; x canvasData.width; x++) {  
  208.  for ( var y = 0; y canvasData.height; y++) {  
  209.   
  210.    // Index of the pixel in the array  
  211.    var idx = (x + y * canvasData.width) * 4;  
  212.    var r = canvasData.data[idx + 0];  
  213.    var g = canvasData.data[idx + 1];  
  214.    var b = canvasData.data[idx + 2];  
  215.    if((r+g+b)>=300)  
  216.    {  
  217.     fr=fg=fb=255;  
  218.    }  
  219.    else  
  220.    {  
  221.     fr=fg=fb=0;  
  222.    }  
  223.    canvasData.data[idx + 0] = fr; // Red channel  
  224.    canvasData.data[idx + 1] = fg; // Green channel  
  225.    canvasData.data[idx + 2] = fb; // Blue channel  
  226.    canvasData.data[idx + 3] = 255; // Alpha channel  
  227.    // add black border  
  228.    if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  229.    {  
  230.      canvasData.data[idx + 0] = 0;  
  231.      canvasData.data[idx + 1] = 0;  
  232.      canvasData.data[idx + 2] = 0;  
  233.    }  
  234.  }  
  235. }  
  236. return canvasData;  
  237. }  
  238.   
  239.    
  240.   
  241. //5 浮雕效果  
  242. //用相邻点的RGB值减去当前点的RGB值并加上128作为新的RGB值。  
  243. //由于图片中相邻点的颜色值是比较接近的,因此这样的算法处理之后,只有颜色的边沿区域,  
  244. //也就是相邻颜色差异较大的部分的结果才会比较明显,而其他平滑区域则值都接近128左右,  
  245. //也就是灰色,这样就具有了浮雕效果。  
  246. //在实际的效果中,这样处理后,有些区域可能还是会有”彩色”的一些点或者条状痕迹,所以最好再对新的RGB值做一个灰度处理。  
  247.    
  248. function cameo(canvasData)  
  249. {  
  250. for ( var x = 0; x canvasData.width; x++) {  
  251.  for ( var y = 0; y canvasData.height; y++) {  
  252.   
  253.    // Index of the pixel in the array  
  254.    var idx = (x + y * canvasData.width) * 4;  
  255.    var r = canvasData.data[idx + 0];  
  256.    var g = canvasData.data[idx + 1];  
  257.    var b = canvasData.data[idx + 2];  
  258.    var idx2 = (x + (y+1) * canvasData.width) * 4;  
  259.    var r2 = canvasData.data[idx2 + 0];  
  260.    var g2 = canvasData.data[idx2 + 1];  
  261.    var b2 = canvasData.data[idx2 + 2];  
  262.    var fr=r2-r+128;  
  263.    var fg=g2-g+128;  
  264.    var fb=b2-b+128;  
  265.    var gray = .299 * fr + .587 * fg + .114 * fb;  
  266.    canvasData.data[idx + 0] = gray; // Red channel  
  267.    canvasData.data[idx + 1] = gray; // Green channel  
  268.    canvasData.data[idx + 2] = gray; // Blue channel  
  269.    canvasData.data[idx + 3] = 255; // Alpha channel  
  270.    // add black border  
  271.    if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  272.    {  
  273.      canvasData.data[idx + 0] = 0;  
  274.      canvasData.data[idx + 1] = 0;  
  275.      canvasData.data[idx + 2] = 0;  
  276.    }  
  277.  }  
  278. }  
  279. return canvasData;  
  280. }  
  281.   
  282.    
  283.    
  284.    
  285.    
  286. //6.连环画效果  
  287. //连环画的效果与图像灰度化后的效果相似,它们都是灰度图,但连环画增大了图像的对比度,使整体明暗效果更强.  
  288. //算法:  
  289. //R = |g – b + g + r| * r / 256  
  290. //G = |b – g + b + r| * r / 256;  
  291. //B = |b – g + b + r| * g / 256;  
  292. function comic(canvasData)  
  293. {  
  294. for ( var x = 0; x canvasData.width; x++) {  
  295.  for ( var y = 0; y canvasData.height; y++) {  
  296.   
  297.    // Index of the pixel in the array  
  298.    var idx = (x + y * canvasData.width) * 4;  
  299.    var r = canvasData.data[idx + 0];  
  300.    var g = canvasData.data[idx + 1];  
  301.    var b = canvasData.data[idx + 2];  
  302.   
  303.     var fr=Math.abs((g-r+g+b))*r/256;  
  304.     var fg=Math.abs((b-r+g+b))*r/256;  
  305.     var fb=Math.abs((b-r+g+b))*g/256;   
  306.     //var fr=(g-r+g+b)*r/256;  
  307.     //var fg=(b-r+g+b)*r/256;  
  308.     //var fb=(b-r+g+b)*g/256;    
  309.    canvasData.data[idx + 0] = fr; // Red channel  
  310.    canvasData.data[idx + 1] = fg; // Green channel  
  311.    canvasData.data[idx + 2] = fb; // Blue channel  
  312.    canvasData.data[idx + 3] = 255; // Alpha channel  
  313.             // add black border  
  314.  if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  315.  {  
  316.    canvasData.data[idx + 0] = 0;  
  317.    canvasData.data[idx + 1] = 0;  
  318.    canvasData.data[idx + 2] = 0;  
  319.  }  
  320.   
  321.  }  
  322. }  
  323. return canvasData;  
  324. }  
  325.   
  326. //9 扩散(毛玻璃)  
  327. //原理:用当前点四周一定范围内任意一点的颜色来替代当前点颜色,最常用的是随机的采用相邻点进行替代。  
  328. function spread(canvasData)  
  329.  {  
  330.      for ( var x = 0; x canvasData.width; x++) {  
  331.          for ( var y = 0; y canvasData.height; y++) {  
  332.   
  333.            // Index of the pixel in the array  
  334.            var idx = (x + y * canvasData.width) * 4;  
  335.            var r = canvasData.data[idx + 0];  
  336.            var g = canvasData.data[idx + 1];  
  337.            var b = canvasData.data[idx + 2];  
  338.   
  339.            var rand=Math.floor(Math.random()*10)%3;  
  340.            var idx2 = (x+rand + (y+rand) * canvasData.width) * 4;  
  341.            var r2 = canvasData.data[idx2 + 0];  
  342.            var g2 = canvasData.data[idx2 + 1];  
  343.            var b2 = canvasData.data[idx2 + 2];  
  344.            var fr=r2;  
  345.            var fg=g2;  
  346.            var fb=b2;  
  347.            canvasData.data[idx + 0] = fr; // Red channel  
  348.            canvasData.data[idx + 1] = fg; // Green channel  
  349.            canvasData.data[idx + 2] = fb; // Blue channel  
  350.            canvasData.data[idx + 3] = 255; // Alpha channel    
  351.            // add black border  
  352.            if(x 8 || y 8 || x > (canvasData.width - 8) || y > (canvasData.height - 8))   
  353.            {  
  354.              canvasData.data[idx + 0] = 0;  
  355.              canvasData.data[idx + 1] = 0;  
  356.              canvasData.data[idx + 2] = 0;  
  357.            }  
  358.              
  359.      
  360.          }  
  361.      }  
  362.      return canvasData;  
  363.  }   
  364.   
  365.   
  366. var cv = document.getElementById('cv');  
  367. var c = cv.getContext('2d');  
  368. var canvas = document.getElementById("myCanvas");  
  369. var context = canvas.getContext("2d");  
  370. var fileBtn = document.getElementById("up-button");  
  371. var img = new Image();  
  372. fileBtn.onchange = getImg;  
  373. function init() {  
  374.     cv.width = img.width;  
  375.     cv.height = img.height;  
  376.     c.drawImage(img, 0, 0);  
  377.     var f="";   
  378.     var filter = document.getElementsByName("filter");   
  379.     for(i=0;i<filter.length;i++)   
  380.     {   
  381.         if(filter[i].checked)  
  382.         {  
  383.             f=filter[i].id;   
  384.         }  
  385.              
  386.     }  
  387.     switch(f){  
  388.        case "gray":setGray();break;  
  389.        case "spread":setSpread();break;  
  390.        case "comic":setComic();break;  
  391.        case "old":setOld();break;  
  392.        case "negatives":setNegatives();break;  
  393.        case "black":setBlack();break;  
  394.        case "cameo":setCameo();break;  
  395.        case "casting":setCasting();break;  
  396.        case "frozen":setFrozen();break;  
  397.        default:setGray();break;  
  398.     }  
  399.     
  400.   };  
  401.   
  402. function getImg(file) {  
  403.     var reader = new FileReader();  
  404.     reader.readAsDataURL(fileBtn.files[0]);  
  405.     reader.onload = function () {  
  406.         img.src = reader.result;  
  407.     }  
  408.   
  409.   
  410. }  
  411.    
  412.  window.onload = function() {  
  413.   
  414.      img.src = 'http://bbs.blueidea.com/forum.php?mod=attachment&aid=MjEyMzA1fDJiYzQxZThkfDEzODMxMDU2NDd8NjU2ODk5fDMxMDU1MTQ%3D';  
  415.      img.onload = init   
  416.   
  417.     // re-size the canvas deminsion  
  418.     canvas.width  = img.width;  
  419.     canvas.height = img.height;  
  420.       
  421.     // get 2D render object  
  422.     var context = canvas.getContext("2d");  
  423.     context.drawImage(img, 0, 0);  
  424.     var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  425.   
  426.    canvasData=gray(canvasData);   
  427. //   canvasData=spread(canvasData);  
  428. //   canvasData=old(canvasData);  
  429. //   canvasData=frozen(canvasData);  
  430. //   canvasData=casting(canvasData);  
  431. //   canvasData=cameo(canvasData);  
  432. //   canvasData=comic(canvasData);  
  433. //   canvasData=black(canvasData);  
  434. //   canvasData=negatives(canvasData);  
  435.   
  436.     context.putImageData(canvasData, 0, 0); // at coords 0,0  
  437.   };  
  438.     
  439.     
  440.   document.getElementById('spread').onclick=setSpread;  
  441.   function setSpread()  
  442.   {  
  443.         canvas.width  = img.width;  
  444.         canvas.height = img.height;  
  445.         var context = canvas.getContext("2d");  
  446.         context.drawImage(img, 0, 0);  
  447.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  448.         canvasData=spread(canvasData);  
  449.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  450.   }  
  451.   document.getElementById('gray').onclick=setGray;  
  452.   function setGray()  
  453.   {  
  454.         canvas.width  = img.width;  
  455.         canvas.height = img.height;  
  456.         var context = canvas.getContext("2d");  
  457.         context.drawImage(img, 0, 0);  
  458.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  459.         canvasData=gray(canvasData);   
  460.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  461.   }  
  462.   document.getElementById('old').onclick=setOld;  
  463.   function setOld()  
  464.   {  
  465.         canvas.width  = img.width;  
  466.         canvas.height = img.height;  
  467.         var context = canvas.getContext("2d");  
  468.         context.drawImage(img, 0, 0);  
  469.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  470.          canvasData=old(canvasData);  
  471.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  472.   }  
  473.   
  474.   
  475.   document.getElementById('cameo').onclick=setCameo;  
  476.   function setCameo()  
  477.   {  
  478.         canvas.width  = img.width;  
  479.         canvas.height = img.height;  
  480.         var context = canvas.getContext("2d");  
  481.         context.drawImage(img, 0, 0);  
  482.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  483.         canvasData=cameo(canvasData);  
  484.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  485.   }  
  486.   document.getElementById('comic').onclick=setComic;  
  487.   function setComic()  
  488.   {  
  489.         canvas.width  = img.width;  
  490.         canvas.height = img.height;  
  491.         var context = canvas.getContext("2d");  
  492.         context.drawImage(img, 0, 0);  
  493.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  494.        canvasData=comic(canvasData);  
  495.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  496.   }  
  497.   document.getElementById('black').onclick=setBlack;  
  498.   function setBlack()  
  499.   {  
  500.         canvas.width  = img.width;  
  501.         canvas.height = img.height;  
  502.         var context = canvas.getContext("2d");  
  503.         context.drawImage(img, 0, 0);  
  504.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  505.         canvasData=black(canvasData);  
  506.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  507.   }  
  508.   document.getElementById('negatives').onclick=setNegatives;  
  509.   function setNegatives()  
  510.   {  
  511.         canvas.width  = img.width;  
  512.         canvas.height = img.height;  
  513.         var context = canvas.getContext("2d");  
  514.         context.drawImage(img, 0, 0);  
  515.         var canvasData = context.getImageData(0, 0, canvas.width, canvas.height);    
  516.         canvasData=negatives(canvasData);  
  517.         context.putImageData(canvasData, 0, 0); // at coords 0,0  
  518.   }  
  519.     
  520. </script>  
  521. </body>  
  522. </html></code>  
posted @ 2018-07-19 10:51  dnoyeb  阅读(748)  评论(0编辑  收藏  举报