效果图:
一直想研究一下图片滤镜怎么实现的,抽空研究了一下,下面是实现部分,代码都有注释,灰常的详细,希望可以帮到正在开发滤镜 图片处理相关的码友_,先把demo地址放出来 ,如果比较着急的可以直接看demo:
demo地址
https://github.com/wxh794708907/YJYYImageFilter.git
代码实践
//
// ViewController.m
// YJYYImageFilter
//
// Created by 遇见远洋 on 17/2/17.
// Copyright © 2017年 遇见远洋. All rights reserved.
//
#import "ViewController.h"
#define ScreenWidth [self.view bounds].size.width
#define ScreenHeight [self.view bounds].size.height
@interface ViewController ()<UIPickerViewDelegate,UIPickerViewDataSource>
/** 数据源 */
@property(nonatomic,strong) NSArray *dataArray;
/** 显示数据 */
@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数据源以及代理方法
#pragma mark -
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 4;
}
//返回每个组件上的行数
- (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;
}
}
//设置每行显示的内容
- (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;
}
}
//选中某一行时调用
- (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 - 对图片进行滤镜处理
#pragma mark -
// 怀旧 --> CIPhotoEffectInstant
// 单色 --> CIPhotoEffectMono
// 黑白 --> CIPhotoEffectNoir
// 褪色 --> CIPhotoEffectFade
// 色调 --> 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转换成CIImage
CIImage *ciImage = [[CIImage alloc] initWithImage:self.originalImage];
//创建滤镜
CIFilter *filter = [CIFilter filterWithName:name keysAndValues:kCIInputImageKey, ciImage, nil];
//已有的值不改变,其他的设为默认值
[filter setDefaults];
//获取绘制上下文
CIContext *context = [CIContext contextWithOptions:nil];
//渲染并输出CIImage
CIImage *outputImage = [filter outputImage];
//创建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;
});
});
}
/**
* 调整图片饱和度, 亮度, 对比度
* @param saturation 饱和度 默认为1
* @param brightness 亮度: -1.0 ~ 1.0 默认是0
* @param contrast 对比度 默认为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:
@"原图",
@"怀旧",
@"单色",
@"黑白",
@"褪色",
@"色调",
@"冲印",
@"岁月",
@"铬黄",
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;
//默认选中
[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;
}
建议大家运行一下demo来看一下效果,为了方便大家查看效果,我已经使用pickView来将效果展示出来,我觉得还是比较方便的,有什么不懂得 一看代码就懂了,这里我还是按照惯例总结一下吧:
滤镜的实现步骤:
- 将原始的UIImage对象转换成CIImage的对象
- 创建滤镜
- 获取绘制上下文
- 渲染并输出CIImage对象
- 创建CGImage句柄
- 将CGImageRef对象转换为UIImage对象
- 释放CGImage句柄(这里要注意 内存释放)
图片饱和度、亮度等设置我就不写步骤了,其实原理是一样的,都是通过创建一个滤镜 设置不同的值来实现效果,建议大家看看代码吧,不是很难。