2011-05-07 62 views

回答

193

Photoshop通过对图像A中的每个像素对图像B中的相应像素执行混合操作来将两个图像混合在一起。每个像素是由多个通道组成的颜色。假设我们正在处理RGB像素,每个像素中的通道将是红色,绿色和蓝色。要混合两个像素,我们混合它们各自的通道。

出现在Photoshop每个混合模式可以在下面的宏来总结出来的混合操作:

#define ChannelBlend_Normal(A,B)  ((uint8)(A)) 
#define ChannelBlend_Lighten(A,B) ((uint8)((B > A) ? B:A)) 
#define ChannelBlend_Darken(A,B)  ((uint8)((B > A) ? A:B)) 
#define ChannelBlend_Multiply(A,B) ((uint8)((A * B)/255)) 
#define ChannelBlend_Average(A,B) ((uint8)((A + B)/2)) 
#define ChannelBlend_Add(A,B)  ((uint8)(min(255, (A + B)))) 
#define ChannelBlend_Subtract(A,B) ((uint8)((A + B < 255) ? 0:(A + B - 255))) 
#define ChannelBlend_Difference(A,B) ((uint8)(abs(A - B))) 
#define ChannelBlend_Negation(A,B) ((uint8)(255 - abs(255 - A - B))) 
#define ChannelBlend_Screen(A,B)  ((uint8)(255 - (((255 - A) * (255 - B)) >> 8))) 
#define ChannelBlend_Exclusion(A,B) ((uint8)(A + B - 2 * A * B/255)) 
#define ChannelBlend_Overlay(A,B) ((uint8)((B < 128) ? (2 * A * B/255):(255 - 2 * (255 - A) * (255 - B)/255))) 
#define ChannelBlend_SoftLight(A,B) ((uint8)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255)))) 
#define ChannelBlend_HardLight(A,B) (ChannelBlend_Overlay(B,A)) 
#define ChannelBlend_ColorDodge(A,B) ((uint8)((B == 255) ? B:min(255, ((A << 8)/(255 - B))))) 
#define ChannelBlend_ColorBurn(A,B) ((uint8)((B == 0) ? B:max(0, (255 - ((255 - A) << 8)/B)))) 
#define ChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B)) 
#define ChannelBlend_LinearBurn(A,B) (ChannelBlend_Subtract(A,B)) 
#define ChannelBlend_LinearLight(A,B)((uint8)(B < 128)?ChannelBlend_LinearBurn(A,(2 * B)):ChannelBlend_LinearDodge(A,(2 * (B - 128)))) 
#define ChannelBlend_VividLight(A,B) ((uint8)(B < 128)?ChannelBlend_ColorBurn(A,(2 * B)):ChannelBlend_ColorDodge(A,(2 * (B - 128)))) 
#define ChannelBlend_PinLight(A,B) ((uint8)(B < 128)?ChannelBlend_Darken(A,(2 * B)):ChannelBlend_Lighten(A,(2 * (B - 128)))) 
#define ChannelBlend_HardMix(A,B) ((uint8)((ChannelBlend_VividLight(A,B) < 128) ? 0:255)) 
#define ChannelBlend_Reflect(A,B) ((uint8)((B == 255) ? B:min(255, (A * A/(255 - B))))) 
#define ChannelBlend_Glow(A,B)  (ChannelBlend_Reflect(B,A)) 
#define ChannelBlend_Phoenix(A,B) ((uint8)(min(A,B) - max(A,B) + 255)) 
#define ChannelBlend_Alpha(A,B,O) ((uint8)(O * A + (1 - O) * B)) 
#define ChannelBlend_AlphaF(A,B,F,O) (ChannelBlend_Alpha(F(A,B),A,O)) 

融入一个单一的RGB像素,你会做到以下几点:

ImageTColorR = ChannelBlend_Glow(ImageAColorR, ImageBColorR); 
ImageTColorB = ChannelBlend_Glow(ImageAColorB, ImageBColorB); 
ImageTColorG = ChannelBlend_Glow(ImageAColorG, ImageBColorG); 

