I have 2 colors: 1 dynamically set and another that's always white 0.5 alpha. I want to calculate the resulting white color as if it was drawn on top of the dynamic color using Overlay blend mode.
I'm aware that Overlay combines Multiply and Screen blend modes.
Multiply blend mode's formula is:
Result Color = (Top Color) * (Bottom Color) /255
While Screen blend mode's is:
Result Color = 255 - [((255 - Top Color)*(255 - Bottom Color))/255]
How do I calculate the resulting color for the Overlay blend mode?
Is there a UIColor
extension class out there that does this out of the box?
Overlay is another of Photoshop's most Commonly Used Blending Modes. It uses Screen at half strength on colors brighter than 50% gray. And the Multiply at half strength on colors darker than 50% gray. 50% gray itself becomes transparent.
The Subtract mode subtracts the color of the blending layer from the base colors, resulting in a darker color. The Lighten mode compares the base colors and the colors of the blending layer, and keeps the lighter color. The Screen mode inverts the base colors and multiplies with the colors of the blending layer.
There are two part of formula:
First part: If Lower Layer Value > 127.5, then do the following -
Value Unit = (255-Lower Layer Value)/127.5
Min Value = Lower Layer Value - (255-Lower Layer Value)
Overlay = (Upper Layer Value * Value Unit) + Min Value
Second part: If Lower Layer Value < 127.5, then do the following -
Value Unit=Lower Layer Value/127.5
Overlay = Upper Layer Value * Value Unit
From the formual we can see that the final result is much depend on the upper layer value. If the upper layer value is higher(lighter), then the final result is more likely to be lighter.
From here.
Following up on willi's answer, here's the formula 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);
I have no idea of your goal, and might be completely off-topic, but why not just using Quartz 2D?
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeOverlay);
... draw with overlay blending
CGBlendMode
offers via 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. */
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With