From 4a57b21eacb62c8e674b5aac169706e36968b7bc Mon Sep 17 00:00:00 2001 From: kramm Date: Sat, 2 Aug 2003 12:23:40 +0000 Subject: [PATCH] * added h.263 support * removed scaling option * changed indent to -kr * merged code with ../lib/modules/swfbits.c --- src/jpeg2swf.c | 861 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 427 insertions(+), 434 deletions(-) diff --git a/src/jpeg2swf.c b/src/jpeg2swf.c index 397721d..7ce2899 100644 --- a/src/jpeg2swf.c +++ b/src/jpeg2swf.c @@ -5,6 +5,7 @@ Part of the swftools package. Copyright (c) 2001 Rainer Böhme + Copyright (c) 2002,2003 Matthias Kramm This file is distributed under the GPL, see file COPYING for details @@ -15,482 +16,474 @@ #include #include #include "../lib/rfxswf.h" -#include "../lib/args.h" // not really a header ;-) +#include "../lib/args.h" // not really a header ;-) #define MAX_INPUT_FILES 1024 #define VERBOSE(x) (global.verbose>=x) -struct -{ int quality; - int framerate; - int max_image_width; - int max_image_height; - int force_width; - int force_height; - int prescale; - int nfiles; - int verbose; - char * outfile; +struct { + int quality; + int framerate; + int max_image_width; + int max_image_height; + int force_width; + int force_height; + int nfiles; + int verbose; + char *outfile; + int mx; } global; -struct -{ char * filename; - int scale; - int quality; -} image[MAX_INPUT_FILES]; +typedef struct _image { + char *filename; + int quality; + int width; + int height; +} image_t; +image_t image[MAX_INPUT_FILES]; -TAG * MovieStart(SWF * swf,int framerate,int dx,int dy) -{ TAG * t; - RGBA rgb; +VIDEOSTREAM stream; - memset(swf,0x00,sizeof(SWF)); +TAG *MovieStart(SWF * swf, int framerate, int dx, int dy) +{ + TAG *t; + RGBA rgb; - swf->fileVersion = 4; - swf->frameRate = (25600/framerate); - swf->movieSize.xmax = dx*20; - swf->movieSize.ymax = dy*20; + memset(swf, 0x00, sizeof(SWF)); - t = swf->firstTag = swf_InsertTag(NULL,ST_SETBACKGROUNDCOLOR); + swf->fileVersion = 4; + swf->frameRate = (25600 / framerate); + swf->movieSize.xmax = dx * 20; + swf->movieSize.ymax = dy * 20; - rgb.r = rgb.g = rgb.b = rgb.a = 0x00; - swf_SetRGB(t,&rgb); + t = swf->firstTag = swf_InsertTag(NULL, ST_SETBACKGROUNDCOLOR); - return t; + rgb.r = rgb.g = rgb.b = rgb.a = 0x00; + swf_SetRGB(t, &rgb); + + if (global.mx) { + t = swf_InsertTag(t, ST_DEFINEVIDEOSTREAM); + swf_SetU16(t, 0xf00d); + swf_SetVideoStreamDefine(t, &stream, 65535, dx, dy); + } + + return t; } -int MovieFinish(SWF * swf,TAG * t,char * sname) -{ int handle, so = fileno(stdout); - t = swf_InsertTag(t,ST_END); - - if ((!isatty(so))&&(!sname)) handle = so; - else - { if (!sname) sname = "output.swf"; - handle = open(sname,O_BINARY|O_RDWR|O_CREAT|O_TRUNC,0666); - } - if FAILED(swf_WriteSWF(handle,swf)) if (VERBOSE(1)) fprintf(stderr,"Unable to write output file: %s\n",sname); - if (handle!=so) close(handle); - - swf_FreeTags(swf); - return 0; +int MovieFinish(SWF * swf, TAG * t, char *sname) +{ + int handle, so = fileno(stdout); + t = swf_InsertTag(t, ST_END); + + if ((!isatty(so)) && (!sname)) + handle = so; + else { + if (!sname) + sname = "output.swf"; + handle = open(sname, O_BINARY | O_RDWR | O_CREAT | O_TRUNC, 0666); + } + if (swf_WriteSWF(handle, swf)<0) + fprintf(stderr, "Unable to write output file: %s\n", sname); + if (handle != so) + close(handle); + + swf_FreeTags(swf); + return 0; } -TAG * MovieAddFrame(SWF * swf,TAG * t,char * sname,int quality,int scale,int id) -{ SHAPE * s; - SRECT r; - MATRIX m; - int fs; - - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - LPJPEGBITS out; - FILE * f; - U8 * scanline; - - if ((f=fopen(sname,"rb"))==NULL) - { if (VERBOSE(1)) fprintf(stderr,"Read access failed: %s\n",sname); - return t; - } - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo,f); - jpeg_read_header(&cinfo, TRUE); - - if (scale>1) - { cinfo.scale_num = 1; - cinfo.scale_denom = scale; - } - - jpeg_start_decompress(&cinfo); +int getJPEG(char*filename, int* width, int* height, RGBA**pic2) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + struct jpeg_source_mgr mgr; + int x,y; + FILE*f; + RGBA*pic,*js; + U8*buf; + + if ((f=fopen(filename,"rb"))==NULL) { + fprintf(stderr, "rfxswf: file open error\n"); + return 0; + } - t = swf_InsertTag(t,ST_DEFINEBITSJPEG2); + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, f); + jpeg_read_header(&cinfo, TRUE); + jpeg_start_decompress(&cinfo); - swf_SetU16(t,id); // id - - out = swf_SetJPEGBitsStart(t,cinfo.output_width,cinfo.output_height,quality); - scanline = (U8*)malloc(4*cinfo.output_width); - - // the following code is a duplication of swf_SetJPEGBits in ../lib/modules/swfbits.c - if (scanline) - { int y; - U8 * js = scanline; - - if(cinfo.out_color_space == JCS_GRAYSCALE) - { - for (y=0;y=0;x--) { - js[x*3] = js[x*3+1] = js[x*3+2] = js[x]; - } - swf_SetJPEGBitsLines(out,(U8**)&js,1); - } - } - else if(cinfo.out_color_space == JCS_RGB) - { - for (y=0;y>8); + js[x].g = y - ((88*(u-128)+183*(v-128))>>8); + js[x].b = y + ((455 * (u-128))>>8); + } + } + else if(cinfo.out_color_space == JCS_CMYK) + { + for(x=0;x>8); + js[x].g = white - ((buf[x*4+1]*white)>>8); + js[x].b = white - ((buf[x*4+2]*white)>>8); + } + } + js += cinfo.output_width; + } + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); - t = swf_InsertTag(t,ST_DEFINESHAPE); - - swf_ShapeNew(&s); - swf_GetMatrix(NULL,&m); - m.sx = 20*0x10000; - m.sy = 20*0x10000; - fs = swf_ShapeAddBitmapFillStyle(s,&m,id,0); - - swf_SetU16(t,id+1); // id - - - r.xmin = r.ymin = 0; - r.xmax = cinfo.output_width*20; - r.ymax = cinfo.output_height*20; - swf_SetRect(t,&r); - - swf_SetShapeHeader(t,s); - - swf_ShapeSetAll(t,s,0,0,0,fs,0); - swf_ShapeSetLine(t,s,r.xmax,0); - swf_ShapeSetLine(t,s,0,r.ymax); - swf_ShapeSetLine(t,s,-r.xmax,0); - swf_ShapeSetLine(t,s,0,-r.ymax); - - swf_ShapeSetEnd(t); - - t = swf_InsertTag(t,ST_REMOVEOBJECT2); - swf_SetU16(t,1); // depth - - t = swf_InsertTag(t,ST_PLACEOBJECT2); - - swf_GetMatrix(NULL,&m); - m.tx = (swf->movieSize.xmax-(int)cinfo.output_width*20)/2; - m.ty = (swf->movieSize.ymax-(int)cinfo.output_height*20)/2; - swf_ObjectPlace(t,id+1,1,&m,NULL,NULL); - - t = swf_InsertTag(t,ST_SHOWFRAME); - - jpeg_finish_decompress(&cinfo); - fclose(f); - - return t; + free(buf); + *pic2 = pic; + return 1; } -int CheckInputFile(char * fname,char ** realname) -{ struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - FILE * f; - char * s = malloc(strlen(fname)+5); - int width, height; - - if (!s) exit(2); - (*realname) = s; - strcpy(s,fname); - - // Check whether file exists (with typical extensions) - - if ((f=fopen(s,"rb"))==NULL) - { sprintf(s,"%s.jpg",fname); - if ((f=fopen(s,"rb"))==NULL) - { sprintf(s,"%s.jpeg",fname); - if ((f=fopen(s,"rb"))==NULL) - { sprintf(s,"%s.JPG",fname); - if ((f=fopen(s,"rb"))==NULL) - { sprintf(s,"%s.JPEG",fname); - if ((f=fopen(s,"rb"))==NULL) - return -1; - } - } + +int frame = 0; +TAG *MovieAddFrame(SWF * swf, TAG * t, char *sname, int quality, + int id, int width, int height) +{ + SHAPE *s; + SRECT r; + MATRIX m; + int fs; + + + if(global.mx) { + int sizex, sizey; + RGBA * pic2; + SWFPLACEOBJECT obj; + int quant=0; + getJPEG(sname, &sizex, &sizey, &pic2); + if(sizex != stream.owidth || sizey != stream.oheight) { + fprintf(stderr, "All images must have the same dimensions if using -m!"); + exit(1); + } + + t = swf_InsertTag(t, ST_VIDEOFRAME); + swf_SetU16(t, 0xf00d); + quant = 1+(30-(30*quality)/100); + if(!(frame&127)) { + swf_SetVideoStreamIFrame(t, &stream, pic2, quant); + } else { + swf_SetVideoStreamPFrame(t, &stream, pic2, quant); + } + + t = swf_InsertTag(t, ST_PLACEOBJECT2); + swf_GetPlaceObject(0, &obj); + if(frame==0) { + obj.depth = 1; + obj.id = 0xf00d; + } else { + obj.depth = 1; + obj.move = 1; + obj.ratio = frame; + } + swf_SetPlaceObject(t,&obj); + + t = swf_InsertTag(t, ST_SHOWFRAME); + } else { + t = swf_InsertTag(t, ST_DEFINEBITSJPEG2); + swf_SetU16(t, id); // id + swf_SetJPEGBits(t,sname,quality); + + t = swf_InsertTag(t, ST_DEFINESHAPE); + swf_ShapeNew(&s); + swf_GetMatrix(NULL, &m); + m.sx = 20 * 0x10000; + m.sy = 20 * 0x10000; + fs = swf_ShapeAddBitmapFillStyle(s, &m, id, 0); + swf_SetU16(t, id + 1); // id + r.xmin = r.ymin = 0; + r.xmax = width * 20; + r.ymax = height * 20; + swf_SetRect(t, &r); + swf_SetShapeHeader(t, s); + swf_ShapeSetAll(t, s, 0, 0, 0, fs, 0); + swf_ShapeSetLine(t, s, r.xmax, 0); + swf_ShapeSetLine(t, s, 0, r.ymax); + swf_ShapeSetLine(t, s, -r.xmax, 0); + swf_ShapeSetLine(t, s, 0, -r.ymax); + swf_ShapeSetEnd(t); + + t = swf_InsertTag(t, ST_REMOVEOBJECT2); + swf_SetU16(t, 1); // depth + + t = swf_InsertTag(t, ST_PLACEOBJECT2); + swf_GetMatrix(NULL, &m); + m.tx = (swf->movieSize.xmax - (int) width * 20) / 2; + m.ty = (swf->movieSize.ymax - (int) height * 20) / 2; + swf_ObjectPlace(t, id + 1, 1, &m, NULL, NULL); + + t = swf_InsertTag(t, ST_SHOWFRAME); } - } - - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo,f); - jpeg_read_header(&cinfo, TRUE); - - // Apply scaling (scale option can be used several times to set different scales) - - if (global.prescale>1) - { cinfo.scale_num = 1; - cinfo.scale_denom = global.prescale; - - jpeg_calc_output_dimensions(&cinfo); - - width = cinfo.output_width; - height = cinfo.output_height; - } - else - { width = cinfo.image_width; + frame++; + + return t; +} + +int CheckInputFile(image_t* i, char *fname, char **realname) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + FILE *f; + char *s = malloc(strlen(fname) + 5); + int width, height; + + if (!s) + exit(2); + (*realname) = s; + strcpy(s, fname); + + // Check whether file exists (with typical extensions) + + if ((f = fopen(s, "rb")) == NULL) { + sprintf(s, "%s.jpg", fname); + if ((f = fopen(s, "rb")) == NULL) { + sprintf(s, "%s.jpeg", fname); + if ((f = fopen(s, "rb")) == NULL) { + sprintf(s, "%s.JPG", fname); + if ((f = fopen(s, "rb")) == NULL) { + sprintf(s, "%s.JPEG", fname); + if ((f = fopen(s, "rb")) == NULL) + return -1; + } + } + } + } + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, f); + jpeg_read_header(&cinfo, TRUE); + + width = cinfo.image_width; height = cinfo.image_height; - } - // Get image dimensions + i->width = width; + i->height = height; - if (global.max_image_width100)) - { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid quality between 1 and 100.\n"); - exit(1); - } - res = 1; - break; - - case 'r': - if (val) global.framerate = atoi(val); - if ((global.framerate<1)||(global.framerate>5000)) - { if (VERBOSE(1)) fprintf(stderr,"Error: You must specify a valid framerate between 1 and 10000.\n"); - exit(1); - } - res = 1; - break; - - case 's': - if (val) global.prescale = atoi(val); - if (!((global.prescale==1)||(global.prescale==2)||(global.prescale==4)||(global.prescale==8))) - { if (VERBOSE(1)) fprintf(stderr,"Error: Prescale denominator is limited to 2, 4 or 8\n"); - exit(1); - } - res = 1; - break; - - case 'o': - if (val) global.outfile = val; res = 1; break; - - case 'v': - if (val) global.verbose = atoi(val); res = 1; break; - - case 'X': - if (val) global.force_width = atoi(val); res = 1; break; - - case 'Y': - if (val) global.force_height = atoi(val); res = 1; break; - - case 'V': - printf("jpeg2swf - part of %s %s\n", PACKAGE, VERSION);exit(0); - - default: - res = -1; - break; - } - - if (res<0) - { if (VERBOSE(1)) fprintf(stderr,"Unknown option: -%s\n",arg); - exit(1); return 0; - } - return res; } -struct options_t options[] = -{{"q","quality"}, - {"o","output"}, - {"r","rate"}, - {"v","verbose"}, - {"X","width"}, - {"Y","height"}, - {"V","version"}, - {"s","scale"} - }; - -int args_callback_longoption(char*name,char*val) { +int args_callback_option(char *arg, char *val) +{ + int res = 0; + if (arg[1]) + res = -1; + else + switch (arg[0]) { + case 'q': + if (val) + global.quality = atoi(val); + if ((global.quality < 1) ||(global.quality > 100)) { + if (VERBOSE(1)) + fprintf(stderr, + "Error: You must specify a valid quality between 1 and 100.\n"); + exit(1); + } + res = 1; + break; + + case 'r': + if (val) + global.framerate = atoi(val); + if ((global.framerate < 1) ||(global.framerate > 5000)) { + if (VERBOSE(1)) + fprintf(stderr, + "Error: You must specify a valid framerate between 1 and 10000.\n"); + exit(1); + } + res = 1; + break; + + case 'o': + if (val) + global.outfile = val; + res = 1; + break; + + case 'v': + if (val) + global.verbose = atoi(val); + res = 1; + break; + + case 'X': + if (val) + global.force_width = atoi(val); + res = 1; + break; + + case 'm': + global.mx = 1; + return 0; + + case 'Y': + if (val) + global.force_height = atoi(val); + res = 1; + break; + + case 'V': + printf("jpeg2swf - part of %s %s\n", PACKAGE, VERSION); + exit(0); + + default: + res = -1; + break; + } + + if (res < 0) { + if (VERBOSE(1)) + fprintf(stderr, "Unknown option: -%s\n", arg); + exit(1); + return 0; + } + return res; +} + +struct options_t options[] = { {"q", "quality"}, +{"o", "output"}, +{"m", "mx"}, +{"r", "rate"}, +{"v", "verbose"}, +{"X", "width"}, +{"Y", "height"}, +{"V", "version"}, +}; + +int args_callback_longoption(char *name, char *val) +{ return args_long2shortoption(options, name, val); } -int args_callback_command(char*arg,char*next) // actually used as filename -{ char * s; - int scale; - if (CheckInputFile(arg,&s)<0) - { if (VERBOSE(1)) fprintf(stderr, "Unable to open input file: %s\n",arg); - free(s); - } - else - { image[global.nfiles].filename = s; - image[global.nfiles].scale = global.prescale; - image[global.nfiles].quality = global.quality; - global.nfiles++; - if (global.nfiles>=MAX_INPUT_FILES) - { if (VERBOSE(1)) fprintf(stderr, "Error: Too many input files.\n"); - exit(1); +int args_callback_command(char *arg, char *next) // actually used as filename +{ + char *s; + image_t* i = &image[global.nfiles]; + if (CheckInputFile(i, arg, &s) < 0) { + if (VERBOSE(1)) + fprintf(stderr, "Unable to open input file: %s\n", arg); + free(s); + } else { + i->filename = s; + i->quality = global.quality; + global.nfiles++; + if (global.nfiles >= MAX_INPUT_FILES) { + if (VERBOSE(1)) + fprintf(stderr, "Error: Too many input files.\n"); + exit(1); + } } - } - return 0; + return 0; } -void args_callback_usage(char*name) -{ fprintf(stderr,"Usage: %s [-options [value]] imagefiles[.jpg]|[.jpeg] [...]\n",name); - fprintf(stderr,"-q quality (quality) Set JPEG compression quality (1-100)\n"); - fprintf(stderr,"-s denominator (scale) 2, 4 or 8: Reduce image size to 1/2, 1/4, 1/8\n"); - fprintf(stderr,"-r framerate (rate) Set movie framerate (100/sec)\n"); - fprintf(stderr,"-o outputfile (output) Set name for SWF output file\n"); - fprintf(stderr,"-X pixel (width) Force movie width to scale (default: autodetect)\n"); - fprintf(stderr,"-Y pixel (height) Force movie height to scale (default: autodetect)\n"); - fprintf(stderr,"-v level (verbose) Set verbose level (0=quiet, 1=default, 2=debug)\n"); - fprintf(stderr,"-V (version) Print version information and exit\n"); - fprintf(stderr,"The following options can be set independently for each image: -q -s\n"); +void args_callback_usage(char *name) +{ + printf + ("Usage: %s [-options [value]] imagefiles[.jpg]|[.jpeg] [...]\n", + name); + printf + ("-o outputfile --output explicitly specify output file. (otherwise, output.swf will be used)\n"); + printf + ("-m --mx Use Flash MX H.263 compression (use for correlated images)\n"); + printf + ("-q quality --quality Set compression quality (1-100, 1=worst, 100=best)\n"); + printf + ("-r framerate --rate Set movie framerate (100/sec)\n"); + printf + ("-o outputfile --output Set name for SWF output file\n"); + printf + ("-X pixel --width Force movie width to pixel (default: autodetect)\n"); + printf + ("-Y pixel --height Force movie height to pixel (default: autodetect)\n"); + printf + ("-v level --verbose Set verbose level (0=quiet, 1=default, 2=debug)\n"); + printf + ("-V --version Print version information and exit\n"); + printf + ("The following options can be set independently for each image: -q -s\n"); } -int main(int argc, char ** argv) -{ SWF swf; - TAG * t; +int main(int argc, char **argv) +{ + SWF swf; + TAG *t; - memset(&global,0x00,sizeof(global)); - - global.quality = 60; - global.framerate = 100; - global.verbose = 1; - global.prescale = 1; - - processargs(argc, argv); - - if (VERBOSE(2)) fprintf(stderr,"Processing %i file(s)...\n",global.nfiles); - - t = MovieStart(&swf,global.framerate, - global.force_width?global.force_width:global.max_image_width, - global.force_height?global.force_height:global.max_image_height); - - { int i; - for (i=0;i