HTML5 Canvas开发详解(4) -- 变形/像素操作

2022-04-07 15:58:43 浏览数 (1)

1. 变形操作

1.1 图形平移

语法:

代码语言:javascript复制
//x:表示图形在x轴方向移动的距离
//y:表示图形在y轴方向移动的距离
cxt.translate(x, y);

注:对于Canvas来说,“状态”都必须在“动作”之前定义。在默认情况下,Canvas会把所有绘制的图形都保留下来,如果不想保留之前绘制的图形,在绘制新图形之前需要把这个Canvas清空,然后再去绘制新的图形。

1.2 图形缩放

语法:

代码语言:javascript复制
//x:表示图形在x轴方向的缩放倍数
//y:表示图形在y轴方向的缩放倍数
//当x或y取值0~1之间时,图形进行缩小;取值大于1时,图形进行放大
cxt.scale(x, y);

注:scale()方法会改变图形的以下几点:

1)左上角坐标;

2)宽度或高度;

3)线条宽度。

1.3 图形旋转

语法:

代码语言:javascript复制
//angle:表示图形旋转饿角度,取值为-Math.PI*2 ~ Math.PI*2
//当angle < 0时,图形逆时针旋转,当angle > 0 时,图形顺时针旋转
cxt.rotate(angle);

默认情况下,图形旋转是以Canvas坐标原点为旋转中心的,如果我们想要以某一点为旋转中心,可以先使用translate(x, y),然后再使用rotate()方法。

在实际开发中,可以使用translate()方法结合图形的长宽将旋转中心移动到图形中心上。

变形操作处了可以用于图形,也可以用于文字和图片。

2. 像素操作

2.1 获取一张图片的像素数据

语法:

代码语言:javascript复制
//x、y表示所选图片区域的坐标
//width、height表示所选图片区域的宽度和高度
let imgData = cxt.getImageData(x, y, width, height);
let data = imgData.data;

getImageData()方法返回一个canvasPixelArray对象,该对象有个data属性,是用来保存一张图片像素数据的数组,数组取值如[r1, g1, b1, a1, r2, g2, b2, a2, ......]。

2.2 输出一张图片的像素数据

语法:

代码语言:javascript复制
//image:表示重新绘制的图形,也就是用getImageData()方法获取的canvasPixelArray对象
//x、y:表示重新绘制图形左上角饿横坐标和纵坐标
cxt.putImageData(image, x, y);

2.3 反转效果

反转效果,也叫“颜色反转”,是指图片颜色颠倒效果。实际算法是:红、绿、蓝这三个通道的像素取各自的相反值,即255-原值。

语法:

代码语言:javascript复制
for(let i = 0; i < data.length; i  = 4){
    data[i   0] = 255 - data[i   0];
    data[i   1] = 255 - data[i   1];
    data[i   2] = 255 - data[i   2];
 }

这节相关代码继续添加到 HTML5 Canvas开发详解(3) -- 图片操作 的my-canvas-img.vue组件中。

示例代码:

代码语言:javascript复制
//反转效果
reversePixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
         data[i] = 255 - data[i];
         data[i   1] = 255 - data[i   1];
         data[i   2] = 255 - data[i   2];
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.4 黑白效果

黑白效果,也叫灰度图(average),是指将彩色图片转换成黑白图片。实现算法是:首先取红、绿、蓝三个通道的平均值,也就是 (data[i 0] data[ i 1] data[i 2]) / 3,然后data[i 0]、data[i 1]和data[i 2]全部保存为这个平均值即可。

语法:

代码语言:javascript复制
for(let i = 0; i < data.length; i  = 4){
    let average = (data[i   0]   data[ i   1]   data[i   2]) / 3;
    data[i   0] = average;
    data[i   1] = average;
    data[i   2] = average;
}

示例代码:

代码语言:javascript复制
//黑白效果
averagePixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
        let average = (data[i]   data[ i   1]   data[i   2]) / 3;
        data[i] = average;
        data[i   1] = average;
        data[i   2] = average;
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.5 亮度效果

亮度效果(brightness),是指让图片变得更亮或者更暗。实现算法是:将红、绿、蓝三个通道值分别同时加上一个正值或者负值。

