UIColorからわずかに明るい色と暗い色を取得する


144

UIColorをグラデーションにできるようにしようとしていました。これを行うつもりの方法は、Core Graphicsを使用してグラデーションを描画することです。私がやろうとしていることは、色を取得することです。

[UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];

いくつかの色合いが暗く、いくつかの色合いが明るいUIColorを取得します。誰でもこれを行う方法を知っていますか?ありがとうございました。


1
「グラデーション」とは、画像のある部分が色の濃淡になる一方、別の部分が濃いまたは明るい濃淡になることを意味します。これは、やりたいことを定義する別の方法ですか?
Michael Dautermann、2007


色相の彩度と明度を使用したSwift stackoverflow.com/a/30012117/2303865
Leo Dabus 2018年

回答:


279
- (UIColor *)lighterColorForColor:(UIColor *)c
{
    CGFloat r, g, b, a;
    if ([c getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MIN(r + 0.2, 1.0)
                               green:MIN(g + 0.2, 1.0)
                                blue:MIN(b + 0.2, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColorForColor:(UIColor *)c
{
    CGFloat r, g, b, a;
    if ([c getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MAX(r - 0.2, 0.0)
                               green:MAX(g - 0.2, 0.0)
                                blue:MAX(b - 0.2, 0.0)
                               alpha:a];
    return nil;
}

次のように使用します。

UIColor *baseColor = // however you obtain your color
UIColor *lighterColor = [self lighterColorForColor:baseColor];
UIColor *darkerColor = [self darkerColorForColor:baseColor];

編集:@Anchu Chimalaが指摘したように、最大​​限の柔軟性を得るには、これらのメソッドをUIColorカテゴリとして実装する必要があります。また、@ Rileyのアイデアから、定数値を加算または減算する代わりに、色を比例的に暗くまたは明るくする方が良いかもしれません。@jrturtonが指摘したように、RGBコンポーネントを操作する必要はありません。輝度プロパティ自体を変更することをお勧めします。概して:

@implementation UIColor (LightAndDark)

- (UIColor *)lighterColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:MIN(b * 1.3, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a])
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:b * 0.75
                               alpha:a];
    return nil;
}
@end

2
色相、彩度、明るさで同じことができるのにRGBを使用し、明るさを変更して色を再構築するのはなぜですか?
jrturton 2012

2
自分でHSBバージョンを試してみましたが、期待どおりに動作しませんでした。getHue:saturation:brightnessUIKit の署名にもかかわらず、HSBではなくHSVで動作するようです。このコンテキストで明るさ(実際には値)を変更しても機能しません。たとえば、純粋な赤(rgb(255,0,0))の明るさ/値は1になるため、明るさ全体を明るくすることはできません。代わりに、RGB値の変更を処理することになりました。
シャンポンリエ2013年

2
私はあなたの答えに混乱を招くものがあると思います:2つのアプローチ(1つはRGBを使用し、もう1つはカテゴリバージョンのHSBを使用)を実行しますが、同じ結果にはなりません...そしてそれは意味:明るくすることは確かに私が色を白に近づける(黒くなる)一方で、明るさ/値を変更することで強く(それぞれ明るく)します。
シャンポンリエ2013年

4
このメソッドは、グレーの色合いで使用すると失敗します。getHue:saturation:brightness:alphaFALSEを返します。
Matthieu Riegler、2014年

2
提案された解決策の両方正しくないので、これがなぜ受け入れられた答えなのかと思います。どちらも、人間が「明るい」または「暗い」色として知覚することとはほとんど関係のない理論値を変更するだけです。私はこの素晴らしい投稿(shortlink:goo.gl/qqgk9V)を読んで私の意味を理解することをお勧めします。LABカラースペースの値は、色を明るくしたり暗くしたりするときに注意すべき真の値であることを説明していますあなたがそれどのように利用し、この問題を正しい方法で解決することができるかについての私の答えを見ください。luminance
Jeehut 2017年

59

TL; DR:

迅速:

extension UIColor {

    var lighterColor: UIColor {
        return lighterColor(removeSaturation: 0.5, resultAlpha: -1)
    }

    func lighterColor(removeSaturation val: CGFloat, resultAlpha alpha: CGFloat) -> UIColor {
        var h: CGFloat = 0, s: CGFloat = 0
        var b: CGFloat = 0, a: CGFloat = 0

        guard getHue(&h, saturation: &s, brightness: &b, alpha: &a)
            else {return self}

        return UIColor(hue: h,
                       saturation: max(s - val, 0.0),
                       brightness: b,
                       alpha: alpha == -1 ? a : alpha)
    }
}

使用法:

let lightColor = somethingDark.lighterColor

Objective-C:

- (UIColor *)lighterColorRemoveSaturation:(CGFloat)removeS
                              resultAlpha:(CGFloat)alpha {
    CGFloat h,s,b,a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:MAX(s - removeS, 0.0)
                          brightness:b
                               alpha:alpha == -1? a:alpha];
    }
    return nil;
}

