Doc icon generation cleanup
[MacVim.git] / src / MacVim / icons / makeicns / makeicns.m
blobcfc2c26fa6b228b4cb103d9bf22e1c218751244c
1 // makeicns
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
14 enum {
15   kIconServices512PixelDataARGB = 'ic09' /* non-premultiplied 512x512 ARGB bitmap*/
17 #endif
19 #define VERSION "1.0 (20081122)"
21 void usage() {
22   fprintf(stderr,
23 "makeicns v%s\n\n", VERSION);
24   fprintf(stderr,
25 "Usage: makeicns [k1=v1] [k2=v2] ...\n\n");
26   fprintf(stderr,
27 "Keys and values include:\n");
28   fprintf(stderr,
29 "    512: Name of input image for 512x512 variant of icon\n");
30   fprintf(stderr,
31 "    256: Name of input image for 256x256 variant of icon\n");
32   fprintf(stderr,
33 "    128: Name of input image for 128x128 variant of icon\n");
34   fprintf(stderr,
35 "     32: Name of input image for 32x32 variant of icon\n");
36   fprintf(stderr,
37 "     16: Name of input image for 16x16 variant of icon\n");
38   fprintf(stderr,
39 "     in: Name of input image for all variants not having an explicit name\n");
40   fprintf(stderr,
41 "    out: Name of output file, defaults to first nonempty input name,\n"
42 "         but with icns extension\n\n");
43   fprintf(stderr,
44 "Examples:\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");
50   exit(1);
54 NSBitmapImageRep* getBitmapImageRepOfSize(NSImage* img, int size) {
56   // Don't resample if it's not necessary
57 #if 0
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];
62   NSImageRep* ir;
63   while ((ir = [e nextObject])) {
64     if (![ir isKindOfClass:[NSBitmapImageRep class]]) continue;
66     NSBitmapImageRep* br = (NSBitmapImageRep*)ir;
67     //NSLog(@"%@", br);
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)
72        )
73       return br;
74   }
75 #endif
77   NSLog(@"Resampling for size %d", size);
78   NSBitmapImageRep* r = [[NSBitmapImageRep alloc]
79     initWithBitmapDataPlanes:NULL
80                        pixelsWide:size
81                        pixelsHigh:size
82                     bitsPerSample:8
83                   samplesPerPixel:4
84                          hasAlpha:YES
85                          isPlanar:NO
86                    colorSpaceName:NSDeviceRGBColorSpace
87                      bitmapFormat:0
88                       bytesPerRow:0
89                      bitsPerPixel:0];
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)
99          fromRect:NSZeroRect
100         operation:NSCompositeCopy
101          fraction:1.0];
103   [NSGraphicsContext restoreGraphicsState];
105   return r;
109 int main(int argc, char* argv[]) {
110   int i;
112   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
113   NSApplicationLoad();
115   struct {
116     NSString* paramName;
117     OSType type, mask;
118     int size;
119     NSString* inputName;
120   } inputs[] = {
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 },
126   };
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"];
146   }
148   if (!foundInputParam)
149     usage();
151   // Create output
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]
157       autorelease];
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];
163   }
165   // Write output
166   if ([output writeToFile:outputName])
167     NSLog(@"Wrote output file \"%@\"", outputName);
168   else
169     NSLog(@"Failed to write \"%@\"", outputName);
171   [pool drain];
172   return 0;