Skip to content

Instantly share code, notes, and snippets.

@boredzo
Created June 1, 2013 21:48
Core Image custom filter to generate an angular gradient. The center is at the origin (0,0). You may want to use CIAffineTransform and/or CICrop on the output.
//
// PRHAngleGradientFilter.h
//
// Created by Peter Hosey on 2013-01-30.
// Copyright (c) 2013 Peter Hosey. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
@interface PRHAngleGradientFilter : CIFilter
@property(strong) CIColor *inputStartColor;
@property(strong) CIColor *inputMidColor;
@property(strong) CIColor *inputEndColor;
- (CIImage *) outputImage;
@end
//
// PRHAngleGradientFilter.m
//
// Created by Peter Hosey on 2013-01-30.
// Copyright (c) 2013 Peter Hosey. All rights reserved.
//
#import "PRHAngleGradientFilter.h"
@implementation PRHAngleGradientFilter
{
CIKernel *_kernel;
}
- (id) init {
if ((self = [super init])) {
NSString *kernelText = @"kernel vec4 coreImageKernel(__color startColor, __color midColor, __color endColor)\n"
"{\n"
"\tvec2 point = destCoord();\n"
"\n"
"\tfloat angle = atan(point.y, point.x) + radians(180.0);\n"
"\t//Start from the upper middle, not the left middle\n"
"\tangle += radians(90.0);\n"
"\tangle = mod(angle, radians(360.0));\n"
"\n"
"\tfloat fraction = angle / radians(360.0);\n"
//"\tfraction = clamp(fraction, 0.0, 1.0);\n"
"\n"
"\tvec4 resultColor = fraction < 0.5\n"
"\t\t? startColor * (1.0 - fraction * 2.0) + midColor * (fraction * 2.0)\n"
"\t\t: midColor * (1.0 - (fraction - 0.5) * 2.0) + endColor * ((fraction - 0.5) * 2.0);\n"
"\treturn resultColor;\n"
"}";
_kernel = [CIKernel kernelsWithString:kernelText][0];
}
return self;
}
- (NSDictionary *) attributes {
NSDictionary *attributes = @{
kCIAttributeFilterCategories: @[
kCICategoryColorAdjustment,
kCICategoryVideo,
kCICategoryStillImage,
kCICategoryGenerator,
kCICategoryGradient
],
kCIAttributeFilterName: @"PRHAngleGradientFilter",
kCIAttributeFilterDisplayName: NSLocalizedString(@"Angle gradient", @"Localized name of PRHAngleGradientFilter"),
@"inputStartColor": @{
kCIAttributeClass: @"CIColor",
kCIAttributeType: kCIAttributeTypeOpaqueColor,
kCIAttributeDefault: [CIColor colorWithCGColor:CGColorGetConstantColor(kCGColorWhite)]
},
@"inputMidColor": @{
kCIAttributeClass: @"CIColor",
kCIAttributeType: kCIAttributeTypeOpaqueColor,
kCIAttributeDefault: [CIColor colorWithCGColor:CGColorGetConstantColor(kCGColorBlack)]
},
@"inputEndColor": @{
kCIAttributeClass: @"CIColor",
kCIAttributeType: kCIAttributeTypeOpaqueColor,
kCIAttributeDefault: [CIColor colorWithCGColor:CGColorGetConstantColor(kCGColorWhite)]
},
kCIOutputImageKey: @{
kCIAttributeClass: @"CIImage"
}
};
return attributes;
}
//Because Apple's implementations don't auto-detect input and output keys for us.
- (NSArray *) inputKeys {
return [[super inputKeys]
arrayByAddingObjectsFromArray:[self.attributes.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
id evaluatedObject, NSDictionary *bindings
) {
return [evaluatedObject hasPrefix:@"input"];
}]]];
}
- (NSArray *) outputKeys {
return [[super outputKeys]
arrayByAddingObjectsFromArray:[self.attributes.allKeys filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
id evaluatedObject, NSDictionary *bindings
) {
return [evaluatedObject hasPrefix:@"output"];
}]]];
}
- (CIImage *) outputImage {
NSArray *args = @[
[self valueForKey:@"inputStartColor"], [self valueForKey:@"inputMidColor"], [self valueForKey:@"inputEndColor"]
];
CIImage *outputImage = [self apply:_kernel arguments:args options:nil];
return outputImage;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment