我想在我的应用程序中使用自定义过滤器。现在我知道我需要使用Core Image框架,但我不确定这是否正确。 核心图像框架用于Mac OS和iOS 5.0 - 我不确定可以用于自定义CIFilter效果。 你能帮我解决这个问题吗? 谢谢大家!如何使用Core Image Framework为iOS创建简单的自定义过滤器?
回答
你不能在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不包括 创建自定义图像过滤器的能力。
(加粗矿)
正如亚当指出,在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的一些东西(比如分支)。
感谢您的回答!是的,如果使用openGL,这对我来说是最好的结果。但是现在我对openGL –
Brad的这个特性有了一点了解,你太棒了! – openfrog
原始接受的答案已折旧。从iOS 8开始,您可以创建过滤器的自定义内核。你可以找到有关此内容的更多信息:
感谢您的更新,这是一个老问题,我认为新的答案可以帮助其他人找到一些新的细节,如果他们使用iOS 8 sdk。 –
您可以创建适用于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
- 1. 为什么CIGloom Core Image过滤器不能在iOS上使用?
- 2. Zend Framework:我的自定义表单过滤器没有过滤!
- 3. 创建自定义Zuul过滤器
- 4. Solr4创建自定义过滤器
- 5. 如何为Drupal视图模块创建自定义过滤器?
- 6. 如何创建自定义过滤器angularjs javascript控制器端?
- 7. 如何使用Zend Framework设置简单的自定义路由?
- 8. ExtJS 6.2:为网格列创建自定义过滤器
- 9. 如何使用自定义过滤器组件过滤React表?
- 10. 使用git创建自定义过滤器来美化js
- 11. 使用PyEnchant创建自定义过滤器
- 12. iOS 6是否支持Core Image过滤器?
- 13. 如何使用Image在Power BI上创建自定义地图?
- 14. 如何创建自定义授权过滤器?
- 15. 如何创建自定义django过滤器标签
- 16. 如何在spring云中创建自定义zuul过滤器
- 17. pg-promise为选择查询创建自定义过滤器
- 18. 如何应用自定义过滤器
- 19. 在Django Admin中为list_filter创建自定义过滤器
- 20. 如何在数据表中使用“自定义过滤器”属性?或者如何创建一个自定义过滤器来按标题进行过滤?
- 21. 如何使用自定义模型过滤器过滤表单数据
- 22. 为Adblock创建自定义过滤器列表+
- 23. 使用过滤器创建一个简单的搜索框
- 24. 使用@ControllerAdvice创建简单的servlet过滤器
- 25. 如何使用ArrayAdapter为ListView编写自定义过滤器
- 26. 如何使用jQuery构建简单的表格过滤器?
- 27. 如何创建简单的自定义WebDav应用程序?
- 28. 自定义订单和过滤器
- 29. 扩展AngularJS过滤器或构建自定义过滤器
- 30. ActiveAdmin自定义过滤器。订单号
注意,虽然你可以不要编写自己的内核,可以将现有的CIFilter结合起来以获得所需的效果。你试图创建什么样的效果? – user1118321
确实。您也可以自己编写自己的图像过滤器功能,直接操作数据。如果明智地使用Accelerate框架,那么您也将获得重要的硬件支持。 –
iOS 8添加了自定义CoreImage过滤器(即自定义'CIKernel')。 –