2 // Converts images to Apple's icns format.
3 // Written by nicolasweber@gmx.de, released under MIT license.
5 #import <Foundation/Foundation.h>
6 #import <AppKit/AppKit.h>
8 #import <Cocoa/Cocoa.h>
10 #include "IconFamily.h"
12 #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
13 // This is defined in 10.5 and beyond in IconStorage.h
15 kIconServices512PixelDataARGB = 'ic09' /* non-premultiplied 512x512 ARGB bitmap*/
19 #define VERSION "1.0 (20081122)"
23 "makeicns v%s\n\n", VERSION);
25 "Usage: makeicns [k1=v1] [k2=v2] ...\n\n");
27 "Keys and values include:\n");
29 " 512: Name of input image for 512x512 variant of icon\n");
31 " 256: Name of input image for 256x256 variant of icon\n");
33 " 128: Name of input image for 128x128 variant of icon\n");
35 " 32: Name of input image for 32x32 variant of icon\n");
37 " 16: Name of input image for 16x16 variant of icon\n");
39 " in: Name of input image for all variants not having an explicit name\n");
41 " out: Name of output file, defaults to first nonempty input name,\n"
42 " but with icns extension\n\n");
45 " icns -512 image.png -32 image.png\n"
46 " Creates image.icns with only a 512x512 and a 32x32 variant.\n\n"
47 " icns -in myfile.jpg -32 otherfile.png -out outfile.icns\n"
48 " Creates outfile.icns with sizes 512, 256, 128, and 16 containing data\n"
49 " from myfile.jpg and with size 32 containing data from otherfile.png.\n");
54 NSBitmapImageRep* getBitmapImageRepOfSize(NSImage* img, int size) {
56 // Don't resample if it's not necessary
58 // IconFamily does not work correctly with
59 // NSAlphaNonpremultipliedBitmapFormat images, so this has to stay disabled
60 // until IconFamily is fixed (if ever).
61 NSEnumerator* e = [[img representations] objectEnumerator];
63 while ((ir = [e nextObject])) {
64 if (![ir isKindOfClass:[NSBitmapImageRep class]]) continue;
66 NSBitmapImageRep* br = (NSBitmapImageRep*)ir;
68 if ([br pixelsWide] == size && [br pixelsHigh] == size
69 && ([[br colorSpaceName] isEqualToString:NSDeviceRGBColorSpace]
70 || [[br colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace])
71 && ([br bitsPerPixel] == 24 || [br bitsPerPixel] == 32)
77 NSLog(@"Resampling for size %d", size);
78 NSBitmapImageRep* r = [[NSBitmapImageRep alloc]
79 initWithBitmapDataPlanes:NULL
86 colorSpaceName:NSDeviceRGBColorSpace
91 [NSGraphicsContext saveGraphicsState];
92 NSGraphicsContext* context = [NSGraphicsContext
93 graphicsContextWithBitmapImageRep:r];
94 [context setShouldAntialias:YES];
95 [context setImageInterpolation:NSImageInterpolationHigh];
96 [NSGraphicsContext setCurrentContext:context];
98 [img drawInRect:NSMakeRect(0, 0, size, size)
100 operation:NSCompositeCopy
103 [NSGraphicsContext restoreGraphicsState];
109 int main(int argc, char* argv[]) {
112 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
121 { @"512", kIconServices512PixelDataARGB, 0, 512, nil },
122 { @"256", kIconServices256PixelDataARGB, 0, 256, nil },
123 { @"128", kThumbnail32BitData, kThumbnail8BitMask, 128, nil },
124 { @"32", kLarge32BitData, kLarge8BitMask, 32, nil },
125 { @"16", kSmall32BitData, kSmall8BitMask, 16, nil },
127 const int N = sizeof(inputs)/sizeof(inputs[0]);
129 // Process arguments -- Thanks Greg!
130 //http://unixjunkie.blogspot.com/2006/07/command-line-processing-in-cocoa.html
131 NSUserDefaults* args = [NSUserDefaults standardUserDefaults];
133 BOOL foundInputParam = NO;
134 NSString* outputName = [args stringForKey:@"out"];
135 NSString* defaultIn = [args stringForKey:@"in"];
136 for (i = 0; i < N; ++i) {
137 inputs[i].inputName = [args stringForKey:inputs[i].paramName];
138 if (inputs[i].inputName == nil)
139 inputs[i].inputName = defaultIn;
140 foundInputParam = foundInputParam || inputs[i].inputName != nil;
142 // Create default output name if necessary
143 if (outputName == nil && inputs[i].inputName != nil)
144 outputName = [[inputs[i].inputName stringByDeletingPathExtension]
145 stringByAppendingPathExtension:@"icns"];
148 if (!foundInputParam)
152 IconFamily* output = [IconFamily iconFamily];
154 for (i = 0; i < N; ++i) {
155 if (inputs[i].inputName == nil) continue;
156 NSImage* img = [[[NSImage alloc] initWithContentsOfFile:inputs[i].inputName]
159 NSBitmapImageRep* rep = getBitmapImageRepOfSize(img, inputs[i].size);
160 [output setIconFamilyElement:inputs[i].type fromBitmapImageRep:rep];
161 if (inputs[i].mask != 0)
162 [output setIconFamilyElement:inputs[i].mask fromBitmapImageRep:rep];
166 if ([output writeToFile:outputName])
167 NSLog(@"Wrote output file \"%@\"", outputName);
169 NSLog(@"Failed to write \"%@\"", outputName);