前言

UIColor是UIKit中存储颜色信息的一个重要类。一个UIColor对象包含了颜色和透明度的值,它的颜色空间已经针对iOS进行了优化。UIColor提供了一些常用的创建颜色的方法,如白色、黑色、红色等。这些颜色的色彩空间也有所不同,例如白色和黑色是kCGColorSpaceDeviceGray,红色的色彩空间是kCGColorSpaceDeviceRGB。此外,UIColor还有两个重要的属性:一个是CGColor,另一个是CIColor(自5.0版本起添加)。这两个属性可以将UIColor、CGColor和CIColor这三个对象联系起来。本篇文章将着重介绍UIColor。

一、创建颜色的方法

1. 使用white和alpha参数创建颜色:

```objective-c

// white的范围是0~1,代表黑~白,中间过度灰色;alpha是透明度,范围为0~1,0表示完全透明,1表示不透明

UIColor *color = [UIColor colorWithWhite:1 alpha:0.5];

```

2. 使用hue、saturation、brightness和alpha参数创建颜色:

```objective-c

// hue表示色调;saturation表示饱和度;brightness表示亮度;alpha表示透明度

UIColor *color = [UIColor colorWithHue:0.5 saturation:0.8 brightness:0.6 alpha:0.7];

```

3. 使用red、green、blue和alpha参数创建颜色:

```objective-c

// red表示红;green表示绿;blue表示蓝;alpha表示透明度

CGFloat redValue = 1;

CGFloat greenValue = 0;

CGFloat blueValue = 0;

UIColor *color = [UIColor colorWithRed:redValue green:greenValue blue:blueValue alpha:0.8];

```

4. 使用CMYK空间创建颜色并转换为UIColor:

```objective-c

CGColorSpaceRef cmykSpace = CGColorSpaceCreateDeviceCMYK();

CGFloat cmykValues[] = {1, 1, 0, 0, 1}; // Cyan Magenta Yellow Key (blue)

CGColorRef colorCMYK = CGColorCreate(cmykSpace, cmykValues);

CGColorSpaceRelease(cmykSpace);

NSLog(@"colorCMYK: %@", colorCMYK);

// color with CGColor, uicolor will just retain it

UIColor *color = [UIColor colorWithCGColor:colorCMYK];

NSLog(@"CGColor from UIColor: %@", color.CGColor);

```

以上就是关于UIColor的一些基本用法和方法。

你可以使用`kCGColorSpaceDeviceGray`来初始化CIColor,然后使用`CGImageGetColorspace()`方法获取图片的颜色空间,最后将CIImage转换为CGImage并获取其颜色。如果你想从一张图片中获取颜色,你可以使用以下代码:

```swift

let image = UIImage(named: "your_image_name")

let color = image?.cgImage?.colorSpace?.createDeviceGrayColor((image?.cgImage)!)

print(color)

```

以下是重构后的代码:

