iOS CoreImage滤镜 图片处理效果

来源:互联网 发布:php输出当前时间戳 编辑:程序博客网 时间:2024/05/21 09:33

前言
现在很多的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.合成之后图像的尺寸   图像.extentCGImageRef imageRef = [context createCGImage:outPutImage fromRect:outPutImage.extent];

这样我就进行了一个简单的图片处理。我们可以看到它已经发生了一些变化。
假如你的图片消失了,请检查一下,第一步获取图片的时候一定要获得图片的CGImage再来来获取,不要直接使用imageView.image.CGImage。

假如你的图片还是没有出来,请检查你使用的效果类是否适合用来处理图片,或者它里面有没有必须要赋值的属性你没有赋值。或者检查一下处理图片的时候有没有给kCIInputImageKey赋值

对于第二步打印效果分类,在这里放上一个图片来便于大家理解

详情

在给一张图片添加多种滤镜效果的时候,我们把它称为滤镜链,我们再添加滤镜链的时候,就是把图片添加一层滤镜,然后,和原图片糅合处理,然后在处理之后的图片上再添加一层滤镜,并不是直接给一张图片添加了两层路径,所以称为滤镜链。

我们继续使用这个图片,在它添加第一层滤镜的时候做一些修改
修改如下

//上接给效果属性赋值//把下面注释的给注释掉,然后添加一个方法    //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(@"保存成功");}

这样就能做一个双重滤镜效果,同时把它保存到了相册。

进行图片处理的时候要了解他的效果类型,还有属性的类型,赋值的过程,理解了这一点,添加滤镜就没有什么大问题了,在这点我来来回回说了三遍,希望能有所有帮助。

0 0
原创粉丝点击