美文网首页iOS精选博文ios框架我的ios进阶
iOS CoreImage滤镜 图片处理效果

iOS CoreImage滤镜 图片处理效果

作者: 清溪丷 | 来源:发表于2016-03-24 20:37 被阅读4424次

    前言
    现在很多的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(@"保存成功");
    }
    

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

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

    相关文章

      网友评论

        本文标题:iOS CoreImage滤镜 图片处理效果

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