I wanted to convert a directory of Windows bitmaps to PNG images today. I must be missing something in Graphic Converter. (I can get to the batch window, but how do I make it convert?) After a few minutes, I decided just to write something for the command line. Apple's image source/destination abstractions make it easy. My program is less than forty lines:
/* Compile with:
gcc -o imageToPNG imageToPNG.m -framework Foundation -framework Carbon
*/
#import <Foundation/Foundation.h>
#import <stdio.h>
int main( int argc, char *argv[] ) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
int i;
for (i = 1; i < argc; i++) {
NSString *spath = [NSString stringWithUTF8String: argv[i]];
CGImageSourceRef sref = CGImageSourceCreateWithURL( (CFURLRef) [NSURL fileURLWithPath: spath], NULL );
if (sref == NULL) {
fprintf( stderr, "Could not create image source for file %s\n", argv[i] );
continue;
}
NSString *dpath = [[[spath stringByExpandingTildeInPath]
stringByDeletingPathExtension]
stringByAppendingPathExtension: @"png"];
CGImageDestinationRef dref = CGImageDestinationCreateWithURL(
(CFURLRef)[NSURL fileURLWithPath: dpath],
(CFStringRef) @"public.png",
1, NULL );
if (dref == NULL) {
fprintf( stderr, "Could not create image destination for file %s\n", argv[i] );
} else {
CGImageDestinationAddImageFromSource( dref, sref, 0, NULL );
if (!CGImageDestinationFinalize(dref)) {
fprintf( stderr, "Error converting %s to %s\n", argv[i], [dpath UTF8String] );
}
CFRelease(dref);
}
CFRelease(sref);
}
[pool release];
return 0;
}
The Cocoa equivalent of the above program is:
/* Compile with:
gcc -o imageToPNG2 imageToPNG2.m -framework AppKit
*/
#import <Cocoa/Cocoa.h>
int main( int argc, char *argv[] ) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSApplicationLoad(); // initializes state before calling AppKit functions from non-AppKit code
int i;
for (i = 1; i < argc; i++) {
NSString *spath = [[NSString stringWithUTF8String: argv[i]] stringByExpandingTildeInPath];
NSImage *image = [[NSImage alloc] initByReferencingFile: spath];
NSSize size = [image size];
[image lockFocus];
NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:
NSMakeRect(0,0,size.width,size.height)];
[image unlockFocus];
NSData *data = [rep representationUsingType: NSPNGFileType properties: nil];
NSString *dpath = [[spath stringByDeletingPathExtension] stringByAppendingPathExtension: @"png"];
[data writeToFile: dpath atomically: NO];
[rep release];
[image release];
printf( "Completed %s -> %s\n", argv[i], [dpath UTF8String]);
}
[pool release];
return 0;
}
You can use the program above to convert handwritten Postscript to a PNG file.
If you feed it a document with a bounding box, the -[initWithFocusedViewRect:] method will use that box as the pixel dimensions of the output. Save the following text as an EPS file, and imageToPNG2 will convert it to a 250x400 PNG:
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 250 400
/Optima findfont 18 scalefont setfont
0 1 0 setrgbcolor
50 350 [ (Hello) (world) (from) (Houston,) (Texas!) ]
{ % stack: x y string
3 copy pop moveto show
% stack: x y
20 sub exch 12 add exch
% stack: x+12 y-20
} forall
pop pop
If I do not specify a bounding box, my system defaults to 692x792 pixels, the point size of an 8.5 inch x 11 inch sheet of paper. I wonder if it defaults to A4 in Europe? Also, be careful of your backgrounds. PostScript assumes the background is white while most bitmap viewers display their contents over a black background. If it matters, explicitly fill your viewable rectangle with your desired background before doing any other output.