美文网首页
Core Graphics 四: 色彩和纹理

Core Graphics 四: 色彩和纹理

作者: Trigger_o | 来源:发表于2020-10-10 21:09 被阅读0次

Core Graphics 一: CGContext基本绘制
Core Graphics 二: CGAffineTransform变换和CTM坐标系
Core Graphics 三: CGPath

一.色彩和色彩空间

电磁波有不同的波长,一定范围内波长的电磁波会被人眼感受到,这部分就是可见光,光源或者物体反射可见光被人眼接受到,就会被大脑解析为对色彩的感知.但是一束电磁波里包含了各种波段,一束可见光也是,混合起来会产生多种多样的色彩.
什么是加减色.三个手电筒,每个手电筒上都装有一个彩色的透明滤波片,颜色分别是红、绿和蓝,然后将光投射到墙上,两个手电筒圈的交叠部分比任何一个单个圈都要亮,而三个圈中间的交叠部分更亮,每种混合,都会增加亮度,因此这种混合光我们称之为加色光.


加色

而减色指的是颜料等着色剂产生的混合效果,颜料在混合中,其波长的光线会被吸收而造成一定的颜色混合,从而出现其他颜色.

描述色彩的模型叫做色彩空间,如RGB,HSB,HSV,HLS等.

  • RGB空间
    RGB空间表示的颜色是三种原色的某种混合:红色,绿色和蓝色.可以显示为一个立方体.


    RGB空间
  • HSV和HLS空间
    H(hue),色相/色调,即光的波长.不同波长的光直观的被人眼感知成各种颜色
    S(Saturation),饱和度/灰度,即色彩的浓度,或者说色彩中的灰色成分多少,饱和度越高,灰色越少,色彩越浓郁
    V(Value),亮度/明度,即色彩的亮度,或者说白色成分的多少,值越高,则越亮,直到纯白,反之越暗,直到纯黑


    HSV
  • CMY空间
    基于CMY的色彩空间最常用于彩色打印系统中。它们本质上是依赖于设备且相减的。CMY系列中的颜色空间组包括CMY,除了低端彩色打印机以外,这不是很常见;CMYK,模拟油墨或染料在打印纸上的应用方式.
    名称CMYK表示青色,洋红色,黄色和键(以黑色表示)。青色,品红色和黄色是此颜色空间中的三个原色,红色,绿色和蓝色是三个第二色。从理论上讲,不需要黑色。但是,当全饱和度的青色,品红色和黄色墨水在纸张上混合均匀时,结果通常是深棕色而不是黑色。因此,黑色墨水会在较暗的区域套印,以扩大动态范围并提供更好的外观。使用黑色墨水进行打印可以减少使用青色,品红色和黄色墨水。这可以防止饱和,尤其是在不能接受过多墨水的普通纸等材料上。使用黑色还可以降低每页成本,因为青色,品红色和黄色墨水通常比黑色墨水贵。它还可以提供更清晰的图像.


    CMY

1.CGColor

  • CGColorRef CGColorGetConstantColor(CFStringRef colorName);
    返回一个CGColorRef,colorName是一个常量,只有kCGColorWhite, kCGColorBlack, kCGColorClear三个值

  • CGColorRef CGColorCreateGenericGray(CGFloat gray, CGFloat alpha);
    生成一个灰色,gray是灰度,0.0-1.0,1.0是白色,0.0是黑色,alpha是透明度

  • CGColorRef CGColorCreateGenericRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);
    根据RGB空间生成颜色,参数范围都是0.0-1.0

  • CGColorRef CGColorCreateSRGB(CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha);
    同上,根据sRGB生成

RGB和sRGB两个方法生成的颜色不一样,同样是(.1, .5, .5, 1),上面是sRGB,下面是RGB


image.png
  • CGColorRef CGColorCreateGenericCMYK(CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha);
    根据CMYK空间生成颜色

  • CGColorRef CGColorCreateCopyWithAlpha(CGColorRef color, CGFloat alpha);
    修改颜色的透明度

  • CGFloat CGColorGetAlpha(CGColorRef color);
    获取颜色透明度

2.color space 色彩空间
在core Graphics中colorSpace主要有设备无关色彩空间,设备色彩空间和通用色彩空间,创建设备无关的色彩空间需要提供很多参数,涉及比较专业的内容,创建设备色彩空间和通用色彩空间基本不需要参数,直接create例如CGColorSpaceCreateDeviceCMYK; CGColorSpaceCreateDeviceGray; CGColorSpaceCreateDeviceRGB

  • CGColorSpaceRef CGColorSpaceCreateWithName(CFStringRef name);
    根据名字创建色彩空间,这里Apple提供了很多种Color Space Names
  • void CGContextSetFillColorSpace(CGContextRef c, CGColorSpaceRef space);
  • void CGContextSetStrokeColorSpace(CGContextRef c, CGColorSpaceRef space);
    这两个方法是给上下文设置色彩空间,给上下文设置颜色已经在第一篇讲过

二.渐变Gradient

