答案 0 :(得分:6)
不久前,我改进了Photoshop混合模式。
看看这里:
http://www.kineticsystem.org/?q=node/13
下面是我用来在RGB(红色,绿色,蓝色)之间转换HSY(色调,饱和度,亮度)的代码。 Photoshop使用一种名为Hexacones的东西来计算饱和度。
乔瓦尼
/**
* 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);
}
答案 1 :(得分:2)
维基百科有一篇关于混合模式的好文章 http://en.wikipedia.org/wiki/Blend_modes
他们为Multiply,Screen和Overlay模式提供公式。
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)
答案 2 :(得分:0)
A是前景像素,B是背景像素,C是新像素。 H是每个像素的Hue值,S是饱和度值,L是亮度值,Y是亮度值。 (不知道亮度和亮度之间有什么区别。
无论如何,在第一个例子中,新像素(C)的Hue(H)和饱和度(S)值是从前景像素(A)复制的,而新像素的亮度(Y)值是从背景(B)像素的亮度(L)值。
答案 3 :(得分:0)
如果您还需要合并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)
味噌