猿问

我怎样才能用画布做一个阈值效果?

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



30秒到达战场
浏览 199回答 2
2回答

慕田峪7331174

该过滤器适用于图像数据ImageData。图像数据无法显示,因此需要转换为某种可显示的形式,例如画布。您还需要从图像中获取图像数据。标准图像不允许访问像素,因此您需要将图像转换为画布以获取像素。请注意,不安全的图像(跨域、本地文件存储)可能无法为您提供像素访问权限。如果您在请求中提供正确的CORS标头并且服务器接受请求(如下例所示) ,一些跨域图像将允许访问。例子我已经向 Filter 对象添加了一些辅助函数,这些函数将复制、创建和从各种图像源中获取像素。Filter在示例中抽象了术语图像。就示例而言,图像是类似对象的图像,可以是CSSImageValue、HTMLImageElement、SVGImageElement、HTMLVideoElement、HTMLCanvasElement、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&nbsp;image.addEventListener("load", () => applyFilter(image), {once: true});const Filters = {&nbsp; &nbsp; createImage(w, h) {&nbsp; &nbsp; &nbsp; &nbsp; const can = document.createElement("canvas");&nbsp; &nbsp; &nbsp; &nbsp; can.width = w;&nbsp; &nbsp; &nbsp; &nbsp; can.height= h;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; return can;&nbsp; &nbsp; },&nbsp; &nbsp; copyImage(img) {&nbsp; &nbsp; &nbsp; &nbsp; const image = this.createImage(img.width, img.height);&nbsp; &nbsp; &nbsp; &nbsp; const ctx = image.getContext("2d");&nbsp; &nbsp; &nbsp; &nbsp; if (img instanceof ImageData) { ctx.putImageData(img, 0, 0) }&nbsp; &nbsp; &nbsp; &nbsp; else { ctx.drawImage(img, 0, 0, img.width, img.height) }&nbsp; &nbsp; &nbsp; &nbsp; return image;&nbsp; &nbsp; },&nbsp; &nbsp; getPixels(img) {&nbsp; &nbsp; &nbsp; &nbsp; if (!(img instanceof HTMLCanvasElement)) { img = this.copyImage(img) }&nbsp; &nbsp; &nbsp; &nbsp; const ctx = img.getContext("2d");&nbsp; &nbsp; &nbsp; &nbsp; return ctx.getImageData(0, 0, img.width, img.height);&nbsp; &nbsp; },&nbsp; &nbsp; threshold(pixels, threshold, light = [255,255,255], dark = [0,0,0]) { // light, dark arrays of RGB&nbsp; &nbsp; &nbsp; &nbsp; var d = pixels.data, i = 0, l = d.length;&nbsp; &nbsp; &nbsp; &nbsp; while (l-- > 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; const v = d[i] * 0.2126 + d[i+1] * 0.7152 + d[i+2] * 0.0722;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [d[i], d[i+1], d[i+2]] = v >= threshold ? light : dark;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; i += 4;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return pixels;&nbsp; &nbsp; }};function applyFilter(image) {&nbsp; &nbsp; const pixels = Filters.getPixels(image);&nbsp; &nbsp; Filters.threshold(pixels, 100);&nbsp; &nbsp; const thresholdImage = Filters.copyImage(pixels);&nbsp; &nbsp; att.classList.remove("hide"); // Image can be seen so show attribution&nbsp; &nbsp; document.body.appendChild(image); // add original to page&nbsp; &nbsp; document.body.appendChild(thresholdImage); // add filtered to page&nbsp;}/* Image source&nbsp;&nbsp; &nbsp;By Rmhermen - Transferred from en.wikipedia to Commons., CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=468996&nbsp;*/.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 {&nbsp; background-image: url(https://i.stack.imgur.com/5Md7Z.jpg);&nbsp; width: 600px;&nbsp; height: 600px;&nbsp; filter: brightness(115%) grayscale(100%) contrast(5000%);}<div id="target"></div>
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答