Core Image
利用Quartz 2D我們可以繪製各類圖形、圖像,功能確實強大。用過photoshop的朋友都知道,使用photoshop可以製作各種濾鏡特效,那麼在iOS中能否實現濾鏡呢?在iOS5.0之前這些算法基本全部要靠程序員編程實現,實現過程相當複雜。從iOS5.0開始蘋果官方已經提供了Core Image框架來幫助開發者進行特效製作。
先來看一下濾鏡使用過程中常用的基類對象:
CIContext:圖像上下文,用於管理整個圖片處理過程,不同的圖形上下文將利用不同的圖像處理硬件進行圖像處理(在iOS中可以通過不同的方式創建圖像上下文,例如可以創建基於CPU的圖像上下方、創建基於GPU的圖像上下方以及創建OpenGL優化過的圖像上下文)。
CIFilter:圖像處理濾鏡,每種濾鏡有不同的參數設置。
CIImage:Core Image框架中的圖像類型,主要用於輸入和輸出圖像。
在使用濾鏡之前我們先要弄清平臺主要支持哪些濾鏡,以及這些濾鏡的方法和參數如何設置,此時不妨使用下面的方法進行打印查看:
#pragma mark 查看所有內置濾鏡
-(void)showAllFilters{
NSArray *filterNames=[CIFilter filterNamesInCategory:kCICategoryBuiltIn];
for (NSString *filterName in filterNames) {
CIFilter *filter=[CIFilter filterWithName:filterName];
NSLog(@"\rfilter:%@\rattributes:%@",filterName,[filter attributes]);
}
}
在iOS7中打印會發現有127中濾鏡,如果我們把每種濾鏡都介紹一遍恐怕用幾章內容也很難介紹詳細,事實上也沒有這個必要。這些濾鏡使用方法是類似的,只是參數設置有所區別。在iOS文檔中可以搜索“core image filter reference”一節的內容,裏面有每種濾鏡的詳細介紹和圖片使用效果。
使用Core Image框架創建濾鏡效果一般分爲以下幾步:
1.創建圖像上下文CIContext
2.創建濾鏡CIFilter
3.創建過濾原圖片CIImage
4.調用CIFilter的setValue: forKey:方法爲濾鏡指定源圖片
5.設置濾鏡參數【可選】
6.取得輸出圖片顯示或保存
大家都知道在美圖秀秀中有一個“增強”功能,利用它可以調整照片的飽和度、亮度、對比度,其實在Core Image中也有這樣一款濾鏡,下面就以顏色濾鏡來演示一下Core Image中濾鏡的使用。
//
// KCMainViewController.m
// CoreImage
//
// Created by Kenshin Cui on 14-3-17.
// Copyright (c) 2014年 Kenshin Cui. All rights reserved.
//
#import "KCMainViewController.h"
#define CONSTROLPANEL_FONTSIZE 12
@interface KCMainViewController ()<UINavigationControllerDelegate,UIImagePickerControllerDelegate>{
UIImagePickerController *_imagePickerController;//系統照片選擇控制器
UIImageView *_imageView;//圖片顯示控件
CIContext *_context;//Core Image上下文
CIImage *_image;//我們要編輯的圖像
CIImage *_outputImage;//處理後的圖像
CIFilter *_colorControlsFilter;//色彩濾鏡
}
@end
@implementation KCMainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initLayout];
}
#pragma mark 初始化佈局
-(void)initLayout{
//初始化圖片選擇器
_imagePickerController=[[UIImagePickerController alloc]init];
_imagePickerController.delegate =self;
//創建圖片顯示控件
_imageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 64, 320, 502)];
_imageView.contentMode=UIViewContentModeScaleAspectFit;
[self.view addSubview:_imageView];
//上方導航按鈕
self.navigationItem.title=@"Enhance";
self.navigationItem.leftBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"Open" style:UIBarButtonItemStyleDone target:self action:@selector(openPhoto:)];
self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(savePhoto:)];
//下方控制面板
UIView *controlView=[[UIView alloc]initWithFrame:CGRectMake(0, 450, 320, 118)];
// controlView.alpha=0.2;
// controlView.backgroundColor=[UIColor colorWithRed:46.0/255.0 green:178.0/255.0 blue:235.0/255.0 alpha:1];
[self.view addSubview:controlView];
//飽和度(默認爲1,大於飽和度增加小於1則降低)
UILabel *lbSaturation=[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 60, 25)];
lbSaturation.text=@"Saturation";
lbSaturation.font=[UIFont systemFontOfSize:CONSTROLPANEL_FONTSIZE];
[controlView addSubview:lbSaturation];
UISlider *sldStaturation=[[UISlider alloc]initWithFrame:CGRectMake(80, 10, 230, 30)];//注意UISlider高度雖然無法調整,很多朋友會說高度設置位0即可,事實上在iOS7中設置爲0後是無法拖動的
[controlView addSubview:sldStaturation];
sldStaturation.minimumValue=0;
sldStaturation.maximumValue=2;
sldStaturation.value=1;
[sldStaturation addTarget:self action:@selector(changeStaturation:) forControlEvents:UIControlEventValueChanged];
//亮度(默認爲0)
UILabel *lbBrightness=[[UILabel alloc]initWithFrame:CGRectMake(10, 40, 60, 25)];
lbBrightness.text=@"Brightness";
lbBrightness.font=[UIFont systemFontOfSize:CONSTROLPANEL_FONTSIZE];
[controlView addSubview:lbBrightness];
UISlider *sldBrightness=[[UISlider alloc]initWithFrame:CGRectMake(80, 40, 230, 30)];
[controlView addSubview:sldBrightness];
sldBrightness.minimumValue=-1;
sldBrightness.maximumValue=1;
sldBrightness.value=0;
[sldBrightness addTarget:self action:@selector(changeBrightness:) forControlEvents:UIControlEventValueChanged];
//對比度(默認爲1)
UILabel *lbContrast=[[UILabel alloc]initWithFrame:CGRectMake(10, 70, 60, 25)];
lbContrast.text=@"Contrast";
lbContrast.font=[UIFont systemFontOfSize:CONSTROLPANEL_FONTSIZE];
[controlView addSubview:lbContrast];
UISlider *sldContrast=[[UISlider alloc]initWithFrame:CGRectMake(80, 70, 230, 30)];
[controlView addSubview:sldContrast];
sldContrast.minimumValue=0;
sldContrast.maximumValue=2;
sldContrast.value=1;
[sldContrast addTarget:self action:@selector(changeContrast:) forControlEvents:UIControlEventValueChanged];
//初始化CIContext
//創建基於CPU的圖像上下文
// NSNumber *number=[NSNumber numberWithBool:YES];
// NSDictionary *option=[NSDictionary dictionaryWithObject:number forKey:kCIContextUseSoftwareRenderer];
// _context=[CIContext contextWithOptions:option];
_context=[CIContext contextWithOptions:nil];//使用GPU渲染,推薦,但注意GPU的CIContext無法跨應用訪問,例如直接在UIImagePickerController的完成方法中調用上下文處理就會自動降級爲CPU渲染,所以推薦現在完成方法中保存圖像,然後在主程序中調用
// EAGLContext *eaglContext=[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES1];
// _context=[CIContext contextWithEAGLContext:eaglContext];//OpenGL優化過的圖像上下文
//取得濾鏡
_colorControlsFilter=[CIFilter filterWithName:@"CIColorControls"];
}
#pragma mark 打開圖片選擇器
-(void)openPhoto:(UIBarButtonItem *)btn{
//打開圖片選擇器
[self presentViewController:_imagePickerController animated:YES completion:nil];
}
#pragma mark 保存圖片
-(void)savePhoto:(UIBarButtonItem *)btn{
//保存照片到相冊
UIImageWriteToSavedPhotosAlbum(_imageView.image, nil, nil, nil);
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"Sytem Info" message:@"Save Success!" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
[alert show];
}
#pragma mark 圖片選擇器選擇圖片代理方法
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
//關閉圖片選擇器
[self dismissViewControllerAnimated:YES completion:nil];
//取得選擇圖片
UIImage *selectedImage=[info objectForKey:UIImagePickerControllerOriginalImage];
_imageView.image=selectedImage;
//初始化CIImage源圖像
_image=[CIImage imageWithCGImage:selectedImage.CGImage];
[_colorControlsFilter setValue:_image forKey:@"inputImage"];//設置濾鏡的輸入圖片
}
#pragma mark 將輸出圖片設置到UIImageView
-(void)setImage{
CIImage *outputImage= [_colorControlsFilter outputImage];//取得輸出圖像
CGImageRef temp=[_context createCGImage:outputImage fromRect:[outputImage extent]];
_imageView.image=[UIImage imageWithCGImage:temp];//轉化爲CGImage顯示在界面中
CGImageRelease(temp);//釋放CGImage對象
}
#pragma mark 調整飽和度
-(void)changeStaturation:(UISlider *)slider{
[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputSaturation"];//設置濾鏡參數
[self setImage];
}
#pragma mark 調整亮度
-(void)changeBrightness:(UISlider *)slider{
[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputBrightness"];
[self setImage];
}
#pragma mark 調整對比度
-(void)changeContrast:(UISlider *)slider{
[_colorControlsFilter setValue:[NSNumber numberWithFloat:slider.value] forKey:@"inputContrast"];
[self setImage];
}
@end
運行效果:
再次給大家強調一下:
- 在上面的代碼中除了使用了基於GPU的圖像上下文(推薦方式),也創建了其他圖像上下文,儘管已經被註釋大家還是需要熟悉。
- Core Image允許你一次給圖像或視頻幀疊加多種效果,同時Core Image還能保證強大的處理效率。
- 和在使用Core Graphics繪圖一樣,UIKit中也封裝了一些方法直接轉換爲Core Image中的對象,例如UIImage對象可以直接調用CIImage屬性轉換爲CIImage類型。