首页 >CMS教程 >WordPress >使用 CamanJS 开发自定义图像编辑器:扩展滤镜选项和混合模式

使用 CamanJS 开发自定义图像编辑器:扩展滤镜选项和混合模式

WBOY
WBOY原创
2023-08-28 10:05:02697浏览

使用 CamanJS 开发自定义图像编辑器:扩展滤镜选项和混合模式

在我们的 CamanJS 图像编辑器系列的第一个教程中,我们仅使用内置过滤器来编辑图像。这限制了我们一些基本效果,如亮度、对比度和 18 个其他更复杂的滤镜,如 Vintage、Sunrise 等。它们都很容易应用,但我们无法完全控制我们想要的图像的各个像素进行编辑。

在第二个教程中,我们了解了图层和混合模式,这使我们能够更好地控制正在编辑的图像。例如,您可以在画布上添加一个新图层,用颜色或图像填充它,然后将其放置在父图层上并应用混合模式。然而,我们仍然没有创建自己的过滤器,并且我们可以应用的混合模式仅限于 CamanJS 已经提供的模式。

本教程的目的是教您如何创建自己的混合模式和滤镜。我们还将解决库中存在的一些错误,以及在您自己的项目中使用 CamanJS 时如何修补它们。

创建新的混合模式

默认情况下,CamanJS 提供十种混合模式。它们是正常、相乘、屏蔽、叠加、差值、加法、排除、柔光、变亮和变暗。该库还允许您注册自己的混合模式。这样,您就可以控制当前图层和父图层的相应像素如何混合在一起以产生最终结果。

您可以使用 Caman.Blender.register("blend_mode", callback); 创建新的混合模式。此处,blend_mode 是您要用来识别您正在创建的混合模式的名称。回调函数接受两个参数,其中包含当前图层上不同像素和父图层上相应像素的 RGB 值。该函数返回一个对象,其中包含 rgb 通道的最终值。

下面是自定义混合模式的示例,如果父图层中相应像素的通道值超过 128,则该像素的各个通道的值设置为 255。如果该值低于 128,则最终通道值是父通道值减去当前层通道值的结果。该混合模式的名称是 maxrgb

Caman.Blender.register("maxrgb", function(rgbaLayer, rgbaParent) {
    return {
        r: rgbaParent.r > 128 ? 255 : rgbaParent.r - rgbaLayer.r,
        g: rgbaParent.g > 128 ? 255 : rgbaParent.g - rgbaLayer.g,
        b: rgbaParent.b > 128 ? 255: rgbaParent.b - rgbaLayer.b
    };
});

让我们以类似的方式创建另一个混合模式。这次,如果父层对应像素的通道值大于128,则最终的通道值将被设置为0。如果父层的通道值小于128,则最终结果将是相加特定像素的当前图层和父图层的通道值。此混合模式已命名为 minrgb

Caman.Blender.register("minrgb", function(rgbaLayer, rgbaParent) {
    return {
        r: rgbaParent.r < 128 ? rgbaParent.r + rgbaLayer.r : 0,
        g: rgbaParent.g < 128 ? rgbaParent.g + rgbaLayer.r : 0,
        b: rgbaParent.b < 128 ? rgbaParent.r + rgbaLayer.r : 0
    };
});

您应该尝试创建自己的混合模式进行练习。

创建新的基于像素的过滤器

CamanJS 中有两大类过滤器。您可以一次对整个图像进行一个像素操作,也可以使用卷积核修改图像。卷积核是一个矩阵,它根据某个像素周围的像素来确定该像素的颜色。在本节中,我们将重点关注基于像素的滤波器。内核操作将在下一节中介绍。

基于像素的滤镜一次给出一个像素的 RGB 通道值。该特定像素的最终 RGB 值不受周围像素的影响。您可以使用 Caman.Filter.register("filter_name", callback); 创建自己的过滤器。您创建的任何过滤器都必须调用 process() 方法。此方法接受过滤器名称和回调函数作为参数。

以下代码片段向您展示如何创建基于像素的过滤器,将图像变成灰度。这是通过计算每个像素的发光,然后将各个通道的值设置为等于计算的发光来完成的。

Caman.Filter.register("grayscale", function () {
    this.process("grayscale", function (rgba) {
        var lumin = (0.2126 * rgba.r) + (0.7152 * rgba.g) + (0.0722 * rgba.b);
        rgba.r = lumin;
        rgba.g = lumin;
        rgba.b = lumin;
    });
    return this;
});