- (UIColor *)lighterColor {
    return [self lighterColorRemoveSaturation:0.5
                                  resultAlpha:-1];
}

@rchampourlierは@ user529758へのコメントで正しかった(受け入れられた回答)-HSB(またはHSV)とRGBソリューションはまったく異なる結果をもたらします。RGBは白を追加する(または色を近づける)だけで、HSBソリューションは色を明るさスケールの端に近づけます-基本的に黒で始まり、純粋な色で終わります...

基本的に明るさ(値)は、色を黒に近づけたり、近づけたりしますが、彩度は、白に近づけたり狭めたりします。

ここに見られるように:

HSVカラーグラフ

したがって、色を実際に明るくする(つまり、白に近づける)ための解決策は、彩度の値を小さくすることであり、結果としてこの解決策が得られます。

- (UIColor *)lighterColor {
    CGFloat h,s,b,a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:MAX(s - 0.3, 0.0)
                          brightness:b /*MIN(b * 1.3, 1.0)*/
                               alpha:a];
    }
    return nil;
}

色を明るくすることについて:彩度を減らし、明るさ/値を上げることで、最良の結果が得られました。この回答は、画像のパイの「上」の色に最適です。しかし、ほとんどの色は、パイの「どこかに」落ちます。それらを白に近づけるには、それらを「上」に移動する必要があります(値を増やす)。
ペジャロ2016年

値を増やしても機能するように見えるかもしれませんが、「明るい色を取得する」という「コア」機能にはなりません。、暗い色を取得するには、適切なアプローチは、唯一の「価値」を減少させ、それが道彩度を残すことであろうと同じよう...
Avielグロス

38

getHueを使用したiOSおよびOS X用のSwiftユニバーサル拡張:

#if os(OSX)

    import Cocoa
    public  typealias PXColor = NSColor

    #else

    import UIKit
    public  typealias PXColor = UIColor

#endif

    extension PXColor {

    func lighter(amount : CGFloat = 0.25) -> PXColor {
        return hueColorWithBrightnessAmount(1 + amount)
    }

    func darker(amount : CGFloat = 0.25) -> PXColor {
        return hueColorWithBrightnessAmount(1 - amount)
    }

    private func hueColorWithBrightnessAmount(amount: CGFloat) -> PXColor {
        var hue         : CGFloat = 0
        var saturation  : CGFloat = 0
        var brightness  : CGFloat = 0
        var alpha       : CGFloat = 0

        #if os(iOS)

            if getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
                return PXColor( hue: hue,
                                saturation: saturation,
                                brightness: brightness * amount,
                                alpha: alpha )
            } else {
                return self
            }

            #else

            getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
            return PXColor( hue: hue,
                            saturation: saturation,
                            brightness: brightness * amount,
                            alpha: alpha )

        #endif

    }

}

使用法 :

let color = UIColor(red: 0.5, green: 0.8, blue: 0.8, alpha: 1.0)
color.lighter(amount:0.5)
color.darker(amount:0.5)

または(デフォルト値を使用):

color.lighter()
color.darker()

サンプル :

ここに画像の説明を入力してください


エラーが発生しました:-getHue:saturation:brightness:alpha:NSColor NSCalibratedWhiteColorSpace 0 1には無効です。最初に色空間を変換する必要があります。
Besi

2
:追加することによってそれを修正 let color = usingColorSpaceName(NSCalibratedRGBColorSpace) した後、置換getHue色を呼び出して通話を:color?.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha)
オスカー

