计算机图形分为两类,矢量图形和位图图形
位图图形就是像素点阵,是由像素点按照特定阵列显示出来,当像素密度足够大时,位图图形可以还原真实的场景,但是当像素密度小的时候,就会出现锯齿,模糊等现象(Aliasing).
矢量图形是用更复杂的数学模型描述的图形,有点类似cgcontext的绘制,比如轮廓和填充策略,文件的大小由图像的复杂程度决定,放大和缩小不会对图形产生影响.
Core Graphics中提供了很多函数,越是灵活的函数复杂度越高,参数涉及的底层内容也更多.这里从常规的使用开始入手.
一.创建位图图像
1.创建图像 CGImageRef
- 1.1通过资源创建图像
创建图像有两种方法,第一种是加载图像资源,图像资源可以是文件,也可以是core graphics的数据结构.最简单的就是直接加载图片文件.
CGImageSourceRef sourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)[[NSURL alloc] initFileURLWithPath:[[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"]], NULL);
CGImageRef imgRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
CGImageSourceRef CGImageSourceCreateWithURL(CFURLRef url, CFDictionaryRef options);
CGImageRef CGImageSourceCreateImageAtIndex(CGImageSourceRef isrc, size_t index, CFDictionaryRef options);
这两个函数都需要一个策略字典,这个字典如果没有特殊需求可以给NULL,字典的详情参照developer documentation.
CGImageSourceCreateImageAtIndex需要一个index,如果是png,jpeg之类的文件,使用0就可以了,因为图像只有一个,而gif可以有多个图像,配合CGImageSourceGetCount可以拿到文件包含的图像个数.
需要注意的是CGImageRef要调用CGImageRelease释放.
当然如果只是需要CGImageRef,UIKit中的UIImage还提供了更便捷的方法
@property(nonatomic, readonly) CGImageRef CGImage;
- 1.2通过上下文创建图像
最常用的函数是
CGImageRef CGBitmapContextCreateImage(CGContextRef context);
绘制之后调用CGBitmapContextCreateImage生成CGImageRef,然后imageWithCGImage生成UIImage对象
CGImageRef imgref = CGBitmapContextCreateImage(UIGraphicsGetCurrentContext());
UIImage *image = [UIImage imageWithCGImage:imgref];
-1.3从图像上选择一部分创建新的图像
CGImageRef CGImageCreateWithImageInRect(CGImageRef image, CGRect rect);
这个函数需要注意像素和点的关系,也就是UIImage的size和UIImageView的size的差距.
CGImageRef imgref = CGImageCreateWithImageInRect(img.CGImage, CGRectMake(img.size.width/4,img.size.height/4,img.size.width/2, img.size.height/2));
imgv.image = [UIImage imageWithCGImage:imgref];

这段代码中,img是前面CGBitmapContextCreateImage获取到的,取中间一部分放大然后显示,会发现线也粗了
UIImageView *imgv = [[UIImageView alloc]init];
[self.view addSubview:imgv];
CGImageRef imgRef = [UIImage imageNamed:@"avatar"].CGImage;
size_t height = CGImageGetHeight(imgRef);
size_t width = CGImageGetWidth(imgRef);
CGImageRef halfimgref = CGImageCreateWithImageInRect(imgRef, CGRectMake(width/4,height/4,width/2, height/2));
imgv.frame = CGRectMake(0, 250, 200, 200.0/width*height);
imgv.image = [UIImage imageWithCGImage:halfimgref];
CGImageRelease(imgRef);
CGImageRelease(halfimgref);
上面这段代码是剪切图片生成新的图片并显示
CGImageGetHeight和CGImageGetWidth可以获取CGImageRef的尺寸
如果imgRef不创建出来,直接把 [UIImage imageNamed:@"avatar"].CGImage作出参数传进去,也就少一次引用,CGImageCreateWithImageInRect使用之后会释放,如果自己没有引用的话,就不用再释放了.

二.创建图像蒙版(或者叫做遮罩)
1.颜色蒙版
通过屏蔽提供给函数的图像中的一种颜色或一系列颜色来创建图像.
CGImageRef CGImageCreateWithMaskingColors(CGImageRef image, const CGFloat *components);
这个函数是抠掉指定范围内的颜色,components是两组rbg值,不过顺序是R1,R2,G1,G2,B1,B2;
意思是将指定范围内的颜色除去
const CGFloat colors[6] = {9,80, 35, 130, 13, 140};
CGImageRef maskref = CGImageCreateWithMaskingColors(imgRef, colors);
imgv.image = [UIImage imageWithCGImage:maskref];
这个例子是先用取色器在图中绿色部分取一个深色取一个浅色,深色是9,35,13;浅色是80,130,140,在这个范围内的颜色被抠掉露出下面洋红色的背景.

2.上下文蒙版
在这之前,需要先了解一点,一些蒙版相关的函数中,叫做mask的参数,虽然都是CGImageRef类型,但是通过CGImageMaskCreate创建出来的CGImageRef是不一样的,叫做图形掩码,是用来作为蒙版的参数.
另外介绍一下CGImageMaskCreate函数
CGImageRef maskRef = [UIImage imageNamed:@"11"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
这个函数需要一大堆的参数,暂时先按照这么去写,具体参照developer documentation
接下来是使用上下文蒙版
void CGContextClipToMask(CGContextRef c, CGRect rect, CGImageRef mask);
这个函数需要一个rect,表示蒙版的范围,mask是一个CGImageRef;
mask是一个普通的CGImageRef,例如[UIImage imageNamed:@"11"].CGImage,(如图2-1)
和
mask是一个通过CGImageMaskCreate创建的CGImageRef,产生的结果是不一样的.(如图2-2)
CGFloat x = rect.size.width/4;
CGFloat y = rect.size.height/4;
CGFloat w = rect.size.width/2;
CGFloat h = rect.size.height/2;
CGRect half = CGRectMake(x, y, w, h);
CGImageRef maskRef = [UIImage imageNamed:@"11"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGContextClipToMask(context, rect, mask);
// CGContextClipToMask(context, rect, maskRef);
[[UIImage imageNamed:@"22"] drawInRect:rect];
这段示例中,两个CGContextClipToMask效果完全相反.
另外CGContextClipToMask如果使用half,那么遮罩之外的图片"22",会被切掉.(如图2-3)



3.使用图片作为蒙版
实质是生成新的图像,并且效果与上下文蒙版相似
CGImageRef CGImageCreateWithMask(CGImageRef image, CGImageRef mask);
CGImageRef imgRef = [UIImage imageNamed:@"avatar"].CGImage;
CGImageRef maskRef = [UIImage imageNamed:@"11"].CGImage;
CGImageRef mask = CGImageMaskCreate(CGImageGetWidth(maskRef),
CGImageGetHeight(maskRef),
CGImageGetBitsPerComponent(maskRef),
CGImageGetBitsPerPixel(maskRef),
CGImageGetBytesPerRow(maskRef),
CGImageGetDataProvider(maskRef), NULL, false);
CGImageRef maskimg = CGImageCreateWithMask(imgRef, mask);
imgv.image = [UIImage imageWithCGImage:maskimg];
露出了下面的背景色

4.混合模式蒙版
void CGContextSetBlendMode(CGContextRef c, CGBlendMode mode);
设置上下文的混合模式,CGBlendMode有很多种,具体参照文档.
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:200/255.0 green:110/255.0 blue:180/255.0 alpha:1].CGColor);
CGContextAddRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height/5));
CGContextDrawPath(context, kCGPathFill);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:190/255.0 green:190/255.0 blue:190/255.0 alpha:1].CGColor);
CGContextAddRect(context, CGRectMake(0, rect.size.height/5, rect.size.width, rect.size.height/5));
CGContextDrawPath(context, kCGPathFill);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:240/255.0 green:70/255.0 blue:150/255.0 alpha:1].CGColor);
CGContextAddRect(context, CGRectMake(0, rect.size.height/5*2, rect.size.width, rect.size.height/5));
CGContextDrawPath(context, kCGPathFill);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:140/255.0 green:220/255.0 blue:70/255.0 alpha:1].CGColor);
CGContextAddRect(context, CGRectMake(0, rect.size.height/5*3, rect.size.width, rect.size.height/5));
CGContextDrawPath(context, kCGPathFill);
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:16/255.0 green:128/255.0 blue:216/255.0 alpha:1].CGColor);
CGContextAddRect(context, CGRectMake(0, rect.size.height/5*4, rect.size.width, rect.size.height/5));
CGContextDrawPath(context, kCGPathFill);
CGContextSetBlendMode(context, kCGBlendModeDifference);
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1, -1);
CGContextDrawImage(context, rect, [UIImage imageNamed:@"22"].CGImage);
过程就是先画背景,然后设置模式,最后绘图


网友评论