在iOS和 OS X中,Core Image有三个处理图像的类:

* CIFilter 是一个代表结果(效果)的可变的对象。一个滤镜对象至少要有一个输入参数并产生一个输出图像。

* CIImage是一个代表图像的不可变的对象。你可以synthesize图像数据或者从文件或其他 CIFilter对象的输出得到它。

* CIContext是一个被滤镜处理后Core Image 绘制的结果的对象。一个Core Image context可以是基于CPU或者基于GPU.

(在APP中使用Core Image的时候,你需要在你的Xcode工程中添加如下framework:CoreImage.framework(ios),QuartzCore.framework(OS X),并添加头文件:<CoreImage/CoreImage.h>(IOS)<QuartzCore/CoreImage.h>(OS X)).

 

ios中,对一张图片使用滤镜的基本步骤:

 1   CIContext *context = [CIContext contextWithOptions:nil];                //1
 2 
 3   CIImage *image = [CIImage imageWithContentsOfURL:myURL];     //2 
 4 
 5   CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];              //3
 6 
 7   [filter setValue:image forKey:kCIInputImageKey];
 8 
 9   [filter setValue:@0.8f forKey:kCIInputIntensityKey];
10  
11   CIImage *result = [filter valueForKey:kCIOutputImageKey];           //4
12  
13   CGRect extent = [result extent];
14 
15   CGImageRef cgImage = [context createCGImage:result fromRect:extent];   // 5

1.创建一个CIContext 对象。

2.创建一个CIImage对象。

3.创建滤镜并对它的输入参数设值。

4.得到输出图像。

5.使CIImage成为一个准备展示或者保存为文件的Core Graphics图像。

 

关于内置滤镜:

Core Image 有大量的内置滤镜。Core Image Filter Reference 列出了这些滤镜,以及它们的特征,在iOS或OS X 平台是否可用,并展示一张被滤镜处理过的图片。因为内置滤镜的 list 是可变的,所以Core Image提供了查询系统可用滤镜的方法。

A filter category specifies the type of effect—blur, distortion, generator, and so forth—or its intended use—still images, video, nonsquare pixels, and so on. A filter can be a member of more than one category. A filter also has a display name, which is the name to show to users and a filter name, which is the name you must use to access the filter programmatically. 

大部分的滤镜有一个或者更多的参数来让你控制如何处理。每一个输入参数都有一个属性类来说明它的数据类型,如:NSNumber.一个输入参数可以可选择的拥有其它属性,如:它的默认值,允许的最小和最大值,参数展示的名字,以及在CIFilter Class Reference  中描述的其它属性。

例如,CIColorMonochrome 滤镜有三个输入参数:要处理的图像,一个单色,颜色亮度。你提供一个图片,并且可以有选择的设置颜色和亮度。大多数的滤镜,对于非图像参数,都有一个默认的值。当你对这些默认参数没有自己设置值的时候,Core Image就会用默认的参数值来处理你的图像。

滤镜的属性是按照键-值对的方式存储的。



 

Core Image 使用KVC,也就是说你可以使用NSKeyValueCodingprotocol 提供的方法来设置或者获取滤镜属性值。

 

1.创建一个Core Image Context:

一个Core Image context 代表绘制图形的目的地,这个目的地决定Core Image是否使用GPU或者CPU来处理。。

 

 

(ios)如果你的app不需要即使展示,你可以用下面的方法来创建一个CIContext:

CIContext *context = [CIContext contextWithOptions:nil];

这个方法可以选择CPU或者GPU其中之一来处理。为了确定使用哪个,可以建立一个可选的字典并添加键:kCIContextUseSoftwareRenderer和合适的布尔值。CPU处理要比GPU慢,但是对于GPU处理的图像,必须将处理的结果拷贝到CPU内存并转化成另外一种图片类型(如UIImage object)才能展现出来。

