iosobjective-ccifilter

CIFilter 'apply:' is unavailable: not available on iOS


I'm creating a simple custom CIFilter that implements CIKernel to decrease alpha value.

My "AlphaFilter.h":

@interface CIAlphaFilter: CIFilter {
    CIImage *inputImage;
}
@property (retain, nonatomic) CIImage *inputImage;
@end

My "AlphaFilter.m":

#import "AlphaFilter.h"

@implementation CIAlphaFilter
@synthesize inputImage;
static CIKernel *alphaRemoveKernel = nil;

- (id)init {
    if(alphaRemoveKernel == nil)
    {
        NSString *code = @"kernel vec4 darkToTransparent(sampler image){vec4 color = sample(image, samplerCoord(image));color.a =0.5;return color;}";
        alphaRemoveKernel = [CIKernel kernelWithString:code];
    }
    return [super init];
}

- (CIImage *)outputImage
{
    CISampler *src = [CISampler samplerWithImage: inputImage];
 
    return [self apply: alphaRemoveKernel, src, nil]; // Error here
}

@end

At the return for (CIImage *)outputImage, Xcode give me an error:

'apply:' is unavailable: not available on iOS

Can anyone tell me what mistake I made? I'm using Xcode 15.2.


Solution

  • You can call the apply method on the kernel instead:

    - (CIImage *)outputImage
    {
        CISampler *src = [CISampler samplerWithImage: inputImage]; 
        CIKernelROICallback roiCallback = ^(int index, CGRect rect) {
            return rect;
        };
        return [Self.alphaRemoveKernel applyWithExtent: [inputImage extent], roiCallback: roiCallback, arguments: @[src]];
    }
    

    And it's actually simpler if you use CIColorKernel instead, because you don't need the roiCallback then. This works for your filter since you have a 1:1 mapping of input to output pixels:

    #import "AlphaFilter.h"
    
    @implementation CIAlphaFilter
    @synthesize inputImage;
    static CIColorKernel *alphaRemoveKernel = nil;
    
    - (id)init {
        if(alphaRemoveKernel == nil)
        {
            NSString *code = @"kernel vec4 darkToTransparent(__sample src){vec4 color = src;color.a = 0.5;return color;}";
            alphaRemoveKernel = [CIColorKernel kernelWithString:code];
        }
        return [super init];
    }
    
    - (CIImage *)outputImage
    {
        CISampler *src = [CISampler samplerWithImage: inputImage];
        return [Self.alphaRemoveKernel applyWithExtent: [inputImage extent], arguments: @[src]];
    }
    
    @end
    

    And, even simpler, for this use case you can use the built-in CIColorMatrix filter. You don't need to write your own kernel:

    #import "AlphaFilter.h"
    
    @implementation CIAlphaFilter
    @synthesize inputImage;
    
    
    - (CIImage *)outputImage
    {
        CIColorMatrix *colorMatrixFilter = [CIFilter colorMatrixFilter];
        colorMatrixFilter.inputImage = inputImage;
        colorMatrixFilter.AVector = [CIVector vectorWithX:0 Y:0 Z:0 W:0.5]
        return colorMatrixFilter.outputImage;
    }
    
    @end