基于CoreImage框架實(shí)現(xiàn)圖片濾鏡、亮度掸掏、對比度茁影、飽和度

效果圖:

CoreImage.gif

一直想研究一下圖片濾鏡怎么實(shí)現(xiàn)的,抽空研究了一下丧凤,下面是實(shí)現(xiàn)部分呼胚,代碼都有注釋,灰常的詳細(xì)息裸,希望可以幫到正在開發(fā)濾鏡 圖片處理相關(guān)的碼友_蝇更,先把demo地址放出來 ,如果比較著急的可以直接看demo:

demo地址
https://github.com/wxh794708907/YJYYImageFilter.git
代碼實(shí)踐
//
//  ViewController.m
//  YJYYImageFilter
//
//  Created by 遇見遠(yuǎn)洋 on 17/2/17.
//  Copyright ? 2017年 遇見遠(yuǎn)洋. All rights reserved.
//

#import "ViewController.h"

#define ScreenWidth [self.view bounds].size.width
#define ScreenHeight [self.view bounds].size.height

@interface ViewController ()<UIPickerViewDelegate,UIPickerViewDataSource>
/** 數(shù)據(jù)源 */
@property(nonatomic,strong) NSArray *dataArray;
/** 顯示數(shù)據(jù) */
@property(nonatomic,strong) NSArray *pickerData;
/** 展示圖 */
@property(nonatomic,strong) UIImageView *showImageV;
/** 原始圖片 */
@property(nonatomic,strong) UIImage *originalImage;
/** pickView */
@property(nonatomic,strong) UIPickerView *pickView;
/** 亮度inputBrightness */
@property(nonatomic,strong) NSMutableArray *inputBrightness;
/** 飽和度inputSaturation */
@property(nonatomic,strong) NSMutableArray *inputSaturation;
/** 對比度inputContrast */
@property(nonatomic,strong) NSMutableArray *inputContrast;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //展示視圖
    [self.view addSubview:self.showImageV];
    
    //pickView
    [self.view addSubview:self.pickView];
}


#pragma  mark -  pickView數(shù)據(jù)源以及代理方法
#pragma  mark -
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 4;
}

//返回每個組件上的行數(shù)
- (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component {
    switch (component) {
        case 0:
            return self.dataArray.count;
            break;
        case 1:
            return self.inputBrightness.count;
            break;
        case 2:
            return self.inputContrast.count;
            break;
        case 3:
            return self.inputSaturation.count;
            break;
        default:
            return 0;
            break;
    }
}

//設(shè)置每行顯示的內(nèi)容
- (NSString *)pickerView:(UIPickerView *)thePickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    switch (component) {
        case 0:
            return [self.pickerData objectAtIndex:row];
            break;
        case 1:
          return  [NSString stringWithFormat:@"%@",self.inputBrightness[row]];
            break;
        case 2:
            return  [NSString stringWithFormat:@"%@",self.inputContrast[row]];
            break;
        case 3:
            return  [NSString stringWithFormat:@"%@",self.inputSaturation[row]];
            break;
        default:
            return nil;
            break;
    }
}

//選中某一行時調(diào)用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
    switch (component) {
        case 0://濾鏡
            [self filterImageWithfilterName:self.dataArray[row]];
            break;
        case 1://亮度
            [self colorControlsWithSaturation:1.f brightness:[self.inputBrightness[row] floatValue] contrast:1.f];
            break;
        case 2://對比度
            [self colorControlsWithSaturation:1.f brightness:0 contrast:[self.inputContrast[row] floatValue]];
            break;
        case 3://飽和度
            [self colorControlsWithSaturation:[self.inputSaturation[row] floatValue] brightness:0 contrast:1.f];
            break;
        default:
            break;
    }
}


