The blend mode formula?

I have 2 colors: 1 dynamically set and another that is always white 0.5 alpha. I want to calculate the resulting white color as if it were drawn on top of a dynamic color using the Overlay blend mode.

I know that Overlay combines Multiply and Screen blending modes.

Mixed Blend Formula:

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

While the screen change mode:

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

How to calculate the resulting color for blending mode?

Is there a UIColor extension class that does this out of the box?

+6
source share
3 answers

There are two parts to the formula:

The first part: if the value of the bottom layer is> 127.5, do the following:

Value Unit = (255-Lower Level) /127.5

Minimum value = lower layer value - (value 255 of the lower layer)

Overlay = (top level value * unit) + minimum value

Second part: if the value of the lower layer is <127.5, then do the following:

Value Unit = Low Level /127.5

Overlay = High Level Value * Unit

From the formal we see that the final result is highly dependent on the value of the upper level. If the value of the upper level is higher (lighter), then the final result will be easier.

From here .

+7
source

Following willi's answer , here the formula is ported to code:

 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); 
+7
source

I have no idea about your goal and may be completely off topic, but why not just use Quartz 2D?

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

CGBlendMode offers through CGContextSetBlendMode Overlay, Multiply, Screen and much more ...:

 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. */ 
+2
source

Source: https://habr.com/ru/post/886922/


All Articles