関数に_単語の前のaがありません。する必要がありますprivate func hueColorWithBrightnessAmount(_ amount: CGFloat) -> PXColor {
Codemonk 2018

回答に@Oskarの提案を追加することをお勧めします。これにより、実行時のクラッシュが修正されました。
Besi

29

RGBで同じ結果を出したかっただけです

  • 白い背景の上にアルファx%の色を配置して明るくする
  • 黒の背景の上にアルファx%の色を配置して暗くします

グラデーションサイズのx%で、「カラーから白」または「カラーから黒」のグラデーションで色を選択するよりも、同じ結果が得られます。

そのため、計算は簡単です。

extension UIColor {
    func mix(with color: UIColor, amount: CGFloat) -> UIColor {
        var red1: CGFloat = 0
        var green1: CGFloat = 0
        var blue1: CGFloat = 0
        var alpha1: CGFloat = 0

        var red2: CGFloat = 0
        var green2: CGFloat = 0
        var blue2: CGFloat = 0
        var alpha2: CGFloat = 0

        getRed(&red1, green: &green1, blue: &blue1, alpha: &alpha1)
        color.getRed(&red2, green: &green2, blue: &blue2, alpha: &alpha2)

        return UIColor(
            red: red1 * (1.0 - amount) + red2 * amount,
            green: green1 * (1.0 - amount) + green2 * amount,
            blue: blue1 * (1.0 - amount) + blue2 * amount,
            alpha: alpha1
        )
    }
}

ここにいくつかの色の例があります

暗くて明るい例


これは、HSLカラースペースを実装する外部ライブラリに頼らない最良の実装だと思います
gog

24

Swiftでのuser529758のソリューション:

暗い色:

func darkerColorForColor(color: UIColor) -> UIColor {

       var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

       if color.getRed(&r, green: &g, blue: &b, alpha: &a){
           return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
       }

       return UIColor()
}

より明るい色:

func lighterColorForColor(color: UIColor) -> UIColor {

       var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

       if color.getRed(&r, green: &g, blue: &b, alpha: &a){
           return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
       }

       return UIColor()
}

1
これは良い答えですが、単にUIColorクラスの拡張として宣言されている場合など、より便利になりvar darker: UIColorます。
Bruno Philipe

13

RGBカラーをHSLカラーモデルに変換すると、L =明度コンポーネントをL = 0.0(黒)からL = 0.5(自然色)からL = 1.0(白)に変更できます。UIColorはHSLを直接処理できませんが、RGB <-> HSLを変換するための式があります。


HSLではありませんが、HSBは問題ありません:developer.apple.com/library/ios/documentation/uikit/reference/…
jrturton

8
HSLとHSB(HSVとも呼ばれる)カラーモデルの違いは、HSBではL = 1.0が純色に対応するのに対し、HSLではL = 1.0が白に、L = 0.5が純色に対応することです。元のポスターで、たとえば、色を青(RGB = 0/0/1)に明るくする方法を求められたので、HSLの方が柔軟性があると思います。
マーティンR

6

ソリューションのどれも掲示しない、非常にすべての色と色合いのために働いていたが、その後、私はつまずいこのライブラリ UIColorに非常によく実装された拡張機能のセットを提供します。

具体的には、HSL実装の一部として軽量化機能があり(UIColor *)lighten:(CGFloat)amountます。これは完全に機能します。


5

Sebyddd 拡張としてのソリューション:

extension UIColor {    
    func darker() -> UIColor {

        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if self.getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
        }

        return UIColor()
    }

    func lighter() -> UIColor {

        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if self.getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
        }

        return UIColor()
    }
}

使用法:

let darkerYellow = UIColor.yellow.darker()
let lighterYellow = UIColor.yellow.lighter()

2

user529758のソリューションを灰色のシェードで動作させたい場合([UIColor lightGrayColor]または、[UIColor darkGrayColor] 次のように改善する必要があります:

- (UIColor *)lighterColor
{
    CGFloat h, s, b, a;
    if ([self getHue:&h saturation:&s brightness:&b alpha:&a]) {
        return [UIColor colorWithHue:h
                          saturation:s
                          brightness:MIN(b * 1.3, 1.0)
                               alpha:a];
    }

    CGFloat white, alpha;
    if ([self getWhite:&white alpha:&alpha]) {
        white = MIN(1.3*white, 1.0);
        return [UIColor colorWithWhite:white alpha:alpha];
    }

    return nil;
}

getHue:saturation:brightness:alphafalseグレーの色合いで呼び出された場合、失敗し、戻りますgetWhite:alpha。したがって、を使用する必要があります。


2

UIColor拡張とlighterColorForColorの修正

extension UIColor {
  class func darkerColorForColor(color: UIColor) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if color.getRed(&r, green: &g, blue: &b, alpha: &a){
      return UIColor(red: max(r - 0.2, 0.0), green: max(g - 0.2, 0.0), blue: max(b - 0.2, 0.0), alpha: a)
    }
    return UIColor()
  }

  class func lighterColorForColor(color: UIColor) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if color.getRed(&r, green: &g, blue: &b, alpha: &a){
      let tmpColor = UIColor(red: min(r + 0.2, 1.0), green: min(g + 0.2, 1.0), blue: min(b + 0.2, 1.0), alpha: a)
      println(tmpColor)
      return tmpColor
    }
    return UIColor()
  }
}

2

このスレッドの他のすべての回答では、RGBカラーシステムを使用する、HSBシステムの色相または明るさの値を変更します。で詳細に説明したように、この偉大なブログ投稿の正しい色を明るくしたり暗くが変更することである作る方法luminance値を。他の答えのどれもそれをしません。あなたがそれを正しくしたいなら、私のブログの記事を読んだ後、私の解決策を使う、自分で書いてください


残念ながら、デフォルトで UIColorの属性を変更するのはかなり面倒です。また、AppleはHCLのようなLABベースの色空間もUIColorクラスでサポートしていません(LLAB内luminanceが探している値です)。

使用HandyUIKit(カルタゴを経由してそれをインストールすること)のためのサポートを追加しHCL、あなたの人生を作る非常に簡単

import HandyUIKit    

let color = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)

// create a new UIColor object with a specific luminance (slightly lighter)
color.change(.luminance, to: 0.7)

相対的な変更を適用するオプションもあります(推奨)。

// create a new UIColor object with slightly darker color
color.change(.luminance, by: -0.2)

HandyUIKitは他の便利なUI機能もプロジェクトに追加します。詳細については、GitHubのREADMEを確認してください。

お役に立てば幸いです。


私のアプリでは、地図上にルートを描画します。100%の明るさの色の内側の線と、その色の暗いバリエーションの境界線でルートを描きたかったのです。内側のラインはすでに100%の明るさであったため、どの方法も機能しませんでした。また、上記のように輝度を変更しても効果はありませんでした。ただし、この非常に優れた拡張機能を使用して明るさを下げると、うまくいきました。'color.change(.brightness、by:-0.5)'このエクステンションは、非常に柔軟に使用でき、多くのオプションがあります。特に、複数のテーマやカラーパレットを備えたアプリがある場合におすすめします。
guido

1

何らかのObjective-Cの答えを探しているかどうかはわかりませんが、RGBAで指定された色がどのように機能するかに基づいて、任意の要素に従ってRGB値を単純にスケーリングし、「ライター」または「暗い」色合い。たとえば、青があるとします。

[UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];

濃い青が必要ですか?RGB値に0.9を掛けます。

[UIColor colorWithRed:0.0 green:0.0 blue:0.9 alpha:1.0];

出来上がり。または多分あなたはオレンジを持っています:

[UIColor colorWithRed:1.0 green:0.4 blue:0.0 alpha:1.0];

別の倍率、たとえば0.8を選択します。

[UIColor colorWithRed:0.8 green:0.32 blue:0.0 alpha:1.0];

それはあなたが求めている種類の効果ですか?


はい、それは私が必要としているものの半分です。青が1(最大)のときに明るい色を取得する方法はありますか
CoreCode

@CoreCodeいいえ、そうではありません。デバイスの画面の明るさを変更したくない場合は、:)私の回答を参照してください。

1

Xcode 10とSwift 4.x for iOS 12でテスト済み

UIColorとしての色から始めて、(CGFloatとして)暗くなる要素を選択します

let baseColor = UIColor.red
let darkenFactor: CGFloat = 2

タイプCGColorにはcomponents、色をRGBAに分解するオプションの値があります(0と1の間の値を持つCGFloat配列として)。次に、CGColorから取得したRGBA値を使用してUIColorを再構築し、それらを操作できます。

let darkenedBase = UIColor(displayP3Red: startColor.cgColor.components![0] / darkenFactor, green: startColor.cgColor.components![1] / darkenFactor, blue: startColor.cgColor.components![2] / darkenFactor, alpha: 1)

