在iOS上,可以将多个CIFilter添加到SpriteKit节点吗? [英] On iOS, can you add multiple CIFilters to a SpriteKit node?

查看:112
本文介绍了在iOS上,可以将多个CIFilter添加到SpriteKit节点吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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 include attributes, setValue(forKey:), and most importantly, outputImage.
  • Subclass CIFilterConstructor, and create a registerFilter() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