我该如何修改UIColor的色调、亮度和饱和度?

16

假设我有一个UIColor

UIColor *color = [UIColor redColor];

现在我想修改颜色的饱和度/色相/亮度,该怎么办呢?我已经阅读了文档,但我还是很困惑。

我想修改我所创建的UIColor([UIColor redColor]),而不是用一些偏好设置初始化一个新的颜色。我该如何修改它并保留原始的颜色?我知道colorWithHue:saturation:brightness:alpha:方法,但我需要更新现有颜色的属性,保持红色颜色。


你可以使用CoreImage框架,这会对你有很大帮助。 - Pratik Somaiya
请参考以下帖子 https://dev59.com/P2kw5IYBdhLWcg3wMHoY。 - Spire
10个回答

23
你可以在你的颜色上调用 getHue:saturation:brightness:alpha:,然后调整数值,并使用 +[UIColor colorWithHue:saturation:brightness:alpha:] 创建一个新的颜色并使用已调整的组件。
CGFloat hue, saturation, brightness, alpha ;
BOOL ok = [ <color> getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha ] ;
if ( !ok ) { 
    // handle error 
}
// ... adjust components..

UIColor * newColor = [ UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:alpha ] ;

非常感谢您的回答,它起作用了!我会在一分钟内接受它(Stackoverflow说我必须等待)。 - s6luwJ0A3I
4
这个方法可行,但它不能满足您要求使用相同颜色对象的需求。但是您想要的并不可能实现。UIColor是不可变的——所以您总是需要创建一个新的颜色对象。 - nielsbot
@nielsbot,我喜欢你简洁地使用BOOL来一举解决两个问题的方法。非常棒的回答... - Charles Robertson

17

这里是一个有用的 UIColor 扩展,适用于 Swift:

extension UIColor {

    func modified(withAdditionalHue hue: CGFloat, additionalSaturation: CGFloat, additionalBrightness: CGFloat) -> UIColor {

        var currentHue: CGFloat = 0.0
        var currentSaturation: CGFloat = 0.0
        var currentBrigthness: CGFloat = 0.0
        var currentAlpha: CGFloat = 0.0

        if self.getHue(&currentHue, saturation: &currentSaturation, brightness: &currentBrigthness, alpha: &currentAlpha){
            return UIColor(hue: currentHue + hue,
                           saturation: currentSaturation + additionalSaturation,
                           brightness: currentBrigthness + additionalBrightness,
                           alpha: currentAlpha)
        } else {
            return self
        }
    }
}

3

这里有一点需要注意,你的UIColor应该在扩展RGB空间中。根据你的颜色最初是如何创建的,如果只是RGB,那么这个函数可能会返回false。

其次,我对@ambientlight的答案进行了改进,使API更加流畅。你可以调整一个或所有属性。

extension UIColor {

    public func adjust(hueBy hue: CGFloat = 0, saturationBy saturation: CGFloat = 0, brightnessBy brightness: CGFloat = 0) -> UIColor {

        var currentHue: CGFloat = 0.0
        var currentSaturation: CGFloat = 0.0
        var currentBrigthness: CGFloat = 0.0
        var currentAlpha: CGFloat = 0.0

        if getHue(&currentHue, saturation: &currentSaturation, brightness: &currentBrigthness, alpha: &currentAlpha) {
            return UIColor(hue: currentHue + hue,
                       saturation: currentSaturation + saturation,
                       brightness: currentBrigthness + brightness,
                       alpha: currentAlpha)
        } else {
            return self
        }
    }
}

3

很遗憾,默认情况下,更改 UIColor 的任何 hsba 或 rgba 值都是相当麻烦的。但使用 HandyUIKit(通过 Carthage 安装)会使您的生活变得容易得多:HandyUIKit

import HandyUIKit  

// each line creates a new UIColor object with the new value
color.change(.hue,        to: 0.1)
color.change(.brightness, to: 0.2)
color.change(.saturation, to: 0.3)
color.change(.alpha,      to: 0.4)

// chaining them returns a single new object with all values changed
color.change(.hue,        to: 0.5)
     .change(.brightness, to: 0.6)
     .change(.saturation, to: 0.7)

