HTML5 Canvas核心技术—图形、动画与游戏开发.pdf6
操作图像的像素:getImageData() putImageData()
ImageData对象
调用getImageData()方法实际是获取了一个指向ImageData对象的引用,返回的对象包含3个属性:1)width以设备像素为单位的图像数据宽度 2)height以设备像素为单位的图像数据高度 3)data包含各个设备像素数值的数组
width和height都是只读的无符号长整数,data属性包含的每个数组元素都表示图像数据中相应的像素值,每个值包含的颜色分量都是含有8个二进制位的整数(后面将详细讲解)
为了使绘图更加逼真,浏览器可能会使用多个像素来表示一个像素,一个边长都为200像素的canvas,共有40000个像素,若浏览器用2个像素来表示原来的1个像素,将有160000像素,可通过width和height查看
putImageData()方法不受全局设置的影响(globalAlpha与globalCompositeOperation等),也不会在绘制时运用图像合成、阴影等效果,drawImage()方法与之相反,会受全局属性影响
getImageData()参数分别是x、y、图像的高和图像的宽
putImageData()方法后4个参数表示图像数据中一块脏矩形区域(以设备像素为单位),这4个参数是可选的,不指定则采取默认值:
所绘脏矩形距离整幅图像数据左上角的水平偏移量,以设备像素为单位,默认0
所绘脏矩形距离整幅图像数据左上角的垂直偏移量,以设备像素为单位,默认0
以设备像素为单位的脏矩形宽度,默认是整幅图像的宽度
以设备像素为单位的脏矩形高度,默认是整幅图像的高度
注意,putImageData()方法的第二个和第三个参数以CSS像素计量
ImageData对象中的数组
ImageData对象中的data属性指向一个包含8位二进制整数的数组,这些整数的值位于0-255之间,分别表示一个像数的红、绿、蓝及透明度分量
遍历每个数组
for(var index=0;index<length;++i){
value=data[index];
}
反向遍历每个像素
index=length-1;
while(index >=0){
value=data[index];
index--;
}
只处理alpha值,不修改红绿蓝分量
for(index=3;index<length-4;index+=4){
data[index]=...;
}
只处理红绿蓝分量,不修改alpha值
for(index=0;index<length-4;index+=4){
data[index]=...;
data[index+1]=...;
data[index+2]=...;
}
图像滤镜
通过操作单个像素实现滤镜效果
负片滤镜,即反向,255减去当前的分量,alpha值不变
黑白滤镜,计算每个像素红绿蓝分量的平均值,将三个分量都设置为这个值
浮雕滤镜, 基于当前像素的前一个像素RGB值与它的后一个像素的RGB值之差再加上128
在与图像数据有关的度量值中,应该使用设备像素而非CSS像素
用工作线程处理图像
浏览器在执行JavaScript代码时,使用的是主线程,可以使用工作线程处理一些复杂运算,以便浏览器能够及时响应用户操作
当主线程执行到sunglassFilter=new Work('sunglassFilter.js')这一行语句时,会创建一个工作线程,传递给Work构造器的文件名表示工作进程将要执行的Javascript代码文件,可以在其他函数中调用变量sunglassFilter,实现一些通信
以图像制作动画
通过设置setInterval()来持续降低每个像素的alpha值,实现淡入淡出效果
图像绘制的安全问题
HTML5Canvas规范允许绘制不属于自己的(其他域)的图像,但却不能通过CanvasAPI保存或修改其他域中的图像
安全机制原理:每个canvas都有一个origin-clean的标志位,初始值是true,如果使用了drawImage()绘制一幅其他域中的图像,origin-clean的值将被设置为false;本身就是false的canvas绘制到当前canvas中,依旧是false,对origin-clean为false的canvas调用toDataURL()或getImageData()会抛出异常
浏览器会将用户的文件系统与运行应用程序的环境视为两个不同的域,所以在默认情况下不能保存或修改文件系统的图片
临时解决办法:在命令行中指定“--allow-file-access-from-files”参数来启东Chrome浏览器,使用火狐浏览器时调用netscape.security.PriviegeManager.enablePrivilege("UniversalBrowserRead");