首先创建一个渐变

  • CGGradientRef CGGradientCreateWithColorComponents(CGColorSpaceRef space, const CGFloat *components, const CGFloat *locations, size_t count);
    space是色彩空间
    components是描述颜色的变化,需要依据space来设置,比如space是RBG或者sRGB,那么components就需要是RGBA四个参数,并且因为是渐变,所以至少需要两个RBGA也就是8个浮点数
    locations是每个RGBA起效的位置,范围是0.0-1.0,比如components是12个浮点数,描述了三个颜色ABC,location是[.0,.5,1.0],那么前一半是A到B渐变,后一半是B到C渐变.
    count是location的长度
    CGGradientRef myGradient;
    CGColorSpaceRef myColorspace;
    size_t num_locations = 2;
    CGFloat locations[2] = { 0.0, 1.0 };
    CGFloat components[8] = { 1.0, 0.5, 0.4, 1.0, 0.8, 0.8, 0.3, 1.0 };
    myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    myGradient = CGGradientCreateWithColorComponents (myColorspace, components, locations, num_locations);
  • CGGradientRef CGGradientCreateWithColors(CGColorSpaceRef space, CFArrayRef colors, const CGFloat *locations);
    colors是一个CGColor的数组
    其他与上一个函数相同,
     CGColorRef colors[] = {UIColor.whiteColor.CGColor,UIColor.blackColor.CGColor};
    CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (void *)colors, (CFIndex)2, NULL);
    CGGradientRef myGradient2 = CGGradientCreateWithColors(myColorspace, array, locations);

创建渐变之后,在上下文绘制

  • void CGContextDrawLinearGradient(CGContextRef c, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options);
    线性渐变,提供两个点,形成一条线A,整个画布看成和线A平行的无数条线,每条线都按照A去做渐变
    CGPoint myStartPoint, myEndPoint;
    myStartPoint.x = 0;
    myStartPoint.y = 0;
    myEndPoint.x = rect.size.width;
    myEndPoint.y = 0;
    CGContextDrawLinearGradient (UIGraphicsGetCurrentContext(), myGradient2, myStartPoint, myEndPoint, 0);
image.png
  • void CGContextDrawRadialGradient(CGContextRef c, CGGradientRef gradient, CGPoint startCenter, CGFloat startRadius, CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options);
    双圆心渐变,提供两个圆心,和两个半径
    CGPoint myStartPoint, myEndPoint;  
    myStartPoint.x = 0;
    myStartPoint.y = rect.size.height / 2;
    myEndPoint.x = rect.size.width;
    myEndPoint.y = rect.size.height / 2;
    CGContextDrawRadialGradient(UIGraphicsGetCurrentContext(), myGradient, myStartPoint, rect.size.height/2,     
 myEndPoint, rect.size.height/2, kCGGradientDrawsAfterEndLocation);
image.png

三.图案pattern

关于pattern官方文档说明的更清晰
pattern是一系列绘制操作,重复绘制到图形上下文。 您可以使用与使用颜色相同的方式使用模式。 当您使用pattern进行绘制时,Quartz将页面划分为一组pattern单元格,每个单元格都是图案pattern图像的大小,并使用您提供的回调绘制每个单元格.

简单的理解,pattern就像一块布上的花纹或者说图案,它是重复平铺的,单元格之间的距离可以设置.


image.png

图案(pattern)可以直接填充上下文,也可以生成color.
直接使用CGPatternCreate创建需要一大堆的参数,下面来解释一下使用方法

CGPatternRef CGPatternCreate (  void *info,
                                CGRect bounds,
                                CGAffineTransform matrix,
                                CGFloat xStep,
                                CGFloat yStep,
                                CGPatternTiling tiling,
                                bool isColored,
                                const CGPatternCallbacks *callbacks );
  • info参数是指向要传递给绘图回调的数据的指针.
  • bounds指定图案单元格的bounds.
  • matrix是单元格的2d变换,不需要的话可以设置为单位矩阵CGAffineTransformIdentity
  • xStep和yStep参数指定图案坐标系中单元格之间的水平和垂直间距
  • tiling是平铺样式
  • isColored是否彩色
  • callbacks 绘制单元格的函数


void customPattern (void *info, CGContextRef myContext)
{
    CGFloat subunit = 20;
 
    CGRect  myRect1 = {{0,0}, {subunit, subunit}},
            myRect2 = {{subunit, subunit}, {subunit, subunit}},
            myRect3 = {{0,subunit}, {subunit, subunit}},
            myRect4 = {{subunit,0}, {subunit, subunit}};
 
    CGContextSetRGBFillColor (myContext, 0, 0, 0, 1);
    CGContextFillRect (myContext, myRect1);
    CGContextSetRGBFillColor (myContext, 0, 0, 0, 1);
    CGContextFillRect (myContext, myRect2);
    CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
    CGContextFillRect (myContext, myRect3);
    CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
    CGContextFillRect (myContext, myRect4);
    
}

void painting (CGContextRef myContext,
                 CGRect rect)
{
    CGPatternRef    pattern;
    CGColorSpaceRef patternSpace;
    CGFloat         alpha = 1;
    static const    CGPatternCallbacks callbacks = {0,
                                        &customPattern,
                                        NULL};
 
    CGContextSaveGState (myContext);
    patternSpace = CGColorSpaceCreatePattern (NULL);
    CGContextSetFillColorSpace (myContext, patternSpace);
    CGColorSpaceRelease (patternSpace);
 
    pattern = CGPatternCreate (NULL,
                    CGRectMake (0, 0, 40, 40),
                    CGAffineTransformRotate(CGAffineTransformIdentity, M_PI_4),
                    50,
                    50,
                    kCGPatternTilingConstantSpacing,
                    true,
                    &callbacks);
 
    CGContextSetFillPattern (myContext, pattern, &alpha);
    CGPatternRelease (pattern);
    CGContextFillRect (myContext, rect);
    CGContextRestoreGState (myContext);
}

- (void)drawRect:(CGRect)rect{
    CGContextRef context = UIGraphicsGetCurrentContext();
    painting(context, rect);
}

1.void customPattern (void *info, CGContextRef myContext)是绘制单元格的回调函数
2.这里不需要info,所以传了NULL
3.用pattern来填充上下文,使用CGContextSetFillPattern或者CGContextSetStrokePattern


绘制出来的效果

相关文章

网友评论

      本文标题:Core Graphics 四: 色彩和纹理

      本文链接:https://www.haomeiwen.com/subject/elbdpktx.html