canvas图像处理汇总

一、canvas的情况

canvas自从出来了之后,在前端的图像处理上面提供了各种各样的遍历,虽然很多的操作其实都是要应用到算法的,但是这个也给前端提供了很多的可能性,其中最终要的一个canvas函数(至少我认为)就是getImageData,这个函数可以提取图像每个像素的RGBA值。因为有这个函数所有才有丰富多彩的canvas图像处理。

二、预备知识

 2.1 获取一个canvas对象

<canvas id="test"></canvas>
<script>
    var test = document.querySelector("#test");// 方法一
    var test_1=document.getElementById("test");// 方法二
    console.log(test);
    console.log(test_1);
</script>

2.2 创建一个画布的空间类型(2D,3D)

创建一个2D的画布

var ctx = test.getContext("2d");

2.3 getImageData对象

getImageData对象可以获取画布中的图片对应的所有像素的RGBA值,这个有利于我们对图片进行重新的计算。在使用这个属性的时候,需要配置好HTTP的访问环境。

2.4 Uint8ClampedArray

这个代表的是一个无类型8位的字符串,也就是说明最多存储到255

2.5 Uint8ClampedArray与getImageData对象

Uint8ClampedArray包含在getImageData对象中,getImageData除了有Uint8ClampedArray之外,还有获取图片数据的长度和宽度。

三、多种图片效果canvas实现

1. 原图

2. 反色(负片)效果

3. 去色效果

4. 单色效果

5. 中国版画效果

6. 高斯模糊效果

7. 浮雕效果与刻雕效果

3.1 原图

通过canvas来渲染原图,首选我们在网上随意找一张图片。

  ·

window.onload = function () {
        var img = new Image();
        img.src = "rx.jpg";
        // 加载完成图片之后才能够执行canvas的操作
        img.onload = function () {
            var canvas = document.querySelector("#canvas");
            var cxt = canvas.getContext("2d");
            canvas.width=293;
            canvas.height=220;
            cxt.drawImage(img, 0, 0, 293, 220);
        }
    }

其中canvas的width,height属性都是必须要设置的,不设置的话,canvas会采用默认的width=300,height=150来设置图片。

3.2 反色(负片)效果

图片反色的原理其实很简单不多做解释:将图片中的每一个元素进行如下的公式运算就可以得到最终的结果

 window.onload = function () {
        var img = new Image();
        img.src = "rx.jpg";
        img.onload = function () {
            var canvas = document.querySelector("#canvas");
            var cxt = canvas.getContext("2d");
            canvas.width = 293;
            canvas.height = 220;
            cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
            var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
            var imageData_length = imageData.data.length / 4;
            // 解析之后进行算法运算
            for (var i = 0; i < imageData_length; i++) {
                imageData.data[i * 4] = 255 - imageData.data[i * 4];
                imageData.data[i * 4 + 1] = 255 - imageData.data[i * 4 + 1];
                imageData.data[i * 4 + 2] = 255 - imageData.data[i * 4 + 2];
            }
            cxt.putImageData(imageData, 0, 0);

        }
    }

运行之后的效果如下:

3.3 去色效果

这里说的去色效果与第二种效果不同的是,去色效果相当于就是老旧相机拍出来的黑白照片。

要得到去色效果的照片有很多种方法,但是卤煮比较推崇的做法是采用基于人眼感觉的加权平均数来实现,这个算法的原理是采用人眼对RGB不同颜色的敏感程度不同,然后通过得出的加权平均数来运算出最后的结果

Gray = (Red * 0.3 + Green * 0.59 + Blue * 0.11)

代码如下实现:

 window.onload = function () {
        var img = new Image();
        img.src = "rx.jpg";
        img.onload = function () {
            var canvas = document.querySelector("#canvas");
            var cxt = canvas.getContext("2d");
            canvas.width = 293;
            canvas.height = 220;
            cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
            var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
            var imageData_length = imageData.data.length / 4;
            // 解析之后进行算法运算
            for (var i = 0; i < imageData_length; i++) {
                var red = imageData.data[i * 4];
                var green = imageData.data[i * 4 + 1];
                var blue = imageData.data[i * 4 + 2];
                var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
                imageData.data[i * 4] = gray;
                imageData.data[i * 4 + 1] = gray;
                imageData.data[i * 4 + 2] = gray;
            }
            cxt.putImageData(imageData, 0, 0);

        }
    }

运行效果如下:

3.4 单色效果

单颜色效果原理就是将当前像素的其他色值去除。

