Automatically generate document icons
[MacVim.git] / src / MacVim / icons / makeicns / makeicns.m
blob7b63527ef756e50544fd4b2e5046a0b49a07060d
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   NSEnumerator* e = [[img representations] objectEnumerator];
58   NSImageRep* ir;
59   while ((ir = [e nextObject])) {
60     if (![ir isKindOfClass:[NSBitmapImageRep class]]) continue;
62     NSBitmapImageRep* br = (NSBitmapImageRep*)ir;
63     //NSLog(@"%@", br);
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)
68        )
69       return br;
70   }
72   NSLog(@"Resampling for size %d", size);
73   NSBitmapImageRep* r = [[NSBitmapImageRep alloc]
74     initWithBitmapDataPlanes:NULL
75                        pixelsWide:size
76                        pixelsHigh:size
77                     bitsPerSample:8
78                   samplesPerPixel:4
79                          hasAlpha:YES
80                          isPlanar:NO
81                    colorSpaceName:NSDeviceRGBColorSpace
82                      bitmapFormat:0
83                       bytesPerRow:0
84                      bitsPerPixel:0];
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)
94          fromRect:NSZeroRect
95         operation:NSCompositeCopy
96          fraction:1.0];
98   [NSGraphicsContext restoreGraphicsState];
100   return r;
104 int main(int argc, char* argv[]) {
105   int i;
107   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
108   NSApplicationLoad();
110   struct {
111     NSString* paramName;
112     OSType type, mask;
113     int size;
114     NSString* inputName;
115   } inputs[] = {
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 },
121   };
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"];
141   }
143   if (!foundInputParam)
144     usage();
146   // Create output
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]
152       autorelease];
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];
158   }
160   // Write output
161   if ([output writeToFile:outputName])
162     NSLog(@"Wrote output file \"%@\"", outputName);
163   else
164     NSLog(@"Failed to write \"%@\"", outputName);
166   [pool drain];
167   return 0;