为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

30秒到达战场 2023-03-03 09:39:21
我发现本指南使用画布和 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属性的)img或canvas元素上复制这种效果,只要它有效就没关系。
查看完整描述

2 回答

?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

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

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

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

例子

我已经向 Filter 对象添加了一些辅助函数,这些函数将复制、创建和从各种图像源中获取像素。

Filter在示例中抽象了术语图像。就示例而言,图像是类似对象的图像,可以是CSSImageValueHTMLImageElementSVGImageElementHTMLVideoElementHTMLCanvasElementImageBitmapOffscreenCanvas中的任何一个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, 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>


查看完整回答
反对 回复 2023-03-03
?
撒科打诨

TA贡献1934条经验 获得超2个赞

如果你想在 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>


查看完整回答
反对 回复 2023-03-03
  • 2 回答
  • 0 关注
  • 101 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信