如何使用画布做阈值效果?

问题描述

我发现本指南展示了使用画布和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元素上的

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提取了术语图像。根据示例,图像是类似对象的图像,并且可以是CSSImageValueHTMLImageElementSVGImageElementHTMLVideoElementHTMLCanvasElement,{{1 }},ImageBitmapOffscreenCanvas

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% }

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...