您可以以类似的方式创建阈值过滤器。这次,我们将允许用户通过一个阈值。如果特定像素的亮度高于用户提供的限制,则该像素将变成白色。如果特定像素的亮度低于用户提供的限制,该像素将变黑。

Caman.Filter.register("threshold", function (limit) {
    this.process("threshold", function (rgba) {
        var lumin = (0.2126 * rgba.r) + (0.7152 * rgba.g) + (0.0722 * rgba.b);
        rgba.r = lumin > limit ? 255 : 0;
        rgba.g = lumin > limit ? 255 : 0;
        rgba.b = lumin > limit ? 255 : 0;
    });
    return this;
});

作为练习,您应该尝试创建自己的基于像素的过滤器,例如,增加所有像素上特定通道的值。

CamanJS 还允许您设置绝对和相对位置像素的颜色,而不是操纵当前像素的颜色。不幸的是,这种行为有点错误,所以我们必须重写一些方法。如果您查看该库的源代码,您会注意到 getPixel()putPixel() 等方法调用了 方法<code class="inline">this 上的 和 上的 和 。但是,这些方法不是在原型上定义的,而是在类本身上定义的。

该库的另一个问题是 putPixelRelative() 方法在两个不同的地方使用变量名称 nowLoc 而不是 newLoc 。您可以通过在脚本中添加以下代码来解决这两个问题。

Caman.Pixel.prototype.coordinatesToLocation = Caman.Pixel.coordinatesToLocation
Caman.Pixel.prototype.locationToCoordinates = Caman.Pixel.locationToCoordinates

Caman.Pixel.prototype.putPixelRelative = function (horiz, vert, rgba) {
    var newLoc;
    if (this.c == null) {
        throw "Requires a CamanJS context";
    }
    newLoc = this.loc + (this.c.dimensions.width * 4 * (vert * -1)) + (4 * horiz);
    if (newLoc > this.c.pixelData.length || newLoc < 0) {
        return;
    }
    this.c.pixelData[newLoc] = rgba.r;
    this.c.pixelData[newLoc + 1] = rgba.g;
    this.c.pixelData[newLoc + 2] = rgba.b;
    this.c.pixelData[newLoc + 3] = rgba.a;
    return true;
};

更正代码后,您现在应该能够创建依赖于 putPixelRelative() 的过滤器,没有任何问题。这是我创建的一个这样的过滤器。

Caman.Filter.register("erased", function (adjust) {
    this.process("erased", function (rgba) {
        if(Math.random() < 0.25) {
        rgba.putPixelRelative(2, 2, {
            r: 255,
            g: 255,
            b: 255,
            a: 255
        });
        }
    });
    return this;
});

此过滤器将当前像素向上两行和右侧两列的像素值随机设置为白色。这会擦除部分图像。这就是过滤器名称的由来。

创建新的基于内核操作的过滤器

正如我之前提到的,CamanJS 允许您创建自定义滤镜,其中当前像素的颜色由其周围的像素决定。基本上,这些滤镜会遍历您正在编辑的图像中的每个像素。图像中的一个像素将被其他八个像素包围。图像中这九个像素的值乘以卷积矩阵的相应条目。然后将所有这些乘积加在一起以获得像素的最终颜色值。您可以在 GIMP 文档中更详细地了解该过程。

就像基于像素的过滤器一样,您可以使用 Caman.Filter.register("filter_name", callback); 定义自己的内核操作过滤器。唯一的区别是您现在将在回调函数内调用 processKernel()

这是使用内核操作创建浮雕过滤器的示例。

Caman.Filter.register("emboss", function () {
    this.processKernel("emboss", [
        -2, -1, 0,
        -1, 1, 1,
        0, 1, 2
    ]);
});

以下 CodePen 演示将展示我们在本教程中创建的所有过滤器的实际操作。

最终想法

在本系列中,我几乎涵盖了 CamanJS 在基于画布的图像编辑方面提供的所有内容。您现在应该能够使用所有内置滤镜、创建新图层、在这些图层上应用混合模式以及定义您自己的混合模式和滤镜功能。

您还可以浏览 CamanJS 网站上的指南,以了解我可能错过的任何内容。我还建议您阅读该库的源代码,以了解有关图像处理的更多信息。这也将帮助您发现库中的任何其他错误。

以上是使用 CamanJS 开发自定义图像编辑器:扩展滤镜选项和混合模式的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn