fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / src / swfrender.c
blob8d7dcb4b421ce53e78b686bffb98afe95506bdf6
1 #include "../config.h"
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <assert.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include "../lib/rfxswf.h"
8 #include "../lib/png.h"
9 #include "../lib/args.h"
10 #include "../lib/gfxsource.h"
11 #include "../lib/readers/swf.h"
12 #include "../lib/devices/render.h"
13 #include "../lib/devices/rescale.h"
15 static struct options_t options[] = {
16 {"h", "help"},
17 {"o", "output"},
18 {"p", "pages"},
19 {"r", "resolution"},
20 {"l", "legacy"},
21 {"V", "version"},
22 {"X", "width"},
23 {"Y", "height"},
24 {0,0}
27 static int ng = 1;
28 static char*filename = 0;
29 static char*outputname = "output.png";
30 static int quantize = 0;
31 static char*pagerange = 0;
33 static int width = 0;
34 static int height = 0;
35 static int resolution = 0;
37 typedef struct _parameter {
38 const char*name;
39 const char*value;
40 struct _parameter*next;
41 } parameter_t;
43 parameter_t*params = 0;
45 int args_callback_option(char*name,char*val)
47 if(!strcmp(name, "V")) {
48 printf("swfrender - part of %s %s\n", PACKAGE, VERSION);
49 exit(0);
50 } else if(!strcmp(name, "o")) {
51 if(!val) {
52 fprintf(stderr, "use \"-o <filename>\"\n");
53 exit(1);
55 outputname = strdup(val);
56 return 1;
57 } else if(!strcmp(name, "l")) {
58 ng = 0;
59 return 0;
60 } else if(!strcmp(name, "q")) {
61 quantize = 1;
62 return 0;
63 } else if(!strcmp(name, "p")) {
64 pagerange = val;
65 return 1;
66 } else if(!strcmp(name, "r")) {
67 resolution = atoi(val);
68 return 1;
69 } else if(!strcmp(name, "s")) {
70 char*s = strdup(val);
71 char*c = strchr(s, '=');
72 parameter_t*p = malloc(sizeof(parameter_t));
73 p->next = params;
74 params = p;
75 if(c && *c && c[1]) {
76 *c = 0;
77 c++;
78 p->name = s;
79 p->value = c;
80 } else {
81 p->name = s;
82 p->value = "1";
84 return 1;
85 } else if(!strcmp(name, "X")) {
86 width = atoi(val);
87 return 1;
88 } else if(!strcmp(name, "Y")) {
89 height = atoi(val);
90 return 1;
91 } else {
92 printf("Unknown option: -%s\n", name);
93 exit(1);
96 return 0;
98 int args_callback_longoption(char*name,char*val)
100 return args_long2shortoption(options, name, val);
102 void args_callback_usage(char *name)
104 printf("\n");
105 printf("Usage: %s file.swf [-options]\n", name);
106 printf("\n");
107 printf("-h , --help Print short help message and exit\n");
108 printf("-l , --legacy Use old rendering framework\n");
109 printf("-o , --output Output file, suffixed for multiple pages (default: output.png)\n");
110 printf("-p , --pages range Render pages in specified range e.g. 9 or 1-20 or 1,4-6,9-11 (default: all pages)\n");
111 printf("-r , --resolution dpi Scale width and height to a specific DPI resolution, assuming input is 1px per pt (default: 72)\n");
112 printf("-X , --width width Scale output to specific width (proportional unless height specified)\n");
113 printf("-Y , --height height Scale output to specific height (proportional unless width specified)\n");
114 printf("\n");
116 int args_callback_command(char*name,char*val)
118 if(filename) {
119 fprintf(stderr, "Only one file allowed. You supplied at least two. (%s and %s)\n",
120 filename, name);
122 filename = name;
123 return 0;
128 int main(int argn, char*argv[])
130 SWF swf;
131 int fi;
133 processargs(argn, argv);
135 if(!filename) {
136 fprintf(stderr, "You must supply a filename.\n");
137 return 1;
140 if (resolution && (width || height)) {
141 fprintf(stderr, "Height/width cannot be specified with resolution.\n");
142 return 1;
145 if(!ng) {
146 fi = open(filename, O_RDONLY|O_BINARY);
147 if (fi<=0) {
148 fprintf(stderr,"Couldn't open %s\n", filename);
149 perror(filename);
150 exit(1);
152 if(swf_ReadSWF(fi,&swf)<0) {
153 fprintf(stderr,"%s is not a valid SWF file or contains errors.\n",argv[1]);
154 close(fi);
156 assert(swf.movieSize.xmax > swf.movieSize.xmin && swf.movieSize.ymax > swf.movieSize.ymin);
157 RENDERBUF buf;
158 swf_Render_Init(&buf, 0,0, (swf.movieSize.xmax - swf.movieSize.xmin) / 20,
159 (swf.movieSize.ymax - swf.movieSize.ymin) / 20, 2, 1);
160 swf_RenderSWF(&buf, &swf);
161 RGBA* img = swf_Render(&buf);
162 if(quantize)
163 png_write_palette_based_2(outputname, (unsigned char*)img, buf.width, buf.height);
164 else
165 png_write(outputname, (unsigned char*)img, buf.width, buf.height);
166 swf_Render_Delete(&buf);
167 } else {
168 parameter_t*p;
170 gfxsource_t*src = gfxsource_swf_create();
171 for(p=params;p;p=p->next) {
172 src->setparameter(src, p->name, p->value);
174 gfxdocument_t*doc = src->open(src, filename);
175 for(p=params;p;p=p->next) {
176 doc->setparameter(doc, p->name, p->value);
178 if(!doc) {
179 fprintf(stderr,"Couldn't open %s\n", filename);
180 exit(1);
182 int t;
183 int count = 0;
184 char to_output[doc->num_pages];
185 for(t=1;t<=doc->num_pages;t++) {
186 to_output[t-1] = 0;
187 if(is_in_range(t, pagerange)) {
188 to_output[t-1] = 1;
189 count++;
192 if (count == 0) {
193 fprintf(stderr,"No pages selected for output. Available pages are 1..%d\n", doc->num_pages);
194 exit(1);
196 for(t=1;t<=sizeof(to_output);t++) {
197 if (to_output[t-1]) {
198 gfxdevice_t dev2,*dev=&dev2;
199 gfxdevice_render_init(dev);
200 dev->setparameter(dev, "antialise", "4");
201 if(quantize) {
202 dev->setparameter(dev, "palette", "1");
204 if(width || height || resolution) {
205 double scale = 0.0;
206 if (resolution) {
207 /* Assume input is generated by pdf2swf at 72dpi (1px == 1pt) */
208 scale = resolution / 72.0;
210 dev = gfxdevice_rescale_new(dev, width, height, scale);
212 for(p=params;p;p=p->next) {
213 dev->setparameter(dev, p->name, p->value);
216 gfxpage_t* page = doc->getpage(doc, t);
217 dev->startpage(dev, page->width, page->height);
218 page->render(page, dev);
219 dev->endpage(dev);
220 page->destroy(page);
222 gfxresult_t* result = dev->finish(dev);
223 if(result) {
224 char* effective_outputname = outputname;
225 char* suffixed_outputname = malloc(strlen(outputname) + 128);
226 if (count > 1) {
227 effective_outputname = suffixed_outputname;
228 char* ext = strrchr(outputname, '.');
229 if (ext) {
230 strncpy(suffixed_outputname, outputname, (ext - outputname));
231 sprintf(suffixed_outputname + (ext-outputname), "-%d.%s", t, (ext+1));
232 } else {
233 sprintf(suffixed_outputname, "%s-%d", outputname, t);
236 if(result->save(result, effective_outputname) < 0) {
237 fprintf(stderr,"Error writing page %d to %s\n", t, outputname);
238 exit(1);
240 free(suffixed_outputname);
241 result->destroy(result);
245 doc->destroy(doc);
247 return 0;