#pragma  mark -  對圖片進(jìn)行濾鏡處理
#pragma  mark -
// 懷舊 --> CIPhotoEffectInstant
// 單色 --> CIPhotoEffectMono
// 黑白 --> CIPhotoEffectNoir
// 褪色 --> CIPhotoEffectFade
// 色調(diào) --> CIPhotoEffectTonal
// 沖印 --> CIPhotoEffectProcess
// 歲月 --> CIPhotoEffectTransfer
// 鉻黃 --> CIPhotoEffectChrome
- (void )filterImageWithfilterName:(NSString *)name{
    if ([name isEqualToString:@"OriginalImage"]) {//原圖
        self.showImageV.image = [UIImage imageNamed:@"original"];
        return;
    }
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        //將UIImage轉(zhuǎn)換成CIImage
        CIImage *ciImage = [[CIImage alloc] initWithImage:self.originalImage];
        
        //創(chuàng)建濾鏡
        CIFilter *filter = [CIFilter filterWithName:name keysAndValues:kCIInputImageKey, ciImage, nil];
        
        //已有的值不改變呼盆,其他的設(shè)為默認(rèn)值
        [filter setDefaults];
        
        //獲取繪制上下文
        CIContext *context = [CIContext contextWithOptions:nil];
        
        //渲染并輸出CIImage
        CIImage *outputImage = [filter outputImage];
        
        //創(chuàng)建CGImage句柄
        CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
        
        //獲取圖片
        UIImage *image = [UIImage imageWithCGImage:cgImage];
        
        //釋放CGImage句柄
        CGImageRelease(cgImage);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            self.showImageV.image = image;
        });
    });
}

/**
 *  調(diào)整圖片飽和度, 亮度, 對比度
 *  @param saturation 飽和度 默認(rèn)為1
 *  @param brightness 亮度: -1.0 ~ 1.0 默認(rèn)是0
 *  @param contrast   對比度 默認(rèn)為1
 *
 */- (void)colorControlsWithSaturation:(CGFloat)saturation
                            brightness:(CGFloat)brightness
                              contrast:(CGFloat)contrast{
     dispatch_async(dispatch_get_global_queue(0, 0), ^{
         
         CIContext *context = [CIContext contextWithOptions:nil];
         CIImage *inputImage = [[CIImage alloc] initWithImage:self.originalImage];
         CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
         [filter setValue:inputImage forKey:kCIInputImageKey];
         
         [filter setValue:@(saturation) forKey:@"inputSaturation"];
         [filter setValue:@(brightness) forKey:@"inputBrightness"];
         [filter setValue:@(contrast) forKey:@"inputContrast"];
         
         CIImage *result = [filter valueForKey:kCIOutputImageKey];
         CGImageRef cgImage = [context createCGImage:result fromRect:[result extent]];
         UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
         CGImageRelease(cgImage);
         
         dispatch_async(dispatch_get_main_queue(), ^{
             self.showImageV.image = resultImage;
         });
     });
 }


#pragma  mark -  懶加載部分
#pragma  mark -
- (NSArray *)dataArray {
    if (!_dataArray) {
        _dataArray = [NSArray arrayWithObjects:
                      @"OriginalImage",
                      @"CIPhotoEffectInstant",
                      @"CIPhotoEffectMono",
                      @"CIPhotoEffectNoir",
                      @"CIPhotoEffectFade",
                      @"CIPhotoEffectTonal",
                      @"CIPhotoEffectProcess",
                      @"CIPhotoEffectTransfer",
                      @"CIPhotoEffectChrome",
                      nil];
    }
    return _dataArray;
}

- (NSArray *)pickerData {
    if (!_pickerData) {
        _pickerData = [NSArray arrayWithObjects:
                       @"原圖",
                       @"懷舊",
                       @"單色",
                       @"黑白",
                       @"褪色",
                       @"色調(diào)",
                       @"沖印",
                       @"歲月",
                       @"鉻黃",
                       nil];
    }
    return _pickerData;
}

- (NSMutableArray *)inputBrightness {//亮度
    if (!_inputBrightness) {
        _inputBrightness = [NSMutableArray arrayWithArray:@[@-1,@-0.5,@0,@0.5,@1]];
    }
    return _inputBrightness;
}


- (NSMutableArray *)inputSaturation {//對比度
    if (!_inputSaturation) {
        _inputSaturation = [NSMutableArray arrayWithArray:@[@0,@1,@2,@3,@4]];
    }
    return _inputSaturation;
}


- (NSMutableArray *)inputContrast {//飽和度
    if (!_inputContrast) {
        _inputContrast = [NSMutableArray arrayWithArray:@[@0,@0.5,@1,@1.5,@2]];
    }
    return _inputContrast;
}

- (UIImageView *)showImageV {
    if (!_showImageV) {
        _showImageV = [[UIImageView alloc]initWithImage:self.originalImage];
        _showImageV.contentMode = UIViewContentModeScaleAspectFit;
        _showImageV.frame = CGRectMake(0, 0, 300, 300);
        _showImageV.center = CGPointMake(self.view.center.x, self.view.center.y - 100);
    }
    return _showImageV;
}