この例では、各RGB値を2で除算して、色を以前の半分に暗くしました。アルファ値は同じままでしたが、RGBではなくアルファ値に暗化係数を適用することもできます。


1

スウィフト5

extension UIColor {

func lighter(by percentage:CGFloat=30.0) -> UIColor? {
    return self.adjust(by: abs(percentage) )
}

func darker(by percentage:CGFloat=30.0) -> UIColor? {
    return self.adjust(by: -1 * abs(percentage) )
}
func adjust(by percentage:CGFloat=30.0) -> UIColor? {
    var r:CGFloat=0, g:CGFloat=0, b:CGFloat=0, a:CGFloat=0;
    if(self.getRed(&r, green: &g, blue: &b, alpha: &a)){
        return UIColor(red: min(r + percentage/100, 1.0),
                       green: min(g + percentage/100, 1.0),
                       blue: min(b + percentage/100, 1.0),
                       alpha: a)
    }else{
        return nil


     }
    }
}

0

理想的には、関数はとUIColor呼ばれる拡張機能内にカプセル化されUIColor+Brightness.swift、構成可能な明るさを持つ必要があります-以下の例を参照してください:

import UIKit

extension UIColor {

  func lighterColorWithBrightnessFactor(brightnessFactor:CGFloat) -> UIColor {
    var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0
    if self.getRed(&r, green:&g, blue:&b, alpha:&a) {
      return UIColor(red:min(r + brightnessFactor, 1.0),
        green:min(g + brightnessFactor, 1.0),
        blue:min(b + brightnessFactor, 1.0),
        alpha:a)
    }
    return UIColor()
  }

}

0

ステータス値に基づいて色付きのセルをレンダリングします。

ステータス画像

このため、CryingHippoの提案を使用してエラーが発生した後、いくつかの古いobjcコードに基づいて迅速な拡張機能を作成しました。

extension UIColor{

    func darker(darker: CGFloat) -> UIColor{

        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0

        if self.colorSpace == UIColorSpace.genericGrayColorSpace(){

            red =  whiteComponent - darker
            green = whiteComponent - darker
            blue  = whiteComponent - darker
        } else {
            red = redComponent - darker
            green = greenComponent - darker
            blue = blueComponent - darker
        }

        if red < 0{
            green += red/2
            blue += red/2
        }

        if green < 0{
            red += green/2
            blue += green/2
        }

        if blue < 0{
            green += blue/2
            red += blue/2
        }

        return UIColor(
            calibratedRed: red,
            green: green,
            blue: blue,
            alpha: alphaComponent
        )
    }

    func lighter(lighter: CGFloat) -> UIColor{
        return darker(-lighter)
    }
}

同様に機能しNSColorます。単純に置き換えるUIColorNSColor


0

以下は、色の変化量を制御できるUIColorカテゴリです。

- (UIColor *)lighterColorWithDelta:(CGFloat)delta
{
    CGFloat r, g, b, a;
    if ([self getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MIN(r + delta, 1.0)
                               green:MIN(g + delta, 1.0)
                                blue:MIN(b + delta, 1.0)
                               alpha:a];
    return nil;
}

- (UIColor *)darkerColorWithDelta:(CGFloat)delta
{
    CGFloat r, g, b, a;
    if ([self getRed:&r green:&g blue:&b alpha:&a])
        return [UIColor colorWithRed:MAX(r - delta, 0.0)
                               green:MAX(g - delta, 0.0)
                                blue:MAX(b - delta, 0.0)
                               alpha:a];
    return nil;
}

0

@Sebydddの回答に基づくSwift拡張:

import Foundation
import UIKit

extension UIColor{
    func colorWith(brightness: CGFloat) -> UIColor{
        var r:CGFloat = 0, g:CGFloat = 0, b:CGFloat = 0, a:CGFloat = 0

        if getRed(&r, green: &g, blue: &b, alpha: &a){
            return UIColor(red: max(r + brightness, 0.0), green: max(g + brightness, 0.0), blue: max(b + brightness, 0.0), alpha: a)
        }

        return UIColor()
    }
}

-1

暗い色の場合、これは最も簡単です。theColor= [theColor shadowWithLevel:s]; //s:0.0から1.0


このメソッドはNSColorでのみ使用でき、UIColorでは使用できません。
followben
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.