前言
现在很多的APP当中选择图片都会带有图片处理效果,一些类似于美图,PS的功能,其实在iOS中系统内部也有这样一个框架,在Xcode7.0之前的版本需要手动去导入这个框架,7.0之后系统已经自动帮我们导入了这个框架。我们想要处理图片直接就可以在方法里面去实现处理图片的效果。
在学习这个框架之前我们要看一下什么是滤镜的效果,我们先找到一张图片,然后拿一个视图层来覆盖到源图上面,这里我就随便找一张图片
修改过的图再来贴一张原图吧
原图可以看到经过处理之后图片变得像那种黄昏一样的效果,我们在美图或者PS上都可以简单的实现这些小功能,那么今天就说一下iOS系统中,系统是如何来做这个图片处理的。
-
1.框架介绍
(1)CoreImage
(2)是一个图片框架
它基于OpenGL顶层创建
底层则用着色器来处理图像
(3)他利用了GPU基于硬件加速来处理图像
(4)CoreImage中有很多滤镜
(5)它们能够一次给予一张图像或者视频帧多种视觉效果 -> 滤镜链
(6)而且滤镜可以连接起来组成一个滤镜链 把滤镜效果叠加起来处理图像 -
2.类的介绍
1.CIImage 保存图像数据的类
CGImageRef->图像中的数据
2.CIFilter 滤镜类
图片属性进行细节处理的类
它对所有的像素进行操作 用键-值(KVC)来设置
3.CIContext 上下文是实现对图像处理的具体对象 用来把滤镜和图片合成成为一张图片 滤镜对象输出的图像并不是合成之后的图像,需要使用图片处理的上下文 合并输出图像
接下来就是他系统内部的效果分类,效果分类就不在这里一一罗列出来了,因为这里根本写不下,可以点进CIFilter里,然后找到128行,从这里开始,可以一一了解一下这些效果。
然后我们就可以做一个图片处理的效果,我们处理图片的原理上面给大家说过了,就是给他添加了一个滤镜,CIFilter,来使他的视图发生一些变化。
在这里我们虽然展示在视图上的仍然是UIImageView上面的image,但是我们做处理的时候使用的是CIImage。然后我们需要找到我们需要的效果类,在CIFilter中查询我们需要的效果类,这里直接上代码给大家解释,因为在找效果类的时候比较复杂。
首先我们创建一个全局变量的UIImageView,然后让他初始化出来
@interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>
{
UIImageView *imageView;
}
@end
因为要访问相册,所以我们同样需要导入导航栏和UIImagePickerController的代理
然后我们写两个按钮,一个按钮用来找到并显示图片,一个按钮用来对图片做一些处理
imageView = [[UIImageView alloc]initWithFrame:self.view.frame];
imageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:imageView];
self.view.backgroundColor = [UIColor colorWithRed:0.813 green:1.000 blue:0.564 alpha:1.000];
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
button1.frame = CGRectMake(100, 100, 120, 45);
[button1 setTitle:@"找图片" forState:UIControlStateNormal];
button1.backgroundColor = [UIColor brownColor];
[button1 addTarget:self action:@selector(doit) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button1];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(250, 200, 150, 45);
[button setTitle:@"让我来修改" forState:UIControlStateNormal];
[button setTitleColor:[UIColor colorWithRed:102/255.0f green:153/255.0f blue:0.0f alpha:1] forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont systemFontOfSize:12]];
[button.layer setCornerRadius:5];
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef colorRef = CGColorCreate(colorSpace,(CGFloat[]){ 102/255.0f, 153/255.0f, 0.0f, 1 });
[button.layer setBorderColor:colorRef];
[button.layer setBorderWidth:1.0f];
[button addTarget:self action:@selector(addColorFilter) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
//跳转相册的触发方法
- (void)doit{
UIImagePickerController *vc = [[UIImagePickerController alloc]init];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
}
//让图片显示在VC上面的方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
NSLog(@"%@",info);
//获得选中的图像
UIImage *chooseImage = info[UIImagePickerControllerOriginalImage];
//先是在试图空间上
imageView.image = chooseImage;
[self dismissViewControllerAnimated:YES completion:nil];
}
这里我就简单的写两个按钮(其实就是从代码片段里拖出来的 =-=)
然后我们重点做一个图片的处理效果的方法。这里我们选择把它的颜色发生一些改变
- (void)addColorFilter{
CIImage *inputImage = [CIImage imageWithCGImage:imageView.image.CGImage];
//先打印NSLog(@"%@",[CIFilter filterNamesInCategory:kCICategoryDistortionEffect]);进去找到需要设置的属性(查询效果分类中都有什么效果) 可以设置什么效果
//然后通过[CIFilter filterWithName:@""];找到属性 具体效果的属性
//然后通过KVC的方式设置属性
NSLog(@"%@",[CIFilter filterNamesInCategory:kCICategoryDistortionEffect]);
/*
1.查询 效果分类中 包含什么效果:filterNamesInCategory:
2.查询 使用的效果中 可以设置什么属性(KVC) attributes
使用步骤
1.需要添加滤镜的源图
2.初始化一个滤镜 设置滤镜(根据查询到的属性来设置)
3.把滤镜 输出的图像 和滤镜 合并 CIContext -> 得到一个合成之后的图像
4.展示
*/
CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome"];
NSLog(@"%@",filter.attributes);
//这个属性是必须赋值的,假如你处理的是图片的话
[filter setValue:inputImage forKey:kCIInputImageKey];
CIColor *color = [CIColor colorWithRed:1.000 green:0.759 blue:0.592 alpha:1];
[filter setValue:color forKey:kCIInputColorKey];
//CIContext
CIContext *context = [CIContext contextWithOptions:nil];
CIImage *outPutImage = filter.outputImage;
CGImageRef image = [context createCGImage:outPutImage fromRect:outPutImage.extent];
imageView.image = [UIImage imageWithCGImage:image];
}
首先我们第一步通过全局变量来获得我们找到的image把他转换成CIImage的类型来获得到。
第二部,进入CIFilter中,找到128行-148行,全都是效果的分类,然后,来找你需要的效果,这里我们就使用kCICategoryDistortionEffect失真的效果类,记住,这里是效果类型,然后nslog打印出这个效果类型,看里面包含了哪些效果。
我们在这里找到CIColorMonochrome这个效果,然后我们使用滤镜使用这个效果。
CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome"];
再打印这个效果包含了哪些属性,这里我们打印他的属性
NSLog(@"%@",filter.attributes);
在里面我们可以看到好多属性,里面是多个字典的形式,找到我们想要修改的属性(key值) 然后在他对应的value里面查看一下他的属性类型,比如我们打印的CIColorMonochrome里面有一个inputColor
inputColor = {
CIAttributeClass = CIColor;
CIAttributeDefault = "(0.6 0.45 0.3 1)";
CIAttributeDescription = "The monochrome color to apply to the image.";
CIAttributeDisplayName = Color;
CIAttributeType = CIAttributeTypeOpaqueColor;
};
我们看到他是一个CIColor类型的,有默认值,这里我们写了一个CIColor来给他进行赋值。
赋值的时候要使用KVC的形式来赋值
[filter setValue:color forKey:kCIInputColorKey];
接下来,赋值之后,被滤镜过滤之后的图片就有了,但是我们这个时候拿出这个图片的时候发现他并没有发生变化,因为它只是单一进行了滤镜处理,还没有和原图片进行一个糅合。
CIImage *outPutImage = filter.outputImage;
我们找到添加效果后的图片,然后使用CIContext找到上下文对他进行糅合
//extent得到图像的尺寸 合并一个包含源图 滤镜效果的图片
//1 滤镜输出的图像 2.合成之后图像的尺寸 图像.extent
CGImageRef imageRef = [context createCGImage:outPutImage fromRect:outPutImage.extent];
这样我就进行了一个简单的图片处理。我们可以看到它已经发生了一些变化。
假如你的图片消失了,请检查一下,第一步获取图片的时候一定要获得图片的CGImage再来来获取,不要直接使用imageView.image.CGImage。
假如你的图片还是没有出来,请检查你使用的效果类是否适合用来处理图片,或者它里面有没有必须要赋值的属性你没有赋值。或者检查一下处理图片的时候有没有给kCIInputImageKey赋值。
对于第二步打印效果分类,在这里放上一个图片来便于大家理解
效果分类详解.jpg在给一张图片添加多种滤镜效果的时候,我们把它称为滤镜链,我们再添加滤镜链的时候,就是把图片添加一层滤镜,然后,和原图片糅合处理,然后在处理之后的图片上再添加一层滤镜,并不是直接给一张图片添加了两层路径,所以称为滤镜链。
我们继续使用这个图片,在它添加第一层滤镜的时候做一些修改
修改如下
//上接给效果属性赋值
//把下面注释的给注释掉,然后添加一个方法
//CIContext
// CIContext *context = [CIContext contextWithOptions:nil];
CIImage *outPutImage = filter.outputImage;
[self addFilterLinkerWithImage:outPutImage];
// CGImageRef image = [context createCGImage:outPutImage fromRect:outPutImage.extent];
// imageView.image = [UIImage imageWithCGImage:image];
//再次添加滤镜 -> 形成滤镜链
- (void)addFilterLinkerWithImage:(CIImage *)image
{
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];
[filter setValue:image forKey:kCIInputImageKey];
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef resultImage = [context createCGImage:filter.outputImage fromRect:filter.outputImage.extent];
imageView.image = [UIImage imageWithCGImage:resultImage];
//把添加好滤镜效果的图片 保存到相册
//不可以直接保存 outputImage -> 这是一个没有吧滤镜效果和源图合成的图像
UIImageWriteToSavedPhotosAlbum(imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
//保存图片回调
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
NSLog(@"保存成功");
}
这样就能做一个双重滤镜效果,同时把它保存到了相册。
进行图片处理的时候要了解他的效果类型,还有属性的类型,赋值的过程,理解了这一点,添加滤镜就没有什么大问题了,在这点我来来回回说了三遍,希望能有所有帮助。
喵
网友评论