```objc

NSLog(@"CGColor white color:%@", [UIColor whiteColor].CGColor); // CGColor white color: (1 1 1)

// 创建CIColor

CIColor *ciColor = [CIColor colorWithCGColor:[UIColor whiteColor].CGColor];

NSLog(@"cicolor: %@", ciColor); // cicolor: (1 1 1 1)

NSLog(@"cicolor colorspace: %@", ciColor.colorSpace); // cicolor colorspace: (kCGColorSpaceDeviceGray)

// 创建UIColor

UIColor *uicolor = [UIColor colorWithCIColor:ciColor];

NSLog(@"uicolor:%@", uicolor); // color CIColor 1 1 1 1

// Core Image 在将颜色空间传递给滤波器内核之前,会将所有颜色空间转换为 Core Image 工作颜色空间。

// kCGColorSpaceDeviceGray ----> kCGColorSpaceDeviceRGB

NSLog(@"cicolor from UIColor: %@", uicolor.CIColor); // cicolor from UIColor: (1 1 1 1)

NSLog(@"cicolor's colorspace: %@", uicolor.CIColor.colorSpace); // cicolor's colorspace: (kCGColorSpaceDeviceGray)

NSLog(@"uicolor CGColor: %@", uicolor.CGColor); // color's CGColor: (1 1 1 1) [ (kCGColorSpaceDeviceRGB)]

总结:

通过运行程序,我们发现,当使用kCGColorSpaceDeviceGray颜色空间的CGColor初始化CIColor时,CIColor的色彩空间始终为kCGColorSpaceDeviceGray。然而,当我们访问UIColor的CGColor属性并打印时,可以发现其色彩空间已经转换为kCGColorSpaceDeviceRGB,并且颜色值也从原始颜色空间正确地转换到了新的颜色空间。

(2) 使用kCGColorSpaceDeviceRGB初始化CIColor

在第二个示例中,我们尝试使用kCGColorSpaceDeviceRGB颜色空间的CGColor来初始化CIColor。运行程序后,我们发现CIColor的色彩空间已经成功转换为kCGColorSpaceDeviceRGB,颜色值也正确地从原始颜色空间转换到了新的颜色空间。这表明,通过正确的颜色空间初始化,我们可以确保CIColor的色彩空间和颜色值与实际图像一致。

```objc

// 打印红色颜色的 CGColor

NSLog(@"CGColor red color: %@", [UIColor redColor].CGColor); // CGColor red color: [ (kCGColorSpaceDeviceRGB)] (1 0 0 1)

// 将 CGColor 转换为 CIColor

CIColor *ciColor = [CIColor colorWithCGColor:[UIColor redColor].CGColor];

NSLog(@"cicolor: %@", ciColor); // cicolor: (1 0 0 1)

// 打印 CIColor 的颜色空间

NSLog(@"cicolor colorspace: %@", ciColor.colorSpace); // cicolor colorspace: (kCGColorSpaceDeviceRGB)

// 将 CIColor 转换为 UIColor

UIColor *uicolor = [UIColor colorWithCIColor:ciColor];

NSLog(@"uicolor %@", uicolor); // color CIColor (1 0 0 1)

// 从 UIColor 中获取 CIColor

NSLog(@"cicolor from UIColor: %@", uicolor.CIColor); // cicolor from UIColor: (1 0 0 1)

// 打印 CIColor 在从 uicolor 中的 colorSpace

NSLog(@"cicolor's colorspace: %@", uicolor.CIColor.colorSpace); // cicolor's colorspace: (kCGColorSpaceDeviceRGB)

// 从 uicolor 中获取 CGColor

NSLog(@"uicolor CGColor: %@", uicolor.CGColor); // uicolor's CGColor: [ (kCGColorSpaceDeviceRGB)] (1 0 0 1)

```

总结:

在本文中,我们通过CIColor、UIColor的CGColor和CIColor属性访问到的值进行了分析。结果显示,这些值都属于kCGColorSpaceDeviceRGB空间。此外,我们还探讨了如何使用kCGColorSpaceDeviceCMYK初始化CIColor。

以下是重构后的代码:

```objective-c

// 创建设备CMYK颜色空间

CGColorSpaceRef cmykSpace = CGColorSpaceCreateDeviceCMYK();

NSLog(@"Components number: %zu", CGColorSpaceGetNumberOfComponents(cmykSpace)); // Components number: 4

// 设置CMYK值

CGFloat cmykValue[] = {1, 1, 0, 0, 1};

// 创建CMYK颜色

CGColorRef colorCMYK = CGColorCreate(cmykSpace, cmykValue);

CGColorSpaceRelease(cmykSpace);

NSLog(@"colorCMYK: %@", colorCMYK); // colorCMYK: [ (kCGColorSpaceDeviceCMYK)] (1 1 0 0 1)

// 将CMYK颜色转换为CIColor

CIColor* ciColor = [CIColor colorWithCGColor:colorCMYK];

NSLog(@"cicolor: %@", ciColor); // cicolor: (0 0 1 1)

