利用HTML5中Canvas处理并存储图片

zsh 2013-05-30

      HTML5中增加的Canvas元素,配合JS灵活的语法,处理起图片变得异常简单,不需要在客户端用C/C++写一大堆代码,对于熟悉JS的程序员来说,只需要考虑处理图片的逻辑了。


      canvas中如果想要处理图片就需要借助ImageData这个对象,就是将画布中某一区域中的图像以RGBA的方式保存下来,存成一个二维数组。

    

[javascript] view plaincopy
  1. ctx.getImageData( x, y, w, h)      //获取ImageData  
  2. ctx.putImageData( x, y, w, h)     //将ImageData绘在画布上  

   

     写了个简单的处理图像的类,可以翻转/灰化/去色/高亮/设单色值

    

[javascript] view plaincopy
  1. /** 
  2.  * @author Norris Tong 
  3.  */  
  4.   
  5. var PS = function( config ){  
  6.     //$.extend( this, config );  
  7.     return this;  
  8. }  
  9.   
  10. PS.prototype = {  
  11.       
  12.     //将图像灰化  
  13.     gray        : function( ctx, imageData ){  
  14.         var w = imageData.width,  
  15.                 h = imageData.height,  
  16.                 ret = ctx.createImageData( w, h );  
  17.           
  18.         for (i=0; i<w; i++)  
  19.         {  
  20.             for (j=0; j<h; j++)  
  21.             {  
  22.                 var index=(i*h+j) * 4;  
  23.               
  24.                 var red=imageData.data[index];  
  25.                 var green=imageData.data[index+1];  
  26.                 var blue=imageData.data[index+2];  
  27.                 var alpha=imageData.data[index+3];  
  28.               
  29.                 var average=(red+green+blue)/3;  
  30.               
  31.                 ret.data[index]=average;  
  32.                 ret.data[index+1]=average;  
  33.                 ret.data[index+2]=average;  
  34.                 ret.data[index+3]=alpha;  
  35.               }  
  36.         }  
  37.           
  38.         return ret;  
  39.     },  
  40.       
  41.     // 生成ImageData  
  42.     createImageData : function( ctx, ori, from, w, h ){  
  43.             var ret = ctx.createImageData( w, h );  
  44.             var total = w * h * 4;  
  45.             from = from * w * 4;  
  46.             for (var i= 0 ; i< total; i++) {  
  47.                 ret.data[ i ] = ori.data[ from + i ];  
  48.             }  
  49.               
  50.             return ret;  
  51.     },  
  52.       
  53.     //生成ImageData  
  54.     //对称图像反转  
  55.      createImageDataTurn    : function( ctx, ori, from, w, h ){  
  56.             var ret = ctx.createImageData( w, h );  
  57.             var total = w * h * 4;  
  58.             from = from * w * 4;  
  59.             for (var j=0; j<h; j++) {  
  60.                 for (var i=0; i<w; i++) {  
  61.                     var  a =  (j * w + i) * 4,  
  62.                             b = from + a,  
  63.                             c =  (j * w + w- i) * 4;  
  64.                               
  65.                     ret.data[ c++ ] = ori.data[ b++ ];  
  66.                     ret.data[ c++ ] = ori.data[ b++ ];  
  67.                     ret.data[ c++ ] = ori.data[ b++ ];  
  68.                     ret.data[ c++ ] = ori.data[ b++ ];  
  69.                 }  
  70.             }  
  71.               
  72.             return ret;  
  73.     },  
  74.       
  75.     //将整个图片设置为某一颜色值  
  76.      setColorR  : function( ctx, imageData, n ){  
  77.         var w = imageData.width,  
  78.                 h = imageData.height,  
  79.                 ret = ctx.createImageData( w, h );  
  80.           
  81.         var total = w * h * 4;  
  82.           
  83.         for (var i=0; i<total; i +=4 ) {  
  84.               
  85.             ret.data[i]  = n; // imageData[ i ];  
  86.             ret.data[i+1]= imageData.data[ i + 1 ];  
  87.             ret.data[i+2]= imageData.data[ i + 2 ];  
  88.             ret.data[ i+3]= imageData.data[ i + 3 ];  
  89.         }     
  90.           
  91.         return ret;  
  92.     },  
  93.       
  94.     //将整个图片设置为某一颜色值  
  95.      setColorG  : function( ctx, imageData, n ){  
  96.         var w = imageData.width,  
  97.                 h = imageData.height,  
  98.                 ret = ctx.createImageData( w, h );  
  99.           
  100.         var total = w * h * 4;  
  101.           
  102.         for (var i=0; i<total; i +=4 ) {  
  103.             var red=imageData.data[i],  
  104.                 green=imageData.data[i+1],  
  105.                 blue=imageData.data[i+2];  
  106.               
  107.             var a = (red + green + blue) / 3;  
  108.                   
  109.             ret.data[i]  = a;  
  110.             ret.data[i+1]= a + n;  
  111.             ret.data[i+2]= a;  
  112.             ret.data[ i+3]= imageData.data[ i + 3 ];  
  113.         }     
  114.           
  115.         return ret;  
  116.     },  
  117.       
  118.     //将整个图片设置为某一颜色值  
  119.      setColorB  : function( ctx, imageData, n ){  
  120.         var w = imageData.width,  
  121.                 h = imageData.height,  
  122.                 ret = ctx.createImageData( w, h );  
  123.           
  124.         var total = w * h * 4;  
  125.           
  126.         for (var i=0; i<total; i +=4 ) {  
  127.               
  128.             ret.data[i]  = imageData.data[ i ];  
  129.             ret.data[i+1]= imageData.data[ i + 1 ];  
  130.             ret.data[i+2]= n;  
  131.             ret.data[ i+3]= imageData.data[ i + 3 ];  
  132.         }     
  133.           
  134.         return ret;  
  135.     },  
  136.       
  137.     //高亮整个图片  
  138.      highlight  : function( ctx, imageData, n ){  
  139.         var w = imageData.width,  
  140.                 h = imageData.height,  
  141.                 ret = ctx.createImageData( w, h );  
  142.           
  143.         var total = w * h * 4;  
  144.           
  145.         for (var i=0; i<total; i +=4 ) {  
  146.               
  147.             ret.data[i]  = imageData.data[ i ] + n;  
  148.             ret.data[i+1]= imageData.data[ i + 1 ] + n;  
  149.             ret.data[i+2]= imageData.data[ i + 2 ] + n;  
  150.             ret.data[ i+3]= imageData.data[ i + 3 ];  
  151.         }     
  152.           
  153.         return ret;  
  154.     },  
  155.       
  156.     //去色   紫色 247, 0, 255  
  157.      removeColor    : function( ctx, imageData, r, g, b ){  
  158.         var w = imageData.width,  
  159.                 h = imageData.height,  
  160.                 ret = ctx.createImageData( w, h );  
  161.           
  162.         var total = w * h * 4;  
  163.           
  164.         for (var i=0; i<total; i +=4 ) {  
  165.             var red=imageData.data[i],  
  166.                 green=imageData.data[i+1],  
  167.                 blue=imageData.data[i+2];  
  168.               
  169.             //相等则全透明      
  170.             if ( r == red && green == g && blue == b ){  
  171.                 ret.data[ i+3]= 0;  
  172.             }else{  
  173.                 ret.data[i]  = red;  
  174.                 ret.data[i+1]= green;  
  175.                 ret.data[i+2]= blue;  
  176.                 ret.data[ i+3]= imageData.data[ i + 3 ];  
  177.             }  
  178.         }     
  179.           
  180.         return ret;  
  181.     }                     
  182.       
  183. };  
  184.   
  185. PS = new PS();  

     通过一系列操作,渲染好图像后,就需要借助如下的代码将画布中的图像保存成图片

    

