图片资源存储在本地时默认没有域名,而canvas的getImageData方法受同源策略限制,使用getImageData处理本地图片时浏览器会判定为跨域而报错。
解决方法:
使用FileReader对象的readAsDataURL读取指定的Blob中的内容,读取完成后,FileReader对象的result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。将result赋值给Image对象的src然后加载到canvas上就能使用getImageData对图像进行操作。
核心代码:
document.querySelector("#File").onchange = function(){
var Reader = new FileReader(); // 创建文件读取对象
Reader.readAsDataURL(this.files[0]); //读取Blob,获取DataURL
Reader.onload = function(){
let img = new Image();
img.src = Reader.result; //将result赋值给Image对象的src
img.onload = function(){
cxt.drawImage(img,0,0,canvas.width,canvas.height);
let imageData = cxt.getImageData(0,0,canvas.width,canvas.height);
console.log(imageData);
}
}
}
示例代码
<!DOCTYPE html>
<html>
<head>
<title>图像滤镜</title>
<meta charset="utf-8">
<style type="text/css">
main{
width: 1400px;
margin: 0 auto;
}
canvas{
box-shadow: 0 0 5px gray;
display: inline-block;
margin-left: 50px;
}
</style>
</head>
<body>
<main>
<canvas id="mycanvas" width="400" height="250"></canvas>
<canvas id="filter" width="400" height="250"></canvas>
<form style="margin: 20px 0 0 42px">
上传本地图片:<input type="file" id="File" name="file"/><br/>
</form>
</main>
<script type="text/javascript">
let canvas = document.getElementById('mycanvas');
let cxt = canvas.getContext("2d");
let filter = document.getElementById('filter');
let filter_cxt = filter.getContext("2d");
window.onload = function(){
document.querySelector("#File").onchange=function(){
var Reader=new FileReader();
Reader.readAsDataURL(this.files[0]);
Reader.onload=function(){
let img = new Image();
img.src = Reader.result;
img.onload = function(){
cxt.drawImage(img,0,0,canvas.width,canvas.height);
let imageData = cxt.getImageData(0,0,canvas.width,canvas.height);
console.log(imageData);
let data = imageData.data;
for(let i=0;i<data.length;i+=4){
let grayscale = data[i]*0.3+data[i+1]*0.6+data[i+2]*0.1;
data[i] = grayscale;
data[i+1] = grayscale;
data[i+2] = grayscale;
}
filter_cxt.putImageData(imageData,0,0);
cxt.font = "20px Calibri";
cxt.fillText("原图",10,30);
filter_cxt.font = "20px Calibri";
filter_cxt.fillStyle = "white";
filter_cxt.fillText("黑白",10,30);
}
}
}
}
</script>
</body>
</html>
效果图: