在iOS上,可以将多个CIFilter添加到SpriteKit节点吗? [英] On iOS, can you add multiple CIFilters to a SpriteKit node?
问题描述
在iOS上,您可以向 SKEffectsNode
中添加多个 CIFilter
吗?
CIFilterGenerator
似乎是我想要的,但在iOS上不可用。
我知道您可以使用通过传递一个图像的输出作为下一个图像的输入来对图像上的多个滤镜进行操作,但这对您没有用。会影响非图像节点。对每个人,我的实际内容都放在最底层?有更好的方法吗?
难以或不可能将多个 CIFilter
调用以实现所需的效果-也许由于类具有单个属性,克服此问题的一种方法是执行以下操作:
- 子类
CIFilter
,将覆盖您需要的所有内容。其中可能包括属性
,setValue(forKey:)
,最重要的是outputImage
。 - 子类
CIFilterConstructor
,并创建registerFilter()
方法。
例如,假设您要组合高斯模糊,然后在图像上添加单色红色调。最基本的操作是:
class BlurThenColor:CIFilter {
let blurFilter = CIFilter (名称: CIGaussianBlur)
覆盖public var属性:[String:Any] {
return [
kCIAttributeFilterDisplayName:先模糊后着色,
inputImage:[kCIAttributeIdentity:0,
kCIAttributeClass: CIImage,
kCIAttributeDisplayName: Image,
kCIAttributeType:kCIAttributeTypeImage]
]
}
覆盖init(){
super.init()
}
@available(*,不可用)是否需要init?(编码器aDecoder:NSCoder){
fatalError( init(coder :)尚未实现)
}
重写public func setValue(_ value:Any ?, forKey key:String){
切换键{
case inputImage:
blurFilter?.setValue(inputIma ge,forKey: inputImage)
默认值:
中断
}
}
覆盖public var outputImage:CIImage {
return(blurFilter?.outputImage )! .applyingFilter( CIColorMonochrome,参数:[ inputColor:CIColor(红色:1.0,绿色:0.0,蓝色:0.0)])
}
}
如果您希望公开更多属性,只需将它们添加到属性
和 setValue(forKey:)
会随即添加变量和 setDefaults
而被覆盖。
现在您已经将效果链接到一个自定义滤镜中,您可以注册并使用它:
let CustomFilterCategory = CustomFilter
公共类CustomFilterConstructor:NSObject,CIFilterConstructor {
静态公共函数registerFilter (){
CIFilter.registerName(
BlurThenColor,
构造函数:CustomFilterConstructor(),
classAttributes:[
kCIAttributeFilterCategories:[CustomFilterCategory]
] )
}
公共功能过滤器(名称为String)-> CIFilter? {
开关名称{
case BlurThenColor:
return BlurThenColor()
默认值:
return nil
}
}
}
要使用此功能,只需确保注册过滤器(我倾向于将我的内容放在 AppDelegate
):
CustomFilterConstructor.registerFilter()
从那里,您可以像其他<< c>一样使用 BlurThenColor
code> CIFilter 。实例化它,使用 setValue
,然后调用 outputImage
。
请注意,由于强制展开 inputImage
和/或错别字,此代码将崩溃。我相信您可以使其更安全-但请放心,我已经对其进行了测试,并且可以正常工作。 (我创建了这个自定义过滤器,并在不会发生强制拆包的应用中将其替换。)
On iOS, can you add more than one CIFilter
to a SKEffectsNode
?
CIFilterGenerator
seems like what I want but it isn't available on iOS.
I know you can use multiple filters on an image by passing the output of one as the input of the next, but that's not helpful if you want to affect non-image nodes.
Does this mean I have to create an artificial hierarchy of SKEffectNode
and add a filter to each of them, with my actual content at the very bottom? Is there a better way?
Where it's difficult or impossible to "chain" together multiple CIFilter
calls to achieve the desired effect - maybe due to a class that has a single property, one way to overcome this is to do the following:
- Subclass
CIFilter
, overriding everything you need to. This may includeattributes
,setValue(forKey:)
, and most importantly,outputImage
. - Subclass
CIFilterConstructor
, and create aregisterFilter()
method.
For example, let's say you wish to combine a gaussian blur and then add a monochrome red tone to an image. At it's most basic you can do this:
class BlurThenColor:CIFilter {
let blurFilter = CIFilter(name: "CIGaussianBlur")
override public var attributes: [String : Any] {
return [
kCIAttributeFilterDisplayName: "Blur then Color",
"inputImage": [kCIAttributeIdentity: 0,
kCIAttributeClass: "CIImage",
kCIAttributeDisplayName: "Image",
kCIAttributeType: kCIAttributeTypeImage]
]
}
override init() {
super.init()
}
@available(*, unavailable) required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func setValue(_ value: Any?, forKey key: String) {
switch key {
case "inputImage":
blurFilter?.setValue(inputImage, forKey: "inputImage")
default:
break
}
}
override public var outputImage: CIImage {
return (blurFilter?.outputImage)! .applyingFilter("CIColorMonochrome", parameters: ["inputColor": CIColor(red: 1.0, green: 0.0, blue: 0.0)])
}
}
If you wish to expose more attributes, you can simply add them to the attributes
and setValue(forKey:)
overrides along wist adding variables and setDefaults
. Here I'm simply using the defaults.
Now that you've chained your effect together into one custom filter, you can register it and use it:
let CustomFilterCategory = "CustomFilter"
public class CustomFilterConstructor: NSObject, CIFilterConstructor {
static public func registerFilter() {
CIFilter.registerName(
"BlurThenColor",
constructor: CustomFilterConstructor(),
classAttributes: [
kCIAttributeFilterCategories: [CustomFilterCategory]
])
}
public func filter(withName name: String) -> CIFilter? {
switch name {
case "BlurThenColor":
return BlurThenColor()
default:
return nil
}
}
}
To use this, just be sure to register the filter (I tend to put mine in AppDelegate
if possible):
CustomFilterConstructor.registerFilter()
From there, you can use BlurThenColor
just like any other CIFilter
. Instantiate it, use setValue
, and call outputImage
.
Please note, this code will crash because of force-unwrapping of inputImage
and/or typos. I'm sure you can make this more safe - but rest assured that I've tested this and it works. (I created this custom filter and replaced it in an app where the force-unwraps don't happen.)
这篇关于在iOS上,可以将多个CIFilter添加到SpriteKit节点吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!