Canvas Javascript画布像素操作

Canvas Javascript画布像素操作,canvas,pixel,javascriptcore,Canvas,Pixel,Javascriptcore,我有产品图片,每个图片有两个可配置区域,如下所示: 1.出身背景 2.前景 我必须开发一个功能,客户可以更改两个区域的颜色并保存设计 我的问题是,我正在遍历图像以读取旧像素值,并使用新的选定颜色对其进行更改 位旧像素值不一致。图像上存在纹理效果,这会导致每个像素的像素值发生变化 如何实现所需的功能 或者,如果你能向我推荐其他方法,那就太好了 示例图像链接: 我假设您已经知道如何使用context.getImageData获取图像的RGBA像素数据 html5画布默认使用的RGBA格式在更改颜色时

我有产品图片,每个图片有两个可配置区域,如下所示: 1.出身背景 2.前景

我必须开发一个功能,客户可以更改两个区域的颜色并保存设计

我的问题是,我正在遍历图像以读取旧像素值,并使用新的选定颜色对其进行更改

位旧像素值不一致。图像上存在纹理效果,这会导致每个像素的像素值发生变化

如何实现所需的功能

或者,如果你能向我推荐其他方法,那就太好了

示例图像链接:

我假设您已经知道如何使用
context.getImageData
获取图像的RGBA像素数据

html5画布默认使用的RGBA格式在更改颜色时不是很有用。两种视觉上相似的颜色通常具有非常不同的RGB值

相反,将这些RGBA颜色转换为HSL格式。HSL中的“H”是“色调”,这就是我们所认为的颜色。您会发现相似的彩色像素具有相似的HSL“色调”值

然后,您可以让用户通过将现有色调值“偏移”一个恒定的偏移量来重新着色图像


演示:

我假设您已经知道如何使用
context.getImageData
获取图像的RGBA像素数据

html5画布默认使用的RGBA格式在更改颜色时不是很有用。两种视觉上相似的颜色通常具有非常不同的RGB值

相反,将这些RGBA颜色转换为HSL格式。HSL中的“H”是“色调”,这就是我们所认为的颜色。您会发现相似的彩色像素具有相似的HSL“色调”值

然后,您可以让用户通过将现有色调值“偏移”一个恒定的偏移量来重新着色图像


演示:

如果我猜对了,您想要的是将“接近”的像素从给定颜色更改为另一种颜色

我看到的最简单的方法是使用h、s、l颜色空间:在这个“自然”颜色空间中,具有相似色调的颜色将被眼睛相似地感知。你只需“改变”色调,同时保持相同的饱和度(=颜色“强度”)和亮度

因此,逐点处理图像:
•将点r、g、b转换为色调、饱和度、亮度
• ? 当前色调与sourceHue是否足够接近?
---->>将其切换到新色调(保持相同的饱和度/亮度)

小提琴在这里:

您可以随意使用参数。您提供的纹理具有18个平均色调,因此如果源色调离18太远,则不会进行任何更改。8-10似乎是一个很好的容忍度

// Provides a new canvas containing [img] where
// all pixels having a hue less than [tolerance] 
// distant from [tgtHue] will be replaced by [newHue]
function shiftHue(img, tgtHue, newHue, tolerance) {
    // normalize inputs
    var normalizedTargetHue = tgtHue / 360;
    var normalizedNewHue = newHue / 360;
    var normalizedTolerance = tolerance / 360;
    // create output canvas
    var cv2 = document.createElement('canvas');
    cv2.width = img.width;
    cv2.height = img.height;
    var ctx2 = cv2.getContext('2d');
    ctx2.drawImage(img, 0, 0);
    // get canvad img data 
    var imgData = ctx2.getImageData(0, 0, img.width, img.height);
    var data = imgData.data;
    var lastIndex = img.width * img.height * 4;
    var rgb = [0, 0, 0];
    var hsv = [0.0, 0.0, 0.0];
    // loop on all pixels
    for (var i = 0; i < lastIndex; i += 4) {
        // retrieve r,g,b (! ignoring alpha !) 
        var r = data[i];
        var g = data[i + 1];
        var b = data[i + 2];
        // convert to hsv
        RGB2HSV(r, g, b, hsv);
        // change color if hue near enough from tgtHue
        var hueDelta = hsv[0] - normalizedTargetHue;
        if (Math.abs(hueDelta) < normalizedTolerance) {
            // adjust hue
            // ??? or do not add the delta ???
            hsv[0] = normalizedNewHue  //+ hueDelta;
            // convert back to rgb
            hsvToRgb(rgb, hsv);
            // store
            data[i] = rgb[0];
            data[i + 1] = rgb[1];
            data[i + 2] = rgb[2];
        }
    }
    ctx2.putImageData(imgData, 0, 0);
    return cv2;
}

