HTML5中增加的Canvas元素,配合JS灵活的语法,处理起图片变得异常简单,不需要在客户端用C/C++写一大堆代码,对于熟悉JS的程序员来说,只需要考虑处理图片的逻辑了。
canvas中如果想要处理图片就需要借助ImageData这个对象,就是将画布中某一区域中的图像以RGBA的方式保存下来,存成一个二维数组。
- ctx.getImageData( x, y, w, h) //获取ImageData
- ctx.putImageData( x, y, w, h) //将ImageData绘在画布上
写了个简单的处理图像的类,可以翻转/灰化/去色/高亮/设单色值
- /**
- * @author Norris Tong
- */
- var PS = function( config ){
- //$.extend( this, config );
- return this;
- }
- PS.prototype = {
- //将图像灰化
- gray : function( ctx, imageData ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- for (i=0; i<w; i++)
- {
- for (j=0; j<h; j++)
- {
- var index=(i*h+j) * 4;
- var red=imageData.data[index];
- var green=imageData.data[index+1];
- var blue=imageData.data[index+2];
- var alpha=imageData.data[index+3];
- var average=(red+green+blue)/3;
- ret.data[index]=average;
- ret.data[index+1]=average;
- ret.data[index+2]=average;
- ret.data[index+3]=alpha;
- }
- }
- return ret;
- },
- // 生成ImageData
- createImageData : function( ctx, ori, from, w, h ){
- var ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- from = from * w * 4;
- for (var i= 0 ; i< total; i++) {
- ret.data[ i ] = ori.data[ from + i ];
- }
- return ret;
- },
- //生成ImageData
- //对称图像反转
- createImageDataTurn : function( ctx, ori, from, w, h ){
- var ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- from = from * w * 4;
- for (var j=0; j<h; j++) {
- for (var i=0; i<w; i++) {
- var a = (j * w + i) * 4,
- b = from + a,
- c = (j * w + w- i) * 4;
- ret.data[ c++ ] = ori.data[ b++ ];
- ret.data[ c++ ] = ori.data[ b++ ];
- ret.data[ c++ ] = ori.data[ b++ ];
- ret.data[ c++ ] = ori.data[ b++ ];
- }
- }
- return ret;
- },
- //将整个图片设置为某一颜色值
- setColorR : function( ctx, imageData, n ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- for (var i=0; i<total; i +=4 ) {
- ret.data[i] = n; // imageData[ i ];
- ret.data[i+1]= imageData.data[ i + 1 ];
- ret.data[i+2]= imageData.data[ i + 2 ];
- ret.data[ i+3]= imageData.data[ i + 3 ];
- }
- return ret;
- },
- //将整个图片设置为某一颜色值
- setColorG : function( ctx, imageData, n ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- for (var i=0; i<total; i +=4 ) {
- var red=imageData.data[i],
- green=imageData.data[i+1],
- blue=imageData.data[i+2];
- var a = (red + green + blue) / 3;
- ret.data[i] = a;
- ret.data[i+1]= a + n;
- ret.data[i+2]= a;
- ret.data[ i+3]= imageData.data[ i + 3 ];
- }
- return ret;
- },
- //将整个图片设置为某一颜色值
- setColorB : function( ctx, imageData, n ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- for (var i=0; i<total; i +=4 ) {
- ret.data[i] = imageData.data[ i ];
- ret.data[i+1]= imageData.data[ i + 1 ];
- ret.data[i+2]= n;
- ret.data[ i+3]= imageData.data[ i + 3 ];
- }
- return ret;
- },
- //高亮整个图片
- highlight : function( ctx, imageData, n ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- for (var i=0; i<total; i +=4 ) {
- ret.data[i] = imageData.data[ i ] + n;
- ret.data[i+1]= imageData.data[ i + 1 ] + n;
- ret.data[i+2]= imageData.data[ i + 2 ] + n;
- ret.data[ i+3]= imageData.data[ i + 3 ];
- }
- return ret;
- },
- //去色 紫色 247, 0, 255
- removeColor : function( ctx, imageData, r, g, b ){
- var w = imageData.width,
- h = imageData.height,
- ret = ctx.createImageData( w, h );
- var total = w * h * 4;
- for (var i=0; i<total; i +=4 ) {
- var red=imageData.data[i],
- green=imageData.data[i+1],
- blue=imageData.data[i+2];
- //相等则全透明
- if ( r == red && green == g && blue == b ){
- ret.data[ i+3]= 0;
- }else{
- ret.data[i] = red;
- ret.data[i+1]= green;
- ret.data[i+2]= blue;
- ret.data[ i+3]= imageData.data[ i + 3 ];
- }
- }
- return ret;
- }
- };
- PS = new PS();
通过一系列操作,渲染好图像后,就需要借助如下的代码将画布中的图像保存成图片
- //将图像输出为base64压缩的字符串 默认为image/png
- var data = canvas.toDataURL();
- //删除字符串前的提示信息 "data:image/png;base64,"
- var b64 = data.substring( 22 );
- //POST到服务器上,生成图片
- $.post( "save.aspx" , { data : b64, name : filename }, function(){
- //OK
- });
save.aspx中的代码如下:
- protected void Page_Load(object sender, EventArgs e)
- {
- if (Request["name"] != null)
- {
- string name = Request["name"];
- String savePath = Server.MapPath("~/images/output/");
- try
- {
- FileStream fs = File.Create(savePath + "/" + name);
- byte[] bytes = Convert.FromBase64String(Request["data"]);
- fs.Write(bytes, 0, bytes.Length);
- fs.Close();
- }
- catch (Exception except)
- {
- }
- }
- }
PS: 由于沙箱的限制,想在浏览器端通过JS直接存为本地图片,似乎是不大可能,现在网上较为折中的方式为
window.location.href = "image/octet-stream" + data
但这种方式不能指定保存的文件名,在FF下默认是xxxxx.part