zoukankan      html  css  js  c++  java
  • 转《canvas实现滤镜效果》

    [html] view plain copy
     
    1. <code class="language-html"><html>  
    2. <head>  
    3.     <style type="text/css">  
    4.   
    5.   
    6.   
    7.     form, input { 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>  
  • 相关阅读:
    【Others】2048逻辑整理
    【MySQL】MySQL学习笔记(一)
    【PHP】对TP中session的理解
    【Python基础】python 作用域
    【phantomJs + selenium】动态cookie,数据采集记录
    [ZJOI2015][LOJ2137]诸神眷顾的幻想乡(广义SAM)
    [CF235C]Cyclical Quest(SAM)
    [BZOJ1426]收集邮票(概率期望dp)
    [HDU5421]Victor and String(PAM)
    [CF932G]Palindrome Partition(PAM回文划分dp)
  • 原文地址:https://www.cnblogs.com/ckAng/p/9334519.html
Copyright © 2011-2022 走看看