iOS CoreImage滤镜 图片处理效果

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

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容