ColorBlend公式

本文深入探讨了Photoshop中各种混合模式的算法实现,包括从基础到高级的混合模式,如正常、光照、暗调等,通过宏定义提供了一种简化RGB像素混合的方法,并详细解释了如何使用这些算法来实现特定的融合效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The blend operation that occurs for each blend mode in Photoshop can be summed up in the following macros:

#defineChannelBlend_Normal(A,B)((uint8)(A))#defineChannelBlend_Lighten(A,B)((uint8)((B > A)? B:A))#defineChannelBlend_Darken(A,B)((uint8)((B > A)? A:B))#defineChannelBlend_Multiply(A,B)((uint8)((A * B)/255))#defineChannelBlend_Average(A,B)((uint8)((A + B)/2))#defineChannelBlend_Add(A,B)((uint8)(min(255,(A + B))))#defineChannelBlend_Subtract(A,B)((uint8)((A + B <255)?0:(A + B -255)))#defineChannelBlend_Difference(A,B)((uint8)(abs(A - B)))#defineChannelBlend_Negation(A,B)((uint8)(255- abs(255- A - B)))#defineChannelBlend_Screen(A,B)((uint8)(255-(((255- A)*(255- B))>>8)))#defineChannelBlend_Exclusion(A,B)((uint8)(A + B -2* A * B /255))#defineChannelBlend_Overlay(A,B)((uint8)((B <128)?(2* A * B /255):(255-2*(255- A)*(255- B)/255)))#defineChannelBlend_SoftLight(A,B)((uint8)((B <128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))))#defineChannelBlend_HardLight(A,B)(ChannelBlend_Overlay(B,A))#defineChannelBlend_ColorDodge(A,B)((uint8)((B ==255)? B:min(255,((A <<8)/(255- B)))))#defineChannelBlend_ColorBurn(A,B)((uint8)((B ==0)? B:max(0,(255-((255- A)<<8)/ B))))#defineChannelBlend_LinearDodge(A,B)(ChannelBlend_Add(A,B))#defineChannelBlend_LinearBurn(A,B)(ChannelBlend_Subtract(A,B))#defineChannelBlend_LinearLight(A,B)((uint8)(B <128)?ChannelBlend_LinearBurn(A,(2* B)):ChannelBlend_LinearDodge(A,(2*(B -128))))#defineChannelBlend_VividLight(A,B)((uint8)(B <128)?ChannelBlend_ColorBurn(A,(2* B)):ChannelBlend_ColorDodge(A,(2*(B -128))))#defineChannelBlend_PinLight(A,B)((uint8)(B <128)?ChannelBlend_Darken(A,(2* B)):ChannelBlend_Lighten(A,(2*(B -128))))#defineChannelBlend_HardMix(A,B)((uint8)((ChannelBlend_VividLight(A,B)<128)?0:255))#defineChannelBlend_Reflect(A,B)((uint8)((B ==255)? B:min(255,(A * A /(255- B)))))#defineChannelBlend_Glow(A,B)(ChannelBlend_Reflect(B,A))#defineChannelBlend_Phoenix(A,B)((uint8)(min(A,B)- max(A,B)+255))#defineChannelBlend_Alpha(A,B,O)((uint8)(O * A +(1- O)* B))#defineChannelBlend_AlphaF(A,B,F,O)(ChannelBlend_Alpha(F(A,B),A,O))
To blend a single RGB pixel you would do the following:
ImageTColorR=ChannelBlend_Glow(ImageAColorR,ImageBColorR);ImageTColorB=ChannelBlend_Glow(ImageAColorB,ImageBColorB);ImageTColorG=ChannelBlend_Glow(ImageAColorG,ImageBColorG);ImageTColor= RGB(ImageTColorR,ImageTColorB,ImageTColorG);
If we wanted to perform a blend operation with a particular opacity, say 50%:
ImageTColorR=ChannelBlend_AlphaF(ImageAColorR,ImageBColorR,Blend_Subtract,0.5F);
If you have pointers to the image data for images A, B, and T (our target), we can simplify the blending of all three channels using this macro:
#defineColorBlend_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])
And can derive the following RGB color blend macros:
#defineColorBlend_Normal(T,A,B)(ColorBlend_Buffer(T,A,B,Normal))#defineColorBlend_Lighten(T,A,B)(ColorBlend_Buffer(T,A,B,Lighten))#defineColorBlend_Darken(T,A,B)(ColorBlend_Buffer(T,A,B,Darken))#defineColorBlend_Multiply(T,A,B)(ColorBlend_Buffer(T,A,B,Multiply))#defineColorBlend_Average(T,A,B)(ColorBlend_Buffer(T,A,B,Average))#defineColorBlend_Add(T,A,B)(ColorBlend_Buffer(T,A,B,Add))#defineColorBlend_Subtract(T,A,B)(ColorBlend_Buffer(T,A,B,Subtract))#defineColorBlend_Difference(T,A,B)(ColorBlend_Buffer(T,A,B,Difference))#defineColorBlend_Negation(T,A,B)(ColorBlend_Buffer(T,A,B,Negation))#defineColorBlend_Screen(T,A,B)(ColorBlend_Buffer(T,A,B,Screen))#defineColorBlend_Exclusion(T,A,B)(ColorBlend_Buffer(T,A,B,Exclusion))#defineColorBlend_Overlay(T,A,B)(ColorBlend_Buffer(T,A,B,Overlay))#defineColorBlend_SoftLight(T,A,B)(ColorBlend_Buffer(T,A,B,SoftLight))#defineColorBlend_HardLight(T,A,B)(ColorBlend_Buffer(T,A,B,HardLight))#defineColorBlend_ColorDodge(T,A,B)(ColorBlend_Buffer(T,A,B,ColorDodge))#defineColorBlend_ColorBurn(T,A,B)(ColorBlend_Buffer(T,A,B,ColorBurn))#defineColorBlend_LinearDodge(T,A,B)(ColorBlend_Buffer(T,A,B,LinearDodge))#defineColorBlend_LinearBurn(T,A,B)(ColorBlend_Buffer(T,A,B,LinearBurn))#defineColorBlend_LinearLight(T,A,B)(ColorBlend_Buffer(T,A,B,LinearLight))#defineColorBlend_VividLight(T,A,B)(ColorBlend_Buffer(T,A,B,VividLight))#defineColorBlend_PinLight(T,A,B)(ColorBlend_Buffer(T,A,B,PinLight))#defineColorBlend_HardMix(T,A,B)(ColorBlend_Buffer(T,A,B,HardMix))#defineColorBlend_Reflect(T,A,B)(ColorBlend_Buffer(T,A,B,Reflect))#defineColorBlend_Glow(T,A,B)(ColorBlend_Buffer(T,A,B,Glow))#defineColorBlend_Phoenix(T,A,B)(ColorBlend_Buffer(T,A,B,Phoenix))
And example would be:
ColorBlend_Glow(TargetPtr,ImageAPtr,ImageBPtr);
The remainder of the photoshop blend modes involve converting RGB to HLS and back again.
#defineColorBlend_Hue(T,A,B)ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationA)#defineColorBlend_Saturation(T,A,B)ColorBlend_Hls(T,A,B,HueA,LuminationA,SaturationB)#defineColorBlend_Color(T,A,B)ColorBlend_Hls(T,A,B,HueB,LuminationA,SaturationB)#defineColorBlend_Luminosity(T,A,B)ColorBlend_Hls(T,A,B,HueA,LuminationB,SaturationA)#defineColorBlend_Hls(T,A,B,O1,O2,O3){float64HueA,LuminationA,SaturationA;float64HueB,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]);}
These functions will be helpful in converting RGB to HLS.
int32Color_HueToRgb(float64 M1,float64 M2,float64Hue,float64*Channel){if(Hue<0.0)Hue+=1.0;elseif(Hue>1.0)Hue-=1.0;if((6.0*Hue)<1.0)*Channel=(M1 +(M2 - M1)*Hue*6.0);elseif((2.0*Hue)<1.0)*Channel=(M2);elseif((3.0*Hue)<2.0)*Channel=(M1 +(M2 - M1)*((2.0F/3.0F)-Hue)*6.0);else*Channel=(M1);return TRUE;}int32Color_RgbToHls(uint8Red,uint8Green,uint8Blue,float64*Hue,float64*Lumination,float64*Saturation){float64Delta;float64Max,Min;float64Redf,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;elseif(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;}int32Color_HlsToRgb(float64Hue,float64Lumination,float64Saturation,uint8*Red,uint8*Green,uint8*Blue){float64 M1, M2;float64Redf,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;}
 
### 正片叠底混合模式的数学计算公式 正片叠底(Multiply)是一种常见的图像混合模式,在数字图像处理中被广泛使用。其核心原理是对两个图层的像素值进行逐像素乘法操作后再标准化到合适的范围。具体来说,对于给定的两个图层,假设它们的像素颜色值分别为 \( C_1 \) 和 \( C_2 \),则正片叠底的结果颜色值 \( C_{\text{result}} \) 可通过以下公式计算: \[ C_{\text{result}} = C_1 \times C_2 \] 这里的颜色值通常是以浮点数形式表示的 RGB 值,范围为 [0, 1]。如果输入的颜色值是以整数值的形式给出,则需要先将其转换为浮点数再执行上述计算[^2]。 在实际应用中,例如 QGIS 或 three.js 这样的工具库实现正片叠底时,会遵循类似的逻辑来定义混合算法[^3][^4]。以下是基于该公式的伪代码实现示例: ```python def multiply_blend_mode(color_bottom, color_top): """ 实现正片叠底混合模式 :param color_bottom: 下方图层的RGB颜色 (R, G, B), 范围为[0, 1] :param color_top: 上方图层的RGB颜色 (R, G, B), 范围为[0, 1] :return: 结果颜色 (R, G, B) """ r_result = color_bottom[0] * color_top[0] g_result = color_bottom[1] * color_top[1] b_result = color_bottom[2] * color_top[2] return (r_result, g_result, b_result) # 示例调用 color_bottom = (0.8, 0.6, 0.4) # 下方图层颜色 color_top = (0.5, 0.7, 0.9) # 上方图层颜色 result_color = multiply_blend_mode(color_bottom, color_top) print(result_color) # 输出结果颜色 ``` 此代码展示了如何根据正片叠底的数学公式计算两个图层的混合结果。需要注意的是,最终结果显示的颜色将是原颜色值的乘积,因此整体亮度会降低,这是正片叠底的一个显著特征。 --- ####
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值