iOS CoreImage濾鏡 圖片處理效果

前言
現(xiàn)在很多的APP當(dāng)中選擇圖片都會帶有圖片處理效果,一些類似于美圖,PS的功能,其實在iOS中系統(tǒng)內(nèi)部也有這樣一個框架,在Xcode7.0之前的版本需要手動去導(dǎo)入這個框架,7.0之后系統(tǒng)已經(jīng)自動幫我們導(dǎo)入了這個框架。我們想要處理圖片直接就可以在方法里面去實現(xiàn)處理圖片的效果。

在學(xué)習(xí)這個框架之前我們要看一下什么是濾鏡的效果,我們先找到一張圖片,然后拿一個視圖層來覆蓋到源圖上面,這里我就隨便找一張圖片

修改過的圖

再來貼一張原圖吧

原圖

可以看到經(jīng)過處理之后圖片變得像那種黃昏一樣的效果,我們在美圖或者PS上都可以簡單的實現(xiàn)這些小功能,那么今天就說一下iOS系統(tǒng)中,系統(tǒng)是如何來做這個圖片處理的。

  • 1.框架介紹
    (1)CoreImage
    (2)是一個圖片框架
    它基于OpenGL頂層創(chuàng)建
    底層則用著色器來處理圖像
    (3)他利用了GPU基于硬件加速來處理圖像
    (4)CoreImage中有很多濾鏡
    (5)它們能夠一次給予一張圖像或者視頻幀多種視覺效果 -> 濾鏡鏈
    (6)而且濾鏡可以連接起來組成一個濾鏡鏈 把濾鏡效果疊加起來處理圖像

  • 2.類的介紹
    1.CIImage 保存圖像數(shù)據(jù)的類
    CGImageRef->圖像中的數(shù)據(jù)
    2.CIFilter 濾鏡類
    圖片屬性進行細(xì)節(jié)處理的類
    它對所有的像素進行操作 用鍵-值(KVC)來設(shè)置
    3.CIContext 上下文是實現(xiàn)對圖像處理的具體對象 用來把濾鏡和圖片合成成為一張圖片 濾鏡對象輸出的圖像并不是合成之后的圖像,需要使用圖片處理的上下文 合并輸出圖像

接下來就是他系統(tǒng)內(nèi)部的效果分類,效果分類就不在這里一一羅列出來了,因為這里根本寫不下,可以點進CIFilter里,然后找到128行,從這里開始,可以一一了解一下這些效果。

然后我們就可以做一個圖片處理的效果,我們處理圖片的原理上面給大家說過了,就是給他添加了一個濾鏡,CIFilter,來使他的視圖發(fā)生一些變化。

在這里我們雖然展示在視圖上的仍然是UIImageView上面的image,但是我們做處理的時候使用的是CIImage。然后我們需要找到我們需要的效果類,在CIFilter中查詢我們需要的效果類,這里直接上代碼給大家解釋,因為在找效果類的時候比較復(fù)雜。

首先我們創(chuàng)建一個全局變量的UIImageView,然后讓他初始化出來

 @interface ViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>
{
     UIImageView *imageView;
}
@end

因為要訪問相冊,所以我們同樣需要導(dǎo)入導(dǎo)航欄和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];

 //跳轉(zhuǎn)相冊的觸發(fā)方法
- (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];
}

這里我就簡單的寫兩個按鈕(其實就是從代碼片段里拖出來的 =-=)

然后我們重點做一個圖片的處理效果的方法。這里我們選擇把它的顏色發(fā)生一些改變

- (void)addColorFilter{

CIImage *inputImage = [CIImage imageWithCGImage:imageView.image.CGImage];
//先打印NSLog(@"%@",[CIFilter filterNamesInCategory:kCICategoryDistortionEffect]);進去找到需要設(shè)置的屬性(查詢效果分類中都有什么效果)  可以設(shè)置什么效果
//然后通過[CIFilter filterWithName:@""];找到屬性   具體效果的屬性
//然后通過KVC的方式設(shè)置屬性
NSLog(@"%@",[CIFilter filterNamesInCategory:kCICategoryDistortionEffect]);
/*
 1.查詢 效果分類中 包含什么效果:filterNamesInCategory:
 2.查詢 使用的效果中 可以設(shè)置什么屬性(KVC) attributes
 
 使用步驟
 1.需要添加濾鏡的源圖
 2.初始化一個濾鏡 設(shè)置濾鏡(根據(jù)查詢到的屬性來設(shè)置)
 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把他轉(zhuǎn)換成CIImage的類型來獲得到。

第二部,進入CIFilter中,找到128行-148行,全都是效果的分類,然后,來找你需要的效果,這里我們就使用kCICategoryDistortionEffect失真的效果類,記住,這里是效果類型,然后nslog打印出這個效果類型,看里面包含了哪些效果。
我們在這里找到CIColorMonochrome這個效果,然后我們使用濾鏡使用這個效果。

CIFilter *filter = [CIFilter filterWithName:@"CIColorMonochrome"];

再打印這個效果包含了哪些屬性,這里我們打印他的屬性

NSLog(@"%@",filter.attributes);

在里面我們可以看到好多屬性,里面是多個字典的形式,找到我們想要修改的屬性(key值) 然后在他對應(yīng)的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類型的,有默認(rèn)值,這里我們寫了一個CIColor來給他進行賦值。

賦值的時候要使用KVC的形式來賦值

[filter setValue:color forKey:kCIInputColorKey];

接下來,賦值之后,被濾鏡過濾之后的圖片就有了,但是我們這個時候拿出這個圖片的時候發(fā)現(xiàn)他并沒有發(fā)生變化,因為它只是單一進行了濾鏡處理,還沒有和原圖片進行一個糅合。

CIImage *outPutImage = filter.outputImage;

我們找到添加效果后的圖片,然后使用CIContext找到上下文對他進行糅合

//extent得到圖像的尺寸    合并一個包含源圖   濾鏡效果的圖片
//1 濾鏡輸出的圖像    2.合成之后圖像的尺寸   圖像.extent
CGImageRef imageRef = [context createCGImage:outPutImage fromRect:outPutImage.extent];

這樣我就進行了一個簡單的圖片處理。我們可以看到它已經(jīng)發(fā)生了一些變化。
假如你的圖片消失了,請檢查一下,第一步獲取圖片的時候一定要獲得圖片的CGImage再來來獲取,不要直接使用imageView.image.CGImage。

假如你的圖片還是沒有出來,請檢查你使用的效果類是否適合用來處理圖片,或者它里面有沒有必須要賦值的屬性你沒有賦值?;蛘邫z查一下處理圖片的時候有沒有給kCIInputImageKey賦值

對于第二步打印效果分類,在這里放上一個圖片來便于大家理解

效果分類詳解.jpg

在給一張圖片添加多種濾鏡效果的時候,我們把它稱為濾鏡鏈,我們再添加濾鏡鏈的時候,就是把圖片添加一層濾鏡,然后,和原圖片糅合處理,然后在處理之后的圖片上再添加一層濾鏡,并不是直接給一張圖片添加了兩層路徑,所以稱為濾鏡鏈。

我們繼續(xù)使用這個圖片,在它添加第一層濾鏡的時候做一些修改
修改如下

//上接給效果屬性賦值
//把下面注釋的給注釋掉,然后添加一個方法
    //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);
 }
//保存圖片回調(diào)
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
    NSLog(@"保存成功");
}

這樣就能做一個雙重濾鏡效果,同時把它保存到了相冊。

進行圖片處理的時候要了解他的效果類型,還有屬性的類型,賦值的過程,理解了這一點,添加濾鏡就沒有什么大問題了,在這點我來來回回說了三遍,希望能有所有幫助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容