Skip to content

Instantly share code, notes, and snippets.

@boredzo
Created June 1, 2013 21:48
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save boredzo/5691822 to your computer and use it in GitHub Desktop.
Save boredzo/5691822 to your computer and use it in GitHub Desktop.
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