ImageTColor = RGB(ImageTColorR, ImageTColorB, ImageTColorG); 

如果我们想用特定的不透明度进行混合操作,比如说50%:

ImageTColorR = ChannelBlend_AlphaF(ImageAColorR, ImageBColorR, Blend_Subtract, 0.5F); 

如果你有一个指针为图像的图像数据A,B,和T(我们的目标),我们可以简化使用该宏所有三个通道的混合:

#define ColorBlend_Buffer(T,A,B,M)  (T)[0] = ChannelBlend_##M((A)[0], (B)[0]), 
             (T)[1] = ChannelBlend_##M((A)[1], (B)[1]), 
             (T)[2] = ChannelBlend_##M((A)[2], (B)[2]) 

而且可以得出以下RGB颜色混合宏:

#define ColorBlend_Normal(T,A,B)  (ColorBlend_Buffer(T,A,B,Normal)) 
#define ColorBlend_Lighten(T,A,B)  (ColorBlend_Buffer(T,A,B,Lighten)) 
#define ColorBlend_Darken(T,A,B)  (ColorBlend_Buffer(T,A,B,Darken)) 
#define ColorBlend_Multiply(T,A,B)  (ColorBlend_Buffer(T,A,B,Multiply)) 
#define ColorBlend_Average(T,A,B)  (ColorBlend_Buffer(T,A,B,Average)) 
#define ColorBlend_Add(T,A,B)   (ColorBlend_Buffer(T,A,B,Add)) 
#define ColorBlend_Subtract(T,A,B)  (ColorBlend_Buffer(T,A,B,Subtract)) 
#define ColorBlend_Difference(T,A,B) (ColorBlend_Buffer(T,A,B,Difference)) 
#define ColorBlend_Negation(T,A,B)  (ColorBlend_Buffer(T,A,B,Negation)) 
#define ColorBlend_Screen(T,A,B)  (ColorBlend_Buffer(T,A,B,Screen)) 
#define ColorBlend_Exclusion(T,A,B)  (ColorBlend_Buffer(T,A,B,Exclusion)) 
#define ColorBlend_Overlay(T,A,B)  (ColorBlend_Buffer(T,A,B,Overlay)) 
#define ColorBlend_SoftLight(T,A,B)  (ColorBlend_Buffer(T,A,B,SoftLight)) 
#define ColorBlend_HardLight(T,A,B)  (ColorBlend_Buffer(T,A,B,HardLight)) 
#define ColorBlend_ColorDodge(T,A,B) (ColorBlend_Buffer(T,A,B,ColorDodge)) 
#define ColorBlend_ColorBurn(T,A,B)  (ColorBlend_Buffer(T,A,B,ColorBurn)) 
#define ColorBlend_LinearDodge(T,A,B) (ColorBlend_Buffer(T,A,B,LinearDodge)) 
#define ColorBlend_LinearBurn(T,A,B) (ColorBlend_Buffer(T,A,B,LinearBurn)) 
#define ColorBlend_LinearLight(T,A,B) (ColorBlend_Buffer(T,A,B,LinearLight)) 
#define ColorBlend_VividLight(T,A,B) (ColorBlend_Buffer(T,A,B,VividLight)) 
#define ColorBlend_PinLight(T,A,B)  (ColorBlend_Buffer(T,A,B,PinLight)) 
#define ColorBlend_HardMix(T,A,B)  (ColorBlend_Buffer(T,A,B,HardMix)) 
#define ColorBlend_Reflect(T,A,B)  (ColorBlend_Buffer(T,A,B,Reflect)) 
#define ColorBlend_Glow(T,A,B)   (ColorBlend_Buffer(T,A,B,Glow)) 
#define ColorBlend_Phoenix(T,A,B)  (ColorBlend_Buffer(T,A,B,Phoenix)) 

而且例子是:

