apicloud apicloud

注册
查看: 6918|回复: 16

[APP开发技巧] 纯js实现的滤镜功能

入门司机

UID:36764

主题:
78
帖子:
470
云币:
30083

中秋节托马斯全旋装逼侠我李白贼6

[APP开发技巧] 纯js实现的滤镜功能

6918 16 | 发表于 2015-8-17 16:42:26 |阅读模式 | |
看到有些同学需要滤镜功能,而官方的滤镜功能暂时又是那么强大,我就给大家分享一个纯js实现的滤镜功能基于canvas开发的滤镜功能,其实原理也很简单,不多说,上代码

// module: 滤镜模块
    var offscreenCanvas=document.createElement('canvas'),
        context=offscreenCanvas.getContext('2d');
    var image=new Image(),imageData,imageDataDefault,userPhoto=$('#userPhoto')[0];
    // image.crossOrigin="anonymous";
    image.src=photoData.fsDir;
    image.onload=function(){
        offscreenCanvas.width=image.width;
        offscreenCanvas.height=image.height;
        context.drawImage(image,0,0,image.width,image.height,0,0,offscreenCanvas.width,offscreenCanvas.height);
        imageData=context.getImageData(0,0,offscreenCanvas.width,offscreenCanvas.height);
        setImage();
        // selectFilter(5);
    };


首先,因为滤镜的处理过程是用户不需要感知的,所以创建一个离屏的canvas,以优化性能
然后,读取一张原图,这里可以做一些你想做的操作,显示图片呀,等等的,如下
function setImage(){
        if(image.width>image.height) $('head').append('<style>.b-tiezi__photo>img{ width: '+window.innerWidth+'px;}</style>');
        else if(image.width<image.height) $('head').append('<style>.b-tiezi__photo>img{ height: '+window.innerWidth+'px;}</style>');
        else $('head').append('<style>.b-tiezi__photo>img{ width: '+window.innerWidth+'px; height: '+window.innerWidth+'px;}</style>');
        userPhoto.src=photoData.base64;
        // alert(photoData.fsDir)
    }


接着,用户选择了某种滤镜的效果
// 选择滤镜效果
    // type = 1:负片 2:黑白 3:浮雕 4:马赛克 5:怀旧
    function selectFilter(type){
        $('#loading').show();
        // imageData=imageDataDefault;
        setTimeout(function(){
        context.drawImage(image,0,0,image.width,image.height,0,0,offscreenCanvas.width,offscreenCanvas.height);
        imageData=context.getImageData(0,0,offscreenCanvas.width,offscreenCanvas.height);
        switch(type){
            case 0: filterNone();break;
            case 1: filterFupian();break;
            case 2: filterHeibai();break;
            case 3: filterFudiao();break;
            case 4: filterMasaike();break;
            case 5: filterHuaijiu();break;
        }
        context.putImageData(imageData,0,0);
        userPhoto.src=offscreenCanvas.toDataURL();  //这里是把滤镜处理后的图像转化为base64,可用于上传和展示
        },100);

    }


这里获取到原图的对象,绘制到离屏的canvas里面,转化为imageData,然后进行data的处理
下面我实现了5种常见的滤镜,自己也可以扩展想要的滤镜效果