假设我们要实现的单颜色效果是红色,那么实现的代码如下:

 window.onload = function () {
        var img = new Image();
        img.src = "rx.jpg";
        img.onload = function () {
            var canvas = document.querySelector("#canvas");
            var cxt = canvas.getContext("2d");
            canvas.width = 293;
            canvas.height = 220;
            cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
            var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
            var imageData_length = imageData.data.length / 4;
            // 解析之后进行算法运算
            for (var i = 0; i < imageData_length; i++) {
                imageData.data[i * 4 + 1] = 0;
                imageData.data[i * 4 + 2] = 0;
            }
            cxt.putImageData(imageData, 0, 0);

        }
    }

效果图:

3.5 中国版画效果

中国版画不同于去色和反色的效果,在中国版画的效果中除了黑就是白色,不存在其他的颜色,下面就是一张传统的中国版画的效果。

这个的实现算法比较的灵活一般是根据你要得到的效果来进行参数配置的,原理就是通过判断当前元素的色值是否高于这个给定值,高于我们就显示为黑色,小于我们就显示为白色这样的一种方法来实现的。

按照卤煮一般的设置值来说会设置为126.因为126是2的8次方的中间数。相对来说比较的对称

实现的代码如下:

window.onload = function () {
        var img = new Image();
        img.src = "rx.jpg";
        img.onload = function () {
            var canvas = document.querySelector("#canvas");
            var cxt = canvas.getContext("2d");
            canvas.width = 293;
            canvas.height = 220;
            cxt.drawImage(img, 0, 0, canvas.width, canvas.height);
            var imageData = cxt.getImageData(0, 0, canvas.width, canvas.height);
            var imageData_length = imageData.data.length / 4;
            // 解析之后进行算法运算
            for (var i = 0; i < imageData_length; i++) {
                var red = imageData.data[i * 4];
                var green = imageData.data[i * 4 + 1];
                var blue = imageData.data[i * 4 + 2];
                var gray = 0.3 * red + 0.59 * green + 0.11 * blue;
                var new_black;
                if (gray > 126) {
                    new_black = 255;
                } else {
                    new_black = 0;
                }
                imageData.data[i * 4] = new_black;
                imageData.data[i * 4 + 1] = new_black;
                imageData.data[i * 4 + 2] = new_black;
            }
            cxt.putImageData(imageData, 0, 0);

        }
    }

运行的效果如下:

如果是我们要渲染更多的黑颜色的话,我们应该要将值调高,反之将其调低,下面我们把值调到150运行一下:

3.6 高斯模糊效果

高斯模糊是一种两维的卷积模糊操作,简单的介绍就是通过让图片的每个像素与四周的像素按照某种权重进行分布求值,要了解具体的同学可以戳戳这里

这里我们就展示结论,推导不做介绍(二维高斯分布函数):

我们直接贴出实现的代码:

function gaussBlur(imgData) {
    console.log(imgData);
    var pixes = imgData.data;
    var width = imgData.width;
    var height = imgData.height;
    var gaussMatrix = [],
        gaussSum = 0,
        x, y,
        r, g, b, a,
        i, j, k, len;

    var radius = 30;
    var sigma = 5;

    a = 1 / (Math.sqrt(2 * Math.PI) * sigma);
    b = -1 / (2 * sigma * sigma);
    //生成高斯矩阵
    for (i = 0, x = -radius; x <= radius; x++, i++){
        g = a * Math.exp(b * x * x);
        gaussMatrix[i] = g;
        gaussSum += g;

    }
    //归一化, 保证高斯矩阵的值在[0,1]之间
    for (i = 0, len = gaussMatrix.length; i < len; i++) {
        gaussMatrix[i] /= gaussSum;
    }
    //x 方向一维高斯运算
    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            r = g = b = a = 0;
            gaussSum = 0;
            for(j = -radius; j <= radius; j++){
                k = x + j;
                if(k >= 0 && k < width){//确保 k 没超出 x 的范围
                    //r,g,b,a 四个一组
                    i = (y * width + k) * 4;
                    r += pixes[i] * gaussMatrix[j + radius];
                    g += pixes[i + 1] * gaussMatrix[j + radius];
                    b += pixes[i + 2] * gaussMatrix[j + radius];
                    // a += pixes[i + 3] * gaussMatrix[j];
                    gaussSum += gaussMatrix[j + radius];
                }
            }
            i = (y * width + x) * 4;
            // 除以 gaussSum 是为了消除处于边缘的像素, 高斯运算不足的问题
            // console.log(gaussSum)
            pixes[i] = r / gaussSum;
            pixes[i + 1] = g / gaussSum;
            pixes[i + 2] = b / gaussSum;
            // pixes[i + 3] = a ;
        }
    }
    //y 方向一维高斯运算
    for (x = 0; x < width; x++) {
        for (y = 0; y < height; y++) {
            r = g = b = a = 0;
            gaussSum = 0;
            for(j = -radius; j <= radius; j++){
                k = y + j;
                if(k >= 0 && k < height){//确保 k 没超出 y 的范围
                    i = (k * width + x) * 4;
                    r += pixes[i] * gaussMatrix[j + radius];
                    g += pixes[i + 1] * gaussMatrix[j + radius];
                    b += pixes[i + 2] * gaussMatrix[j + radius];
                    // a += pixes[i + 3] * gaussMatrix[j];
                    gaussSum += gaussMatrix[j + radius];
                }
            }
            i = (y * width + x) * 4;
            pixes[i] = r / gaussSum;
            pixes[i + 1] = g / gaussSum;
            pixes[i + 2] = b / gaussSum;
        }
    }
    console.log(imgData);
    return imgData;
}