还有应用相对变化的选项:

// create a new UIColor object with hue & brightness increased by 0.2
color.change(.hue,        by: 0.2)
     .change(.brightness, by: 0.2)

该库还向您的项目中添加了一些其他方便的UI功能-请查看其在GitHub上的README以获取更多详细信息。
希望它能帮到您!

0

你可以通过设置以下数值来使用这个方法

UIColor *customColor = [UIColor colorWithHue: x.xx saturation: x.xx brightness: x.xx alpha: 1.0];


0

-1
CGSize imageSize = [ba size];
CGRect imageExtent = CGRectMake(0,0,imageSize.width,imageSize.height);

// Create a context containing the image.
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();

[sourceimage drawInRect:imageExtent];
// Draw the hue on top of the image.
CGContextSetBlendMode(context, kCGBlendModeHue);
[[UIColor colorWithHue:yourvalue saturation:1.0 brightness:1 alpha:1.0] set];
UIBezierPath *imagePath = [UIBezierPath bezierPathWithRect:imageExtent];
[imagePath fill];

CGImageRef imageref=CGBitmapContextCreateImage(context);

UIImage *result =[UIImage imageWithCGImage:imageref];

CGImageRelease(imageref);

在前两行中,它描述了图像大小和图像矩形。 CGContextRef 用于在核心图形中创建上下文。之后的第5行是您要应用色调和图像矩形的图像。之后是重要的混合模式。之后是UI colorWithHue,其中传递了色相、饱和度、亮度和alpha的值。为了获得正确的效果,请给出1.0的alpha值。最后,您应该设置 uicolor.create bezerpath 或者直接给出 cgcontextsetfill(context)。最后创建 imageref 并将该图像放入 UIImage 中。最后,在choreographics中,始终释放 CGImageRelease 以避免内存问题。


提供的代码可能有所帮助,但为了使其成为一个好的答案,您还应该描述/解释您的代码是如何解决问题的。 - ZygD
前两行描述了图像大小和图像矩形。cgcontext用于在核心图形中创建上下文。接下来的第5行是您要应用色调和图像矩形的图像。之后是重要的混合模式。然后是ui colorWithHue,在其中传递色调、饱和度、亮度和alpha值以获得适当的效果,将alpha值设为1.0。最后设置uicolor。创建bezerpath或直接给出cgcontextsetfill(context)。最后创建imageref并将该图像放入uiimage。最后在核心图形中始终释放cgimageRef以解决内存问题。 - Arvind Rajpurohit
最好将相关信息放在答案中,因为并非每个人都会深入评论区查找类似问题的解决方案。另外,您所说的choreographics是什么意思? - ZygD

-1

你可以通过简单修改来实现这个功能

[UIColor colorWithHue:YourHueValue saturation:YourSaturationValue brightness:YourBrightnessValueValue alpha:1.00];

alpha 表示视图的不透明度,取值范围为 0.0 到 1.0


-1

UIColor 无法改变饱和度/色调/亮度,您可以使用 CoreImage。

以下是一些示例代码:

CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];

[filter setValue:[NSNumber numberWithFloat:1.0] forKey:@"inputContrast"];
[filter setValue:[NSNumber numberWithFloat:1.0] forKey:@"inputSaturation"];
[filter setValue:[NSNumber numberWithFloat:0.0] forKey:@"inputBrightness"];


[filter setValue:_A_CIImage_ forKey:kCIInputImageKey];

CIImage *_outputImage = filter.outputImage;

CIContext context = [CIContext contextWithOptions:nil];

CGImageRef outputImageRef = [context createCGImage: _outputImage fromRect:[_outputImage extent]];

colorWithHue:saturation:brightness:alpha: 使用指定的不透明度和HSB颜色空间分量值创建并返回颜色对象。该方法用于使用HSB颜色空间创建颜色,就像使用RGB颜色空间一样。无法将红色更改为其他颜色。 - zhoujinhao

-4
[UIColor colorWithHue:0.10 saturation:0.16 brightness:0.13 alpha:1.00];

一行简单的代码并不被认为是一个好的答案。请解释你为什么这样做以及它如何帮助。 - Lukas Knuth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接