#import void EchoKeywords (NSArray *files); void SetKeywords (NSArray *stuff, NSArray *files, BOOL flag); //@interface FDFArgvFileList : NSArray {} //+ (NSMutableArray *)argvFilesExist:(NSArray *)files withWritableKeywords:(BOOL)flag; //@end @interface NSArray (argvFilesExist) + (NSMutableArray *)argvFilesExist:(NSArray *)files withWritableKeywords:(BOOL)flag; @end @interface CurrentKeywordsFromFile : NSArray {} + (NSArray *)currentKeywordsFromFile:(char *)fileFromArg; @end //@interface CreateKeywordArray : NSArray {} //+ (CFArrayRef)createKeywordArray:(CFStringRef)setArg; //@end @interface NSArray (arrayWithOpts) + (NSArray *)arrayWithOpts:(NSString *)argvKeywords; @end @interface WriteKeywordsToFile : NSObject {} + (void)writeKeywordsToFile:(char *)file keywordsToWrite:(NSArray *)keywords; @end //@implementation FDFArgvFileList //+ (NSMutableArray *)argvFilesExist:(NSArray *)files withWritableKeywords:(BOOL)flag { // NSMutableArray *returnArray = [NSMutableArray array]; // NSEnumerator *enumerator = [files objectEnumerator]; // CFStringRef file, kind; // MDItemRef item; // id arg; // while (arg = [enumerator nextObject]) { // file = CFStringCreateWithFileSystemRepresentation(NULL, [arg UTF8String]); // if ([[NSFileManager defaultManager] fileExistsAtPath:(NSString *)file]) { // item = MDItemCreate(NULL, file); // kind = MDItemCopyAttribute(item, kMDItemContentType); // if (flag && ([(NSString *)kind isEqualToString:@"public.tiff"] || [(NSString *)kind isEqualToString:@"public.jpeg"])) // [returnArray addObject:(NSString *)file]; // if (!flag && ([(NSString *)kind isEqualToString:@"com.adobe.photoshop-image"] || [(NSString *)kind isEqualToString:@"public.tiff"] || [(NSString *)kind isEqualToString:@"public.jpeg"])) // [returnArray addObject:(NSString *)file]; // } // } // return ([returnArray count] > 0) ? returnArray : nil; //} //@end @implementation NSArray (argvFilesExist) + (NSMutableArray *)argvFilesExist:(NSArray *)files withWritableKeywords:(BOOL)flag { NSMutableArray *returnArray = [NSMutableArray array]; NSEnumerator *enumerator = [files objectEnumerator]; CFStringRef file, kind; MDItemRef item; id arg; while (arg = [enumerator nextObject]) { file = CFStringCreateWithFileSystemRepresentation(NULL, [arg UTF8String]); if ([[NSFileManager defaultManager] fileExistsAtPath:(NSString *)file]) { item = MDItemCreate(NULL, file); kind = MDItemCopyAttribute(item, kMDItemContentType); if (flag && ([(NSString *)kind isEqualToString:@"public.tiff"] || [(NSString *)kind isEqualToString:@"public.jpeg"])) [returnArray addObject:(NSString *)file]; if (!flag && ([(NSString *)kind isEqualToString:@"com.adobe.photoshop-image"] || [(NSString *)kind isEqualToString:@"public.tiff"] || [(NSString *)kind isEqualToString:@"public.jpeg"])) [returnArray addObject:(NSString *)file]; } } return ([returnArray count] > 0) ? returnArray : nil; } @end @implementation CurrentKeywordsFromFile + (NSArray *)currentKeywordsFromFile:(char *)fileFromArg { CFStringRef file; MDItemRef item; CFTypeRef keywords; file = CFStringCreateWithFileSystemRepresentation(NULL, fileFromArg); item = MDItemCreate(NULL, file); keywords = MDItemCopyAttribute(item, kMDItemKeywords); return ([(NSArray *)keywords count] > 0) ? (NSArray *)keywords : nil; } @end //@implementation CreateKeywordArray //+ (CFArrayRef)createKeywordArray:(CFStringRef)setArg { // CFArrayRef insert = CFStringCreateArrayBySeparatingStrings(NULL, setArg, CFSTR(",")); // NSEnumerator *enm2 = [(NSArray *)insert objectEnumerator]; // id words; // int i = 0; // while (words = [enm2 nextObject]) { // CFStringRef str = CFArrayGetValueAtIndex(insert, i); // CFIndex len = CFStringGetLength(str); // CFMutableStringRef copy = CFStringCreateMutableCopy(kCFAllocatorDefault, len, str); // CFStringTrimWhitespace(copy); // CFArraySetValueAtIndex((CFMutableArrayRef)insert, i, copy); // CFRelease(copy); // i++; // } // CFArrayRef CLIKeywords = CFArrayCreateCopy(NULL,insert); // return ([(NSArray *)CLIKeywords count] > 0) ? [CLIKeywords autorelease] : nil; //} //@end @implementation NSArray (arrayWithOpts) + (NSArray *)arrayWithOpts:(NSString *)argvKeywords { NSArray * keywords = [argvKeywords componentsSeparatedByString:@","]; NSEnumerator * enm = [keywords objectEnumerator]; CFStringRef str; CFMutableStringRef copy; int i = 0; id word; while (word = [enm nextObject]) { str = CFArrayGetValueAtIndex((CFArrayRef)keywords, i); copy = CFStringCreateMutableCopy(kCFAllocatorDefault, CFStringGetLength(str), str); CFStringTrimWhitespace(copy); CFArraySetValueAtIndex((CFMutableArrayRef)keywords, i, copy); CFRelease(copy); i++; } return ([keywords count] > 0) ? keywords : nil; } @end @implementation WriteKeywordsToFile + (void)writeKeywordsToFile:(char *)file keywordsToWrite:(NSArray *)keywords { NSDictionary *iptcKeywords = [NSDictionary dictionaryWithObject:keywords forKey:(NSString *)kCGImagePropertyIPTCKeywords]; NSDictionary *iptcProperties = [NSDictionary dictionaryWithObject:iptcKeywords forKey:(NSString *)kCGImagePropertyIPTCDictionary]; NSMutableData *imageData = [[NSMutableData alloc] init]; CFStringRef input = CFStringCreateWithCString(kCFAllocatorDefault, file, kCFStringEncodingUTF8); CFStringRef path = CFStringCreateWithFileSystemRepresentation(kCFAllocatorDefault, file); CGImageSourceRef imageSource = CGImageSourceCreateWithURL ((CFURLRef)[NSURL fileURLWithPath:(NSString *)input], nil); CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((CFMutableDataRef)imageData, CGImageSourceGetType(imageSource), 1, NULL); CGImageDestinationAddImageFromSource(imageDestination, imageSource, 0, (CFDictionaryRef)iptcProperties); if (CGImageDestinationFinalize(imageDestination)) [imageData writeToFile:(NSString *)path atomically:YES]; CFRelease(input); CFRelease(path); CFRelease(imageDestination); CFRelease(imageSource); [imageData release]; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSArray *args = [[NSProcessInfo processInfo] arguments]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *shortSetOption = [defaults stringForKey:@"s"]; NSString *longSetOption = [defaults stringForKey:@"-set"]; NSString *shortAppendOption = [defaults stringForKey:@"a"]; NSString *longAppendOption = [defaults stringForKey:@"-append"]; NSString *shortArgs = (shortSetOption) ? shortSetOption : ((shortAppendOption) ? shortAppendOption : nil); NSString *longArgs = (longSetOption) ? longSetOption : ((longAppendOption) ? longAppendOption : nil); NSString *optArgs = (shortArgs) ? shortArgs : ((longArgs) ? longArgs : nil); NSEnumerator *enm = [args objectEnumerator]; bool help = false; id arg; while (arg = [enm nextObject]) if ([(NSString *)arg isEqualToString:@"-h"] || [(NSString *)arg isEqualToString:@"--help"]) help = true; if(optArgs) { //CFArrayRef keyWords = [CreateKeywordArray createKeywordArray:(CFStringRef)setArgs]; NSArray *keywords = [NSArray arrayWithOpts:optArgs]; NSArray *files = [NSArray argvFilesExist:args withWritableKeywords:1]; BOOL flag = (shortSetOption || longSetOption) ? 0 : 1; if(files) SetKeywords (keywords, files, flag); if(!files) help = true; } if(!optArgs && !help) { CFStringRef echo; NSArray *files = [NSArray argvFilesExist:args withWritableKeywords:0]; if(files) EchoKeywords (files); if(!files) help = true; } if(help) { CFShow(CFSTR("\nmdkw only reads keywords from JPEG, TIFF, and Adobe Photoshop files")); CFShow(CFSTR("mdkw will only write keywords to JPEG and TIFF files\n\n")); CFShow(CFSTR("usage: mdkw [file(s)]")); CFShow(CFSTR("usage: mdkw [-h, --help]")); CFShow(CFSTR("usage: mdkw [-a, --append] ['keyword'] [file(s)]")); CFShow(CFSTR("usage: mdkw [-s, --set] ['keyword'] [file(s)]\n\n")); CFShow(CFSTR("example: mdkw ~/Pictures/Birthday.jpg")); CFShow(CFSTR("example: mdkw -s Cake ~/Pictures/Birthday.jpg")); CFShow(CFSTR("example: mdkw -s 'Birthday Cake' ~/Pictures/Birthday.jpg")); CFShow(CFSTR("example: mdkw -s 'Ballons, Birthday Cake' ~/Pictures/Birthday.jpg\n\n")); } [pool release]; return 0; } void EchoKeywords (NSArray *files) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; CFStringRef echo; NSArray *keywords; NSEnumerator *enm = [files objectEnumerator]; id word; while (word = [enm nextObject]) { keywords = [CurrentKeywordsFromFile currentKeywordsFromFile:(char *)[word UTF8String]]; printf("%s -------------\n", [word UTF8String]); echo = (keywords) ? CFStringCreateByCombiningStrings(NULL, (CFArrayRef)keywords, CFSTR(", ")) : CFSTR("No Keywords!"); CFShow(echo); } [pool release]; } void SetKeywords (NSArray *keyWordsFromArgs, NSArray *files, BOOL flag) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSEnumerator *enm = [files objectEnumerator]; NSArray *keywords; CFStringRef echo; CFIndex a, b; CFArrayRef merge, writeBack; CFRange range; id word; while (word = [enm nextObject]) { keywords = [CurrentKeywordsFromFile currentKeywordsFromFile:(char *)[word UTF8String]]; if (keywords) { a = CFArrayGetCount((CFArrayRef)keywords); // b = CFArrayGetCount(keyWordsFromArgs); b = [keyWordsFromArgs count]; merge = CFArrayCreateMutableCopy(kCFAllocatorDefault, a+b, (CFArrayRef)keywords); CFRange range = {0, b}; CFArrayAppendArray((CFMutableArrayRef)merge, (CFArrayRef)keyWordsFromArgs, range); } writeBack = (flag && keywords) ? CFArrayCreateCopy(NULL, merge) : CFArrayCreateCopy(NULL, (CFArrayRef)keyWordsFromArgs); [WriteKeywordsToFile writeKeywordsToFile:(char *)[word UTF8String] keywordsToWrite:(NSArray *)writeBack]; printf("%s -------------\n", [word UTF8String]); echo = CFStringCreateByCombiningStrings(NULL, writeBack, CFSTR(", ")); CFShow(echo); } CFRelease(writeBack); CFRelease(merge); [pool release]; }