In Swift Calculate Color Without Transparency Obtained by Overlaying a Color with an Transparant Color

In Swift calculate color without transparency obtained by overlaying a color with an transparant color

The alpha of the overlay color (a2) tells you the percentage that color contributes to the total, and (1 - a2) tells you the percentage the original color contributes. From that, it is a straightforward calculation:

func calculateColor(orgColor: UIColor, overlayColor: UIColor) -> UIColor {
// Helper function to clamp values to range (0.0 ... 1.0)
func clampValue(_ v: CGFloat) -> CGFloat {
guard v > 0 else { return 0 }
guard v < 1 else { return 1 }
return v
}

var (r1, g1, b1, a1) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))
var (r2, g2, b2, a2) = (CGFloat(0), CGFloat(0), CGFloat(0), CGFloat(0))

orgColor.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
overlayColor.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)

// Make sure the input colors are well behaved
// Components should be in the range (0.0 ... 1.0)
r1 = clampValue(r1)
g1 = clampValue(g1)
b1 = clampValue(b1)

r2 = clampValue(r2)
g2 = clampValue(g2)
b2 = clampValue(b2)
a2 = clampValue(a2)

let color = UIColor( red: r1 * (1 - a2) + r2 * a2,
green: g1 * (1 - a2) + g2 * a2,
blue: b1 * (1 - a2) + b2 * a2,
alpha: 1)

return color
}

Intuitively this checks out. If the overlay color is fully opaque (a2 == 1) then the result will be the overlay color. If the overlay color is fully transparent (a2 == 0), the result will be the original color. If the overlay color's alpha is 0.5, you will get a blend that is exactly halfway between the two colors.


Testing it in a Playground:

// Make these colors anything you want
let c1 = UIColor(red: 27/255, green: 155/255, blue: 199/255, alpha: 1.0)
let c2 = UIColor(red: 188/255, green: 13/255, blue: 51/255, alpha: 0.37)

let c3 = calculateColor(orgColor: c1, overlayColor: c2)

let view1 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
let view2 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

view1.backgroundColor = c1
view2.backgroundColor = c2

// Overlay view2 onto view1
view1.addSubview(view2)

// view3 has the calculated color
let view3 = UIView(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
view3.backgroundColor = c3

// display the views side by side in view4
let view4 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
view4.addSubview(view1)
view4.addSubview(view3)

// display this view and see that the two halves match
view4

Playground output:

Playground output

How to calculate result of overlaying two color integers with alpha channels on Android

I think this will blend colours respecting their alphas.

@ColorInt infix fun @receiver:ColorInt Int.overlay(@ColorInt bottomColor: Int): Int {
val topAlpha = Color.alpha(this)
val bottomAlpha = Color.alpha(bottomColor)
val alphaSum = bottomAlpha + topAlpha
return Color.argb(
Math.min(255, alphaSum),
(Color.red(bottomColor) * bottomAlpha + Color.red(this) * topAlpha) / alphaSum,
(Color.green(bottomColor) * bottomAlpha + Color.green(this) * topAlpha) / alphaSum,
(Color.blue(bottomColor) * bottomAlpha + Color.blue(this) * topAlpha) / alphaSum
)
}

NSAttributedString: How to mimic opacity or alpha equivalent using color

You can change any color alpha using

UIColor.red.withAlphaComponent(0.5)

Of course, you have to know the original color.

There is no universal alpha modifier.

Text opacity gradient

Just use .mask instead.

struct ContentView: View {
var body: some View {
ZStack {
Color.red

Text("Hello world!")

/// for iOS 14 and below, replace { } with ( )
.mask {
/// no need for .opacity, just use .clear
LinearGradient(colors: [.white, .clear], startPoint: .leading, endPoint: .trailing)
}
}
}
}

Result:

Text fades out on right

How can I have an opaque UIView as a subview of a semi-transparent UIView?

No, not really. What you want is to take your overlay view, and make it just have a clear background color. As a subview of that new overlay place your view that will grey things out. And as a sibling view to that put your view you want to be opaque.

[OpaqueView] [DimmingView]
| |
[OverlayView]

Transparent UILabel textColor on superview.superview (sort of)

Since iOS 8 Apple offer a new class, UIVibrancyEffect, which can be added to a UIVisualEffectView. This combined with a UIBlurEffect can achieve the exact same result as my screenshot above.

Source: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIVibrancyEffect/index.html

How to set the opacity of an overlay in SwiftUI

You're adding opacity to your whole view, add it to your overlay instead:

.overlay(Color.gray.opacity(0.1))

Overlay non transparent Pixels in iOS Cocoa

I think you are probably looking for the blend mode kCGBlendModeSourceAtop. First, draw the UIImage into your view. Then obtain the current graphics context with

CGContext currentCtx = UIGraphicsGetCurrentContext();

Then save the context state, and set the blend mode:

CGContextSaveGState(currentCtx);
CGContextSetBlendMode(currentCtx, kCGBlendModeSourceAtop);

Then you can draw whatever you want to be overlaid over the opaque pixels of the UIImage. Afterward, just reset the context state:

CGContextRestoreGState(currentCtx);

Hope this helps!



Related Topics



Leave a reply



Submit