Tag Archives: cocoa

Adjusting the hue of an NSImage

Core Image is fantastic for complex image processing on both Mac OS X and iOS. However, it can also be used for relatively simple image adjustments with just a few lines of code.

This following method snippet adjusts the hue of an NSImage. I use it in an internal app that has colour coded icon status indicators which can’t be easily drawn totally in code. This method means that I can ship one icon resource and change it’s colour at runtime, rather than creating and shipping dozens of coloured icon resources.

As it uses Core Image, you will need to #import <QuartzCore/QuartzCore.h>.

- (NSImage*) adjustImage:(NSImage*)img withHue:(float)hue {

CIImage *inputImage = [[CIImage alloc] initWithData:[img TIFFRepresentation]];

CIFilter *hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
[hueAdjust setValue: inputImage forKey: @"inputImage"];
[hueAdjust setValue: [NSNumber numberWithFloat: hue]
forKey: @"inputAngle"];
CIImage *outputImage = [hueAdjust valueForKey: @"outputImage"];

NSImage *resultImage = [[NSImage alloc] initWithSize:[outputImage extent].size];
NSCIImageRep *rep = [NSCIImageRep imageRepWithCIImage:outputImage];
[resultImage addRepresentation:rep];

return resultImage;


Verifying plugin bundles using code signing

Code signing your apps is a great way of verifying that they haven’t been messed with before an end user executes your code, but you can also utilise the same techniques to implement a very secure plugin system for your apps.

If your application implements a plugin architecture based on NSBundles, you can use the following snippet in your loading code to ensure that each plugin is signed by an appropriate certificate.

You will need to create a certificate authority, and then have that sign a code signing certificate for your plugins. Doing it this way means that you can provide valid signing certificates to third parties to create plugins for your app if desired. TechRepublic have a good article on creating a CA in Keychain Access on your Mac.

Update (14 July 2012): Updated the snippet to be ARC compliant.

- (BOOL) validateSignature:(NSBundle*)pluginBundle {
NSTask * task = [[NSTask alloc] init];
NSPipe * pipe = [NSPipe pipe];
NSFileHandle * handle = [pipe fileHandleForReading];
NSData * taskData;
NSString * taskString;
NSArray* args = [NSArray arrayWithObjects:@"--verify", [NSString stringWithFormat:@"-R=anchor = \"%@\"", [[NSBundle mainBundle] pathForResource:@"BlargsoftCodeCA" ofType:@"cer"]], [pluginBundle bundlePath], nil];
[task setLaunchPath:@"/usr/bin/codesign"];
[task setStandardOutput:pipe];
[task setStandardError:pipe];
[task setArguments:args];
[task launch];
[task waitUntilExit];
taskData = [handle readDataToEndOfFile];
taskString = [[NSString alloc] initWithData:taskData encoding:NSASCIIStringEncoding];

if ([task terminationStatus] != 0) {
// Something went wrong. Check for specific errors

if ([taskString rangeOfString:@"modified"].length &gt; 0 || [taskString rangeOfString:@"a sealed resource is missing or invalid"].length &gt; 0) {
// The plugin has been modified or resources removed since being signed. You probably don't want to load this.
NSLog(@"Plugin modified - not loaded"); // log a real error here
} else if ([taskString rangeOfString:@"failed to satisfy"].length &gt; 0) {
// The plugin is missing resources since being signed. Don't load.
// throw an error
NSLog(@"Plugin not signed by correct CA - not loaded"); // log a real error here
} else if ([taskString rangeOfString:@"not signed at all"].length &gt; 0) {
// The plugin was not code signed at all. Don't load.
NSLog(@"Plugin not signed at all - don't load."); // log a real error here
} else {
// Some other codesign error

return FALSE;

} else {

// The plugin passed validation!
return TRUE;