[c-sharp] view plaincopy
  1. //将图像输出为base64压缩的字符串  默认为image/png  
  2. var data = canvas.toDataURL();                      
  3. //删除字符串前的提示信息 "data:image/png;base64,"  
  4. var b64 = data.substring( 22 );  
  5. //POST到服务器上,生成图片                      
  6. $.post( "save.aspx" , { data : b64, name : filename }, function(){  
  7.     //OK  
  8. });  

    

    save.aspx中的代码如下:

   

[c-sharp] view plaincopy
  1. protected void Page_Load(object sender, EventArgs e)  
  2. {  
  3.     if (Request["name"] != null)  
  4.     {  
  5.         string name = Request["name"];  
  6.   
  7.         String savePath = Server.MapPath("~/images/output/");  
  8.   
  9.         try  
  10.         {  
  11.             FileStream fs = File.Create(savePath + "/" + name);  
  12.   
  13.             byte[] bytes = Convert.FromBase64String(Request["data"]);  
  14.   
  15.             fs.Write(bytes, 0, bytes.Length);  
  16.             fs.Close();  
  17.         }  
  18.         catch (Exception except)  
  19.         {  
  20.         }  
  21.   
  22.     }  
  23. }  

   PS: 由于沙箱的限制,想在浏览器端通过JS直接存为本地图片,似乎是不大可能,现在网上较为折中的方式为

   window.location.href = "image/octet-stream" + data

   但这种方式不能指定保存的文件名,在FF下默认是xxxxx.part

   参照 : http://www.nihilogic.dk/labs/canvas2image/

相关推荐