Canvas图像与视频基础,离屏19

/*除了可以把图像绘制到canvas中,还可以把自身或其它canvas、视频的某一帧绘制到当前绘图环境中。

--1--有时两个canvas的相互绘制需要创建离屏canvas,离屏技术实际上是用空间换时间的一种技术

创建离屏canvas元素,可以动态创建元素,也可以用网页中一个隐藏区域的元素

offscreenCanvas = document.createElement('canvas'), offscreenContext = offscreenCanvas.getContext('2d'),

设置离屏canvas的宽和高

在离屏canvas中进行绘制

把离屏canvas中的全部或一部分绘制到另一个canvas中

--2--图像的绘制存在安全问题,默认的情况下允许绘制不属于自己域的图像,但不能通过Canvas API保存或修改其它域中的图像。如果修改其它域的图像则会抛出安全异常,一些浏览器都招供了解决方法,比如:

chrome:在命令行中指定:'--allow-file-access-from-files'参数来启动浏览器;

firefox:通过调用netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");

--3--在使用这些API时性能也是一个需要关注的方面,不同的编码其效率不太一样,有一个大致的参考网站:【http://jsperf.com

drawImage()的速度要优于putImageData();

*/

/**************************************************context.drawImage()方法有如下几种参数形式,图像的绘制不会考虑当前路径,但它会考虑alpha, 阴影,剪辑区域以及图像合成效果等效果*/

1、context.drawImage(img, dx, dy);//dx, dy指定图片与原点的距离

2、context.drawImage(img, dx, dy, dw, dh);//dw, dh指定在目标区域内绘制整张图片,起到了缩放的效果。如果尺寸小于canvas的大小则是缩小,如果大于canvas的大小,则起到了放大的效果,并且一部分图像会绘制在canvas外面,可以通过坐标平移起到背景滚动的效果

3、context.drawImage(img, sx, sy, sw, sh,dx, dy, dw, dh);//会将图像的整体或一部分绘制到canvas中,并在绘制时根据目标的宽度和高度进行缩放,前5个参数与图片有关,后4个参数与画布有关,即S源和D目录

//图片缩放后,永远居中的实现方法............................................

function drawScaled() {

var w = canvas.width,

h = canvas.height,

sw = w * scale,

sh = h * scale;

context.drawImage(offscreenCanvas, 0, 0,

offscreenCanvas.width, offscreenCanvas.height,

-sw/2 + w/2, -sh/2 + h/2, sw, sh);

}

//最简单的例子

var img = new Image();

img.src = "countrypath.jpg";

img.onload = function(){

context.drawImage(img, 10, 10, 1500, 1500);

}

/***************************************************context.getImageData()返回ImageData对象,它有以下三个属性:*/

width:图像的宽度

height:图像的高度

data:包括各个像素值的数组,是一个数组,每4个整数值代表一个像素点RGBA,通过遍历数组,对不同的通道加以运算就可以做出不同的效果来,数组的总个数是4*width*height个,W3C规范现把data以ArrayBuffer来存放

context.getImageData(sx, sy, swidth, sheight);//这4个参数是必须的。指定了取得绘图区域的矩形大小

/***************************************************context.putImageData(),这个方法在绘制图像时不受一些全局参数的影响,而drawImage()则会受限制*/

context.putImageData(ImageData, dx, dy);//将ImageData绘制在canvas的[dx, dy]处

context.putImageData(ImageData, dx, dy, dirtyX, dirtyY, dirtyW, dirtyY);//后四个参数是可选的指定的是ImageData图像的属性,并不是canvas的属性,起到截取图像的作用,按一定比例设置后可以起到缩放的效果

context.createImageData();

/*下面是对ImageData数据的操作例子,实现了几个不同的滤镜功能,如果利用上述几种特殊滤镜结合setTimeout和setInterval来制作动画(不过效率太低,一般用.requestAnimationFrame()方法),制作时可以用离屏,设置总体的透明度,以及改变数据值:

【1】负片滤镜:把原像素用255去减

【2】黑白滤镜:算出三个像素的平均值,然后赋值给三个RGB

【3】浮雕滤镜:相对复杂一些

【4】墨镜滤镜:

*/

//负片滤镜

var imageData = context.getImageData(0, 0, canvas.width, canvas.height);//这处注意应该是对象,它里面的data是一个指针,指向数据数组

var data = imageData.data;

for (var 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];

}

//浮雕滤镜

for (i=0; i < length; i++) { // loop through every pixel

if (i <= length-width*4) {// if we won't overrun the bounds of the array

if ((i+1) % 4 !== 0) {// if it's not an alpha

// if it's the last pixel in the row, there is

// no pixel to the right, so copy previous pixel's

// values.

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 { // not the last pixel in the row

data[i] = 255/2 // Average value

  • 2*data[i] // current pixel
  • data[i+4] // next pixel

  • data[i+width*4]; // pixel underneath

}

}

}

else { // last row, no pixels underneath,

// so copy pixel above

if ((i+1) % 4 !== 0) {

data[i] = data[i-width*4];

}

}

}

// 墨镜滤镜

for (i=0; i < length; ++i) {

if ((i+1) % 4 != 0) {

if ((i+4) % (width*4) == 0) { // last pixel in a row

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] = 2*data[i] - data[i+4] - 0.5*data[i+4];

}

}

}

相关推荐
打小就很皮...4 分钟前
ShowCountCard 功能迭代:新增周月对比属性,完善数据可视化场景
前端·react.js·信息可视化
JAVA学习通10 分钟前
OJ竞赛平台----C端题目列表
java·开发语言·jvm·vue.js·elasticsearch
IT_陈寒13 分钟前
Redis性能翻倍的7个冷门技巧:从P5到P8都在偷偷用的优化策略!
前端·人工智能·后端
Moonbit25 分钟前
MoonBit Meetup 丨 手把手带你走进 AI 编程新世代
前端·后端·程序员
携欢26 分钟前
PortSwigger靶场之 CSRF where token is not tied to user session通关秘籍
前端·csrf
想唱rap34 分钟前
C++ string类的使用
开发语言·c++·笔记·算法·新浪微博
胖咕噜的稞达鸭35 分钟前
C++中的父继子承(2)多继承菱形继承问题,多继承指针偏移,继承组合分析+高质量习题扫尾继承多态
c语言·开发语言·数据结构·c++·算法·链表·c#
执剑、天涯40 分钟前
通过一个typescript的小游戏,使用单元测试实战(二)
javascript·typescript·单元测试
JAVA学习通43 分钟前
基本功 | 一文讲清多线程和多线程同步
java·开发语言·多线程
啦啦9117141 小时前
如何理解Java中的并发?
java·开发语言