Cowboy Tech

使用CoreImage处理图片

CoreImage滤镜的使用

  1. CoreImage是苹果公司为了简化图片处理的难度而开发出来的类库。
  2. 随着iOS版本升级以及硬件性能的不断提升,CoreImage将支持越来越多的滤镜。
    大部分的滤镜都很容易使用。
  3. core image也可以支持视频

- (void)viewDidLoad {
[super viewDidLoad];

// 0. 导入CIImage图片
CIImage *ciImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:@"demo"]];

// 1. 创建出Filter滤镜.使用另一款滤镜,换个名字即可
CIFilter *filter = [CIFilter filterWithName:@"CIPixellate"];

[filter setValue:ciImage
          forKey:kCIInputImageKey];

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

[filter setDefaults];

CIImage *outImage = [filter valueForKey:kCIOutputImageKey];

// 2. 用CIContext将滤镜中的图片渲染出来
CIContext *context = [CIContext contextWithOptions:nil];

CGImageRef cgImage = [context createCGImage:outImage
                                   fromRect:[outImage extent]];

// 3. 导出图片
UIImage *showImage = [UIImage imageWithCGImage:cgImage];

//需要手动释放
CGImageRelease(cgImage);

// 4. 加载出来
UIImageView *imageView = [[UIImageView alloc] initWithImage:showImage];
imageView.center       = self.view.center;
[self.view addSubview:imageView];
}

CoreImage滤镜的组合

  1. 不同的滤镜可以组合在一起使用。
  2. 可以动态的修改滤镜组合中单个滤镜的参数来实现一种动态调整的效果。

- (void)viewDidLoad {
[super viewDidLoad];

// 0. 导入CIImage图片
CIImage *ciImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:@"demo"]];

// 1. 创建出Filter滤镜
CIFilter *filterOne = [CIFilter filterWithName:@"CIPixellate"];

[filterOne setValue:ciImage
             forKey:kCIInputImageKey];

[filterOne setDefaults];

CIImage *outImage = [filterOne valueForKey:kCIOutputImageKey];

CIFilter *filterTwo = [CIFilter filterWithName:@"CIHueAdjust"];
[filterTwo setValue:outImage
             forKey:kCIInputImageKey];

[filterTwo setDefaults];

[filterTwo setValue:@(3.14)
             forKey:kCIInputAngleKey];

CIImage *outputImage = [filterTwo valueForKey:kCIOutputImageKey];

// 2. 用CIContext将滤镜中的图片渲染出来
CIContext *context = [CIContext contextWithOptions:nil];

CGImageRef cgImage = [context createCGImage:outputImage
                                   fromRect:[outImage extent]];

// 3. 导出图片
UIImage *showImage = [UIImage imageWithCGImage:cgImage];

CGImageRelease(cgImage);

// 4. 加载出来
UIImageView *imageView = [[UIImageView alloc] initWithImage:showImage];
imageView.center       = self.view.center;
[self.view addSubview:imageView];
}

在OpenGLES下进行渲染

在OpenGLES下进行滤镜的渲染可以提高效率。如果需要实时查看多个滤镜动态渲染的效果,使用OpenGLES是一个好的选择。

#import "ViewController.h"
#import <GLKit/GLKit.h>

@interface ViewController ()
@property (nonatomic, strong) GLKView   *glkView; // 渲染用的buffer视图

@property (nonatomic, strong) CIFilter  *filter;
@property (nonatomic, strong) CIImage   *ciImage;
@property (nonatomic, strong) CIContext *ciContext;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

UIImage *showImage = [UIImage imageNamed:@"demo"];
CGRect  rect       = CGRectMake(0, 0, showImage.size.width, showImage.size.height);

// 获取OpenGLES渲染的上下文
EAGLContext *eagContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

// 创建出渲染的buffer
_glkView = [[GLKView alloc] initWithFrame:rect
                                  context:eagContext];
[_glkView bindDrawable];
[self.view addSubview:_glkView];

// 创建出CoreImage用的上下文
_ciContext = [CIContext contextWithEAGLContext:eagContext
                                       options:@{kCIContextWorkingColorSpace : [NSNull null]}];

// CoreImage相关设置
_ciImage = [[CIImage alloc] initWithImage:showImage];

_filter = [CIFilter filterWithName:@"CISepiaTone"];

[_filter setValue:_ciImage forKey:kCIInputImageKey];
[_filter setValue:@(0) forKey:kCIInputIntensityKey];

// 开始渲染
[_ciContext drawImage:[_filter outputImage]
               inRect:CGRectMake(0, 0, _glkView.drawableWidth, _glkView.drawableHeight)
             fromRect:[_ciImage extent]];
[_glkView display];

// 动态渲染
UISlider *slider    = [[UISlider alloc] initWithFrame:CGRectMake(0, 400, 320, 20)];
slider.minimumValue = 0.f;
slider.maximumValue = 1.f;
[slider addTarget:self action:@selector(sliderEvent:) forControlEvents:UIControlEventValueChanged];
[self.view addSubview:slider];
}

- (void)sliderEvent:(UISlider *)slider {


[_filter setValue:_ciImage forKey:kCIInputImageKey];
[_filter setValue:@(slider.value)
           forKey:kCIInputIntensityKey];

// 开始渲染
[_ciContext drawImage:[_filter outputImage]
               inRect:CGRectMake(0, 0, _glkView.drawableWidth, _glkView.drawableHeight)
             fromRect:[_ciImage extent]];
[_glkView display];
}