ColorBlend_Glow(TargetPtr, ImageAPtr, ImageBPtr); 

的Photoshop的混合模式的剩余部分涉及转换RGB到HLS,然后再返回。

#define ColorBlend_Hue(T,A,B)   ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationA) 
#define ColorBlend_Saturation(T,A,B)  ColorBlend_Hls(T,A,B,HueA,LuminationA,SaturationB) 
#define ColorBlend_Color(T,A,B)   ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationB) 
#define ColorBlend_Luminosity(T,A,B)  ColorBlend_Hls(T,A,B,HueA,LuminationB,SaturationA) 

#define ColorBlend_Hls(T,A,B,O1,O2,O3) { 
    float64 HueA, LuminationA, SaturationA; 
    float64 HueB, LuminationB, SaturationL; 
    Color_RgbToHls((A)[2],(A)[1],(A)[0], &HueA, &LuminationA, &SaturationA); 
    Color_RgbToHls((B)[2],(B)[1],(B)[0], &HueB, &LuminationB, &SaturationB); 
    Color_HlsToRgb(O1,O2,O3,&(T)[2],&(T)[1],&(T)[0]); 
    } 

这些函数将有助于将RGB转换为HLS。

int32 Color_HueToRgb(float64 M1, float64 M2, float64 Hue, float64 *Channel) 
{ 
    if (Hue < 0.0) 
     Hue += 1.0; 
    else if (Hue > 1.0) 
     Hue -= 1.0; 

    if ((6.0 * Hue) < 1.0) 
     *Channel = (M1 + (M2 - M1) * Hue * 6.0); 
    else if ((2.0 * Hue) < 1.0) 
     *Channel = (M2); 
    else if ((3.0 * Hue) < 2.0) 
     *Channel = (M1 + (M2 - M1) * ((2.0F/3.0F) - Hue) * 6.0); 
    else 
     *Channel = (M1); 

    return TRUE; 
} 

int32 Color_RgbToHls(uint8 Red, uint8 Green, uint8 Blue, float64 *Hue, float64 *Lumination, float64 *Saturation) 
{ 
    float64 Delta; 
    float64 Max, Min; 
    float64 Redf, Greenf, Bluef; 

    Redf = ((float64)Red /255.0F); 
    Greenf = ((float64)Green/255.0F); 
    Bluef = ((float64)Blue/255.0F); 

    Max  = max(max(Redf, Greenf), Bluef); 
    Min  = min(min(Redf, Greenf), Bluef); 

    *Hue  = 0; 
    *Lumination = (Max + Min)/2.0F; 
    *Saturation = 0; 

    if (Max == Min) 
     return TRUE; 

    Delta = (Max - Min); 

    if (*Lumination < 0.5) 
     *Saturation = Delta/(Max + Min); 
    else 
     *Saturation = Delta/(2.0 - Max - Min); 

    if (Redf == Max) 
     *Hue = (Greenf - Bluef)/Delta; 
    else if (Greenf == Max) 
     *Hue = 2.0 + (Bluef - Redf)/Delta; 
    else 
     *Hue = 4.0 + (Redf - Greenf)/Delta; 

    *Hue /= 6.0; 

    if (*Hue < 0.0) 
     *Hue += 1.0;  

    return TRUE; 
} 

int32 Color_HlsToRgb(float64 Hue, float64 Lumination, float64 Saturation, uint8 *Red, uint8 *Green, uint8 *Blue) 
{ 
    float64 M1, M2; 
    float64 Redf, Greenf, Bluef; 

    if (Saturation == 0) 
     { 
     Redf = Lumination; 
     Greenf = Lumination; 
     Bluef = Lumination; 
     } 
    else 
     { 
     if (Lumination <= 0.5) 
      M2 = Lumination * (1.0 + Saturation); 
     else 
      M2 = Lumination + Saturation - Lumination * Saturation; 

     M1 = (2.0 * Lumination - M2); 

     Color_HueToRgb(M1, M2, Hue + (1.0F/3.0F), &Redf); 
     Color_HueToRgb(M1, M2, Hue, &Greenf); 
     Color_HueToRgb(M1, M2, Hue - (1.0F/3.0F), &Bluef); 
     } 

    *Red = (uint8)(Redf * 255); 
    *Blue = (uint8)(Bluef * 255); 
    *Green = (uint8)(Greenf * 255); 

    return TRUE; 
} 

