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
57 NSEnumerator* e = [[img representations] objectEnumerator];
59 while ((ir = [e nextObject])) {
60 if (![ir isKindOfClass:[NSBitmapImageRep class]]) continue;
62 NSBitmapImageRep* br = (NSBitmapImageRep*)ir;
64 if ([br pixelsWide] == size && [br pixelsHigh] == size
65 && ([[br colorSpaceName] isEqualToString:NSDeviceRGBColorSpace]
66 || [[br colorSpaceName] isEqualToString:NSCalibratedRGBColorSpace])
67 && ([br bitsPerPixel] == 24 || [br bitsPerPixel] == 32)
72 NSLog(@"Resampling for size %d", size);
73 NSBitmapImageRep* r = [[NSBitmapImageRep alloc]
74 initWithBitmapDataPlanes:NULL
81 colorSpaceName:NSDeviceRGBColorSpace
86 [NSGraphicsContext saveGraphicsState];
87 NSGraphicsContext* context = [NSGraphicsContext
88 graphicsContextWithBitmapImageRep:r];
89 [context setShouldAntialias:YES];
90 [context setImageInterpolation:NSImageInterpolationHigh];
91 [NSGraphicsContext setCurrentContext:context];
93 [img drawInRect:NSMakeRect(0, 0, size, size)
95 operation:NSCompositeCopy
98 [NSGraphicsContext restoreGraphicsState];
104 int main(int argc, char* argv[]) {
107 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
116 { @"512", kIconServices512PixelDataARGB, 0, 512, nil },
117 { @"256", kIconServices256PixelDataARGB, 0, 256, nil },
118 { @"128", kThumbnail32BitData, kThumbnail8BitMask, 128, nil },
119 { @"32", kLarge32BitData, kLarge8BitMask, 32, nil },
120 { @"16", kSmall32BitData, kSmall8BitMask, 16, nil },
122 const int N = sizeof(inputs)/sizeof(inputs[0]);
124 // Process arguments -- Thanks Greg!
125 //http://unixjunkie.blogspot.com/2006/07/command-line-processing-in-cocoa.html
126 NSUserDefaults* args = [NSUserDefaults standardUserDefaults];
128 BOOL foundInputParam = NO;
129 NSString* outputName = [args stringForKey:@"out"];
130 NSString* defaultIn = [args stringForKey:@"in"];
131 for (i = 0; i < N; ++i) {
132 inputs[i].inputName = [args stringForKey:inputs[i].paramName];
133 if (inputs[i].inputName == nil)
134 inputs[i].inputName = defaultIn;
135 foundInputParam = foundInputParam || inputs[i].inputName != nil;
137 // Create default output name if necessary
138 if (outputName == nil && inputs[i].inputName != nil)
139 outputName = [[inputs[i].inputName stringByDeletingPathExtension]
140 stringByAppendingPathExtension:@"icns"];
143 if (!foundInputParam)
147 IconFamily* output = [IconFamily iconFamily];
149 for (i = 0; i < N; ++i) {
150 if (inputs[i].inputName == nil) continue;
151 NSImage* img = [[[NSImage alloc] initWithContentsOfFile:inputs[i].inputName]
154 NSBitmapImageRep* rep = getBitmapImageRepOfSize(img, inputs[i].size);
155 [output setIconFamilyElement:inputs[i].type fromBitmapImageRep:rep];
156 if (inputs[i].mask != 0)
157 [output setIconFamilyElement:inputs[i].mask fromBitmapImageRep:rep];
161 if ([output writeToFile:outputName])
162 NSLog(@"Wrote output file \"%@\"", outputName);
164 NSLog(@"Failed to write \"%@\"", outputName);