//提供包含[img]的新画布,其中
//色调小于[容差]的所有像素
//远离[tgtHue]的将被[newHue]替换
功能移位(img、tgtHue、newHue、公差){
//标准化输入
var归一化目标=tgtHue/360;
var normalizedNewHue=newHue/360;
var标准化公差=公差/360;
//创建输出画布
var cv2=document.createElement('canvas');
cv2.width=img.width;
cv2.height=img.height;
var ctx2=cv2.getContext('2d');
ctx2.drawImage(img,0,0);
//获取canvad img数据
var imgData=ctx2.getImageData(0,0,img.width,img.height);
var数据=imgData.data;
var lastIndex=img.width*img.height*4;
var rgb=[0,0,0];
var hsv=[0.0,0.0,0.0];
//在所有像素上循环
对于(var i=0;i
编辑: 为了得到颜色,我安慰道。记录颜色…;-)但很多(如果不是全部的话) 图像软件具有显示hsl的颜色选择器。
对于hsl,我没有具体的链接。谷歌它,也玩 它位于图形软件中。
为了避免编码噩梦,我想你必须决定一个惯例 在你使用的纹理上,像是60+/-5色调之类。那么你就只有
你必须决定比赛的最终色调。检测可能很棘手。

如果我猜对了,您想要的是将“接近”的像素从给定颜色更改为另一种颜色

我看到的最简单的方法是使用h、s、l颜色空间:在这个“自然”颜色空间中,具有相似色调的颜色将被眼睛相似地感知。你只需“改变”色调,同时保持相同的饱和度(=颜色“强度”)和亮度

因此,逐点处理图像:
•将点r、g、b转换为色调、饱和度、亮度
• ? 当前色调与sourceHue是否足够接近?
---->>将其切换到新色调(保持相同的饱和度/亮度)

小提琴在这里:

您可以随意使用参数。您提供的纹理具有18个平均色调,因此如果源色调离18太远,则不会进行任何更改。8-10似乎是一个很好的容忍度

// Provides a new canvas containing [img] where
// all pixels having a hue less than [tolerance] 
// distant from [tgtHue] will be replaced by [newHue]
function shiftHue(img, tgtHue, newHue, tolerance) {
    // normalize inputs
    var normalizedTargetHue = tgtHue / 360;
    var normalizedNewHue = newHue / 360;
    var normalizedTolerance = tolerance / 360;
    // create output canvas
    var cv2 = document.createElement('canvas');
    cv2.width = img.width;
    cv2.height = img.height;
    var ctx2 = cv2.getContext('2d');
    ctx2.drawImage(img, 0, 0);
    // get canvad img data 
    var imgData = ctx2.getImageData(0, 0, img.width, img.height);
    var data = imgData.data;
    var lastIndex = img.width * img.height * 4;
    var rgb = [0, 0, 0];
    var hsv = [0.0, 0.0, 0.0];
    // loop on all pixels
    for (var i = 0; i < lastIndex; i += 4) {
        // retrieve r,g,b (! ignoring alpha !) 
        var r = data[i];
        var g = data[i + 1];
        var b = data[i + 2];
        // convert to hsv
        RGB2HSV(r, g, b, hsv);
        // change color if hue near enough from tgtHue
        var hueDelta = hsv[0] - normalizedTargetHue;
        if (Math.abs(hueDelta) < normalizedTolerance) {
            // adjust hue
            // ??? or do not add the delta ???
            hsv[0] = normalizedNewHue  //+ hueDelta;
            // convert back to rgb
            hsvToRgb(rgb, hsv);
            // store
            data[i] = rgb[0];
            data[i + 1] = rgb[1];
            data[i + 2] = rgb[2];
        }
    }
    ctx2.putImageData(imgData, 0, 0);
    return cv2;
}

//提供包含[img]的新画布,其中
//色调小于[容差]的所有像素
//远离[tgtHue]的将被[newHue]替换
功能移位(img、tgtHue、newHue、公差){
//标准化输入
var归一化目标=tgtHue/360;
var normalizedNewHue=newHue/360;