有更多的资源在这个题目,主要是:

  1. PegTop blend modes
  2. Forensic Photoshop
  3. Insight into Photoshop 7.0 Blend Modes
  4. SF - Basics - Blending Modes
  5. finish the blend modes
  6. Romz blog
  7. ReactOS RGB-HLS conversion functions
+21

哇........... – CMircea 2011-05-08 05:45:56

+3

谢谢,很好的问题和答案! – thumbmunkeys 2012-01-27 13:06:24

+1

是的,很好的答案,谢谢!我想知道是否有人知道如何在Photoshop中完成图层不透明?即我想使用混合变暗功能,但只有50%...我检查了在Photoshop中的值,它似乎并没有,这是足够的只采用50%的混合图像的值... – Maecky 2012-11-11 12:22:32

0

虽然流行的答案是正确的大部分,下面的语句是错误的。 “其余的Photoshop混合模式涉及将RGB转换为HLS并再次返回。”不,Photoshop(只有Photoshop)使用Chroma和Luma来代替HLS。

因此对于色调,颜色,亮度和饱和度模式,您不能使用简单的算法。要在这些情况下匹配Photoshop的方法,您需要为Adobe工作。

3

受欢迎的答案是99。9%正确,但正如Greyfriars所说,它不会得到确切的结果,因为Adobe在混合中不会使用HLS。

但你并不需要在Adobe公司为了做到这一点...你可以完全达到此以下的所有规则本文档中从Adobe相同的混合工作:

基本上章4 7: ​​

然后,您将达到Adobe的确切结果! Pixel by Pixel!

6

此答案中的色调,颜色,饱和度混合模式是错误的。没有Adobe产品转换为HSB,他们直接对RGB值进行操作。

下面是设置亮度,例如GLSL:

float lum(vec4 color) 
{ 
    return ((0.3 * color.r) + (0.59 * color.g) + (0.11 * color.b)); 
} 

vec4 clipColor(vec4 color) 
{ 
    vec4 newColor=color; 
    float l=lum(color); 
    float n=min(min(color.r,color.g),color.b); 
    float x=max(max(color.r,color.g),color.b); 

    newColor.r=(n<0.0) ? l+(((color.r-l)*l)/(l-n)) : color.r; 
    newColor.r=(x>1.0) ? l+(((color.r-l)*(1.0-l))/(x-l)) : color.r; 

    newColor.g=(n<0.0) ? l+(((color.g-l)*l)/(l-n)) : color.g; 
    newColor.g=(x>1.0) ? l+(((color.g-l)*(1.0-l))/(x-l)) : color.g; 

    newColor.b=(n<0.0) ? l+(((color.b-l)*l)/(l-n)) : color.b; 
    newColor.b=(x>1.0) ? l+(((color.b-l)*(1.0-l))/(x-l)) : color.b; 

    return clamp(newColor,0.0,1.0); 
} 

vec4 setlum(vec4 color, float l) 
{ 
    float d=l-lum(color); 
    color.r+=d; 
    color.g+=d; 
    color.b+=d; 

    return clipColor(color);  
} 

kernel vec4 blendLuminosity(sampler topimage, sampler bottomimage) 
{ 
    vec4 base=sample(bottomimage, samplerCoord(bottomimage)); 
    vec4 blend=sample(topimage, samplerCoord(topimage)); 

    float bl=lum(blend); 
    return setlum(base,bl); 
} 

不支持if ... else语句在CIKernels,因此,使用三元运算符。

相关问题