运行之后的效果如下:

3.7 浮雕效果与刻雕效果

这里要感谢CSDN的算法专家gloomyfish,他的博文给我提供了一个好的思路,同时根据他的一个代码逻辑我们可以得出如下的公式:

    (C常量,Xa后一个像素的RGB,Xb前一个像素的RGB)

其中color代表的是最后的色值,Xa和Xb代表的是当前像素前后两点的RGB(中的某一个值),C代表的是一个常量【根据你的具体需要来定】

原理就是将某个像素与周边的差值较大的检测出来,然后替换成为255,一般我们将这个常量C设置成为128【255的一半】

/**
     * after pixel value - before pixel value + 128
     * 代码引用自 gloomyfish
     * 浮雕效果
     */
    reliefProcess: function(context, canvasData) {
        //caontext 画布对象  document.querySelector().getContext("2d");
        // conavas document.querySelector().getContext("2d").getImageData();
        console.log("Canvas Filter - relief process");
        var tempCanvasData = this.copyImageData(context, canvasData);
        for ( var x = 0; x < tempCanvasData.width-1; x++)
        {
            for ( var y = 0; y < tempCanvasData.height-1; y++)
            {

                // Index of the pixel in the array
                var idx = (x + y * tempCanvasData.width) * 4;
                var bidx = ((x-1) + y * tempCanvasData.width) * 4;
                var aidx = ((x+1) + y * tempCanvasData.width) * 4;

                // calculate new RGB value
                var nr = tempCanvasData.data[aidx + 0] - tempCanvasData.data[bidx + 0] + 128;
                var ng = tempCanvasData.data[aidx + 1] - tempCanvasData.data[bidx + 1] + 128;
                var nb = tempCanvasData.data[aidx + 2] - tempCanvasData.data[bidx + 2] + 128;
                nr = (nr < 0) ? 0 : ((nr >255) ? 255 : nr);
                ng = (ng < 0) ? 0 : ((ng >255) ? 255 : ng);
                nb = (nb < 0) ? 0 : ((nb >255) ? 255 : nb);

                // assign new pixel value
                canvasData.data[idx + 0] = nr; // Red channel
                canvasData.data[idx + 1] = ng; // Green channel
                canvasData.data[idx + 2] = nb; // Blue channel
                canvasData.data[idx + 3] = 255; // Alpha channel
            }
        }
    },

运行的图像如下:

 其中常量的数值越大,浮雕的颜色越浅,反之加深。我们把它设置到50看下效果:

刻雕效果与浮雕效果基本一样,就是要调整公式里面的Xa和Xb的位置,调整如下:

四、小结

由于canvas涉及到的知识点比较的深奥,所以里面有很多的内容没法再这里一一的进行说明,这一篇文章也就是对于canvas实际应用的一个简单的说明,在图形学方面,磨皮处理和高通滤波,低通滤波等等方面的处理还没有实现,在一些粒子化,动画,碰撞方面也不能一一道来,深表遗憾

原文地址:https://www.cnblogs.com/st-leslie/p/8317850.html

时间: 2024-11-09 01:01:10

canvas图像处理汇总的相关文章

canvas图像处理

