2011-04-28 58 views
6

我有2种颜色:1个动态设置,另一个总是白色的0.5 alpha。我想要使​​用叠加混合模式来计算最终的白色,就好像它是在动态颜色的顶部绘制的一样。重叠混合模式公式?

我知道,覆盖结合屏幕混合模式。

乘混合模式的计算公式为:

Result Color = (Top Color) * (Bottom Color) /255 

虽然屏幕混合模式的是:

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

如何计算叠加混合模式所产生的颜色?

是否有一个UIColor扩展类在那里开箱即用?

回答

7

有式的两个部分:

第一部分:如果低层值> 127.5,然后执行下列操作 -

值单位=(255下层值)/127.5

最小值=低层值 - (255下层值)

叠加=(上层值*值单位)+最小值

第二部分:如果下高层值< 127.5,然后执行以下操作 -

值单位=低层价值/ 127.5

覆盖=上层值*值单位

从我们可以看到,分子式,最后的结果是多少取决于上层的值。如果上层值更高(更轻),则最终结果更可能更轻。

here

+0

大。这不是我原来的问题的一部分,但是你知道有哪些UIColor扩展课程可以开箱吗? – samvermette 2011-04-28 21:42:21

+0

不是一个otb实现,但这可能会帮助你:https://github.com/facebook/three20/blob/master/src/Three20Style/Sources/UIColorAdditions.m – 2011-04-28 21:48:32

2

我不知道你的目标,可能是完全脱离主题,但为什么不只是使用Quartz 2D?通过CGContextSetBlendMode覆盖,乘,屏幕和更

CGContextRef ctx = UIGraphicsGetCurrentContext(); 
CGContextSetBlendMode(ctx, kCGBlendModeOverlay); 
... draw with overlay blending 

CGBlendMode优惠...:

enum CGBlendMode { 
    /* Available in Mac OS X 10.4 & later. */ 
    kCGBlendModeNormal, 
    kCGBlendModeMultiply, 
    kCGBlendModeScreen, 
    kCGBlendModeOverlay, 
    kCGBlendModeDarken, 
    kCGBlendModeLighten, 
    kCGBlendModeColorDodge, 
    kCGBlendModeColorBurn, 
    kCGBlendModeSoftLight, 
    kCGBlendModeHardLight, 
    kCGBlendModeDifference, 
    kCGBlendModeExclusion, 
    kCGBlendModeHue, 
    kCGBlendModeSaturation, 
    kCGBlendModeColor, 
    kCGBlendModeLuminosity, 

    /* Available in Mac OS X 10.5 & later. R, S, and D are, respectively, 
     premultiplied result, source, and destination colors with alpha; Ra, 
     Sa, and Da are the alpha components of these colors. 

     The Porter-Duff "source over" mode is called `kCGBlendModeNormal': 
     R = S + D*(1 - Sa) 

     Note that the Porter-Duff "XOR" mode is only titularly related to the 
     classical bitmap XOR operation (which is unsupported by 
     CoreGraphics). */ 

    kCGBlendModeClear,   /* R = 0 */ 
    kCGBlendModeCopy,   /* R = S */ 
    kCGBlendModeSourceIn,  /* R = S*Da */ 
    kCGBlendModeSourceOut,  /* R = S*(1 - Da) */ 
    kCGBlendModeSourceAtop,  /* R = S*Da + D*(1 - Sa) */ 
    kCGBlendModeDestinationOver, /* R = S*(1 - Da) + D */ 
    kCGBlendModeDestinationIn,  /* R = D*Sa */ 
    kCGBlendModeDestinationOut,  /* R = D*(1 - Sa) */ 
    kCGBlendModeDestinationAtop, /* R = S*(1 - Da) + D*Sa */ 
    kCGBlendModeXOR,   /* R = S*(1 - Da) + D*(1 - Sa) */ 
    kCGBlendModePlusDarker,  /* R = MAX(0, (1 - D) + (1 - S)) */ 
    kCGBlendModePlusLighter  /* R = MIN(1, S + D) */ 
}; 
typedef enum CGBlendMode CGBlendMode; /* Available in Mac OS X 10.4 & later. */ 
+0

这就是我一直在做的。但我需要保持使用叠加混合模式绘制的结果白色0.5 alpha颜色的参考。这样我可以在其他地方使用它并使用kCGBlendModeNormal绘制它,它看起来好像我使用kCGBlendModeOverlay绘制它。 – samvermette 2011-04-28 21:40:57

+0

啊我看,我想你可以结合几个图纸来做到这一点,我不想代码这个,就像你我猜,无论如何,如果这样的作品... :) – 2011-04-28 21:47:46

7

willi's answer跟进,这里的移植到代码中的公式:

CGFloat newComponents[4]; 
const CGFloat *topComponents = CGColorGetComponents([[UIColor colorWithRed:1 green:1 blue:1 alpha:1] CGColor]); 
const CGFloat *components = CGColorGetComponents(self.color.CGColor); 
const int n = CGColorGetNumberOfComponents(self.color.CGColor); 

for(int i=0; i < n; i++) { 

    if(components[i] > 0.5) { 
     CGFloat value = (topComponents[i]-components[i])/0.5; 
     CGFloat min = components[i]-(topComponents[i]-components[i]); 
     newComponents[i] = topComponents[i]*value+min; 
    } else { 
     CGFloat value = components[i]/0.5; 
     newComponents[i] = topComponents[i]*value; 
    } 
} 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
UIColor *resultColor = [UIColor colorWithCGColor:CGColorCreate(colorSpace, newComponents)]; 
CGColorSpaceRelease(colorSpace);