叠加混合模式公式?

发布于 2024-11-03 19:29:04 字数 426 浏览 9 评论 0原文

我有两种颜色:一种是动态设置的,另一种是始终白色的 0.5 alpha。我想计算生成的白色,就好像它是使用叠加混合模式绘制在动态颜色之上一样。

我知道叠加结合了正片叠底滤色混合模式。

乘法混合模式的公式为:

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

而屏幕混合模式的公式为:

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

如何计算叠加混合模式的结果颜色?

是否有一个 UIColor 扩展类可以开箱即用?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

巷雨优美回忆 2024-11-10 19:29:04

公式分为两部分:

第一部分:如果下层值> 127.5,则执行以下操作 -

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

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

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

第二部分:如果下层值< 127.5,则执行以下操作:

Value Unit=Lower Layer Value/127.5

Overlay = Upper Layer Value * Value Unit

从公式中我们可以看出,最终的结果很大程度上取决于上层值。如果上层值较高(较亮),则最终结果更有可能较亮。

来自此处

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.

染柒℉ 2024-11-10 19:29:04

willi 的回答之后,以下是将公式移植到代码中:

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

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);
維他命╮ 2024-11-10 19:29:04

我不知道你的目标,可能完全偏离主题,但为什么不直接使用 Quartz 2D 呢?

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

< code>CGBlendMode 通过 CGContextSetBlendMode 提供叠加、乘法、屏幕等等...:

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. */

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. */
活泼老夫 2024-11-10 19:29:04

对于后代(因为这是谷歌的顶级结果),维基百科的公式更清晰、更简单。

这是它的伪代码版本。如果处理 1 字节颜色,​​则可以使用 255 和 127。

// For 'a' base layer, 'b' top layer.

if (a < 0.5) {
    result = 2 * a * b;
} else {
    result = 1 - 2 * (1 - a) * (1 - b);
}

https://en.wikipedia.org/wiki/Blend_modes#Overlay

For posterity (since this is top google result), the wikipedia formula is cleaner and more straightforward.

Here is a pseudo-code version of it. You'd use 255 and 127 if you are dealing with 1 Byte colors.

// For 'a' base layer, 'b' top layer.

if (a < 0.5) {
    result = 2 * a * b;
} else {
    result = 1 - 2 * (1 - a) * (1 - b);
}

https://en.wikipedia.org/wiki/Blend_modes#Overlay

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文