I’ve been really interested in possibility of writing my own filters without using special libraries. When I started to search solution I found Apple doc which was rather helpful for me.
And this is about using of kernel language.

So let’s start from:
1. Create MacOS project.
2. Implement filters.
3. Configuring of views and apply filters.

Create MacOS project.

It should be MacOS (Objective-C) project or you can download the sample
1

Implement filters.

Now let’s create 3 files and put it in NoiseFilter
NoiseFilter.h
Put here just a declaration of methods


#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
@interface MedianFilter: CIFilter
+ (void)registerFilter;
@end

NoiseFilter.m
Here would be all additional methods to help us to combine


#import "NoiseFilter.h"
@implementation NoiseFilter
{
CIImage *inputImage;
CIImage *mapImage;
NSNumber *scaleX;
NSNumber *scaleY;
}
static CIKernel *testKernel = nil;
// Filter registration
+ (void)registerFilter
{
NSArray *filterCategories = @[kCICategoryColorAdjustment, kCICategoryVideo, kCICategoryStillImage,
kCICategoryInterlaced, kCICategoryNonSquarePixels];
NSDictionary *attributes = @{
kCIAttributeFilterDisplayName : @"NoiseFilter",
kCIAttributeFilterCategories : filterCategories };
[CIFilter registerFilterName:@"NoiseFilter" constructor:(id )self classAttributes:attributes];
}
+ (CIFilter *)filterWithName:(NSString *)name
{
return [[self alloc] init];
}
// Initialization
- (id)init
{
self = [super init];
if (self) {
if (testKernel == nil)
{
// Load the haze removal kernel.
NSBundle *bundle = [NSBundle bundleForClass: [self class]];
NSURL *kernelURL = [bundle URLForResource:@"NoiseFilter" withExtension:@"cikernel"];
NSError *error;
NSString *kernelCode = [NSString stringWithContentsOfURL:kernelURL encoding:NSUTF8StringEncoding error:&error];
if (kernelCode == nil) {
NSLog(@"Error loading kernel code string in %@\n%@", NSStringFromSelector(_cmd), [error localizedDescription]);
abort();
}
NSArray *kernels = [CIKernel kernelsWithString:kernelCode];
testKernel = [kernels objectAtIndex:0];
}
}
return self;
}
// to apply filter
- (CIImage *)outputImage
{
CISampler *src = [CISampler samplerWithImage: inputImage];
CISampler *srcMap = [CISampler samplerWithImage: mapImage];
return [self apply: testKernel, src, srcMap, scaleX, scaleY, kCIApplyOptionDefinition, [src definition], nil];
}
// Configuration of additional attributes of filter
- (NSDictionary *)customAttributes
{
scaleX = [NSNumber numberWithInt:5];
scaleY = [NSNumber numberWithInt:5];
return @{
@"scaleX": scaleX,
@"scaleY": scaleY,
kCIAttributeFilterName : @"NoiseFilter"
};
}
@end

NoiseFilter.cikernel
Here is the code of your filter. You can took some sample from internet and configure for your needs as I did.

kernel vec4 displace(sampler source, sampler map, float scaleX, float scaleY)
{
vec2 d = destCoord();
vec4 mapPixel = sample(map, samplerTransform(map, d));
float shiftX = ((mapPixel.x * 2.0) - 1.0) * scaleX;
float shiftY = ((mapPixel.y * 2.0) - 1.0) * scaleY;
vec2 s = samplerTransform(source, d + vec2(shiftX, shiftY));
return sample(source, s);
}

NOTE: for making of noise like this you need to find the image for displace map. In my case I chose this:
displacemap
Put it into Resources folder and call it displaceMap.jpeg (.png is also works).

Views configure and apply filters.

Then Proceed with View configuration. You can remove storyboard and auto-created files ViewController. The create NoiseFilterView lass and MainMenu.xib

NoiseFilterView.h

#import <Cocoa/Cocoa.h>
#import <QuartzCore/QuartzCore.h>
@interface NoiseFilterView: NSView
@end

NoiseFilterView.m

#import "NoiseFilterView.h"
#import "NoiseFilter.h"
@interface NoiseFilterView ()
@property (nonatomic, strong) CIFilter *filter;
@property (assign) float scaleX;
@property (assign) float scaleY;
@end
@implementation NoiseFilterView
- (CIFilter *)filter
{
if (_filter == nil) {
// Make sure initialize is called. This should only be done once
[NoiseFilter registerFilter];
//Load your image
NSURL *imageURL = [[NSBundle mainBundle] URLForResource:@"CraterLake" withExtension:@"jpg"];
CIImage *image = [CIImage imageWithContentsOfURL:imageURL];
// Apply image for displacement
NSURL *imageMapURL = [[NSBundle mainBundle] URLForResource:@"displaceMap" withExtension:@"jpeg"];
CIImage *imageMap = [CIImage imageWithContentsOfURL:imageMapURL];
// set up Noise filter
_filter = [CIFilter filterWithName: @"NoiseFilter" keysAndValues:@"inputImage", image, @"mapImage", imageMap, nil];
}
return _filter;
}
// Draw filter here
- (void)drawRect:(NSRect)rect
{
CIContext* context = [[NSGraphicsContext currentContext] CIContext];
if (context != nil) {
CIFilter *filter = self.filter;
_scaleX = 25;
_scaleY = 25;
[filter setValue:@(self.scaleX) forKey:@"scaleX"];
[filter setValue:@(self.scaleY) forKey:@"scaleY"];
CGRect drawRect = CGRectMake(NSMinX(rect), NSMinY(rect), NSWidth(rect), NSHeight(rect));
CIImage *image = [filter valueForKey:@"outputImage"];
[context drawImage:image atPoint:drawRect.origin fromRect:drawRect];
}
}
@end

MainView.xib
Put here NSImageView with original image and the second one to apply filters.
2
Final result
3
I also created several examples with other filters like Blur
screen-shot-2016-12-19-at-6-19-50-am


Feel free to download sources and try. Appreciate your comments…