Canvas 将图像分割成 rgba 组件

Jul*_*nie 2 javascript canvas image-processing html5-canvas

我正在尝试将黑白图像分割为其 RGB 分量,并偏移每个图层,将其设置为叠加。这个想法是让英雄图像稍微偏离套准并随机稍微移动它。

我想知道这实际上是否是解决此问题的正确方法。

如果我敢在函数中添加控制台日志来查看哪里出错了,我往往会导致浏览器崩溃。

有人在浏览器中做过这种操作吗?它可行吗?

https://github.com/Julieslv/image-shift/blob/master/index.js

Bli*_*n67 7

将图像分割为 RGBA 通道

首先请注意,您无法将通道与图像分开。您只能将不需要的通道设置为零。然而,将 Alpha 通道设置为零会自动将所有通道归零。因此您必须保留 Alpha 通道。

复制图片

要复制图像,请创建第二个画布并将原始图像绘制到其上。

下面的函数可以做到这一点

function copyToCanvas(image) {
    const can = document.createElement("canvas");
    can.width = image.naturalWidth || image.width;
    can.height = image.naturalHeight || image.height;
    can.ctx = can.getContext("2d");
    can.ctx.drawImage(image, 0, 0);
    return can;
}
Run Code Online (Sandbox Code Playgroud)

删除频道数据

二是从前面的方法复制的图像中去除不需要的通道数据需要两个步骤。

  1. 使用复合操作"multiply"去除不需要的通道数据。
  2. 上述步骤将 Alpha 通道设置为 255。要恢复 Alpha,您可以使用合成操作"destination-in",并将原始图像绘制在新图像上。

以下函数将复制图像、删除不需要的通道数据并保持 Alpha 通道完整。

const channels = {
   red: "#F00",
   green: "#0F0",
   blue: "#00F",
};

function getChannel(channelName, image) {
    const copy = copyToCanvas(image);
    const ctx = copy.ctx;
    ctx.fillStyle = channels[channelName];
    ctx.globalCompositeOperation = "multiply";
    ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    ctx.globalCompositeOperation = "destination-in";
    ctx.drawImage(image, 0, 0);
    ctx.globalCompositeOperation = "source-over";
    return copy;
}
Run Code Online (Sandbox Code Playgroud)

获取 RGB 通道

由于保留了 Alpha 通道,因此您只需要分离出红、绿和蓝色通道。

使用前面的函数,下面将创建一个对象来保存原始图像和 3 个通道

 function seperateRGB(image) {
     return {
         red: getChannel("red", image),
         green: getChannel("green", image),
         blue: getChannel("blue", image),
     };
 }
Run Code Online (Sandbox Code Playgroud)

重组渠道

现在通道已经分离,您可以通过首先制作一个与原始图像大小相同的新画布加上您在重新组合图像时添加的任何偏移量来重新组合通道(如果您不添加回 Alpha)。

function createCanvas(w, h) {
    const can = document.createElement("canvas");
    can.width = w;
    can.height = h;
    can.ctx = can.getContext("2d");
    return can;
}
Run Code Online (Sandbox Code Playgroud)

然后将第一个通道(可以是 3 个通道中的任何一个)绘制到新画布上。然后使用复合操作绘制另外两个通道"lighter"。然后使用复合操作恢复alpha"destination-in"

const RGB = seperateRGB(image);
const recombined = createCanvas(RGB.red.width, RGB.red.height);
const ctx = recombined.ctx;

ctx.drawImage(RGB.red, -2, -2);
ctx.globalCompositeOperation = "lighter";
ctx.drawImage(RGB.green, 0, 0);
ctx.drawImage(RGB.blue, 2, 2);
ctx.globalCompositeOperation = "destination-in";
ctx.drawImage(image, 0, 0);
ctx.globalCompositeOperation = "source-over";
Run Code Online (Sandbox Code Playgroud)

全做完了

canvas 元素recombined保存重新组合的图像,其中绿色和蓝色通道偏移 2 个像素,并恢复原始 Alpha。

请注意,您不需要恢复 Alpha。如果某些通道发生偏移,则恢复 Alpha 将删除一些非重叠像素。