// // MPT_CaptureFaces.m // MPT_CaptureFaces // // Created by Andrew Salamon on 6/3/08. // Copyright 2008 Machine Perception Laboratory, University of California San Diego.. All rights reserved. // #import "MPT_CaptureFaces.h" #import #import #import #import #import "MPT_Face.h" const int MPT_RImageFileType = -1; static NSString *ExtensionForBitmapImageFileType( NSBitmapImageFileType bitmapImageFileType ); @implementation MPT_CaptureFaces - (id)initWithBundle:(NSBundle *)_bundle { if( self = [super initWithBundle:_bundle] ) { NSUserDefaults *_prefs = [NSUserDefaults standardUserDefaults]; NSDictionary *plugPrefs = [NSDictionary dictionaryWithObjectsAndKeys: @"~/Sites/Faces", @"directory", [NSNumber numberWithInt:NSJPEGFileType], @"format", [NSNumber numberWithInt:20], @"maxCaptures", [NSNumber numberWithBool:NO], @"enabled", nil]; NSDictionary *defPrefs = [NSDictionary dictionaryWithObject:plugPrefs forKey:[self pluginID]]; [_prefs registerDefaults:defPrefs]; [self setFormatExtension:ExtensionForBitmapImageFileType((NSBitmapImageFileType)[self format])]; if( ![NSBundle loadNibNamed:@"CaptureFacesPref" owner:self] ) NSLog( @"Unable to load pref pane for MPT_CaptureFaces plugin." ); [self setLastCapture:[NSDate distantPast]]; nextFace = 1; } return self; } - (void)dealloc { [formatExtension release]; [super dealloc]; } // It's not OK to copy this plugin, so return nil. - (id)copyWithZone:(NSZone *)zone { return nil; } - (BOOL)loadLabels { labels = [[NSArray alloc] init]; return YES; } - (NSString *)pluginID { NSString *ident = [super pluginID]; if( [ident length] > 0 ) return ident; return @"edu.ucsd.mplab.plugins.CaptureFaces"; } - (NSString *)localizedName { return NSLocalizedStringFromTableInBundle(@"Capture Faces", nil, [self bundle], @""); } - (NSString *)internalName { return @"capturefaces"; } - (NSString *)step { return MPT_PluginStep_Results; } - (NSView *)prefPane { return prefView; } - (NSDate *)lastCapture { return lastCapture; } - (void)setLastCapture:(NSDate *)value { if( lastCapture != value ) { [lastCapture release]; lastCapture = [value retain]; } } - (NSMutableDictionary *)processResults:(NSDictionary *)results usingController:(id)controller { NSArray *faces = [results objectForKey:@"CERT.faces"]; if( [faces count] > 0 ) { // Capture images at most once per second NSTimeInterval diff = [[self lastCapture] timeIntervalSinceNow]; if( diff < -1.0 ) { NSImage *image = [results objectForKey:@"CERT.image"]; if( !image ) { MPT_RimageAdaptor *adaptor = [results objectForKey:@"CERT.patch"]; image = [adaptor image]; } if( image ) { [self captureFaces:faces inImage:image]; [self setLastCapture:[NSDate date]]; } } } return nil; } - (void)captureFaces:(NSArray *)faces inImage:(NSImage *)image { NSString *dest = [self filenameFromPath:[NSString stringWithFormat:@"CapturedFace%d", nextFace] ext:formatExtension]; NSBitmapImageRep *imageRep = NULL; BOOL captureWithFaceBox = NO; if( captureWithFaceBox ) { MPT_Face *firstFace = [faces objectAtIndex:0]; NSRect faceRect = [firstFace face]; image = [[image copy] autorelease]; NSSize size = [image size]; [image lockFocus]; [[NSColor blueColor] setFill]; [[NSColor blueColor] setStroke]; faceRect.origin.y = size.height - faceRect.origin.y - faceRect.size.height; NSFrameRect(faceRect); imageRep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect: NSMakeRect(0,0,size.width,size.height)] autorelease]; [image unlockFocus]; } else { NSArray *reps = [image representations]; NSEnumerator *repEnum = [reps objectEnumerator]; NSBitmapImageRep *locRep = NULL; while( (locRep = [repEnum nextObject]) && ![locRep isKindOfClass:[NSBitmapImageRep class]] ) { } if( [locRep isKindOfClass:[NSBitmapImageRep class]] ) imageRep = locRep; } if( imageRep ) { // save as JPEG NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat:0.85], NSImageCompressionFactor, NULL]; NSData *bitmapData = [imageRep representationUsingType:(NSBitmapImageFileType)[self format] properties:properties]; if( bitmapData ) { if( [bitmapData writeToFile:dest atomically:YES] ) { ++nextFace; unsigned int max = [self maxCaptures]; if( (0 != max) && (nextFace > max) ) nextFace = 1; } } } } - (NSString *)directory { NSDictionary *myPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]]; NSString *dir = [myPrefs objectForKey:@"directory"]; return (dir?dir:@"~/Sites/Faces"); } - (void)setDirectory:(NSString *)value { NSMutableDictionary *myPrefs = [[[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]] mutableCopy]; if( !myPrefs ) myPrefs = [[NSMutableDictionary alloc] init]; [myPrefs setObject:(value?value:@"") forKey:@"directory"]; [[NSUserDefaults standardUserDefaults] setObject:myPrefs forKey:[self pluginID]]; [myPrefs release]; } static NSString *ExtensionForBitmapImageFileType( NSBitmapImageFileType bitmapImageFileType ) { NSString *result = @""; switch( bitmapImageFileType ) { case NSTIFFFileType: result = @"tiff"; break; case NSBMPFileType: result = @"bmp"; break; case NSGIFFileType: result = @"gif"; break; case NSJPEGFileType: result = @"jpg"; break; case NSPNGFileType: result = @"png"; break; case NSJPEG2000FileType: result = @"jp2"; break; default: result = @"jpg"; break; } return result; } - (int)format { NSDictionary *myPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]]; NSNumber *fmt = [myPrefs objectForKey:@"format"]; return fmt?[fmt intValue]:NSJPEGFileType; } - (void)setFormat:(int)value { NSMutableDictionary *myPrefs = [[[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]] mutableCopy]; if( !myPrefs ) myPrefs = [[NSMutableDictionary alloc] init]; [myPrefs setObject:[NSNumber numberWithInt:value] forKey:@"format"]; [[NSUserDefaults standardUserDefaults] setObject:myPrefs forKey:[self pluginID]]; [myPrefs release]; [self setFormatExtension:ExtensionForBitmapImageFileType( (NSBitmapImageFileType)value)]; } - (unsigned int)maxCaptures { NSDictionary *myPrefs = [[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]]; NSNumber *fmt = [myPrefs objectForKey:@"maxCaptures"]; return fmt?[fmt intValue]:20; } - (void)setMaxCaptures:(unsigned int)value { NSMutableDictionary *myPrefs = [[[NSUserDefaults standardUserDefaults] objectForKey:[self pluginID]] mutableCopy]; if( !myPrefs ) myPrefs = [[NSMutableDictionary alloc] init]; [myPrefs setObject:[NSNumber numberWithInt:value] forKey:@"maxCaptures"]; [[NSUserDefaults standardUserDefaults] setObject:myPrefs forKey:[self pluginID]]; [myPrefs release]; } - (NSString *)formatExtension { return formatExtension; } - (void)setFormatExtension:(NSString *)value { if( formatExtension != value ) { [formatExtension release]; formatExtension = [value retain]; } } - (NSString *)filenameFromPath:(NSString *)path ext:(NSString *)ext { return [[[[self directory] stringByAppendingPathComponent:[path lastPathComponent]] stringByAppendingPathExtension:ext] stringByStandardizingPath]; } - (IBAction)chooseDirectory:(id)sender { NSOpenPanel *panel = [NSOpenPanel openPanel]; [panel setPrompt:@"Choose Folder"]; [panel setTitle:@"Choose a folder for saving images."]; [panel setCanChooseDirectories:YES]; [panel setCanCreateDirectories:YES]; [panel setCanChooseFiles:NO]; [panel setAllowsMultipleSelection:NO]; [panel beginSheetForDirectory:nil file:nil types:nil modalForWindow:[prefView window] modalDelegate:self didEndSelector:@selector(chooseDirectoryPanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; } - (void)chooseDirectoryPanelDidEnd:(NSOpenPanel *)panel returnCode:(int)returnCode contextInfo:(void *)contextInfo { if( returnCode == NSOKButton ) { NSArray *filenames = [panel filenames]; if( [filenames count] > 0 ) { NSString *path = [filenames objectAtIndex:0]; if( [path length] > 0 ) { [self setDirectory:path]; } } } } @end