3 JPEG to SWF converter tool
5 Part of the swftools package.
7 Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
9 This file is distributed under the GPL, see file COPYING for details
17 #include "../lib/rfxswf.h"
18 #include "../lib/args.h" // not really a header ;-)
20 #define MAX_INPUT_FILES 1024
21 #define VERBOSE(x) (global.verbose>=x)
40 } image[MAX_INPUT_FILES];
42 TAG * MovieStart(SWF * swf,int framerate,int dx,int dy)
46 memset(swf,0x00,sizeof(SWF));
49 swf->frameRate = (25600/framerate);
50 swf->movieSize.xmax = dx*20;
51 swf->movieSize.ymax = dy*20;
53 t = swf->firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
55 rgb.r = rgb.g = rgb.b = rgb.a = 0x00;
61 int MovieFinish(SWF * swf,TAG * t,char * sname)
62 { int handle, so = fileno(stdout);
63 t = swf_InsertTag(t,ST_END);
65 if ((!isatty(so))&&(!sname)) handle = so;
67 { if (!sname) sname = "output.swf";
68 handle = open(sname,O_BINARY|O_RDWR|O_CREAT|O_TRUNC,0666);
70 if FAILED(swf_WriteSWF(handle,swf)) if (VERBOSE(1)) fprintf(stderr,"Unable to write output file: %s\n",sname);
71 if (handle!=so) close(handle);
77 TAG * MovieAddFrame(SWF * swf,TAG * t,char * sname,int quality,int scale,int id)
83 struct jpeg_decompress_struct cinfo;
84 struct jpeg_error_mgr jerr;
89 if ((f=fopen(sname,"rb"))==NULL)
90 { if (VERBOSE(1)) fprintf(stderr,"Read access failed: %s\n",sname);
94 cinfo.err = jpeg_std_error(&jerr);
95 jpeg_create_decompress(&cinfo);
96 jpeg_stdio_src(&cinfo,f);
97 jpeg_read_header(&cinfo, TRUE);
100 { cinfo.scale_num = 1;
101 cinfo.scale_denom = scale;
104 jpeg_start_decompress(&cinfo);
106 t = swf_InsertTag(t,ST_DEFINEBITSJPEG2);
108 swf_SetU16(t,id); // id
110 out = swf_SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
111 scanline = (U8*)malloc(4*cinfo.output_width);
113 // the following code is a duplication of swf_SetJPEGBits in ../lib/modules/swfbits.c
118 if(cinfo.out_color_space == JCS_GRAYSCALE)
120 for (y=0;y<cinfo.output_height;y++)
122 jpeg_read_scanlines(&cinfo,&js,1);
123 for(x=cinfo.output_width-1;x>=0;x--) {
124 js[x*3] = js[x*3+1] = js[x*3+2] = js[x];
126 swf_SetJPEGBitsLines(out,(U8**)&js,1);
129 else if(cinfo.out_color_space == JCS_RGB)
131 for (y=0;y<cinfo.output_height;y++)
132 { jpeg_read_scanlines(&cinfo,&js,1);
133 swf_SetJPEGBitsLines(out,(U8**)&js,1);
139 swf_SetJPEGBitsFinish(out);
141 t = swf_InsertTag(t,ST_DEFINESHAPE);
144 swf_GetMatrix(NULL,&m);
147 fs = swf_ShapeAddBitmapFillStyle(s,&m,id,0);
149 swf_SetU16(t,id+1); // id
153 r.xmax = cinfo.output_width*20;
154 r.ymax = cinfo.output_height*20;
157 swf_SetShapeHeader(t,s);
159 swf_ShapeSetAll(t,s,0,0,0,fs,0);
160 swf_ShapeSetLine(t,s,r.xmax,0);
161 swf_ShapeSetLine(t,s,0,r.ymax);
162 swf_ShapeSetLine(t,s,-r.xmax,0);
163 swf_ShapeSetLine(t,s,0,-r.ymax);
167 t = swf_InsertTag(t,ST_REMOVEOBJECT2);
168 swf_SetU16(t,1); // depth
170 t = swf_InsertTag(t,ST_PLACEOBJECT2);
172 swf_GetMatrix(NULL,&m);
173 m.tx = (swf->movieSize.xmax-(int)cinfo.output_width*20)/2;
174 m.ty = (swf->movieSize.ymax-(int)cinfo.output_height*20)/2;
175 swf_ObjectPlace(t,id+1,1,&m,NULL,NULL);
177 t = swf_InsertTag(t,ST_SHOWFRAME);
179 jpeg_finish_decompress(&cinfo);
185 int CheckInputFile(char * fname,char ** realname)
186 { struct jpeg_decompress_struct cinfo;
187 struct jpeg_error_mgr jerr;
189 char * s = malloc(strlen(fname)+5);
196 // Check whether file exists (with typical extensions)
198 if ((f=fopen(s,"rb"))==NULL)
199 { sprintf(s,"%s.jpg",fname);
200 if ((f=fopen(s,"rb"))==NULL)
201 { sprintf(s,"%s.jpeg",fname);
202 if ((f=fopen(s,"rb"))==NULL)
203 { sprintf(s,"%s.JPG",fname);
204 if ((f=fopen(s,"rb"))==NULL)
205 { sprintf(s,"%s.JPEG",fname);
206 if ((f=fopen(s,"rb"))==NULL)
213 cinfo.err = jpeg_std_error(&jerr);
214 jpeg_create_decompress(&cinfo);
215 jpeg_stdio_src(&cinfo,f);
216 jpeg_read_header(&cinfo, TRUE);
218 // Apply scaling (scale option can be used several times to set different scales)
220 if (global.prescale>1)
221 { cinfo.scale_num = 1;
222 cinfo.scale_denom = global.prescale;
224 jpeg_calc_output_dimensions(&cinfo);
226 width = cinfo.output_width;
227 height = cinfo.output_height;
230 { width = cinfo.image_width;
231 height = cinfo.image_height;
234 // Get image dimensions
236 if (global.max_image_width<width) global.max_image_width = width;
237 if (global.max_image_height<height) global.max_image_height = height;
239 jpeg_destroy_decompress(&cinfo);
245 int args_callback_option(char*arg,char*val)
247 if (arg[1]) res = -1;
250 if (val) global.quality = atoi(val);
251 if ((global.quality<1)||(global.quality>100))
252 { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid quality between 1 and 100.\n");
259 if (val) global.framerate = atoi(val);
260 if ((global.framerate<1)||(global.framerate>5000))
261 { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid framerate between 1 and 10000.\n");
268 if (val) global.prescale = atoi(val);
269 if (!((global.prescale==1)||(global.prescale==2)||(global.prescale==4)||(global.prescale==8)))
270 { if (VERBOSE(1)) fprintf(stderr,"Error: Prescale denominator is limited to 2, 4 or 8\n");
277 if (val) global.outfile = val; res = 1; break;
280 if (val) global.verbose = atoi(val); res = 1; break;
283 if (val) global.force_width = atoi(val); res = 1; break;
286 if (val) global.force_height = atoi(val); res = 1; break;
289 printf("jpeg2swf - part of %s %s\n", PACKAGE, VERSION);exit(0);
297 { if (VERBOSE(1)) fprintf(stderr,"Unknown option: -%s\n",arg);
304 struct options_t options[] =
315 int args_callback_longoption(char*name,char*val) {
316 return args_long2shortoption(options, name, val);
319 int args_callback_command(char*arg,char*next) // actually used as filename
322 if (CheckInputFile(arg,&s)<0)
323 { if (VERBOSE(1)) fprintf(stderr, "Unable to open input file: %s\n",arg);
327 { image[global.nfiles].filename = s;
328 image[global.nfiles].scale = global.prescale;
329 image[global.nfiles].quality = global.quality;
331 if (global.nfiles>=MAX_INPUT_FILES)
332 { if (VERBOSE(1)) fprintf(stderr, "Error: Too many input files.\n");
339 void args_callback_usage(char*name)
340 { fprintf(stderr,"Usage: %s [-options [value]] imagefiles[.jpg]|[.jpeg] [...]\n",name);
341 fprintf(stderr,"-q quality (quality) Set JPEG compression quality (1-100)\n");
342 fprintf(stderr,"-s denominator (scale) 2, 4 or 8: Reduce image size to 1/2, 1/4, 1/8\n");
343 fprintf(stderr,"-r framerate (rate) Set movie framerate (100/sec)\n");
344 fprintf(stderr,"-o outputfile (output) Set name for SWF output file\n");
345 fprintf(stderr,"-X pixel (width) Force movie width to scale (default: autodetect)\n");
346 fprintf(stderr,"-Y pixel (height) Force movie height to scale (default: autodetect)\n");
347 fprintf(stderr,"-v level (verbose) Set verbose level (0=quiet, 1=default, 2=debug)\n");
348 fprintf(stderr,"-V (version) Print version information and exit\n");
349 fprintf(stderr,"The following options can be set independently for each image: -q -s\n");
353 int main(int argc, char ** argv)
357 memset(&global,0x00,sizeof(global));
360 global.framerate = 100;
364 processargs(argc, argv);
366 if (VERBOSE(2)) fprintf(stderr,"Processing %i file(s)...\n",global.nfiles);
368 t = MovieStart(&swf,global.framerate,
369 global.force_width?global.force_width:global.max_image_width,
370 global.force_height?global.force_height:global.max_image_height);
373 for (i=0;i<global.nfiles;i++)
374 { if (VERBOSE(3)) fprintf(stderr,"[%03i] %s (%i%%, 1/%i)\n",i,image[i].filename,image[i].quality,image[i].scale);
375 t = MovieAddFrame(&swf,t,image[i].filename,
377 image[i].scale,(i*2)+1);
378 free(image[i].filename);
382 MovieFinish(&swf,t,global.outfile);
391 int ConvertJPEG2SWF(char * sname,char * dname,int quality)
401 struct jpeg_decompress_struct cinfo;
402 struct jpeg_error_mgr jerr;
409 cinfo.err = jpeg_std_error(&jerr);
410 jpeg_create_decompress(&cinfo);
412 if ((f=fopen(sname,"rb"))==NULL)
413 { fprintf(stderr,"Read access failed: %s\n",sname);
417 jpeg_stdio_src(&cinfo,f);
418 jpeg_read_header(&cinfo, TRUE);
419 jpeg_start_decompress(&cinfo);
421 memset(&swf,0x00,sizeof(SWF));
424 swf.FrameRate = 0x1000;
425 swf.MovieSize.xmax = cinfo.output_width*20;
426 swf.MovieSize.ymax = cinfo.output_height*20;
428 printf("dx = %i, dy = %i\n",cinfo.output_width,cinfo.output_height);
430 t = swf.FirstTag = InsertTag(NULL,ST_SETBACKGROUNDCOLOR);
432 rgb.r = rgb.g = rgb.b = rgb.a = 0x00;
435 t = InsertTag(t,ST_DEFINEBITSJPEG2);
439 out = SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality);
440 scanline = (U8*)malloc(4*cinfo.output_width);
445 for (y=0;y<cinfo.output_height;y++)
446 { jpeg_read_scanlines(&cinfo,&js,1);
447 SetJPEGBitsLines(out,(U8**)&js,1);
452 SetJPEGBitsFinish(out);
454 printf("JPEG Tag-Length: %06x\n",GetDataSize(t));
456 t = InsertTag(t,ST_DEFINESHAPE);
463 fs = ShapeAddBitmapFillStyle(s,&m,1,0);
464 // fs = ShapeAddSolidFillStyle(s,&rgb);
467 SetRect(t,&swf.MovieSize);
470 ShapeSetAll(t,s,0,0,0,fs,0);
471 ShapeSetLine(t,s,swf.MovieSize.xmax,0);
472 ShapeSetLine(t,s,0,swf.MovieSize.ymax);
473 ShapeSetLine(t,s,-swf.MovieSize.xmax,0);
474 ShapeSetLine(t,s,0,-swf.MovieSize.ymax);
478 t = InsertTag(t,ST_PLACEOBJECT2);
480 ObjectPlace(t,2,1,NULL,NULL,NULL);
482 t = InsertTag(t,ST_SHOWFRAME);
484 t = InsertTag(t,ST_END);
486 jpeg_finish_decompress(&cinfo);
489 handle = open(dname,O_BINARY|O_RDWR|O_CREAT|O_TRUNC,0666);
490 if FAILED(WriteSWF(handle,&swf)) fprintf(stderr,"WriteSWF() failed.\n");