2012-01-17 36 views

回答

5

你不能在iOS中创建自己的定制内核/过滤器。见http://developer.apple.com/library/mac/#documentation/graphicsimaging/Conceptual/CoreImaging/ci_intro/ci_intro.html,具体有:

虽然本文件包括在参考库中,它具有 没有详细更新为iOS 5.0。即将发布的版本将会在 中详细说明iOS上Core Image的差异。特别是关键 的区别在于iOS上的Core Image不包括 创建自定义图像过滤器的能力。

(加粗矿)

+0

注意,虽然你可以不要编写自己的内核,可以将现有的CIFilter结合起来以获得所需的效果。你试图创建什么样的效果? – user1118321

+0

确实。您也可以自己编写自己的图像过滤器功能,直接操作数据。如果明智地使用Accelerate框架,那么您也将获得重要的硬件支持。 –

+2

iOS 8添加了自定义CoreImage过滤器(即自定义'CIKernel')。 –

20

正如亚当指出,在iOS目前核心并不支持自定义内核像旧的Mac OS实现一样。这限制了您可以使用框架对现有过滤器进行某种组合。

(更新:2/13/2012)

出于这个原因,我创建了iOS版的开源框架称为GPUImage,使您可以创建自定义过滤器被应用到使用OpenGL ES的图像和视频2.0片段着色器。我在my post on the topic中详细描述了这个框架是如何运作的。基本上,您可以提供自己的自定义OpenGL着色语言(GLSL)片段着色器来创建自定义过滤器,然后针对静态图像或实时视频运行该过滤器。该框架与支持OpenGL ES 2.0的所有iOS设备兼容,并且可以创建面向iOS 4.0的应用程序。

例如,可以使用如下所示的代码建立的实时视频滤波:

GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack]; 
GPUImageFilter *customFilter = [[GPUImageFilter alloc] initWithFragmentShaderFromFile:@"CustomShader"]; 
GPUImageView *filteredVideoView = [[GPUImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, viewWidth, viewHeight)]; 

// Add the view somewhere so it's visible 

[videoCamera addTarget:thresholdFilter]; 
[customFilter addTarget:filteredVideoView]; 

[videoCamera startCameraCapture]; 

作为限定了过滤器的自定义片段着色器程序的一个例子,以下适用深褐色调效果:

varying highp vec2 textureCoordinate; 

uniform sampler2D inputImageTexture; 

void main() 
{ 
    lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate); 
    lowp vec4 outputColor; 
    outputColor.r = (textureColor.r * 0.393) + (textureColor.g * 0.769) + (textureColor.b * 0.189); 
    outputColor.g = (textureColor.r * 0.349) + (textureColor.g * 0.686) + (textureColor.b * 0.168);  
    outputColor.b = (textureColor.r * 0.272) + (textureColor.g * 0.534) + (textureColor.b * 0.131); 

    gl_FragColor = outputColor; 
} 

用于在Mac上编写自定义Core Image内核的语言与GLSL非常相似。事实上,你可以做一些你在桌面Core Image中不能做的事情,因为Core Image的内核语言缺少GLSL的一些东西(比如分支)。

+0

感谢您的回答!是的,如果使用openGL,这对我来说是最好的结果。但是现在我对openGL –

+1

Brad的这个特性有了一点了解,你太棒了! – openfrog

0

您可以创建适用于iOS比图像模块插件,方便自定义过滤器即使iOS支持Image Unit插件,MacOS X也是首选。问题是你实际上不能“打包”它们,或者将它们捆绑为像Image Unit插件这样的资源;您必须将您的源代码公开给使用它们的开发人员。而且,它们只对开发者有用;您无法像导入第三方Core Image过滤器的MacOS X图形应用程序那样将它们分发给iOS图形应用程序的最终用户。为此,您必须将它们嵌入照片编辑扩展中。

即使使用iOS定制Core Image滤镜处理图像比使用Image Unit插件也更容易。没有导入,然后是配置.plist和描述文件以及不是什么的混乱任务。

iOS的自定义核心图像过滤器只是一个Cocoa Touch类,它是CIFilter的子类;在其中指定输入参数(始终至少是图像),自定义属性设置及其默认值,然后指定内置或自定义核心图像过滤器的任意组合。如果您想将OpenGL内核添加到图像处理管道中,只需添加一个CIKernel方法,该方法将您编写的.cikernel加载到单独的文件中。

用于开发iOS的自定义核心图像过滤器这种特殊的方法的好处是,自定义过滤器被实例化,并呼吁以同样的方式为内置过滤器:

CIFilter* PrewittKernel = [CIFilter filterWithName:@"PrewittKernel"]; 

CIImage *result = [CIFilter filterWithName:@"PrewittKernel" keysAndValues:kCIInputImageKey, self.inputImage, nil].outputImage; 

这是一个使用OpenGL的一个简单的例子将Prewitt算子应用于图像;首先,可可触摸类(子类CIFilter),然后,将CIKernel文件(包含了OpenGL ES 3.0代码):

头文件:

// 
// PrewittKernel.h 
// Photo Filter 
// 
// Created by James Alan Bush on 5/23/15. 
// 
// 

#import <CoreImage/CoreImage.h> 

@interface PrewittKernel : CIFilter 
{ 
    CIImage *inputImage; 
} 

@property (retain, nonatomic) CIImage *inputImage; 

@end 

实现文件:

// 
// PrewittKernel.m 
// Photo Filter 
// 
// Created by James Alan Bush on 5/23/15. 
// 
// 

