繁体   English   中英

如何用画布做阈值效果?

[英]How can I do a threshold effect with canvas?

我发现本指南使用画布和 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属性)、 imgcanvas元素上复制这种效果,只要它有效就没有关系。

该过滤器适用于图像数据ImageData 图像数据无法显示,需要转换为一些可显示的形式,例如画布。

您还需要从图像中获取图像数据。 标准图像无法访问像素,因此您需要将图像转换为画布以获取像素。

请注意,不安全的图像(跨域、本地文件存储)可能无法提供像素访问权限。 如果您在请求中提供正确的CORS标头并且服务器接受请求(如下例所示),则某些跨域图像将允许访问。

例子

我在 Filter 对象中添加了一些辅助函数,这些函数可以从各种图像(如源)中复制、创建和获取像素。

示例中的Filter抽象了术语图像。 就示例而言,图像是类似图像的对象,可以是CSSImageValueHTMLImageElementSVGImageElementHTMLVideoElementHTMLCanvasElementImageBitmapOffscreenCanvasImageData

 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, 0) } else { ctx.drawImage(img, 0, 0, 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, 0, img.width, img.height); }, threshold(pixels, threshold, light = [255,255,255], dark = [0,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% }
 <div id="att" class="hide">By Rmhermen - Transferred from en.wikipedia to Commons., CC BY-SA 3.0, <a href="https://commons.wikimedia.org/w/index.php?curid=468996">image source</a></div>

如果你想在 HTML <div>上应用这个过滤器,那么画布解决方案不是最好的。

相反,对于简单的情况,请查看CSS 过滤,对于更复杂的情况,请查看SVG 过滤器

你想要的是一个简单的,只能用 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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM