2011-04-28 116 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);