// 负片滤镜
    function filterFupian(){
        var data=imageData.data;
        for(var i=0;i<data.length-4;i+=4){
            data[i]=255-data[i];
            data[i+1]=255-data[i+1];
            data[i+2]=255-data[i+2];
        }
    }

    // 黑白滤镜
    function filterHeibai(){
        var data=imageData.data;
        var average;
        for(var i=0;i<data.length-4;i+=4){
            average=( data[i] + data[i+1] + data[i+2] ) / 3;
            data[i]=average;
            data[i+1]=average;
            data[i+2]=average;
        }
    }

    // 浮雕滤镜
    function filterFudiao(){
        var data=imageData.data,
            width=imageData.width,
            length=data.length;

        for(var i=0;i<length;i++){
            if(i<=length-width*4){
                if( (i+1)%4 !==0 ){
                    if( (i+4)%(width*4) ==0 ){
                        data[i]=data[i-4];
                        data[i+1]=data[i-3];
                        data[i+2]=data[i-2];
                        data[i+3]=data[i-1];
                        i+=4;
                    }else{
                        data[i]=255/2+2*data[i]-data[i+4]-data[i+width*4];
                    }
                }
            }else{
                if( (i+1)%4!==0 ) data[i]=data[i-width*4];
            }
        }
    }

    // 马赛克滤镜
    function filterMasaike(){
        var data=imageData.data;
        var mosaic={x:10,y:10};
        for(var i=0;i<image.height;i+=mosaic.y){
            for(var j=0;j<image.width;j+=mosaic.x){
                var num=Math.random();
                var randomPixel={
                    x:Math.floor(num*mosaic.x+i),
                    y:Math.floor(num*mosaic.y+j)
                };

                for(var k=j;k<j+mosaic.x;k++){
                    for(var l=i;l<i+mosaic.y;l++){
                        data[(l*image.width+k)*4]=data[(randomPixel.x*image.width+randomPixel.y)*4];
                        data[(l*image.width+k)*4+1]=data[(randomPixel.x*image.width+randomPixel.y)*4+1];
                        data[(l*image.width+k)*4+2]=data[(randomPixel.x*image.width+randomPixel.y)*4+2];
                        data[(l*image.width+k)*4+3]=data[(randomPixel.x*image.width+randomPixel.y)*4+3];
                    }
                }
            }
        }
    }

    // 怀旧滤镜
    function filterHuaijiu(){
        var data=imageData.data;
        for(var i=0;i<data.length-4;i+=4){
            data[i]=data[i]*0.393 + data[i+1]*0.769 + data[i+2]*0.189;
            data[i+1]=data[i]*0.349 + data[i+1]*0.686 + data[i+2]*0.168;
            data[i+2]=data[i]*0.272 + data[i+1]*0.534 + data[i+2]*0.131;
        }
    }


分享就到这里了,要认真看代码哦,加油


3

查看全部评分

主题:
1102
帖子:
5126
云币:
2147214880

圣诞节捣蛋鬼APICloud大会专属勋章足球狗儿童节快乐

发表于 2015-8-17 16:43:13 |
感谢版主分享!

新手上路

UID:132088

主题:
2
帖子:
39
云币:
113
发表于 2015-8-17 16:45:13 |
很不错,支持一下!

新手上路

UID:111779

主题:
14
帖子:
127
云币:
67
发表于 2015-8-17 16:45:22 |
小草,好吊

主题:
73
帖子:
4727
云币:
1469

足球狗狗年旺旺旺APICloud粉丝连续签到100天APICloud毕业勋章APICloud骨灰粉模块开发者签到党土豪志愿者一周年中秋节社会摇圣诞节老司机你吃屎!首长好!我还是个孩子!托马斯全旋女朋友不想上班!装逼侠单身狗超人SB侠

发表于 2015-8-17 16:46:08 |
感谢版主分享!

主题:
73
帖子:
4727
云币:
1469

足球狗狗年旺旺旺APICloud粉丝连续签到100天APICloud毕业勋章APICloud骨灰粉模块开发者签到党土豪志愿者一周年中秋节社会摇圣诞节老司机你吃屎!首长好!我还是个孩子!托马斯全旋女朋友不想上班!装逼侠单身狗超人SB侠

发表于 2015-8-17 16:47:23 |
:@:@:@:@:@:@:@:@::@:@::@

主题:
13
帖子:
80
云币:
319
发表于 2015-8-17 16:48:06 |
好东西  mark

主题:
21
帖子:
514
云币:
578

APICloud粉丝APICloud毕业勋章一周年圣诞节托马斯全旋女朋友

发表于 2015-8-17 16:48:06 |
好棒好棒!谢谢分享!

主题:
14
帖子:
318
云币:
2318

APICloud粉丝圣诞节

发表于 2015-8-17 16:48:25 |
好东西,回头试试

主题:
0
帖子:
39
云币:
108
发表于 2015-8-17 17:51:43 |
能否上张图!!!!
12下一页
您需要登录后才可以回帖 登录 | 立即注册

快速回复 返回顶部 返回列表