IOS开发之滤镜 CIImage、CIFilter
滤镜这个词也许大家会耳生,特别是男生,不是歧视哦,只是你不经常用而已,那么肯定就有人说,我是女生怎么了,我也没有听过这个词啊,是不是过滤代码的?(你真是想多了-3-!)
但是你会对一下的几个词比较耳熟,比如说anglelababy代言的美颜相机,还有你们经常使用的美图秀秀,你以为你照下来就是那么美若天仙的样子?本人表示再也不相信网上的美女了,忽然觉得咱班花都挺好。哈哈;
好了,话不多说,我们来进入今天的主题:滤镜
- 介绍
框架介绍
类的介绍
效果介绍
- 使用
使用步骤
滤镜属性
- 滤镜链的使用
1. *框架介绍
(1) CoreImage
(2) 是一个图像框架 他是基于OpenGL顶层创建的一个框架
(3) 它是利用GPU机遇硬件加速来处理图像
(4) CoreImage中有很多滤镜
(5)它们能够一次给予一张图像或者视频帧多种视觉效果 -> 滤镜链
(6)而且滤镜可以连接起来组成一个滤镜链 把滤镜效果叠加起来处理图像
2.类的介绍
(1)CIImage 保存图像数据的类 可以和UIImage去转换
CGImgeRef 图像里面的数据‘
(2)CIFilter:滤镜类 对滤镜对象进行设置的时候是通过键值编码来设置的(KVC)
(3)CIContext :上下文 是实现对图像处理的具体对象 ——》滤镜对象输出的对象并不是合成之后的对象、需要使用图像处理的上下文 合并输出的图像
3.效果介绍
100+效果可以通过可以通过Attribute这个属性得到你先要在滤镜上面展示的效果(详细不列举,列举明天早上就起不来了)
*使用
使用步骤:
1、有一个CIImage的对象 不能直接把UIIMage转成CIImage 应该先把UIIMage转成CGImgeRef再转成CIImage
2、创建一个滤镜的对象,设置他的参数(KVC)
3、创建CIContext上下文
4、合并滤镜输出的图像 —— 合并之后会得到一个图像
5、赋值给UIImageView显示出来
6、如果想要继续添加滤镜可以继续循环
滤镜属性:
注意:我们这里是直接查询到自己需要的属性,并不需要去记,不然就会有一种纪英汉大字典的感觉
1.查询效果分类里面的效果
filterNamesInCategory:
2.查询效果的属性
[CIFilter filterWithName:XXX].attributes
下面老夫为大家上代码:(不给你整点料,你是不知道我文武全才)
先做准备工作,实在是剧情需要,不然看不出特效:两个button,一个pickViewController(因为要访问到你的相册)、一个ImageView
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.navigationController.navigationBarHidden = YES;
imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 200, 500, 600)];
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.backgroundColor = [UIColor grayColor];
[self.view addSubview:imageView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 50, 50);
button.backgroundColor = [UIColor grayColor];
[button addTarget:self action:@selector(tap:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
//
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
button1.frame = CGRectMake(100, 100, 100, 100);
[button1 setTitle:@"TICK" forState:UIControlStateNormal];
button1.backgroundColor = [UIColor brownColor];
[button1 addTarget:self action:@selector(addEffect) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
}
- (void)tap:(UIButton *) sender{
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
// picker.sourceType = 默认是照片
[self presentViewController:picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
[self dismissViewControllerAnimated:YES completion:nil];
UIImage *image = info[UIImagePickerControllerOriginalImage];
// 得到的照片显示在视图上
imageView.image = image;
// NSLog(@"%@",info);
}
现在先讲一下滤镜的大概流程,我觉得一张图就足矣表达:
- (void)addFilter{ // 1. 需要有一个输入的原图 CIImage *inputImage = [CIImage imageWithCGImage:imageView.image.CGImage]; // 2. 需要一个滤镜 CIFilter *filter = [CIFilter filterWithName:@"CIBumpDistortion"]; // 通过打印可以设置的属性里面 得到可以设置 inputImage ——》在接口文件里面查找得到的key
// 这里我们使用的是KVC的方式给filter设置属性 [filter setValue:inputImage forKey:kCIInputImageKey]; // 设置凹凸的效果半径 越大越明显 [filter setValue:@500 forKey:kCIInputRadiusKey]; // CIVector :表示 X Y 坐标的一个类 // 设置中心点的 [filter setValue:[CIVector vectorWithX:200 Y:200] forKey:kCIInputCenterKey]; // 3.有一个CIContext的对象去合并原图和滤镜效果 CIImage *outputImage = filter.outputImage; // 创建一个图像操作的上下文 CIContext *context = [CIContext contextWithOptions:nil]; // 把原图和滤镜合并起来 包含原图和滤镜效果的图像 /** * Image : 合成之后的图像 * fromRect: 合成之后图像的尺寸: 图像.extent */ CGImageRef imageRef = [context createCGImage:outputImage fromRect:outputImage.extent]; imageView.image = [UIImage imageWithCGImage:imageRef]; }
注意 :这里有几个坑啊:1。需要原图的时候我们需要的是一个CIImage Class的对象,不是CGIMage的对象,很多人都写错了,所以我们只能转化把CGImage转成CIImage
2. 我们所需要的滤镜属性以及特效的类都只能NSLog出来,而且这里特别容易混淆,具体方法如下:
1.查询 效果分类中 包含什么效果:filterNamesInCategory:
(1)按住command 点击CIFilter 进入接口文件 找到第128行-148行全部都是 效果分类
(2)选择其中某一个分类 NSLog -> [CIFilter filterNamesInCategory:刚才拷贝的分类]; -> 打印出来的 是这个分类包含的所有 效果 -> 拷贝选择其中的某一个效果
2.查询 使用的效果中 可以设置什么属性(KVC) attributes
NSLog -> [CIFilter filterWithName:刚才拷贝选择其中的某一个效果].attributes ->得到这个滤镜所有可以设置的属性
你要是还理不清的话:1.求神保佑你蒙对了(可能性为负数) 2.如图所示,多多参悟
大概流程是:先CIFiliter ——》 点进去得到category中的其中一个 ——》使用 [CIFilter filterNamesInCategory:刚才拷贝的分类] 方法nslog出所需要的类; ————》 在类里有很多的子类 随便copy一个 ——》 [CIFilter filterWithName:刚才拷贝选择其中的某一个效果].attributes 获得到所有可设置的属性 ————》 使用KVC的方法设置属性 setValue:Forkey:(注意:这里的key也需要进CIFilter里去找和你所选的属性类似的Key,在CIFilter的165-191行)
*滤镜链:就是滤镜的嵌套组合使用
#pragma mark===滤镜链 //再次添加滤镜 形成滤镜链 - (void)addfilterLinkerWithImage:(CIImage *)image{ CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"]; [filter setValue:image forKey:kCIInputImageKey]; [filter setValue:@0.5 forKey:kCIInputIntensityKey]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef imageRef = [context createCGImage:filter.outputImage fromRect:filter.outputImage.extent]; imageView.image = [UIImage imageWithCGImage:imageRef]; //保存图片到相册 不可以直接保存outputImage 因为这是一个没有合成的图像 UIImageWriteToSavedPhotosAlbum(imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); }
当然 ,你也可以一直添加,到最后一步再把滤镜和原图结合起来,这样更省代码-3-!