// 注意:实际上,CIColor的颜色值已经转换为RGB颜色空间

NSLog(@"cicolor colorspace: %@", ciColor.colorSpace); // cicolor colorspace: (kCGColorSpaceDeviceCMYK)

// 将CIColor转换为UIColor

UIColor* uicolor = [UIColor colorWithCIColor:ciColor];

NSLog(@"UIColor with CIColor: %@", uicolor); // UIColor with CIColor: CIColor 0 0 1 1

NSLog(@"cicolor from UIColor: %@", uicolor.CIColor); // cicolor from UIColor: (0 0 1 1)

NSLog(@"cicolor's colorspace: %@", uicolor.CIColor.colorSpace); // cicolor's colorspace: (kCGColorSpaceDeviceCMYK)

NSLog(@"cgcolor from UIColor: %@", uicolor.CGColor); // cgcolor from UIColor: [ (kCGColorSpaceDeviceRGB)] (0 0 1 1)

```

在颜色处理过程中,我们发现了一个有趣的现象:当我们使用CMYK颜色空间的CGColor初始化CIColor时,CIColor的颜色空间仍然是CMYK,但颜色值已转换为RGB值。而当我们使用该CIColor创建一个UIColor并通过CGColor属性打印信息时,我们会发现CIColor的色彩空间仍然是CMYK,但CGColor打印所得到的信息说明它已经被转换成RGB空间了。

以下是关于颜色初始化的方法总结:

1. 使用白色和透明度参数:`- (UIColor *)initWithWhite:(CGFloat)white alpha:(CGFloat)alpha;`

2. 使用色调、饱和度、亮度和透明度参数:`- (UIColor *)initWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha;`

3. 使用红、绿、蓝和透明度参数:`- (UIColor *)initWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;`

4. 使用CGColor初始化:`- (UIColor *)initWithCGColor:(CGColorRef)cgColor;`

5. 使用UIImage初始化:`- (UIColor *)initWithPatternImage:(UIImage *)image;`

6. 使用CIColor初始化(仅适用于iOS 5.0及以上版本):`- (UIColor *)initWithCIColor:(CIColor)ciColor NS_AVAILABLE_IOS(5_0);`

此外,还有一些方便创建颜色的方法,这些颜色会尽可能精确地校准,并且已经缓存。例如:

1. 黑色:`+ (UIColor *)blackColor; // 0.0 white`

2. 深灰色:`+ (UIColor *)darkGrayColor; // 0.333 white`

3. 浅灰色:`+ (UIColor *)lightGrayColor; // 0.667 white`

```objc

// 定义颜色常量

#define kColorWhite (UIColor *)[UIColor whiteColor] // 1.0 white

#define kColorGray [UIColor grayColor] // 0.5 white

#define kColorRed [UIColor redColor] // 1.0, 0.0, 0.0 RGB

#define kColorGreen [UIColor greenColor] // 0.0, 1.0, 0.0 RGB

#define kColorBlue [UIColor blueColor] // 0.0, 0.0, 1.0 RGB

#define kColorCyan [UIColor cyanColor] // 0.0, 1.0, 1.0 RGB

#define kColorYellow [UIColor yellowColor] // 1.0, 1.0, 0.0 RGB

#define kColorMagenta [UIColor magentaColor] // 1.0, 0.0, 1.0 RGB

#define kColorOrange [UIColor orangeColor] // 1.0, 0.5, 0.0 RGB

#define kColorPurple [UIColor purpleColor] // 0.5, 0.0, 0.5 RGB

#define kColorBrown [UIColor brownColor] // 0.6, 0.4, 0.2 RGB

#define kColorClear [UIColor clearColor] // 0.0 white, 0.0 alpha

// 其他操作

// 获取当前颜色改变透明度后的一个颜色

- (UIColor *)getColorWithAlpha:(CGFloat)alpha;

// 设置颜色:在当前绘制上下文中设置填充和线段颜色;

- (void)setFillAndLineColor:(UIColor *)color;

// 设置填充

- (void)setStrokeWidth:(CGFloat)width;

// 设置线段

- (void)setStrokeColor:(UIColor *)color;

```

