8

昨天我遇到了一个需要减轻 UIColor 的情况,所以我创建了一个类别并添加了一个lighten方法。我认为将值乘以颜色的每个分量是直截了当的,但我的绿色开始变黄,所以我知道它必须更复杂。

我想出的解决方案是从 sRGB 转换为线性,乘以颜色,然后再转换回来。这似乎有效,但我不确定它是否“正确”。我在文档中找不到任何说明 UIColor 在 sRGB 空间中的内容。我也不是色彩科学家,所以我对所涉及的数学只有初步的了解。

无论如何,这是我的代码,我要求进行一些同行评审,看看是否有人对修改 UIColors 有更好的理解。

CGFloat sRGB2Linear(CGFloat x){
    CGFloat a = 0.055;
    if(x <= 0.04045){
        return x * (1.0 / 12.92);
    }else{
        return pow((x + a) * (1.0 / (1 + a)), 2.4);
    }
}

CGFloat linear2sRGB(CGFloat x){
    CGFloat a = 0.055;
    if(x <= 0.0031308){
        return x * 12.92;
    }else{
        return (1 + a) * pow(x, 1 / 2.4) - a;
    }
}

- (UIColor *)lighten:(CGFloat)value{
    const CGFloat *components = CGColorGetComponents([self CGColor]);
    CGFloat newR = (sRGB2Linear(components[0])+1)*value;
    CGFloat newG = (sRGB2Linear(components[1])+1)*value;
    CGFloat newB = (sRGB2Linear(components[2])+1)*value;
    newR = MAX(0, MIN(1, linear2sRGB(newR)));
    newG = MAX(0, MIN(1, linear2sRGB(newG)));
    newB = MAX(0, MIN(1, linear2sRGB(newB)));
    return [UIColor colorWithRed:newR green:newG blue:newB alpha:components[3]];
}
4

7 回答 7

24

这是我的 iOS5+ 解决方案,可以轻松更改相对亮度(一体式变亮和变暗):

+ (UIColor*)changeBrightness:(UIColor*)color amount:(CGFloat)amount
{

    CGFloat hue, saturation, brightness, alpha;
    if ([color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
        brightness += (amount-1.0);
        brightness = MAX(MIN(brightness, 1.0), 0.0);
        return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
    }

    CGFloat white;
    if ([color getWhite:&white alpha:&alpha]) {
        white += (amount-1.0);
        white = MAX(MIN(white, 1.0), 0.0);
        return [UIColor colorWithWhite:white alpha:alpha];
    }

    return nil;
}

它是这样调用的:

[self changeBrightness:someUiColor amount:1.1]

使用 1.1 会增加 10% 的亮度;0.9 将亮度降低 10%。请注意,10% 是相对于纯白色而言的(即,10% 总是增加 0.1 的亮度。)如果您希望增加百分比以一致地使颜色变亮或变暗,而不管它们的初始亮度如何,这是预期的行为。

于 2013-01-26T07:24:16.467 回答
4

您可以使用色调、饱和度和亮度。

使用获取旧值

- (BOOL)getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha

然后调整亮度,并构造一个新的颜色:

- (UIColor *)initWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha

请记住,您需要将指针传递给第一个函数。

于 2012-10-03T20:20:01.047 回答
2

Kof 在 Swift 中的回答:

extension UIColor {
    public func changeBrightness(b: CGFloat, saturation s: CGFloat = 1.0, hue h: CGFloat = 1.0) -> UIColor? {
        var hue : CGFloat = 0.0
        var saturation : CGFloat = 0.0
        var brightness : CGFloat = 0.0
        var alpha : CGFloat = 0.0

        if self.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) {
            brightness *= b
            brightness = max(min(brightness, 1.0), 0.0)
            saturation *= s
            saturation = max(min(saturation, 1.0), 0.0)
            hue *= h
            hue = max(min(hue, 1.0), 0.0)

            return UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
        }

        var white: CGFloat = 0.0
        if self.getWhite(&white, alpha: &alpha) {
            white += (b - 1.0)
            white = max(min(b, 1.0), 0.0)

            return UIColor(white: white, alpha: alpha)
        }

        return nil
    }
}
于 2016-01-03T00:37:43.617 回答
1

尝试

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

它应该返回与您的颜色混合的白色

所以你可以将 alpha 设置为 0.2,我认为它会没问题

于 2015-06-16T11:09:27.440 回答
1

与白色混合是我发现不会扭曲原始颜色的唯一方法,就像在这个 Swift 扩展中一样:

extension UIColor {

    @objc func lighten(_ alpha: CGFloat) -> UIColor {
        var r: CGFloat = 0
        var g: CGFloat = 0
        var b: CGFloat = 0
        var a: CGFloat = 0
        guard self.getRed(&r, green: &g, blue: &b, alpha: &a) else { return self }
        return UIColor(red:r + (1.0-r) * alpha, green:g + (1.0-g) * alpha, blue:b + (1.0-b) * alpha, alpha: a)
    }
}
于 2020-02-04T16:03:49.830 回答
0

我已经改进了 ank 的方法以允许修改饱和度和色调。

输入被视为百分比,因此b1.0 等于 100%(无变化)。要将亮度降低 30%,请设置b为 0.7。

+ (UIColor*)changeColor:(UIColor*)color brightness:(CGFloat)b saturation:(CGFloat)s hue:(CGFloat)h
{

    CGFloat hue, saturation, brightness, alpha;
    if ([color getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
        brightness *= b;
        brightness = MAX(MIN(brightness, 1.0), 0.0);
        saturation *= s;
        saturation = MAX(MIN(saturation, 1.0), 0.0);
        hue *= h;
        hue = MAX(MIN(hue, 1.0), 0.0);
        return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
    }

    CGFloat white;
    if ([color getWhite:&white alpha:&alpha]) {
        white += (b-1.0);
        white = MAX(MIN(b, 1.0), 0.0);
        return [UIColor colorWithWhite:white alpha:alpha];
    }

    return nil;
}
于 2014-06-27T12:48:12.260 回答
0
- (UIColor *)changeBrightnessToPercentage:(CGFloat)percentage {
    CGFloat hue, saturation, brightness, alpha;
    if ([self getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
        brightness += (percentage - 1.0);
        brightness = MAX(MIN(brightness, 1.0), 0.0);
        return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha];
    }

    CGFloat white;
    if ([self getWhite:&white alpha:&alpha]) {
        white += (percentage - 1.0);
        white = MAX(MIN(white, 1.0), 0.0);
        return [UIColor colorWithWhite:white alpha:alpha];
    }

    return nil;
}

==1.0 是提供的颜色,>1.0 是较浅的颜色,<1.0 是较深的颜色。

于 2016-03-24T15:24:18.837 回答