How to Get Rgb Components from Color in Swiftui

How to get RGB components from Color in SwiftUI

iOS 14 / macOS 10.16

There is a new initializer that takes a Color and returns a UIColor for iOS or NSColor for macOS now. With the help of those you can implement the following extensions:

iOS / macOS

import SwiftUI

#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif

extension Color {
var components: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) {

#if canImport(UIKit)
typealias NativeColor = UIColor
#elseif canImport(AppKit)
typealias NativeColor = NSColor
#endif

var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var o: CGFloat = 0

guard NativeColor(self).getRed(&r, green: &g, blue: &b, alpha: &o) else {
// You can handle the failure here as you want
return (0, 0, 0, 0)
}

return (r, g, b, o)
}
}


Usage

Color.red.components.red // 0.9999999403953552 // <- SwiftUI Colors are not pure!

Hex codes/RGB values for SwiftUI colors?

If you are coding in SwiftUI 2 you can convert your Color to UIColor and use getRed method to get the red, green, blue and alpha components. Once you have the components you can convert the values to hexa string:



extension Color {
var uiColor: UIColor { .init(self) }
typealias RGBA = (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat)
var rgba: RGBA? {
var (r, g, b, a): RGBA = (0, 0, 0, 0)
return uiColor.getRed(&r, green: &g, blue: &b, alpha: &a) ? (r, g, b, a) : nil
}
var hexaRGB: String? {
guard let (red, green, blue, _) = rgba else { return nil }
return String(format: "#%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255))
}
var hexaRGBA: String? {
guard let (red, green, blue, alpha) = rgba else { return nil }
return String(format: "#%02x%02x%02x%02x",
Int(red * 255),
Int(green * 255),
Int(blue * 255),
Int(alpha * 255))
}
}


Color.purple.hexaRGB     // "#af52de"
Color.purple.hexaRGBA // "#af52deff"
if let (red, green, blue, alpha) = Color.purple.rgba {
red // 0.686274528503418
green // 0.321568638086319
blue // 0.8705882430076599
alpha // 1
}

Get Value from SwiftUI Color Picker

In majority of cases you use Color in SwiftUI directly, ie it is not needed to extract anything from it.

Anyway if it is needed to have UIColor SwiftUI 2.0 provides new API for that

extension UIColor {

@available(iOS 14.0, tvOS 14.0, watchOS 7.0, *)
@available(OSX, unavailable)
public convenience init(_ color: Color)
}

How to use Color with RGB or hex value in SwiftUI using Swift 5?

The UIColor init method UIColor(red:green:blue:alpha) takes float values from 0 to 1 for each value.

Any value ≥ 1.0 is going to "max out" that color. So an expression like UIColor(red: 220, green: 24, blue: 311, alpha: 1) will set all 3 color channels and alpha to 1.0, resulting in white. So would UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)

You could create an extension to UIColor that adds convenience initializers that would take values of different types. First, and initializer that would take values from 0-255 for each. Then you could create another intializer UIColor.init(hexString:String).

The one that took values from 0-255 would be a lot easier to write. The one that took hex strings would involve implementing a hex parser. I bet somebody has already written it though.

Take a look at this code, for example:

https://gist.github.com/anonymous/fd07ecf47591c9f9ed1a

How to check if a specific color is selected with SwiftUI's ColorPicker?

As @workingdog pointed out to me, the best approach to comparing colors here is converting them to a comparable system by taking their color components.

SwiftUI‘s Color type doesn‘t grant access to its components out of the box but by converting to UIColor we get methods for retrieving the color’s rgb, hsb and grayscale components.

By using this trick we can extend Color and add properties for conveniently getting the components we need in our comparisons:

extension Color {
var rgbComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, opacity: CGFloat) {
var (r, g, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getRed(&r, green: &g, blue: &b, alpha: &a)
return (r, g, b, a)
}

var hsbComponents: (hue: CGFloat, saturation: CGFloat, brightness: CGFloat, opacity: CGFloat) {
var (h, s, b, a): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
UIColor(self).getHue(&h, saturation: &s, brightness: &b, alpha: &a)
return (h, s, b, a)
}

var grayscaleComponents: (white: CGFloat, opacity: CGFloat) {
var (w, o): (CGFloat, CGFloat) = (0, 0)
UIColor(self).getWhite(&w, alpha: &o)
return (w, o)
}
}

As I just want to check if black or white is selected for knowing when to adjust the color on theme change, getting the grayscale components is sufficient in my use case.

We can then use these components to compare the colors selected in the color picker. I found that the values generated by moving the sliders in the picker are sometimes a bit inaccurate however. For instance, selecting pure black by setting all rgb values to 0 can result in rgb components that are actually slightly above zero, possibly due to inaccurate rounding of float values. I accounted for this by comparing the component values to a small range of values respectively:

func updateColorScheme() {
// set the theme
let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene
scene?.keyWindow?.overrideUserInterfaceStyle = theme

// update the selected color
let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark
if isDarkMode && baseColor.grayscaleComponents.white < 0.0001 {
baseColor = .white
}
if !isDarkMode && baseColor.grayscaleComponents.white > 0.9999 {
baseColor = .black
}
}

Color rgb initializer not working as background in SwiftUI

It looks like it is asking for the colors in percentages, I was able to get it to work doing this

Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255)

How to compare three Color in SwiftUI

I really dont undestand what you want to achieve but you can compare them like

        let colorr = UIColor(red: 122/255, green: 100/255, blue: 180/255, alpha: 1.0)
let rgbColorr = colorr.cgColor
let rgbColorrs = rgbColorr.components

This rgbColorrs prints and array like [0.47843137254901963, 0.39215686274509803, 0.7058823529411765, 1.0] its like [red,green,blue,alpha]

if rgbColorrs[0] == rgbColors[1] == rgbColors[2]{
//....
}

Or if you want to compare equality

 if UIColor.red.isEqual(UIColor.green.isEqual(UIColor.blue)){
...
}


Related Topics



Leave a reply



Submit