```objc

#import

@interface MyView : UIView

- (void)drawRect:(CGRect)rect;

- (BOOL)isColorEqual:(UIColor *)color1 color2:(UIColor *)color2;

@end

@implementation MyView

- (void)drawRect:(CGRect)rect {

[super drawRect:rect];

UIColor *redColor = [UIColor redColor];

UIColor *purpleColor = [UIColor purpleColor];

// 判断两个颜色是否相等

BOOL isEqual = [self isColorEqual:redColor color2:purpleColor];

NSLog(@"两个颜色是否相等: %@", isEqual ? @"相等" : @"不相等");

//1.获得图形上下文

CGContextRef context = UIGraphicsGetCurrentContext();

//2.绘制路径(相当于前面创建路径并添加路径到图形上下文两步操作)

CGContextMoveToPoint(context, 20, 50);

CGContextAddLineToPoint(context, 20, 100);

CGContextAddLineToPoint(context, 300, 100);

//封闭路径:a.创建一条起点和终点的线,不推荐

//CGPathAddLineToPoint(path, nil, 20, 50);

//封闭路径:b.直接调用路径封闭方法

CGContextClosePath(context);

//4.绘制路径

CGContextDrawPath(context, kCGPathFillStroke);

}

- (BOOL)isColorEqual:(UIColor *)color1 color2:(UIColor *)color2 {

// 通过判断两个UIColor是否相等来判断CGColor是否相等

BOOL isEqual = [[color1 CGColor] == [[color2 CGColor]]];

return isEqual;

}

@end

```

```objc

if (CGColorEqualToColor([UIColor whiteColor].CGColor, [UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor)) {

NSLog(@"The two CGColor is equal!");

} else {

NSLog(@"The two CGColor is not equal!");

}

if (CGColorEqualToColor([UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor, [UIColor colorWithRed:1 green:1 blue:1 alpha:1].CGColor)) {

NSLog(@"The two CGColor is equal!");

} else {

NSLog(@"The two CGColor is not equal!");

}

```

例子中第一部分是判断两个白色的UIColor是否相等,虽然都是白色,但是颜色控件是不一样的,通过运行我们可以发现,打印出『 The two CGColor is not equal!』。例子的第二部分简单的创建两个RGB空间的UIColor,运行程序可以看出,这两个颜色是相同的。

以下是将提供的内容重构并保持段落结构后的代码:

CGColor from UIColor <CGColor 0x7f8411f61ac0> [<CGColorSpace 0x7f8411e63990> (kCGColorSpaceDeviceGray)] ( 1 1 )

#if __has_include(<CoreImage/CoreImage.h>) @property(nonatomic,readonly) CIColor *CIColor NS_AVAILABLE_IOS(5_0); #endif

UIColor *color = [UIColor whiteColor]; //未使用CIColor初始化的颜色,使用如下方法获取CIColor会产生崩溃 NSLog(@"CIColor from UIColor %@", color.CIColor); // crush

// CGColor from UIColor [ (kCGColorSpaceDeviceGray)] ( 1 1 )

// #if __has_include(<CoreImage/CoreImage.h>) @property(nonatomic,readonly) CIColor *CIColor NS_AVAILABLE_IOS(5_0); #endif

// UIColor *color = [UIColor whiteColor]; //未使用CIColor初始化的颜色,使用如下方法获取CIColor会产生崩溃 NSLog(@"CIColor from UIColor %@", color.CIColor); // crush

// 将提供的内容重构为一个函数,以避免崩溃的问题

- (CIColor *)getCIColorFromUIKitColor:(UIColor *)uiKitColor {

return [uiKitColor getCIColor];

}

// 在需要的地方调用该函数来获取CIColor

CIColor *ciColor = [self getCIColorFromUIKitColor:color];