- (UIImage *)originalImage {
    if (!_originalImage) {
        _originalImage = [UIImage imageNamed:@"original"];
    }
    return _originalImage;
}

- (UIPickerView *)pickView {
    if (!_pickView) {
        _pickView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, ScreenHeight - 300, ScreenWidth, 300)];
        _pickView.dataSource = self;
        _pickView.delegate = self;
        //默認(rèn)選中
        [self.pickView selectRow:0 inComponent:0 animated:YES];
        [self.pickView selectRow:2 inComponent:1 animated:YES];
        [self.pickView selectRow:2 inComponent:2 animated:YES];
        [self.pickView selectRow:1 inComponent:3 animated:YES];
        
    }
    return _pickView;
}

建議大家運(yùn)行一下demo來看一下效果年扩,為了方便大家查看效果,我已經(jīng)使用pickView來將效果展示出來访圃,我覺得還是比較方便的厨幻,有什么不懂得 一看代碼就懂了,這里我還是按照慣例總結(jié)一下吧:

濾鏡的實(shí)現(xiàn)步驟:
  • 將原始的UIImage對象轉(zhuǎn)換成CIImage的對象
  • 創(chuàng)建濾鏡
  • 獲取繪制上下文
  • 渲染并輸出CIImage對象
  • 創(chuàng)建CGImage句柄
  • 將CGImageRef對象轉(zhuǎn)換為UIImage對象
  • 釋放CGImage句柄(這里要注意 內(nèi)存釋放)

圖片飽和度腿时、亮度等設(shè)置我就不寫步驟了况脆,其實(shí)原理是一樣的,都是通過創(chuàng)建一個濾鏡 設(shè)置不同的值來實(shí)現(xiàn)效果批糟,建議大家看看代碼吧格了,不是很難。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末徽鼎,一起剝皮案震驚了整個濱河市盛末,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌否淤,老刑警劉巖悄但,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異石抡,居然都是意外死亡檐嚣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門啰扛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嚎京,“玉大人,你說我怎么就攤上這事侠讯⊥诓兀” “怎么了?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵厢漩,是天一觀的道長膜眠。 經(jīng)常有香客問我,道長溜嗜,這世上最難降的妖魔是什么宵膨? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮炸宵,結(jié)果婚禮上辟躏,老公的妹妹穿的比我還像新娘。我一直安慰自己土全,他們只是感情好捎琐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布会涎。 她就那樣靜靜地躺著,像睡著了一般瑞凑。 火紅的嫁衣襯著肌膚如雪末秃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天籽御,我揣著相機(jī)與錄音练慕,去河邊找鬼。 笑死技掏,一個胖子當(dāng)著我的面吹牛铃将,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哑梳,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼劲阎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了涧衙?” 一聲冷哼從身側(cè)響起哪工,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弧哎,沒想到半個月后雁比,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撤嫩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年偎捎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片序攘。...
    茶點(diǎn)故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡茴她,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出程奠,到底是詐尸還是另有隱情丈牢,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布瞄沙,位于F島的核電站己沛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏距境。R本人自食惡果不足惜申尼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望垫桂。 院中可真熱鬧师幕,春花似錦、人聲如沸诬滩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至后控,卻和暖如春宗侦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忆蚀。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留姑裂,地道東北人馋袜。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像舶斧,于是被迫代替她去往敵國和親欣鳖。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內(nèi)容

  • 許多UIView的子類茴厉,如一個UIButton或一個UILabel泽台,它們知道怎么繪制自己。遲早矾缓,你也將想要做一些自...
    shenzhenboy閱讀 1,633評論 2 8
  • Core Graphics Framework是一套基于C的API框架怀酷,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,523評論 0 20
  • 原鏈接:http://www.csdn.net/article/2015-02-13/2823961-core-i...
    hament閱讀 998評論 0 1
  • 婦產(chǎn)科實(shí)驗(yàn)到今天就結(jié)束了∈任牛現(xiàn)在是第7周蜕依。等到13周就要去附屬醫(yī)院見習(xí)了,見習(xí)4周后就要真正意義上實(shí)習(xí)了琉雳,好快Q摺!翠肘!...
    夢霞mm閱讀 439評論 0 0
  • 此時此刻我頭疼欲裂檐束,本來想著要不今天請假吧,可是我怕自己一請假就不能堅(jiān)持了束倍,想了想還是拿起手機(jī)被丧,說說自己的健康問題...
    月兒的2016閱讀 297評論 2 1