Colors 请解释这个颜色混合模式公式,以便我可以在PHP/ImageMagick中复制它

Colors 请解释这个颜色混合模式公式,以便我可以在PHP/ImageMagick中复制它,colors,imagemagick,photoshop,blending,Colors,Imagemagick,Photoshop,Blending,我一直在尝试使用ImageMagick复制Photoshop的颜色混合模式。我在一个例子中发现了以下公式,但我不知道它们的意思。我只需要交换某些频道吗 A是前景像素,B是背景像素,C是新像素。H是每个像素的色调值,S是饱和度值,L是亮度值,Y是亮度值。(但不确定亮度和亮度之间的差异是什么 无论如何,在第一个示例中,新像素(C)的色调(H)和饱和度(S)值是从前景像素(A)复制的,而新像素的亮度(Y)值是从背景像素(B)的亮度(L)值获取的。维基百科有一篇关于混合模式的好文章 它们给出了乘法、

我一直在尝试使用ImageMagick复制Photoshop的颜色混合模式。我在一个例子中发现了以下公式,但我不知道它们的意思。我只需要交换某些频道吗


A是前景像素,B是背景像素,C是新像素。H是每个像素的色调值,S是饱和度值,L是亮度值,Y是亮度值。(但不确定亮度和亮度之间的差异是什么


无论如何,在第一个示例中,新像素(C)的色调(H)和饱和度(S)值是从前景像素(A)复制的,而新像素的亮度(Y)值是从背景像素(B)的亮度(L)值获取的。

维基百科有一篇关于混合模式的好文章

它们给出了乘法、屏幕和叠加模式的公式

Multiply
Formula: Result Color = (Top Color) * (Bottom Color) /255

Screen
Formula: Result Color = 255 - [((255 - Top Color)*(255 - Bottom Color))/255]

Overlay
Formula: Result Color = if (Bottom Color < 128) 
    then (2 * Top Color * Bottom Color / 255) 
    else (255 - 2 * (255 - Top Color) * (255 - Bottom Color) / 255)
乘法
公式:结果颜色=(顶色)*(底色)/255
屏风
公式:结果颜色=255-[(255-顶色)*(255-底色))/255]
覆盖层
公式:结果颜色=if(底色<128)
然后(2*顶色*底色/255)
其他(255-2*(255-顶色)*(255-底色)/255)

不久前,我改变了工程Photoshop混合模式

请看这里:

下面是我用来在HSY(色调、饱和度、亮度)和RGB(红、绿、蓝)之间转换的代码。Photoshop使用称为六锥的东西来计算饱和度

乔瓦尼

/**
 * This is the formula used by Photoshop to convert a color from
 * RGB (Red, Green, Blue) to HSY (Hue, Saturation, Luminosity).
 * The hue is calculated using the exacone approximation of the saturation
 * cone.
 * @param rgb The input color RGB normalized components.
 * @param hsy The output color HSY normalized components.
 */
public static void rgbToHsy(double rgb[], double hsy[]) {

    double r = Math.min(Math.max(rgb[0], 0d), 1d);
    double g = Math.min(Math.max(rgb[1], 0d), 1d);
    double b = Math.min(Math.max(rgb[2], 0d), 1d);

    double h;
    double s;
    double y;

    // For saturation equals to 0 any value of hue are valid.
    // In this case we choose 0 as a default value.

    if (r == g && g == b) {            // Limit case.
        s = 0d; 
        h = 0d; 
    } else if ((r >= g) && (g >= b)) { // Sector 0: 0° - 60°
        s = r - b;
        h = 60d * (g - b) / s;
    } else if ((g > r) && (r >= b)) {  // Sector 1: 60° - 120°
        s = g - b;
        h = 60d * (g - r) / s  + 60d;
    } else if ((g >= b) && (b > r)) {  // Sector 2: 120° - 180°
        s = g - r;
        h = 60d * (b - r) / s + 120d;
    } else if ((b > g) && (g > r)) {   // Sector 3: 180° - 240°
        s = b - r;
        h = 60d * (b - g) / s + 180d;
    } else if ((b > r) && (r >= g)) {  // Sector 4: 240° - 300°
        s = b - g;
        h = 60d * (r - g) / s + 240d;
    } else {                           // Sector 5: 300° - 360°
        s = r - g;
        h = 60d * (r - b) / s + 300d;
    }

    y = R * r + G * g + B * b;

    // Approximations erros can cause values to exceed bounds.

    hsy[0] = h % 360;
    hsy[1] = Math.min(Math.max(s, 0d), 1d);
    hsy[2] = Math.min(Math.max(y, 0d), 1d);
}

/**
 * This is the formula used by Photoshop to convert a color from
 * HSY (Hue, Saturation, Luminosity) to RGB (Red, Green, Blue).
 * The hue is calculated using the exacone approximation of the saturation
 * cone.
 * @param hsy The input color HSY normalized components.
 * @param rgb The output color RGB normalized components.
 */
public static void hsyToRgb(double hsy[], double rgb[]) {

    double h = hsy[0] % 360;
    double s = Math.min(Math.max(hsy[1], 0d), 1d);
    double y = Math.min(Math.max(hsy[2], 0d), 1d);

    double r;
    double g;
    double b;

    double k; // Intermediate variable.

    if (h >= 0d && h < 60d) {           // Sector 0: 0° - 60°
        k = s * h / 60d;
        b = y - R * s - G * k;
        r = b + s;
        g = b + k;
    } else if (h >= 60d && h < 120d) {  // Sector 1: 60° - 120°
        k = s * (h - 60d) / 60d;
        g = y + B * s + R * k;
        b = g - s;
        r = g - k;
    } else if (h >= 120d && h < 180d) { // Sector 2: 120° - 180°
        k = s * (h - 120d) / 60d;
        r = y - G * s - B * k;
        g = r + s;
        b = r + k;
    } else if (h >= 180d && h < 240d) { // Sector 3: 180° - 240°
        k = s * (h - 180d) / 60d;
        b = y + R * s + G * k;
        r = b - s;
        g = b - k;
    } else if (h >= 240d && h < 300d) { // Sector 4: 240° - 300°
        k = s * (h - 240d) / 60d;
        g = y - B * s - R * k;
        b = g + s;
        r = g + k;
    } else {                          // Sector 5: 300° - 360°
        k = s * (h - 300d) / 60d;
        r = y + G * s + B * k;
        g = r - s;
        b = r - k;
    }

    // Approximations erros can cause values to exceed bounds.

    rgb[0] = Math.min(Math.max(r, 0d), 1d);
    rgb[1] = Math.min(Math.max(g, 0d), 1d);
    rgb[2] = Math.min(Math.max(b, 0d), 1d);
}
/**
*这是Photoshop用来转换颜色的公式
*RGB(红、绿、蓝)到HSY(色调、饱和度、亮度)。
*使用饱和度的exacone近似值计算色调
*圆锥体。
*@param rgb输入颜色rgb规范化组件。
*@param hsy输出颜色hsy规格化组件。
*/
公共静态无效rgbToHsy(双rgb[],双hsy[]{
双r=数学最小值(数学最大值(rgb[0],0d),1d);
双g=数学最小值(数学最大值(rgb[1],0d),1d);
双b=数学最小值(数学最大值(rgb[2],0d),1d);
双h;
双s;
双y;
//对于饱和度等于0的情况,任何色调值都有效。
//在这种情况下,我们选择0作为默认值。
如果(r==g&&g==b){//极限情况。
s=0d;
h=0d;
}如果((r>=g)和&(g>=b)){//扇区0:0°-60°
s=r-b;
h=60d*(g-b)/s;
}如果((g>r)&(r>=b)){//扇区1:60°-120°
s=g-b;
h=60d*(g-r)/s+60d;
}如果((g>=b)和&(b>r)){//扇区2:120°-180°
s=g-r;
h=60d*(b-r)/s+120d;
}如果((b>g)和(&(g>r)){//扇区3:180°-240°
s=b-r;
h=60d*(b-g)/s+180d;
}如果((b>r)&(r>=g)){//扇区4:240°-300°
s=b-g;
h=60d*(r-g)/s+240d;
}其他{//扇区5:300°-360°
s=r-g;
h=60d*(r-b)/s+300d;
}
y=R*R+G*G+B*B;
//近似错误可能导致值超出边界。
hsy[0]=h%360;
hsy[1]=数学最小值(数学最大值(s,0d),1d);
hsy[2]=数学最小值(数学最大值(y,0d),1d);
}
/**
*这是Photoshop用来转换颜色的公式
*HSY(色调、饱和度、亮度)到RGB(红、绿、蓝)。
*使用饱和度的exacone近似值计算色调
*圆锥体。
*@param hsy输入颜色hsy标准化组件。
*@param rgb输出颜色rgb规范化组件。
*/
公共静态无效hsyToRgb(双hsy[],双rgb[]){
双h=hsy[0]%360;
双s=数学最小值(数学最大值(hsy[1],0d),1d);
双y=数学最小值(数学最大值(hsy[2],0d),1d);
双r;
双g;
双b;
双k;//中间变量。
如果(h>=0d&&h<60d){//扇区0:0°-60°
k=s*h/60d;
b=y-R*s-G*k;
r=b+s;
g=b+k;
}如果(h>=60d&&h<120d){//扇区1:60°-120°
k=s*(h-60d)/60d;
g=y+B*s+R*k;
b=g-s;
r=g-k;
}如果(h>=120d&&h<180d){//扇区2:120°-180°
k=s*(h-120d)/60d;
r=y-G*s-B*k;
g=r+s;
b=r+k;
}如果(h>=180d&&h<240d){//扇区3:180°-240°
k=s*(h-180d)/60d;
b=y+R*s+G*k;
r=b-s;
g=b-k;
}如果(h>=240d&&h<300d){//扇区4:240°-300°
k=s*(h-240d)/60d;
g=y-B*s-R*k;
b=g+s;
r=g+k;
}其他{//扇区5:300°-360°
k=s*(h-300d)/60d;
r=y+G*s+B*k;
g=r-s;
b=r-k;
}
//近似错误可能导致值超出边界。
rgb[0]=数学最小值(数学最大值(r,0d),1d);
rgb[1]=数学最小值(数学最大值(g,0d),1d);
rgb[2]=数学最小值(数学最大值(b,0d),1d);
}

如果您还需要合并alpha通道,这些颜色混合公式相当棘手。我无法复制Photoshop的混合,但Gimp的工作原理如下:

Color mix_hsv(
    ColorMixMode::Enum mode, // blending mode
    Color cd,                // destination color (bottom pixel)
    Color cs)                // source color (top pixel)
{
    // Modify the source color
    float dh, ds, dv; // destination hsv
    float sh, ss, sv; // source hsv
    cd.GetHsv(dh, ds, dv);
    cs.GetHsv(sh, ss, sv);

    switch (mode) {
        case HUE:        cs.InitFromHsv(sh, ds, dv); break;
        case SATURATION: cs.InitFromHsv(dh, ss, dv); break;
        case COLOR:      cs.InitFromHsv(sh, ss, dv); break;
        case LUMINOSITY: cs.InitFromHsv(dh, ds, sv); break;
    }
    cs.A = std::min(cd.A, cs.A);

    // Blend the modified source color onto the destination color
    unsigned char cd_A_orig = cd.A;
    cd = mix(NORMAL, cd, cs); // normal blending
    cd.A = cd_A_orig;
    return cd;
}
如果您使用预乘alpha,请不要忘记在上面的代码中正确处理它。我无法在Gimp的源代码中找到用于混合的代码,但生成的图像非常相似

Photoshop的颜色混合明显不同,因此如果有人找到实现它的方法,请让我们都知道:o)


味噌

谢谢,这正是我需要的。然而,这个公式毕竟不是那么简单,因为结果有点过时了。最后,我设法让它在以下帮助下工作:谢谢,这在解释维基百科的公式方面帮了我很大的忙(我之前已经查过了)。要补充的是,这些公式应该在se中运行