#import <CoreImage/CoreImage.h> 

@interface PrewittKernel : CIFilter 
{ 
    CIImage *inputImage; 
} 

@property (retain, nonatomic) CIImage *inputImage; 

@end 


@implementation PrewittKernel 

@synthesize inputImage; 

- (CIKernel *)prewittKernel 
{ 
    static CIKernel *kernelPrewitt = nil; 

    NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"PrewittKernel")]; 
    NSStringEncoding encoding = NSUTF8StringEncoding; 
    NSError  *error = nil; 
    NSString *code = [NSString stringWithContentsOfFile:[bundle pathForResource:@"PrewittKernel" ofType:@"cikernel"] encoding:encoding error:&error]; 

    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     kernelPrewitt = [CIKernel kernelWithString:code]; 
    }); 

    return kernelPrewitt; 
} 

- (CIImage *)outputImage 
{ 
    CIImage *result = self.inputImage; 
    return [[self prewittKernel] applyWithExtent:result.extent roiCallback:^CGRect(int index, CGRect rect) { 
     return CGRectMake(0, 0, CGRectGetWidth(result.extent), CGRectGetHeight(result.extent)); 
    } arguments:@[result]]; 
} 

@end 

的CIKernel(OpenGL ES的3.0):

/* PrewittKernel.cikernel */ 

kernel vec4 prewittKernel(sampler image) 
{ 
    vec2 xy = destCoord(); 
    vec4 bottomLeftIntensity = sample(image, samplerTransform(image, xy + vec2(-1, -1))); 
    vec4 topRightIntensity = sample(image, samplerTransform(image, xy + vec2(+1, +1))); 
    vec4 topLeftIntensity = sample(image, samplerTransform(image, xy + vec2(+1, -1))); 
    vec4 bottomRightIntensity = sample(image, samplerTransform(image, xy + vec2(-1, +1))); 
    vec4 leftIntensity = sample(image, samplerTransform(image, xy + vec2(-1, 0))); 
    vec4 rightIntensity = sample(image, samplerTransform(image, xy + vec2(+1, 0))); 
    vec4 bottomIntensity = sample(image, samplerTransform(image, xy + vec2(0, -1))); 
    vec4 topIntensity = sample(image, samplerTransform(image, xy + vec2(0, +1))); 
    vec4 h = vec4(-topLeftIntensity - topIntensity - topRightIntensity + bottomLeftIntensity + bottomIntensity + bottomRightIntensity); 
    vec4 v = vec4(-bottomLeftIntensity - leftIntensity - topLeftIntensity + bottomRightIntensity + rightIntensity + topRightIntensity); 
    float h_max = max(h.r, max(h.g, h.b)); 
    float v_max = max(v.r, max(v.g, v.b)); 
    float mag = length(vec2(h_max, v_max)) * 1.0; 

    return vec4(vec3(mag), 1.0); 
} 

这里的另一个过滤器,其产生unsh通过使用内置的核心图像滤镜 - 无核心图像内核代码(OpenGL),从原始图像中减去(或相反地,差分)高斯模糊图像。它显示了如何指定和使用自定义属性,即高斯模糊半径:

头文件:

// 
// GaussianKernel.h 
// Chroma 
// 
// Created by James Alan Bush on 7/12/15. 
// Copyright © 2015 James Alan Bush. All rights reserved. 
// 

#import <CoreImage/CoreImage.h> 

@interface GaussianKernel : CIFilter 
{ 
    CIImage *inputImage; 
    NSNumber *inputRadius; 
} 

@property (retain, nonatomic) CIImage *inputImage; 
@property (retain, nonatomic) NSNumber *inputRadius; 

@end 

实现文件:

// 
// GaussianKernel.m 
// Chroma 
// 
// Created by James Alan Bush on 7/12/15. 
// Copyright © 2015 James Alan Bush. All rights reserved. 
// 

#import "GaussianKernel.h" 

@implementation GaussianKernel 

@synthesize inputImage; 
@synthesize inputRadius; 

+ (NSDictionary *)customAttributes 
{ 
    return @{ 
      @"inputRadius" : 
       @{ 
        kCIAttributeMin  : @3.0, 
        kCIAttributeMax  : @15.0, 
        kCIAttributeDefault : @7.5, 
        kCIAttributeType  : kCIAttributeTypeScalar 
        } 
      }; 
} 

- (void)setDefaults 
{ 
    self.inputRadius = @7.5; 
} 

    - (CIImage *)outputImage 
    { 
     CIImage *result = self.inputImage; 

     CGRect rect = [[GlobalCIImage sharedSingleton].ciImage extent]; 
     rect.origin = CGPointZero; 
     CGRect cropRectLeft = CGRectMake(0, 0, rect.size.width, rect.size.height); 
     CIVector *cropRect = [CIVector vectorWithX:rect.origin.x Y:rect.origin.y Z:rect.size.width W:rect.size.height]; 

    result = [[CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:kCIInputImageKey, result, @"inputRadius", [NSNumber numberWithFloat:inputRadius.floatValue], nil].outputImage imageByCroppingToRect:cropRectLeft]; 

    result = [CIFilter filterWithName:@"CICrop" keysAndValues:@"inputImage", result, @"inputRectangle", cropRect, nil].outputImage; 

    result = [CIFilter filterWithName:@"CIDifferenceBlendMode" keysAndValues:kCIInputImageKey, result, kCIInputBackgroundImageKey, result, nil].outputImage; 

     return result; 
    } 

    @end 
相关问题