3 JPEG to SWF converter tool
5 Part of the swftools package.
7 Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
8 Copyright (c) 2002,2003 Matthias Kramm <kramm@quiss.org>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
28 #include "../lib/rfxswf.h"
29 #include "../lib/args.h" // not really a header ;-)
31 #define MAX_INPUT_FILES 1024
32 #define VERBOSE(x) (global.verbose>=x)
48 typedef struct _image
{
54 image_t image
[MAX_INPUT_FILES
];
58 TAG
*MovieStart(SWF
* swf
, float framerate
, int dx
, int dy
)
63 memset(swf
, 0x00, sizeof(SWF
));
65 swf
->fileVersion
= global
.version
;
66 swf
->frameRate
= (int)(256.0 * framerate
);
67 swf
->movieSize
.xmax
= dx
* 20;
68 swf
->movieSize
.ymax
= dy
* 20;
70 t
= swf
->firstTag
= swf_InsertTag(NULL
, ST_SETBACKGROUNDCOLOR
);
72 rgb
.r
= rgb
.g
= rgb
.b
= rgb
.a
= 0x00;
76 t
= swf_InsertTag(t
, ST_DEFINEVIDEOSTREAM
);
77 swf_SetU16(t
, 0xf00d);
78 swf_SetVideoStreamDefine(t
, &stream
, 65535, dx
, dy
);
84 int MovieFinish(SWF
* swf
, TAG
* t
, char *sname
)
86 int handle
, so
= fileno(stdout
);
87 t
= swf_InsertTag(t
, ST_END
);
89 if ((!isatty(so
)) && (!sname
))
94 handle
= open(sname
, O_BINARY
| O_RDWR
| O_CREAT
| O_TRUNC
, 0666);
96 if (swf_WriteSWF(handle
, swf
)<0)
97 fprintf(stderr
, "Unable to write output file: %s\n", sname
);
105 int getJPEG(char*filename
, int* width
, int* height
, RGBA
**pic2
)
107 struct jpeg_decompress_struct cinfo
;
108 struct jpeg_error_mgr jerr
;
109 struct jpeg_source_mgr mgr
;
115 if ((f
=fopen(filename
,"rb"))==NULL
) {
116 fprintf(stderr
, "rfxswf: file open error\n");
120 cinfo
.err
= jpeg_std_error(&jerr
);
121 jpeg_create_decompress(&cinfo
);
122 jpeg_stdio_src(&cinfo
, f
);
123 jpeg_read_header(&cinfo
, TRUE
);
124 jpeg_start_decompress(&cinfo
);
126 pic
= malloc(cinfo
.output_width
*cinfo
.output_height
*sizeof(RGBA
));
127 buf
= malloc(cinfo
.output_width
*4);
128 memset(pic
, 255, cinfo
.output_width
*cinfo
.output_height
*sizeof(RGBA
));
131 *width
= cinfo
.output_width
;
132 *height
= cinfo
.output_height
;
134 for (y
=0;y
<cinfo
.output_height
;y
++) {
136 jpeg_read_scanlines(&cinfo
,&buf
,1);
138 if(cinfo
.out_color_space
== JCS_GRAYSCALE
) {
139 for(x
=0;x
<cinfo
.output_width
;x
++) {
140 js
[x
].r
= js
[x
].g
= js
[x
].b
= buf
[x
];
142 } else if(cinfo
.out_color_space
== JCS_RGB
) {
143 for (x
=0;x
<cinfo
.output_width
;x
++)
145 js
[x
].r
= buf
[x
*3+0];
146 js
[x
].g
= buf
[x
*3+1];
147 js
[x
].b
= buf
[x
*3+2];
149 } else if(cinfo
.out_color_space
== JCS_YCCK
) {
151 fprintf(stderr
, "Error: Can't convert YCCK to RGB.\n");
153 } else if(cinfo
.out_color_space
== JCS_YCbCr
) {
154 for(x
=0;x
<cinfo
.output_width
;x
++) {
158 js
[x
].r
= y
+ ((360*(v
-128))>>8);
159 js
[x
].g
= y
- ((88*(u
-128)+183*(v
-128))>>8);
160 js
[x
].b
= y
+ ((455 * (u
-128))>>8);
163 else if(cinfo
.out_color_space
== JCS_CMYK
)
165 for(x
=0;x
<cinfo
.output_width
;x
++) {
166 int white
= 255 - buf
[x
*4+3];
167 js
[x
].r
= white
- ((buf
[x
*4]*white
)>>8);
168 js
[x
].g
= white
- ((buf
[x
*4+1]*white
)>>8);
169 js
[x
].b
= white
- ((buf
[x
*4+2]*white
)>>8);
172 js
+= cinfo
.output_width
;
175 jpeg_finish_decompress(&cinfo
);
176 jpeg_destroy_decompress(&cinfo
);
185 TAG
*MovieAddFrame(SWF
* swf
, TAG
* t
, char *sname
, int quality
,
186 int id
, int width
, int height
)
199 getJPEG(sname
, &sizex
, &sizey
, &pic2
);
200 if(sizex
!= stream
.owidth
|| sizey
!= stream
.oheight
) {
201 fprintf(stderr
, "All images must have the same dimensions if using -m!");
205 t
= swf_InsertTag(t
, ST_VIDEOFRAME
);
206 swf_SetU16(t
, 0xf00d);
207 quant
= 1+(30-(30*quality
)/100);
209 swf_SetVideoStreamIFrame(t
, &stream
, pic2
, quant
);
211 swf_SetVideoStreamPFrame(t
, &stream
, pic2
, quant
);
214 t
= swf_InsertTag(t
, ST_PLACEOBJECT2
);
215 swf_GetPlaceObject(0, &obj
);
224 swf_SetPlaceObject(t
,&obj
);
226 t
= swf_InsertTag(t
, ST_SHOWFRAME
);
228 t
= swf_InsertTag(t
, ST_DEFINEBITSJPEG2
);
229 swf_SetU16(t
, id
); // id
230 swf_SetJPEGBits(t
,sname
,quality
);
232 t
= swf_InsertTag(t
, ST_DEFINESHAPE
);
234 swf_GetMatrix(NULL
, &m
);
237 fs
= swf_ShapeAddBitmapFillStyle(s
, &m
, id
, 0);
238 swf_SetU16(t
, id
+ 1); // id
241 r
.ymax
= height
* 20;
243 swf_SetShapeHeader(t
, s
);
244 swf_ShapeSetAll(t
, s
, 0, 0, 0, fs
, 0);
245 swf_ShapeSetLine(t
, s
, r
.xmax
, 0);
246 swf_ShapeSetLine(t
, s
, 0, r
.ymax
);
247 swf_ShapeSetLine(t
, s
, -r
.xmax
, 0);
248 swf_ShapeSetLine(t
, s
, 0, -r
.ymax
);
251 t
= swf_InsertTag(t
, ST_REMOVEOBJECT2
);
252 swf_SetU16(t
, 1); // depth
254 t
= swf_InsertTag(t
, ST_PLACEOBJECT2
);
255 swf_GetMatrix(NULL
, &m
);
256 m
.tx
= (swf
->movieSize
.xmax
- (int) width
* 20) / 2;
257 m
.ty
= (swf
->movieSize
.ymax
- (int) height
* 20) / 2;
258 swf_ObjectPlace(t
, id
+ 1, 1, &m
, NULL
, NULL
);
260 t
= swf_InsertTag(t
, ST_SHOWFRAME
);
267 int CheckInputFile(image_t
* i
, char *fname
, char **realname
)
269 struct jpeg_decompress_struct cinfo
;
270 struct jpeg_error_mgr jerr
;
272 char *s
= malloc(strlen(fname
) + 5);
280 // Check whether file exists (with typical extensions)
282 if ((f
= fopen(s
, "rb")) == NULL
) {
283 sprintf(s
, "%s.jpg", fname
);
284 if ((f
= fopen(s
, "rb")) == NULL
) {
285 sprintf(s
, "%s.jpeg", fname
);
286 if ((f
= fopen(s
, "rb")) == NULL
) {
287 sprintf(s
, "%s.JPG", fname
);
288 if ((f
= fopen(s
, "rb")) == NULL
) {
289 sprintf(s
, "%s.JPEG", fname
);
290 if ((f
= fopen(s
, "rb")) == NULL
)
297 cinfo
.err
= jpeg_std_error(&jerr
);
298 jpeg_create_decompress(&cinfo
);
299 jpeg_stdio_src(&cinfo
, f
);
300 jpeg_read_header(&cinfo
, TRUE
);
302 width
= cinfo
.image_width
;
303 height
= cinfo
.image_height
;
308 // Get image dimensions
310 if (global
.max_image_width
< width
)
311 global
.max_image_width
= width
;
312 if (global
.max_image_height
< height
)
313 global
.max_image_height
= height
;
315 jpeg_destroy_decompress(&cinfo
);
321 int args_callback_option(char *arg
, char *val
)
330 global
.quality
= atoi(val
);
331 if ((global
.quality
< 1) ||(global
.quality
> 100)) {
334 "Error: You must specify a valid quality between 1 and 100.\n");
342 global
.framerate
= atof(val
);
343 if ((global
.framerate
< 1.0/256) || (global
.framerate
>= 256.0)) {
346 "Error: You must specify a valid framerate between 1 and 10000.\n");
354 global
.outfile
= val
;
360 global
.verbose
= atoi(val
);
366 global
.force_width
= atoi(val
);
377 global
.force_height
= atoi(val
);
382 printf("jpeg2swf - part of %s %s\n", PACKAGE
, VERSION
);
392 fprintf(stderr
, "Unknown option: -%s\n", arg
);
399 static struct options_t options
[] = {
411 int args_callback_longoption(char *name
, char *val
)
413 return args_long2shortoption(options
, name
, val
);
416 int args_callback_command(char *arg
, char *next
) // actually used as filename
419 image_t
* i
= &image
[global
.nfiles
];
420 if (CheckInputFile(i
, arg
, &s
) < 0) {
422 fprintf(stderr
, "Unable to open input file: %s\n", arg
);
426 i
->quality
= global
.quality
;
428 if (global
.nfiles
>= MAX_INPUT_FILES
) {
430 fprintf(stderr
, "Error: Too many input files.\n");
437 void args_callback_usage(char *name
)
440 printf("Usage: %s [-options [value]] imagefiles[.jpg]|[.jpeg] [...]\n", name
);
442 printf("-o , --output <outputfile> Explicitly specify output file. (otherwise, output.swf will be used)\n");
443 printf("-m , --mx Use Flash MX H.263 compression (use for correlated images)\n");
444 printf("-q , --quality <quality> Set compression quality (1-100, 1=worst, 100=best)\n");
445 printf("-r , --rate <framerate> Set movie framerate (frames per second)\n");
446 printf("-X , --width <width> Force movie width to <width> (default: autodetect)\n");
447 printf("-Y , --height <height> Force movie height to <height> (default: autodetect)\n");
448 printf("-v , --verbose <level> Set verbose level to <level> (0=quiet, 1=default, 2=debug)\n");
449 printf("-V , --version Print version information and exit\n");
454 int main(int argc
, char **argv
)
459 memset(&global
, 0x00, sizeof(global
));
462 global
.framerate
= 1.0;
466 processargs(argc
, argv
);
469 fprintf(stderr
, "Processing %i file(s)...\n", global
.nfiles
);
471 t
= MovieStart(&swf
, global
.framerate
,
472 global
.force_width
? global
.force_width
: global
.
474 global
.force_height
? global
.force_height
: global
.
479 for (i
= 0; i
< global
.nfiles
; i
++) {
481 fprintf(stderr
, "[%03i] %s (%i%%, 1/%i)\n", i
,
482 image
[i
].filename
, image
[i
].quality
);
483 t
= MovieAddFrame(&swf
, t
, image
[i
].filename
, image
[i
].quality
,
485 image
[i
].width
, image
[i
].height
);
486 free(image
[i
].filename
);
490 MovieFinish(&swf
, t
, global
.outfile
);