rfxswf cleanups: added prefixes and altered structure name conventions
[swftools.git] / src / jpeg2swf.c
1 /* jpeg2swf.c
2
3    JPEG to SWF converter tool
4
5    Part of the swftools package.
6
7    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
8  
9    This file is distributed under the GPL, see file COPYING for details 
10
11 */
12
13 #include <stdio.h>
14 #include <math.h>
15 #include <fcntl.h>
16 #include <jpeglib.h>
17 #include "../lib/rfxswf.h"
18 #include "../lib/args.h" // not really a header ;-)
19
20 #define MAX_INPUT_FILES 1024
21 #define VERBOSE(x) (global.verbose>=x)
22
23 struct
24 { int quality;
25   int framerate;
26   int max_image_width;
27   int max_image_height;
28   int force_width;
29   int force_height;
30   int nfiles;
31   int verbose;
32   char * files[MAX_INPUT_FILES];
33   char * outfile;
34 } global;
35
36 TAG * MovieStart(SWF * swf,int framerate,int dx,int dy)
37 { TAG * t;
38   RGBA rgb;
39
40   memset(swf,0x00,sizeof(SWF));
41
42   swf->fileVersion       = 4;
43   swf->frameRate         = (25600/framerate);
44   swf->movieSize.xmax    = dx*20;
45   swf->movieSize.ymax    = dy*20;
46
47   t = swf->firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
48
49   rgb.r = rgb.g = rgb.b = rgb.a  = 0x00;
50   swf_SetRGB(t,&rgb);
51
52   return t;
53 }
54
55 int MovieFinish(SWF * swf,TAG * t,char * sname)
56 {  int handle, so = fileno(stdout);
57    t = swf_InsertTag(t,ST_END);
58
59    if ((!isatty(so))&&(!sname)) handle = so;
60    else
61    { if (!sname) sname = "out.swf";
62      handle = open(sname,O_RDWR|O_CREAT|O_TRUNC,0666);
63    }
64    if FAILED(swf_WriteSWF(handle,swf)) if (VERBOSE(1)) fprintf(stderr,"Unable to write output file: %s\n",sname);
65    if (handle!=so) close(handle);
66    
67    swf_FreeTags(swf);
68    return 0;
69 }
70
71 TAG * MovieAddFrame(SWF * swf,TAG * t,char * sname,int quality,int id)
72 { SHAPE * s;
73   SRECT r;
74   MATRIX m;
75   int fs;
76   
77   struct jpeg_decompress_struct cinfo;
78   struct jpeg_error_mgr jerr;
79   LPJPEGBITS out;
80   FILE * f;
81   U8 * scanline;
82
83   if ((f=fopen(sname,"rb"))==NULL)
84   { if (VERBOSE(1)) fprintf(stderr,"Read access failed: %s\n",sname);
85     return t;
86   }
87   
88   cinfo.err = jpeg_std_error(&jerr);
89   jpeg_create_decompress(&cinfo); 
90   jpeg_stdio_src(&cinfo,f);
91   jpeg_read_header(&cinfo, TRUE);
92   jpeg_start_decompress(&cinfo);
93
94   t = swf_InsertTag(t,ST_DEFINEBITSJPEG2);
95
96         swf_SetU16(t,id);  // id
97   
98         out = swf_SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
99         scanline = (U8*)malloc(4*cinfo.output_width);
100   
101         if (scanline)
102         { int y;
103           U8 * js = scanline;
104           for (y=0;y<cinfo.output_height;y++)
105           { jpeg_read_scanlines(&cinfo,&js,1);
106             swf_SetJPEGBitsLines(out,(U8**)&js,1);
107           }
108           free(scanline);
109         }
110         
111         swf_SetJPEGBitsFinish(out);
112     
113   t = swf_InsertTag(t,ST_DEFINESHAPE);
114
115         swf_ShapeNew(&s);
116         swf_GetMatrix(NULL,&m);
117         m.sx = 20*0x10000;
118         m.sy = 20*0x10000;
119         fs = swf_ShapeAddBitmapFillStyle(s,&m,id,0);
120         
121         swf_SetU16(t,id+1); // id
122
123
124         r.xmin = r.ymin = 0;
125         r.xmax = cinfo.output_width*20;
126         r.ymax = cinfo.output_height*20;
127         swf_SetRect(t,&r);
128         
129         swf_SetShapeHeader(t,s);
130
131         swf_ShapeSetAll(t,s,0,0,0,fs,0);
132         swf_ShapeSetLine(t,s,r.xmax,0);
133         swf_ShapeSetLine(t,s,0,r.ymax);
134         swf_ShapeSetLine(t,s,-r.xmax,0);
135         swf_ShapeSetLine(t,s,0,-r.ymax);
136         
137         swf_ShapeSetEnd(t);
138         
139   t = swf_InsertTag(t,ST_REMOVEOBJECT2);
140         swf_SetU16(t,1); // depth
141
142   t = swf_InsertTag(t,ST_PLACEOBJECT2);
143
144         swf_GetMatrix(NULL,&m);
145         m.tx = (swf->movieSize.xmax-(int)cinfo.output_width*20)/2;
146         m.ty = (swf->movieSize.ymax-(int)cinfo.output_height*20)/2;
147         swf_ObjectPlace(t,id+1,1,&m,NULL,NULL);
148
149   t = swf_InsertTag(t,ST_SHOWFRAME);
150
151   jpeg_finish_decompress(&cinfo);
152   fclose(f);
153
154   return t;
155 }
156
157 int CheckInputFile(char * fname,char ** realname)
158 { struct jpeg_decompress_struct cinfo;
159   struct jpeg_error_mgr jerr;
160   FILE * f;
161   char * s = malloc(strlen(fname)+5);
162   
163   if (!s) exit(2);
164   (*realname) = s;
165   strcpy(s,fname);
166
167   // Check whether file exists (with typical extensions)
168
169   if ((f=fopen(s,"rb"))==NULL)
170   { sprintf(s,"%s.jpg",fname);
171     if ((f=fopen(s,"rb"))==NULL)
172     { sprintf(s,"%s.jpeg",fname);
173       if ((f=fopen(s,"rb"))==NULL)
174       { sprintf(s,"%s.JPG",fname);
175         if ((f=fopen(s,"rb"))==NULL)
176         { sprintf(s,"%s.JPEG",fname);
177           if ((f=fopen(s,"rb"))==NULL)
178             return -1;
179         }
180       }
181     }
182   }
183   
184   cinfo.err = jpeg_std_error(&jerr);
185   jpeg_create_decompress(&cinfo); 
186   jpeg_stdio_src(&cinfo,f);
187   jpeg_read_header(&cinfo, TRUE);
188
189   // Get image dimensions
190
191   if (global.max_image_width<cinfo.image_width) global.max_image_width = cinfo.image_width;
192   if (global.max_image_height<cinfo.image_height) global.max_image_height = cinfo.image_height;
193   
194   jpeg_destroy_decompress(&cinfo);
195   fclose(f);
196
197   return 0;
198 }
199
200 int args_callback_option(char*arg,char*val)
201 { int res = 0;
202   if (arg[1]) res = -1;
203   else switch (arg[0])
204   { case 'q':
205       if (val) global.quality = atoi(val);
206       if ((global.quality<1)||(global.quality>100))
207       { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid quality between 1 and 100.\n");
208         exit(1);
209       }
210       res = 1;
211       break;
212
213     case 'r':
214       if (val) global.framerate = atoi(val);
215       if ((global.framerate<1)||(global.framerate>5000))
216       { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid framerate between 1 and 10000.\n");
217         exit(1);
218       }
219       res = 1;
220       break;
221
222     case 'o':
223       if (val) global.outfile = val; res = 1; break;
224
225     case 'v':
226       if (val) global.verbose = atoi(val); res = 1; break;
227
228     case 'X':
229       if (val) global.force_width = atoi(val); res = 1; break;
230
231     case 'Y':
232       if (val) global.force_height = atoi(val); res = 1; break;
233
234     case 'V':
235       printf("jpeg2swf - part of %s %s\n", PACKAGE, VERSION);exit(0);
236       
237     default:
238       res = -1;
239       break;
240   }
241   
242   if (res<0)
243   { if (VERBOSE(1)) fprintf(stderr,"Unknown option: -v%s\n",arg);
244     return 0;
245   }
246   return res;
247 }
248
249 struct options_t options[] =
250 {{"q","quality"},
251  {"o","output"},
252  {"r","rate"},
253  {"v","verbose"},
254  {"X","width"},
255  {"Y","height"},
256  {"V","version"}
257 };
258
259 int args_callback_longoption(char*name,char*val) {
260     return args_long2shortoption(options, name, val);
261 }
262
263 int args_callback_command(char*arg,char*next)  // actually used as filename
264 { char * s;
265   if (CheckInputFile(arg,&s)<0)
266   { if (VERBOSE(1)) fprintf(stderr, "Unable to open input file: %s\n",arg);
267     free(s);
268   }
269   else
270   { global.files[global.nfiles] = s;
271     global.nfiles++;
272     if (global.nfiles>=MAX_INPUT_FILES)
273     { if (VERBOSE(1)) fprintf(stderr, "Error: Too many input files.\n");
274       exit(1);
275     }
276   }
277   return 0;
278 }
279
280 void args_callback_usage(char*name)
281 { fprintf(stderr,"Usage: %s imagefiles[.jpg]|[.jpeg] [...] [-options [value]]\n",name);
282   fprintf(stderr,"-q quality            (quality) Set JPEG compression quality (1-100)\n");
283   fprintf(stderr,"-r framerate          (rate) Set movie framerate (100/sec)\n");
284   fprintf(stderr,"-o outputfile         (output) Set name for SWF output file\n");
285   fprintf(stderr,"-v level              (verbose) Set verbose level (0=quiet, 1=default, 2=debug)\n");
286   fprintf(stderr,"-X pixel              (width) Force movie width to scale (default: autodetect)\n");
287   fprintf(stderr,"-Y pixel              (height) Force movie height to scale (default: autodetect)\n");
288   fprintf(stderr,"-V                    (version) Print version information and exit\n");
289 }
290
291
292 int main(int argc, char ** argv)
293 { SWF swf;
294   TAG * t;
295
296   memset(&global,0x00,sizeof(global));
297     
298   global.quality                = 60;
299   global.framerate              = 100;
300   global.verbose                = 1;
301   
302   processargs(argc, argv);
303
304   if (VERBOSE(2)) fprintf(stderr,"Processing %i file(s)...\n",global.nfiles);
305
306   t = MovieStart(&swf,global.framerate,
307                       global.force_width?global.force_width:global.max_image_width,
308                       global.force_height?global.force_height:global.max_image_height);
309
310   { int i;
311     for (i=0;i<global.nfiles;i++)
312     { if (VERBOSE(3)) fprintf(stderr,"[%03i] %s\n",i,global.files[i]);
313       t = MovieAddFrame(&swf,t,global.files[i],global.quality,(i*2)+1);
314       free(global.files[i]);
315     }
316   }
317
318   MovieFinish(&swf,t,global.outfile);
319
320   return 0;
321 }
322
323
324 // Old main routine
325
326 /*
327 int ConvertJPEG2SWF(char * sname,char * dname,int quality)
328 { RGBA rgb;
329   SWF swf;
330   TAG * t;
331   
332   SHAPE * s;
333   SRECT r;
334   MATRIX m;
335   int fs;
336   
337   struct jpeg_decompress_struct cinfo;
338   struct jpeg_error_mgr jerr;
339   LPJPEGBITS out;
340   FILE * f;
341   U8 * scanline;
342
343   int handle;
344
345   cinfo.err = jpeg_std_error(&jerr);
346   jpeg_create_decompress(&cinfo); 
347
348   if ((f=fopen(sname,"rb"))==NULL)
349   { fprintf(stderr,"Read access failed: %s\n",sname);
350     return -1;
351   }
352   
353   jpeg_stdio_src(&cinfo,f);
354   jpeg_read_header(&cinfo, TRUE);
355   jpeg_start_decompress(&cinfo);
356   
357   memset(&swf,0x00,sizeof(SWF));
358
359   swf.FileVersion       = 4;
360   swf.FrameRate         = 0x1000;
361   swf.MovieSize.xmax    = cinfo.output_width*20;
362   swf.MovieSize.ymax    = cinfo.output_height*20;
363
364   printf("dx = %i, dy = %i\n",cinfo.output_width,cinfo.output_height);
365
366   t = swf.FirstTag = InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
367
368         rgb.r = rgb.g = rgb.b = rgb.a  = 0x00;
369         SetRGB(t,&rgb);
370
371   t = InsertTag(t,ST_DEFINEBITSJPEG2);
372
373         SetU16(t,1);  // id
374   
375         out = SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
376         scanline = (U8*)malloc(4*cinfo.output_width);
377   
378         if (scanline)
379         { int y;
380           U8 * js = scanline;
381           for (y=0;y<cinfo.output_height;y++)
382           { jpeg_read_scanlines(&cinfo,&js,1);
383             SetJPEGBitsLines(out,(U8**)&js,1);
384           }
385           free(scanline);
386         }
387         
388         SetJPEGBitsFinish(out);
389
390         printf("JPEG Tag-Length: %06x\n",GetDataSize(t));
391
392   t = InsertTag(t,ST_DEFINESHAPE);
393
394         NewShape(&s);
395         GetMatrix(NULL,&m);
396         m.sx = 20*0x10000;
397         m.sy = 20*0x10000;
398         rgb.r = 0xff;
399         fs = ShapeAddBitmapFillStyle(s,&m,1,0);
400 //        fs = ShapeAddSolidFillStyle(s,&rgb);
401         
402         SetU16(t,2); // id
403         SetRect(t,&swf.MovieSize);
404         SetShapeHeader(t,s);
405
406         ShapeSetAll(t,s,0,0,0,fs,0);
407         ShapeSetLine(t,s,swf.MovieSize.xmax,0);
408         ShapeSetLine(t,s,0,swf.MovieSize.ymax);
409         ShapeSetLine(t,s,-swf.MovieSize.xmax,0);
410         ShapeSetLine(t,s,0,-swf.MovieSize.ymax);
411         
412         ShapeSetEnd(t);
413
414   t = InsertTag(t,ST_PLACEOBJECT2);
415
416         ObjectPlace(t,2,1,NULL,NULL,NULL);
417
418   t = InsertTag(t,ST_SHOWFRAME);
419   
420   t = InsertTag(t,ST_END);
421
422   jpeg_finish_decompress(&cinfo);
423   fclose(f);
424   
425   handle = open(dname,O_RDWR|O_CREAT|O_TRUNC,0666);
426   if FAILED(WriteSWF(handle,&swf)) fprintf(stderr,"WriteSWF() failed.\n");
427   close(handle);
428
429   return 0;
430 }
431 */
432