最近在慕课网看到一个canvas图像处理的教程,现在总结一下. 不多说其它了,开始说代码吧. 以下canvasA是原图的画布,canvasB是处理后的图像的画布 RGB通道过滤 RGB通道过滤 function filter(){ var imageData = contextA.getImageData(0,0,canvasA.width,canvasA.height); //Uncaught SecurityError: Failed to execute 'getImageData' on

HTML5标签canvas图像处理

摘要: canvas可以读取图片后,使用drawImage方法在画布内进行重绘.本文介绍canvas的图像处理 drawImage drawImage() 方法在画布上绘制图像.画布或视频.drawImage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸. 语法 在画布上定位图像: context.drawImage(img,x,y); 在画布上定位图像,并规定图像的宽度和高度: context.drawImage(img,x,y,width,height); 剪切图像,并在

HTML5实验室简介之Canvas图像处理(一)

作为一个前端,想必对HTML5都不陌生,特别是移动端,如今已经比较火了,捞金量远胜于PC端,与其说HTML5是一项Web新时代革命性的技术,不如说其是现代化Web应用的新理念:一方面结合JavaScript,前端的羽翼更加丰满:另一方面,跨终端将Web应用推向了一个新的高度:你看到的视觉将更加高端.大气.炫酷:你浏览时的交互体验将更加人性化:你的设备消耗大大降低,运行更流畅:总之,你会惊叹,同时你会很舒服!而这一切都是基于HTML5的! 作为一个小前端,才疏学浅,个人小站(花满楼:http://

基于canvas图像处理的图片展示demo

position:static(静态定位) 当position属性定义为static时,可以将元素定义为静态位置,所谓静态位置就是各个元素在HTML文档流中应有的位置 podisition定位问题.所以当没有定义position属性时,并不说明该元素没有自己的位置,它会遵循默认显示为静态位置,在静态定位状态下无法通过坐标值(top,left,right,bottom)来改变它的位置. position:absolute(绝对定位) 当position属性定义为absolute时,元素会脱离文档流

Atitit.attilax软件研发与项目管理之道

1. 前言4 2. 鸣谢4 3. Genesis 创世记4 4. 软件发展史4 5. 箴言4 6. 使徒行传 4 7. attilax书 4 8. 启示录4 9. 技术标准的7条原则4 9.1. 后向兼容性4 10. 软件之道5 11. 计算机科学导论(原书第3版5 12. 数字电路5 13. 通用管理学5 14. 项目管理5 15. 团队建设与人力资源管理5 16. 软件工程5 16.1. 软件编写5 16.2. 软件构件化理论与技术5 16.3. 软件与编程理论6 16.4. 理论原则6 1

Delphi基本图像处理方法汇总

这篇文章主要介绍了Delphi基本图像处理方法,实例汇总了Delphi操作图像实现浮雕.反色.模糊.翻转等常用效果的方法,非常具有实用价值,需要的朋友可以参考下 本文实例汇总了Delphi基本图像处理方法.分享给大家供大家参考.具体分析如下: //浮雕 procedure Emboss(SrcBmp,DestBmp:TBitmap;AzimuthChange:integer);overload; var i, j, Gray, Azimuthvalue, R, G, B: integer; Sr

Canvas绘图方法和图像处理方法(转)

转自:http://javascript.ruanyifeng.com/htmlapi/canvas.html 概述 Canvas API(画布)用于在网页实时生成图像,并且可以操作图像内容,基本上它是一个可以用JavaScript操作的位图(bitmap). 使用前,首先需要新建一个canvas网页元素. <canvas id="myCanvas" width="400" height="200"> 您的浏览器不支持canvas!

Android图像处理(二)--Paint,Canvas,ColorMatrix详细

android开发中可能经常会用到这些东西; 一.介绍 Paint:画笔 Canvas:画布 Matrix:变换矩阵 Paint 根据我们要画的类型,我们可以选择不同的笔,比如大气磅礴的山水画,我们可以选择大头的毛笔:细腻入微的肖像画我们可以选择尖头的铅笔.并且根据我们想要的效果,我们在绘画的时候,还会选择不同的颜料或不同颜色的笔: 那么在程序中,Paint 就足以满足以上所有的需要,我们可以根据我们自己的需要去自行设置我们画笔的属性,首先来看看都能设置哪些属性: Public Construc

【一天一个canvas】图像处理教程(十二)

Canvas是一个功能相当强大的画布,任由你去书写,当然,他也支持了图像处理的功能. drawImage(image,Dx,Dy)://用于显示,有时会超出 drawImage(image,Dx,Dy,Dw,Dh)://用于缩放 drawImage(image,Sx,Sy,Sw,Sh,Dx,Dy,Dw,Sh)://用于剪裁.缩放.显示 注:image是一个图像对象: Dx是画布中的x坐标,Dy是画布中的y坐标,Dw是图像在画布中的宽度,Dy是图像在画布中的高度,Sx,Sy,Sw,Sh分别是原图像