D3临摹作业(西安交大国家艺术基金数据可视化培训第26天)
第十章 Canvas 与简单图像处理
第一节 Canvas功能概述
一 Canvas与SVG的区别
定义 | 特征 | 代码[W3school] | |
Canvas |
通过 JavaScript 来绘制 2D 图形。是一个可以使用脚本(通常为JavaScript)来绘制图形的 HTML 元素.例如,它可以用于绘制图表、制作图片构图或者制作简单的(以及不那么简单的)动画. |
逐像素进行渲染的。 依赖分辨率 |
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #c3c3c3;"> <script type="text/javascript"> var c=document.getElementById("myCanvas"); </script> |
SVG |
使用 XML 描述 2D 图形的语言。 SVG 基于 XML,SVG DOM中的每个元素都是可用的。可以为某个元素附加JavaScript事件处理器。 |
不依赖分辨率 支持事件处理器 最适合带有大型渲染区域的应用程序 复杂度高会减慢渲染速度 不适合游戏应用 |
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="190"> <polygon points="100,10 40,180 190,60 10,60 160,180" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:evenodd;" /> </svg> |
二 Canvas标签和属性
JavaScript 使用 id 来寻找 canvas 元素:
var c=document.getElementById("myCanvas");
然后,创建 context 对象:
var cxt=c.getContext("2d");
getContext("2d") 对象是内建的 HTML5 对象,拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。
案例:简单的圆[源码]
<!DOCTYPE HTML>
<html>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
cxt.fillStyle="#FF0000";
cxt.beginPath();
cxt.arc(70,18,15,0,Math.PI*2,true);
cxt.closePath();
cxt.fill();
</script>
</body>
</html>
案例:Canvas绘制直方图[源码]
<html>
<head>
<title>简单的直方图</title>
</head>
<body>
<canvas id="myCanvas" width="1200" height="700"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var n=10;
var x=100,y=500
for(var i=0;i<n;i++){
var h=Math.floor(Math.random()*y);
cxt.fillStyle="#0000FF";
cxt.fillRect(i*(x+10),y-h,x,h);
}
</script>
</body>
</html>
三 Canvas加载图像
案例:canvas加载图像[源码]
<!DOCTYPE HTML>
<html>
<body>
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="/i/eg_flower.png"
cxt.drawImage(img,0,0);
</script>
</body>
</html>
第二节 Canvas基本图像处理
Canvas图像操作API与处理流程
代码 | ||
创建canvas | <canvas> | |
canvas上下文 | ctx=c.getContext("2d") | |
绘制原图 | ctx.drawImage(image,0,0) | |
获取像素数组 | idata=ctx.getImageData(0,0,w,h) | |
分通道处理 | ||
重写图像数据 | ctx.putImageData(img,0,0) | |
导出图像 | toDataURL() |
案例 图像负片[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="invert" color="blue">翻转</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #c3c3c3;"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
var invert = function() {
for (var i = 0; i < data.length; i += 4) {
data[i] = 255 - data[i]; // red
data[i + 1] = 255 - data[i + 1]; // green
data[i + 2] = 255 - data[i + 2]; // blue
}
cxt.putImageData(imageData,0,0);
}
var invertbtn = document.getElementById('invert');
invertbtn.addEventListener('click', invert);
</script>
</center>
</body>
</html>
案例 灰度图像[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="gray">灰度图</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #c3c3c3;"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
var grayScale = function() {
for (var i = 0; i < data.length; i += 4) {
var avg = (data[i] + data[i +1] + data[i +2]) / 3;
data[i] = avg; // red
data[i + 1] = avg; // green
data[i + 2] = avg; // blue
}
cxt.putImageData(imageData, 0, 0);
};
var grayBtn = document.getElementById('gray');
grayBtn.addEventListener('click',grayScale);
</script>
</center>
</body>
</html>
案例 图像二值化[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="bin">二值图</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400" style="border:1px solid #c3c3c3;"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
var binImage = function() {
for (var i = 0; i < data.length; i += 4) {
var gray=Math.floor(imageData.data[i]*0.3+imageData.data[i+1]*0.59+imageData.data[i+2]*0.11);
if(gray<100)
{
data[i] =0; // red
data[i + 1] =0; // green
data[i + 2] =0; // blue
//console.log(gray);
}
else
{
data[i] =255; // red
data[i + 1] =255; // green
data[i + 2] =255; // blue
}
}
cxt.putImageData(imageData, 0, 0);
};
var binBtn = document.getElementById('bin');
binBtn.addEventListener('click',binImage);
</script>
</center>
</body>
</html>
第三节 Canvas复杂图像处理
案例 水平翻转[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="flip">水平翻转</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
//dataMatrix
var DM=new Array(c.height);
for(var i=0;i<c.height;i++){
DM[i]=new Array(c.width);
for(var j=0;j<c.width;j++){
DM[i][j]=new Array(4);
DM[i][j][0]=data[(i*(c.width)+j)*4];
DM[i][j][1]=data[(i*(c.width)+j)*4+1];
DM[i][j][2]=data[(i*(c.width)+j)*4+2];
DM[i][j][3]=data[(i*(c.width)+j)*4+3];
}
}
var flipImage = function() {
//水平翻转
var tempPix
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
if((i>0)&&(i<c.height-1)&&(j>0)&&(j<c.width-1)){
if(j<c.width/2)
{
for(var k=0;k<4;k++){
tempPix=DM[i][j][k];
DM[i][j][k]=DM[i][c.width-1-j][k];
DM[i][c.width-1-j][k]=tempPix;
}
}
}
}
}
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
data[(i*(c.width)+j)*4]=DM[i][j][0];
data[(i*(c.width)+j)*4+1]=DM[i][j][1];
data[(i*(c.width)+j)*4+2]=DM[i][j][2];
data[(i*(c.width)+j)*4+3]=DM[i][j][3];
}
}
cxt.putImageData(imageData, 0, 0);
};
var flipBtn = document.getElementById('flip');
flipBtn.addEventListener('click',flipImage);
</script>
</center>
</body>
</html>
案例: 柔化效果[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="blur">柔化</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
//dataMatrix
var DM=new Array(c.height);
for(var i=0;i<c.height;i++){
DM[i]=new Array(c.width);
for(var j=0;j<c.width;j++){
DM[i][j]=new Array(4);
DM[i][j][0]=data[(i*(c.width)+j)*4];
DM[i][j][1]=data[(i*(c.width)+j)*4+1];
DM[i][j][2]=data[(i*(c.width)+j)*4+2];
DM[i][j][3]=data[(i*(c.width)+j)*4+3];
}
}
var blurImage = function() {
//9宫格平均,实现柔化Blur
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
if((i>0)&&(i<c.height-1)&&(j>0)&&(j<c.width-1)){
DM[i][j][0]=(DM[i-1][j-1][0]+DM[i-1][j][0]+DM[i-1][j+1][0]+DM[i][j-1][0]+DM[i][j][0]+DM[i][j+1][0]+DM[i+1][j-1][0]+DM[i+1][j][0]+DM[i+1][j+1][0])/9;
DM[i][j][1]=(DM[i-1][j-1][1]+DM[i-1][j][1]+DM[i-1][j+1][1]+DM[i][j-1][1]+DM[i][j][1]+DM[i][j+1][1]+DM[i+1][j-1][1]+DM[i+1][j][1]+DM[i+1][j+1][1])/9;
DM[i][j][2]=(DM[i-1][j-1][2]+DM[i-1][j][2]+DM[i-1][j+1][2]+DM[i][j-1][2]+DM[i][j][2]+DM[i][j+1][2]+DM[i+1][j-1][2]+DM[i+1][j][2]+DM[i+1][j+1][2])/9;
}
}
}
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
data[(i*(c.width)+j)*4]=DM[i][j][0];
data[(i*(c.width)+j)*4+1]=DM[i][j][1];
data[(i*(c.width)+j)*4+2]=DM[i][j][2];
data[(i*(c.width)+j)*4+3]=DM[i][j][3];
}
}
cxt.putImageData(imageData, 0, 0);
};
var blurBtn = document.getElementById('blur');
blurBtn.addEventListener('click',blurImage);
</script>
</center>
</body>
</html>
案例: 锐化效果[源码]
<html>
<body>
<center>
<h2>数据可视化之JS Canvas 图像处理</h2>
<button id="sharpen">锐化</button>
<hr width=70%></hr>
<canvas id="myCanvas" width="600" height="400"></canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var cxt=c.getContext("2d");
var img=new Image()
img.src="flowerS.jpg"
cxt.drawImage(img,0,0);
var imageData = cxt.getImageData(0,0,c.width, c.height);
var data = imageData.data;
//dataMatrix
var DM=new Array(c.height);
for(var i=0;i<c.height;i++){
DM[i]=new Array(c.width);
for(var j=0;j<c.width;j++){
DM[i][j]=new Array(4);
DM[i][j][0]=data[(i*(c.width)+j)*4];
DM[i][j][1]=data[(i*(c.width)+j)*4+1];
DM[i][j][2]=data[(i*(c.width)+j)*4+2];
DM[i][j][3]=data[(i*(c.width)+j)*4+3];
}
}
var sharpenImage = function() {
//9宫格平均,实现柔化Blur
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
if((i>0)&&(i<c.height-1)&&(j>0)&&(j<c.width-1)){
DM[i][j][0]=(DM[i-1][j-1][0]*0-DM[i-1][j][0]+DM[i-1][j+1][0]*0-DM[i][j-1][0]+DM[i][j][0]*10-DM[i][j+1][0]+DM[i+1][j-1][0]*0-DM[i+1][j][0]+DM[i+1][j+1][0]*0)/6;
DM[i][j][1]=(DM[i-1][j-1][1]*0-DM[i-1][j][1]+DM[i-1][j+1][1]*0-DM[i][j-1][1]+DM[i][j][1]*10-DM[i][j+1][1]+DM[i+1][j-1][1]*0-DM[i+1][j][1]+DM[i+1][j+1][1]*0)/6;
DM[i][j][2]=(DM[i-1][j-1][2]*0-DM[i-1][j][2]+DM[i-1][j+1][2]*0-DM[i][j-1][2]+DM[i][j][2]*10-DM[i][j+1][2]+DM[i+1][j-1][2]*0-DM[i+1][j][2]+DM[i+1][j+1][2]*0)/6;
}
}
}
for(var i=0;i<c.height;i++){
for(var j=0;j<c.width;j++){
data[(i*(c.width)+j)*4]=DM[i][j][0];
data[(i*(c.width)+j)*4+1]=DM[i][j][1];
data[(i*(c.width)+j)*4+2]=DM[i][j][2];
data[(i*(c.width)+j)*4+3]=DM[i][j][3];
}
}
cxt.putImageData(imageData, 0, 0);
};
var sharpenBtn = document.getElementById('sharpen');
sharpenBtn.addEventListener('click',sharpenImage);
</script>
</center>
</body>
</html>
更多的canvas