如果你的app支持实时图像处理,你应该从EAGL context创建一个 CIContext object 而不是使用 contextWithOptions: 并指定GPU。好处就是被处理的图像会一直保存在GPU 中而不需要拷贝到CPU内存。首先你要做的是创建一个EAGL context:

    EAGLContext *myEAGLContext = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];

你应该通过对颜色工作空间设置为空来关闭颜色管理。因为颜色管理会让展示变的缓慢。

  NSDictionary *options = @{ kCIContextWorkingColorSpace:[NSNull null] };

  CIContext *myContext = [CIContext contextWithEAGLContext:myEAGLContext options:options];

 

2.创建一个CIImage 对象:

创建CIImage对象的方法:

3.创建一个CIFilter 对象并设值
可以通过 filterWithName: 这个方法创建一个具体类型的滤镜。参数 name 这个字符串的值必须与内置滤镜的名字一致。你可以通过Querying the System for Filters 中的指令获得滤镜的名字列表,或者查询 core Image Filter Reference获得滤镜名字。

在ios中,当你调用filterWithName: 这个方法的时候,滤镜的输入值被设置为默认值。
如果你不知道一个滤镜的输入参数,你可以通过 inputKeys这个方法得到一个关于它们的数组。(或者你可以查询Core Image Filter Reference得到大多数内置滤镜的输入参数)除了 generator 滤镜,其他滤镜都需要一个输入图像。有的需要两个或者更多的图像或者 textures。可以通过setValue:forKey: 这个方法改变每一个输入参数的默认值。

如:
   hueAdjuest = [CIFilter filterWithName:@"CIHueAdjust"];
   [hueAdjust setDefaults];   //这句仅os x 有必要
这个滤镜有两个输入参数:输入图像和输入角度。色调调整滤镜的输入角度适用于色彩空间为HSL 和 HLS 的色调位置。这个取值范围是从 0.0 到 2pi。值为0的时候指示红色,绿色为2/3pi的弧度,蓝色为4/3pi 弧度。
  [hueAdjust setValue:myCIImage forKey: kCIInputImageKey];
  [hueAdjust setValue: @2.094f forKey:kCIInputAngleKey];

 (
   hueAdjust = [[CIFilter filterWithName:@"CIHueAdjust"] keysAndValues:
                                        kCIInputImageKey, myCIImage,
                                        kCIInputAngleKey, @2.094f
                                       nil];

)
  


4.得到输出图像: 

 

可以通过取回 outputImage 这个键的值来得到 输出图像:

   CIImage *result = [hueAdjust valueForKey: kCIOutImageKey];

 

Core Image does not perform any image processing until you call a method that actually renders the image (see Rendering the Resulting Output Image (page 21)). When you request the output image, Core Image assembles the calculations that it needs to produce an output image and stores those calculations (that is, image “recipe”) in a CIImage object. The actual image is only rendered (and hence, the calculations performed) if there is an explicit call to one of the image-drawing methods. See Rendering the Resulting Output Image (page 21).

Deferring processing until rendering time makes Core Image fast and efficient. At rendering time, Core Image can see if more than one filter needs to be applied to an image. If so, it automatically concatenates multiple “recipes” into one operation, which means each pixel is processed only once rather than many times. Figure 1-2 illustrates a multiple-operations workflow that Core Image can make more efficient. The final image is a scaled-down version of the original. For the case of a large image, applying color adjustment before scaling down the image requires more processing power than scaling down the image and then applying color adjustment. By waiting until render time to apply filters, Core Image can determine that it is more efficient to perform these operations in reverse order. 

 

5.描绘输出图像的结果:

 

     [myContext drawImage:result inRect:destinationRect fromRect:contextRect];

 

6.保证线程安全:

CIContext 和CIImage 的对象都是不可变的,也就是说都可以通过线程安全的分享。多线程可以使用相同的CPU或者GPU CIContext 对象来绘制CIImage 对象。However, this is not the case for CIFilter objects, which are mutable.   一个 CIFilter 对象不能通过线程安全的分享。如果你的程序是多线程的,每一个线程必须创建它自己的CIFilter对象。否则,你的程序将会出现异常。