From http://www.jwz.org/xscreensaver/xscreensaver-5.18.tar.gz
[xscreensaver] / driver / pdf2jpeg.m
1 /* pdf2jpeg -- converts a PDF file to a JPEG file, using Cocoa
2  *
3  * Copyright (c) 2003, 2008 by Jamie Zawinski <jwz@jwz.org>
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and its
6  * documentation for any purpose is hereby granted without fee, provided that
7  * the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation.  No representations are made about the suitability of this
10  * software for any purpose.  It is provided "as is" without express or 
11  * implied warranty.
12  *
13  * Inspired by clues provided by Jan Kujawa and Jonathan Hendry.
14  */
15
16 #import <Cocoa/Cocoa.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19
20 int
21 main (int argc, char** argv)
22 {
23   const char *progname = argv[0];
24   const char *infile = 0, *outfile = 0;
25   double compression = 0.85;
26   double scale = 1.0;
27   int verbose = 0;
28   int i;
29
30   for (i = 1; i < argc; i++)
31     {
32       char c;
33       if (argv[i][0] == '-' && argv[i][1] == '-')
34         argv[i]++;
35       if (!strcmp (argv[i], "-q") ||
36           !strcmp (argv[i], "-qual") ||
37           !strcmp (argv[i], "-quality"))
38         {
39           int q;
40           if (1 != sscanf (argv[++i], " %d %c", &q, &c) ||
41               q < 5 || q > 100)
42             {
43               fprintf (stderr, "%s: quality must be 5 - 100 (%d)\n",
44                        progname, q);
45               goto USAGE;
46             }
47           compression = q / 100.0;
48         }
49       else if (!strcmp (argv[i], "-scale"))
50         {
51           float s;
52           if (1 != sscanf (argv[++i], " %f %c", &s, &c) ||
53               s <= 0 || s > 50)
54             {
55               fprintf (stderr, "%s: scale must be 0.0 - 50.0 (%f)\n",
56                        progname, s);
57               goto USAGE;
58             }
59           scale = s;
60         }
61       else if (!strcmp (argv[i], "-verbose"))
62         verbose++;
63       else if (!strcmp (argv[i], "-v") ||
64                !strcmp (argv[i], "-vv") ||
65                !strcmp (argv[i], "-vvv"))
66         verbose += strlen(argv[i])-1;
67       else if (argv[i][0] == '-')
68         {
69           fprintf (stderr, "%s: unknown option %s\n", progname, argv[i]);
70           goto USAGE;
71         }
72       else if (!infile)
73         infile  = argv[i];
74       else if (!outfile)
75         outfile = argv[i];
76       else
77         {
78         USAGE:
79           fprintf (stderr,
80                    "usage: %s [-verbose] [-scale N] [-quality NN] "
81                    "infile.pdf outfile.jpg\n",
82                    progname);
83           exit (1);
84         }
85     }
86
87   if (!infile || !outfile)
88     goto USAGE;
89
90
91   // Much of Cocoa needs one of these to be available.
92   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
93
94   //Need an NSApp instance to make [NSImage TIFFRepresentation] work
95   NSApp = [NSApplication sharedApplication];
96   [NSApp autorelease];
97
98   if (verbose)
99     fprintf (stderr, "%s: reading %s...\n", progname, infile);
100
101   // Load the PDF file into an NSData object:
102   NSData *pdf_data = [NSData dataWithContentsOfFile:
103                                [NSString stringWithCString:infile
104                                          encoding:NSUTF8StringEncoding]];
105
106   // Create an NSPDFImageRep from the data:
107   NSPDFImageRep *pdf_rep = [NSPDFImageRep imageRepWithData:pdf_data];
108
109   // Create an NSImage instance
110   NSRect rect;
111   rect.size = [pdf_rep size];
112   rect.size.width  *= scale;
113   rect.size.height *= scale;
114   rect.origin.x = rect.origin.y = 0;
115   NSImage *image = [[NSImage alloc] initWithSize:rect.size];
116
117   // Draw the PDFImageRep in the NSImage
118   [image lockFocus];
119   [pdf_rep drawInRect:rect];
120   [image unlockFocus];
121
122   // Load the NSImage's contents into an NSBitmapImageRep:
123   NSBitmapImageRep *bit_rep = [NSBitmapImageRep
124                                 imageRepWithData:[image TIFFRepresentation]];
125
126   // Write the bitmapImageRep to a JPEG file:
127   if (bit_rep == nil)
128     {
129       fprintf (stderr, "%s: error converting image?\n", argv[0]);
130       exit (1);
131     }
132
133   if (verbose)
134     fprintf (stderr, "%s: writing %s (%d%% quality)...\n",
135              progname, outfile, (int) (compression * 100));
136
137   NSDictionary *props = [NSDictionary
138                           dictionaryWithObject:
139                             [NSNumber numberWithFloat:compression]
140                           forKey:NSImageCompressionFactor];
141   NSData *jpeg_data = [bit_rep representationUsingType:NSJPEGFileType
142                                properties:props];
143
144   [jpeg_data writeToFile:
145                [NSString stringWithCString:outfile
146                          encoding:NSUTF8StringEncoding]
147              atomically:YES];
148   [image release];
149
150   [pool release];
151   exit (0);
152 }