首頁  >  文章  >  web前端  >  使用 CamanJS 建立自訂濾鏡和混合模式影像編輯器

使用 CamanJS 建立自訂濾鏡和混合模式影像編輯器

PHPz
PHPz原創
2023-09-04 10:41:021488瀏覽

使用 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