问题描述
我发现本指南展示了使用画布和JavaScript的图像滤镜/效果:https://www.html5rocks.com/en/tutorials/canvas/imagefilters
但是,我对如何实现它一无所知。我对JavaScript不满意(我是图形设计师),所以我什至都不了解语法。我从页面中提取了此代码,但不知道它是否完整或如何使用:
Filters = {};
Filters.threshold = function(pixels,threshold) {
var d = pixels.data;
for (var i=0; i<d.length; i+=4) {
var r = d[i];
var g = d[i+1];
var b = d[i+2];
var v = (0.2126*r + 0.7152*g + 0.0722*b >= threshold) ? 255 : 0;
d[i] = d[i+1] = d[i+2] = v
}
return pixels;
};
threshold = function() {
runFilter('threshold',Filters.threshold,128);
}
在div
(具有CSS background-image
属性),img
或canvas
元素上的I want to replicate this effect上,只要有效就无所谓。
解决方法
如果您想将此过滤器应用于HTML <div>
,那么画布解决方案不是最佳选择。
对于简单的情况,请看CSS filters,对于更复杂的情况,请看SVG filters。
您想要的是一个简单的对象,只能通过CSS过滤器实现:
#target {
background-image: url(https://i.stack.imgur.com/5Md7Z.jpg);
width: 600px;
height: 600px;
filter: brightness(115%) grayscale(100%) contrast(5000%);
}
<div id="target"></div>
,
过滤器可处理图像数据ImageData
。图片数据无法显示,因此需要转换为某种可显示的形式,例如画布。
此外,您还需要从图像中获取图像数据。标准图片无法访问像素,因此您需要将其转换为画布以获取像素。
请注意:不安全的图像(跨域,本地文件存储)可能无法为您提供像素访问权限。如果您在请求中提供正确的CORS标头,并且服务器接受了请求,则某些跨域图像将允许访问(如下例所示)。
示例
我已经向Filter对象添加了一些辅助函数,这些函数将从各种图像源中复制,创建和获取像素。
示例中的 Filter
提取了术语图像。根据示例,图像是类似对象的图像,并且可以是CSSImageValue
,HTMLImageElement
,SVGImageElement
,HTMLVideoElement
,HTMLCanvasElement
,{{1 }},ImageBitmap
或OffscreenCanvas
。
ImageData
const image = new Image;
image.src = "https://upload.wikimedia.org/wikipedia/commons/1/15/Late_model_Ford_Model_T.jpg";
image.crossOrigin = "Anonymous"; // CORS
image.addEventListener("load",() => applyFilter(image),{once: true});
const Filters = {
createImage(w,h) {
const can = document.createElement("canvas");
can.width = w;
can.height= h;
return can;
},copyImage(img) {
const image = this.createImage(img.width,img.height);
const ctx = image.getContext("2d");
if (img instanceof ImageData) { ctx.putImageData(img,0) }
else { ctx.drawImage(img,img.width,img.height) }
return image;
},getPixels(img) {
if (!(img instanceof HTMLCanvasElement)) { img = this.copyImage(img) }
const ctx = img.getContext("2d");
return ctx.getImageData(0,img.height);
},threshold(pixels,threshold,light = [255,255,255],dark = [0,0]) { // light,dark arrays of RGB
var d = pixels.data,i = 0,l = d.length;
while (l-- > 0) {
const v = d[i] * 0.2126 + d[i+1] * 0.7152 + d[i+2] * 0.0722;
[d[i],d[i+1],d[i+2]] = v >= threshold ? light : dark;
i += 4;
}
return pixels;
}
};
function applyFilter(image) {
const pixels = Filters.getPixels(image);
Filters.threshold(pixels,100);
const thresholdImage = Filters.copyImage(pixels);
att.classList.remove("hide"); // Image can be seen so show attribution
document.body.appendChild(image); // add original to page
document.body.appendChild(thresholdImage); // add filtered to page
}
/* Image source
By Rmhermen - Transferred from en.wikipedia to Commons.,CC BY-SA 3.0,https://commons.wikimedia.org/w/index.php?curid=468996
*/
.hide {display: none}
div { font-size: x-small }
canvas { width: 46% }
img { width: 46% }