语法:

代码语言:javascript复制
for(let i = 0; i < data.length; i  = 4){
    let a = 50;
    data[i]  = a;
    data[i   1]  = a;
    data[i   2]  = a;
}

示例代码:

代码语言:javascript复制
//亮度效果
brightnessPixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
        let a = 50;
        data[i]  = a;
        data[i   1]  = a;
        data[i   2]  = a;
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.6 复古效果

复古效果(sepia),是指使得图片有一种古旧效果。实现算法:将红、绿、蓝三个通道分别取这个三个值的某种加权平均值。

语法:

代码语言:javascript复制
for(let i = 0; i < data.length; i  = 4){
    let r = data[i];
    let g = data[i   1];
    let b = data[i   2];
    data[i] = r * 0.39   g * 0.76   b * 0.18;
    data[i   1] = r * 0.35   g * 0.68   b * 0.16;
    data[i   2] = r * 0.27   g * 0.53   b * 0.13;
}

示例代码:

代码语言:javascript复制
//复古效果
sepiaPixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
        let r = data[i];
        let g = data[i   1];
        let b = data[i   2];
        data[i] = r * 0.39   g * 0.76   b * 0.18;
        data[i   1] = r * 0.35   g * 0.68   b * 0.16;
        data[i   2] = r * 0.27   g * 0.53   b * 0.13;
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.7 红色蒙版

红色蒙版,指的是让图片呈现一种偏红的效果。实现算法是:将红色通道(r)赋值为红、绿、蓝这三个的平均值,并且将绿通道和蓝通道都赋值为0。

语法:

代码语言:javascript复制
for(let i = 0; i < data.length; i  = 4){
    let r = data[i];
    let g = data[i   1];
    let b = data[i   2];
    let average = (r   g   b) / 3;
    data[i] = average;
    data[i   1] = 0;
    data[i   2] = 0;
}

示例代码:

代码语言:javascript复制
//红色蒙版效果
redMaskPixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
        let r = data[i];
        let g = data[i   1];
        let b = data[i   2];
        let average = (r   g   b) / 3;
        data[i] = average;
        data[i   1] = 0;
        data[i   2] = 0;
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.8 透明处理

对于透明处理,我们都是在得到像素数组后,将该数组中每一个像素的透明度乘以n,然后保存像素数组,最后使用putImageData()方法将图像重新绘制在画布上。

语法:

代码语言:javascript复制
//n的取值范围为0.0~1.0
for(let i = 0; i < data.length; i  = 4){
    data[i   3] = data[i   3] * n;
}

示例代码:

代码语言:javascript复制
 //透明效果
transPixel(cxt){
    cxt.drawImage(this.imgObj, 10, 10, 120, 80);
    let imgData = cxt.getImageData(10, 10, 120, 80);
    let data = imgData.data;
    for(let i = 0; i < data.length; i  = 4){
        data[i   3] = data[i   3] * 0.3;
    }
    cxt.putImageData(imgData, 150, 10);
}

示例效果:

2.9 createImageData()方法

用于在画布中创建一个区域,使得这个区域可以进行像素操作。

语法:

代码语言:javascript复制
//格式一
//sw、sh:分别表示要创建区域的宽度的高度
cxt.createImageData(sw, sh);
//格式二
//imageData:像素对象,表示要“创建区域”的宽度和高度与这个像素对象的宽度和高度相等
cxt.createImageData(imageData);

getImageData()和putImageData()配合使用是对一张图片进行像素操作,createImageData()和putImageData()配合使用是对一个区域进行像素操作。

示例代码:

代码语言:javascript复制
//创建像素操作区域
createPixelArea(cxt){
    cxt.drawImage(this.imgObj, 0, 0, 120, 80);
    let imgData1 = cxt.getImageData(0, 0, 120, 80);
    let imgData2 = cxt.createImageData(imgData1);
    let data = imgData2.data;
    for(let i = 0; i < 100 * 100 * 4; i  = 4){
        data[i] = 0;
        data[i   1] = 0;
        data[i   2] = 255;
        data[i   3] = 255;
    }
    cxt.putImageData(imgData2, 150, 0);
}

示例效果:

0 人点赞