1 
2 /*
3  * jslice.c
4  *
5  * This program will take a slice of a given picture and save it to
6  * a second file name
7  *
8  */
9 
10 /*
11  * CHANGES
12  *
13  * 31/05/2000 - Added JavaScript enhancements and direct embedding
14  * 21/05/2000 - Added image-dimentions
15  * 25/05/2000 - Fixed up hyperlink detection from slice file
16  *
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 
23 /*
24  * Include file for users of JPEG library.
25  * You will need to have included system headers that define at least
26  * the typedefs FILE and size_t before you can include jpeglib.h.
27  * (stdio.h is sufficient on ANSI-conforming systems.)
28  * You may also wish to include "jerror.h".
29  */
30 
31 #include "jpeglib.h"
32 #include <setjmp.h>
33 
34 JSAMPROW * arow;	/* points to a row of JSAMPLES*/
35 JSAMPLE * buffer;	/* Points to large array of R,G,B-order data */
36 JSAMPLE * image;
37 JSAMPROW wimage[4097]; /* array of rows for the "whole" image */
38 JSAMPROW pimage[4097]; /* array of rows for the "partial" image */
39 
40 #define _VERSION "1.0.0"
41 #define _MESSAGE "<!-- ----------------------------------------\n\
42 	Created with the assistance of jslice, v1.0.0 \n\
43 	written by Paul L Daniels\n\
44 	pldaniels@pldaniels.com\n\
45 	http://www.pldaniels.com/jslice\n\
46 	(C) P.L.Daniels 2000\n\
47 	------------------------------------------ -->\n\n"
48 #define _HELP "jslice v1.0.0 - (C) Paul L Daniels 2000\n\n\
49 	Options Available -\n\
50 	-i Input JPEG file [ie frontPage.jpg]\n\
51 	-p Ouput JPEG file prefix [ie fpactive]\n\
52 	-c Cut/Slice file [ie frontpage.slices]\n\
53 	-q Quality of JPEG output [ie 85]\n\
54 	-h OPTIONAL - Header file to prefix to HTML output [ie header.html]\n\
55 	-f OPTIONAL - Footer file to suffix to HTML output [ie footer.html]\n\
56 	--help produce this help.\n\
57 	\n\
58 	example of using jslice...\n\
59 		jslice -i frontpage_active.jpg -p fpa -c frontpage.slices -q 75 -h header.html -f footer.html > index.html\n\n\
60 	end of help.\n\n"
61 #define MAX_HEIGHT 4096
62 #define MAX_WIDTH 4096
63 #define MAX_LINK_SIZE 1024
64 #define MAX_SLICES 1000
65 
66 #define _CUT 1
67 #define _UNCUT 0
68 
69 #define _QUALITY_DEFAULT 75
70 
71 #define _ERR_CANTOPENJPEG 101
72 #define _ERR_CANTWRITEJPEG 102
73 #define _ERR_CANTREADSCRIPT 103
74 #define _ERR_INSUFFICENTMEM 200
75 
76 int image_height;	/* Number of rows in image */
77 int image_width;		/* Number of columns in image */
78 int p_height; 	/* width of image after cut */
79 int p_width;  	/* height of image after cut */
80 
81 
82 /* define a structure that will keep the details of each box slice.
83 */
84 
85 struct _aslice {
86 
87 	int ax, bx, ay, by;
88 	char link[MAX_LINK_SIZE+1];
89 	};
90 
91 typedef struct _aslice _tslice;
92 int slicesx[MAX_WIDTH];
93 int slicesy[MAX_HEIGHT];
94 
95 
96 /* And of course, create a global variable out of it.
97 */
98 
99 _tslice slices[MAX_SLICES];
100 
101 
102 GLOBAL(void)
write_JPEG_file(char * filename,int quality)103 write_JPEG_file (char * filename, int quality)
104 {
105   /* This struct contains the JPEG compression parameters and pointers to
106    * working space (which is allocated as needed by the JPEG library).
107    * It is possible to have several such structures, representing multiple
108    * compression/decompression processes, in existence at once.  We refer
109    * to any one struct (and its associated working data) as a "JPEG object".
110    */
111   struct jpeg_compress_struct cinfo;
112   /* This struct represents a JPEG error handler.  It is declared separately
113    * because applications often want to supply a specialized error handler
114    * (see the second half of this file for an example).  But here we just
115    * take the easy way out and use the standard error handler, which will
116    * print a message on stderr and call exit() if compression fails.
117    * Note that this struct must live as long as the main JPEG parameter
118    * struct, to avoid dangling-pointer problems.
119    */
120   struct jpeg_error_mgr jerr;
121   /* More stuff */
122   FILE * outfile;		/* target file */
123   JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
124   int row_stride;		/* physical row width in image buffer */
125 
126   /* Step 1: allocate and initialize JPEG compression object */
127 
128   /* We have to set up the error handler first, in case the initialization
129    * step fails.  (Unlikely, but it could happen if you are out of memory.)
130    * This routine fills in the contents of struct jerr, and returns jerr's
131    * address which we place into the link field in cinfo.
132    */
133   cinfo.err = jpeg_std_error(&jerr);
134   /* Now we can initialize the JPEG compression object. */
135   jpeg_create_compress(&cinfo);
136 
137   /* Step 2: specify data destination (eg, a file) */
138   /* Note: steps 2 and 3 can be done in either order. */
139 
140   /* Here we use the library-supplied code to send compressed data to a
141    * stdio stream.  You can also write your own code to do something else.
142    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
143    * requires it in order to write binary files.
144    */
145   if ((outfile = fopen(filename, "wb")) == NULL) {
146     fprintf(stderr, "can't open %s\n", filename);
147     exit(_ERR_CANTWRITEJPEG);
148   }
149   jpeg_stdio_dest(&cinfo, outfile);
150 
151   /* Step 3: set parameters for compression */
152 
153   /* First we supply a description of the input image.
154    * Four fields of the cinfo struct must be filled in:
155    */
156   cinfo.image_width = p_width; 	/* image width and height, in pixels */
157   cinfo.image_height = p_height;
158   cinfo.input_components = 3;		/* # of color components per pixel */
159   cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
160   /* Now use the library's routine to set default compression parameters.
161    * (You must set at least cinfo.in_color_space before calling this,
162    * since the defaults depend on the source color space.)
163    */
164   jpeg_set_defaults(&cinfo);
165   /* Now you can set any non-default parameters you wish to.
166    * Here we just illustrate the use of quality (quantization table) scaling:
167    */
168   jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
169 
170   /* Step 4: Start compressor */
171 
172   /* TRUE ensures that we will write a complete interchange-JPEG file.
173    * Pass TRUE unless you are very sure of what you're doing.
174    */
175   jpeg_start_compress(&cinfo, TRUE);
176 
177   /* Step 5: while (scan lines remain to be written) */
178   /*           jpeg_write_scanlines(...); */
179 
180   /* Here we use the library's state variable cinfo.next_scanline as the
181    * loop counter, so that we don't have to keep track ourselves.
182    * To keep things simple, we pass one scanline per call; you can pass
183    * more if you wish, though.
184    */
185   row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */
186 
187   while (cinfo.next_scanline < cinfo.image_height) {
188     /* jpeg_write_scanlines expects an array of pointers to scanlines.
189      * Here the array is only one element long, but you could pass
190      * more than one scanline at a time if that's more convenient.
191      */
192 		 row_pointer[0] = pimage[cinfo.next_scanline];
193     (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
194   }
195 
196   /* Step 6: Finish compression */
197 
198   jpeg_finish_compress(&cinfo);
199   /* After finish_compress, we can close the output file. */
200   fclose(outfile);
201 
202   /* Step 7: release JPEG compression object */
203 
204   /* This is an important step since it will release a good deal of memory. */
205   jpeg_destroy_compress(&cinfo);
206 
207   /* And we're done! */
208 }
209 
210 
211 /*
212  * Here's the extended error handler struct:
213  */
214 
215 struct my_error_mgr {
216   struct jpeg_error_mgr pub;	/* "public" fields */
217 
218   jmp_buf setjmp_buffer;	/* for return to caller */
219 };
220 
221 typedef struct my_error_mgr * my_error_ptr;
222 
223 /*
224  * Here's the routine that will replace the standard error_exit method:
225  */
226 
227 METHODDEF(void)
my_error_exit(j_common_ptr cinfo)228 my_error_exit (j_common_ptr cinfo)
229 {
230   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
231   my_error_ptr myerr = (my_error_ptr) cinfo->err;
232 
233   /* Always display the message. */
234   /* We could postpone this until after returning, if we chose. */
235   (*cinfo->err->output_message) (cinfo);
236 
237   /* Return control to the setjmp point */
238   longjmp(myerr->setjmp_buffer, 1);
239 }
240 
241 
242 /*
243  * Sample routine for JPEG decompression.  We assume that the source file name
244  * is passed in.  We want to return 1 on success, 0 on error.
245  */
246 
247 
248 GLOBAL(int)
read_JPEG_file(char * filename)249 read_JPEG_file (char * filename)
250 {
251 
252 
253   /* This struct contains the JPEG decompression parameters and pointers to
254    * working space (which is allocated as needed by the JPEG library).
255    */
256   struct jpeg_decompress_struct cinfo;
257   /* We use our private extension JPEG error handler.
258    * Note that this struct must live as long as the main JPEG parameter
259    * struct, to avoid dangling-pointer problems.
260    */
261   struct my_error_mgr jerr;
262   /* More stuff */
263   FILE * infile;		/* source file */
264 	JSAMPROW row_pointer[1];
265 
266   int row_stride;		/* physical row width in output buffer */
267 
268 
269   if ((infile = fopen(filename, "rb")) == NULL) {
270     fprintf(stderr, "can't open %s\n", filename);
271     exit(_ERR_CANTOPENJPEG);
272   }
273 
274   cinfo.err = jpeg_std_error(&jerr.pub);
275   jerr.pub.error_exit = my_error_exit;
276 
277   if (setjmp(jerr.setjmp_buffer)) {
278     jpeg_destroy_decompress(&cinfo);
279     fclose(infile);
280     exit(_ERR_INSUFFICENTMEM);
281   }
282 
283   jpeg_create_decompress(&cinfo);
284 
285   jpeg_stdio_src(&cinfo, infile);
286 
287   (void) jpeg_read_header(&cinfo, TRUE);
288   (void) jpeg_start_decompress(&cinfo);
289 
290 
291 	image_width = cinfo.output_width;
292 	image_height = cinfo.output_height;
293 
294   row_stride = cinfo.output_width * cinfo.output_components;
295 
296 
297   while (cinfo.output_scanline < cinfo.output_height) {
298 
299 		wimage[cinfo.output_scanline] = malloc(sizeof(JSAMPLE) *(row_stride+1));
300   	row_pointer[0] = wimage[cinfo.output_scanline];
301 
302     (void) jpeg_read_scanlines(&cinfo, row_pointer, 1);
303 
304     /* Assume put_scanline_someplace wants a pointer and sample count. */
305 
306 	  }
307 
308   /* Step 7: Finish decompression */
309 
310   (void) jpeg_finish_decompress(&cinfo);
311   /* We can ignore the return value since suspension is not possible
312    * with the stdio data source.
313    */
314 
315   /* Step 8: Release JPEG decompression object */
316 
317   /* This is an important step since it will release a good deal of memory. */
318   jpeg_destroy_decompress(&cinfo);
319 
320   /* After finish_decompress, we can close the input file.
321    * Here we postpone it until after no more JPEG errors are possible,
322    * so as to simplify the setjmp error logic above.  (Actually, I don't
323    * think that jpeg_destroy can do an error exit, but why assume anything...)
324    */
325   fclose(infile);
326 
327   /* At this point you may want to check to see whether any corrupt-data
328    * warnings occurred (test whether jerr.pub.num_warnings is nonzero).
329    */
330 
331   /* And we're done! */
332   return 1;
333 }
334 
335 
336 
337 
338 
get_cut_count_x(int maxx)339 int get_cut_count_x( int maxx ) {
340 
341 	int count = 0;
342 	int x;
343 
344 	for (x = 0; x < maxx; x++) {
345 		if (slicesx[x] != _UNCUT) count++;
346 		}
347 
348 	return count;
349 	}
350 
351 
get_cut_count_y(int maxy)352 int get_cut_count_y( int maxy ) {
353 
354 	int count = 0;
355 	int y;
356 
357 	for (y = 0; y < maxy; y++) {
358 		if (slicesy[y] != _UNCUT) count++;
359 		}
360 
361 	return count;
362 	}
363 
364 
365 
366 
367 
count_cuts(int sx,int fx)368 int count_cuts( int sx, int fx ) {
369 
370 	int cuts = 0;
371 	int cx;
372 
373 	/* for every pixel across the horizontal...*/
374 	for (cx = sx; cx < fx; cx++){
375 
376 		/* if we've found a cut mark...*/
377 		if (slicesx[cx] != _UNCUT) {
378 
379 			/* increase our cut count */
380 			cuts++;
381 
382 			/* if the next pixel is also cut, but from the same row
383 			 * then we must skip it, as it's just consecutive cutouts
384 			 */
385 			if (slicesx[cx+1] == slicesx[cx]) {
386 				cx++;
387 				}
388 
389 			} /* if slices != UNCUT */
390 
391 		} /* for */
392 
393 	return cuts;
394 	}
395 
396 
397 
398 
399 
400 /* cut
401  *
402  * this procesdure "cuts" out the required portion of the picture.
403  *
404  */
405 
cut(int ax,int ay,int bx,int by)406 int cut( int ax, int ay, int bx, int by ) {
407 
408 	int cx, cy;
409 
410 	/* get our dimentions of the image,
411 	 * remember, that a image has a MINIMUM size of 1x1
412 	 * NOT 0x0
413 	 */
414 	p_width = bx - ax +1;
415 	p_height = by - ay +1;
416 
417 	/* for every row... */
418 	for (cy = 0; cy < p_height; cy++) {
419 
420 		/* allocate the memory for the new row of the image */
421 		pimage[cy] = malloc(sizeof(JSAMPLE) *(p_width*3));
422 
423 		/* for every pixel */
424 		for (cx = 0; cx < (p_width*3); cx++) {
425 
426 			/* copy across the pixels */
427 			pimage[cy][cx] = wimage[cy+ay][cx+(ax*3)];
428 
429 			} /* for cx */
430 		} /* for cy */
431 
432 	return 0;
433 
434 	}
435 
436 
437 
438 	/*
439 	 * dump_slices
440 	 *
441 	 * Debugging and information routine
442 	 */
dump_slices(void)443 int dump_slices( void ) {
444 
445 	int i;
446 	fprintf(stdout,"\n<!-- ");
447 	for (i = 0; i < MAX_WIDTH; i++){
448 		if (slicesx[i] != _UNCUT) fprintf(stdout,"%d, ",i);
449 	}
450 	fprintf(stdout," -->\n");
451 
452 	return 0;
453 }
454 
455 
456 
457 
458 
script_cut(char * script_name,char * foutprefix,int quality)459 int script_cut( char *script_name, char *foutprefix, int quality ){
460 
461 #define MAX 1023
462 
463 	FILE *script;
464 	int count;
465 	int ax;
466 	int i;
467 	int slicewidth;
468 	int tally;
469 	int cols;
470 	int lastx;
471 	int ffr;
472 	int slicew, sliceh;
473 	int real_url = 0;
474 	int urltest;
475 	int linecount = 0;
476 	char line[1024];
477 	char foutname[1024];
478 	char *link;
479 
480 	script = fopen(script_name,"r");
481 
482 	/*
483 	 * Make sure we don't try reading dud files
484 	 */
485 	if (script == NULL) {
486 		fprintf(stderr,"Error when trying to open the slice-coordinate file %s\nPlease check to see that the file name is correct, and that it is a text only file\n",script_name);
487 		exit(_ERR_CANTREADSCRIPT);
488 		}
489 
490 	count = 0;
491 
492 	/* clean out the slices rulers */
493 	for (ax = 0; ax < MAX_WIDTH; ax++) {
494 		slicesx[ax] = _UNCUT;
495 		slicesy[ax] = _UNCUT;
496 		}
497 
498 	/* get all our lines... */
499 	while (fgets(line, MAX, script) != NULL) {
500 
501 		linecount++;
502 
503 		/*
504 		 * Digest our line if it's not a comment
505 		 */
506 		if ((line[0] != '#')&&(strlen(line) > 7)){
507 
508 			/* get the coordinates... */
509 			slices[count].ax = atoi(strtok(line," "));
510 			if (slices[count].ax > image_width) {
511 				fprintf(stderr,"Line %d: X1 value of %d too large, reduced to %d\n",linecount,slices[count].ax,image_width);
512 				slices[count].ax = image_width;
513 				}
514 			if (slices[count].ax < 0) {
515 				fprintf(stderr,"Line %d: X1 value of %d too small, value now 0.\n",linecount,slices[count].ax);
516 				slices[count].ax = 0;
517 				}
518 
519 		slices[count].ay = atoi(strtok(NULL," "));
520 			if (slices[count].ay >= image_height) {
521 				fprintf(stderr,"Line %d: Y1 value of %d too large, reduced to %d\n",linecount,slices[count].ay,image_height-2);
522 				slices[count].ay = image_height-2;
523 				}
524 			if (slices[count].ay < 0) {
525 				fprintf(stderr,"Line %d: Y1 value of %d too small, value now 0.\n",linecount,slices[count].ay);
526 				slices[count].ay = 0;
527 				}
528 
529 		slices[count].bx = atoi(strtok(NULL," "));
530 			if (slices[count].bx > image_width) {
531 				fprintf(stderr,"Line %d: X2 value of %d too large, reduced to %d\n",linecount,slices[count].bx,image_width);
532 				slices[count].bx = image_width;
533 				}
534 			if (slices[count].bx < 0) {
535 				fprintf(stderr,"Line %d: X2 value of %d too small, value now 0.\n",linecount,slices[count].bx);
536 				slices[count].bx = 0;
537 				}
538 
539 		slices[count].by = atoi(strtok(NULL," "));
540 			if (slices[count].by >= image_height) {
541 				fprintf(stderr,"Line %d: Y2 value of %d too large, reduced to %d\n",linecount,slices[count].by,image_height-2);
542 				slices[count].by = image_height-2;
543 				}
544 			if (slices[count].by < 0) {
545 				fprintf(stderr,"Line %d: Y2 value of %d too small, value now 0.\n",linecount,slices[count].by);
546 				slices[count].by = 0;
547 				}
548 
549 		/* get our link... */
550 		link = strtok(NULL,"\n\r");
551 
552 		/*
553 		 * Test to see that the URL string is potentially valid
554 		 *
555 		 */
556 		if (link != NULL) {
557 			for (urltest = 0; urltest < strlen(link); urltest++){
558 				real_url += isalnum(link[urltest]);
559 				}
560 			if (urltest > 0) strcpy(slices[count].link, link);
561 			}
562 		else slices[count].link[0] = '\0';
563 
564 
565 		/*
566 		 * Stamp in the slice arrays our marks where we have to slice
567 		 *
568 		 * 0.1.3 - We mark in the top-y value in the ax and bx here
569 		 * so that we can determin if we are counting one or two
570 		 * columns when we come to counting up the number of cuts
571 		 * between a given ax -> bx
572 		 *
573 		 */
574 		slicesx[slices[count].ax] = slices[count].ay +_CUT;
575 		slicesx[slices[count].bx] = slices[count].ay +_CUT;
576 		slicesy[slices[count].ay] = _CUT;
577 		slicesy[slices[count].by] = _CUT;
578 
579 		count++;
580 		}
581 	}
582 
583 	/*
584 	 * Let the HTML Table start flowing
585 	 *
586 	 */
587 	fprintf(stdout,"<TABLE border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><TR>\n");
588 
589 	/*
590 	 * Print out our SLICING SPACERS!
591 	 *
592 	 */
593 	slicewidth = tally = 1;
594 	for ( ax = 1; ax <= image_width; ax++ ){
595 		if (slicesx[ax] != _UNCUT) {
596 			if (slicesx[ax-1] != slicesx[ax]){
597 				fprintf(stdout,"<TD><img src=\"spacer.gif\" width=\"%d\" height=\"1\"></td>",slicewidth);
598 				tally += slicewidth;
599 				slicewidth=0;
600 				}
601 			}
602 		slicewidth++;
603 		}
604 
605 	fprintf(stdout,"\n<!-- total width = %d -->\n",tally);
606 	fprintf(stdout,"</tr>\n<TR>\n");
607 
608 	/* print out commentory information about the slices
609 	 * to the HTML file
610 	 */
611 	dump_slices();
612 
613 	lastx = -1;
614 	ffr = 1;
615 	tally = 0;
616 
617 	for ( i = 0; i < count; i++ ){
618 
619 		/* create our filename of the output slice */
620 		sprintf(foutname,"%s%d.jpg",foutprefix,i+1);
621 
622 		/* determine how many columns we have for this slice */
623 		cols = count_cuts(slices[i].ax, slices[i].bx);
624 
625 		/* Catch the scenario where the blocks wrap back around */
626 		if (lastx >= slices[i].ax){
627 			ffr = 1;
628 			fprintf(stdout,"</tr>\n<TR>\n");
629 		}
630 
631 		lastx = slices[i].ax;
632 
633 
634 		slicew = slices[i].bx -slices[i].ax +1;
635 		sliceh = slices[i].by -slices[i].ay +1;
636 
637 		if (slices[i].link[0] != '\0') {
638 			fprintf(stdout,"<TD colspan=\"%d\"><a href=\"%s\"><img src=\"%s\" border=\"0\" width=\"%d\" height=\"%d\"></a></td>\n",cols,slices[i].link,foutname,slicew,sliceh);
639 		} else {
640 		fprintf(stdout,"<TD colspan=\"%d\"><img src=\"%s\" border=\"0\" width=\"%d\" height=\"%d\"></td>\n",cols,foutname,slicew, sliceh);
641 		}
642 
643 		cut(slices[i].ax, slices[i].ay, slices[i].bx, slices[i].by);
644 
645 		write_JPEG_file(foutname,quality);
646 
647 		ffr = 0;
648 	}
649 
650 	fprintf(stdout,"\n<!-- total width = %d -->\n",tally);
651 
652 	fprintf(stdout,"</tr></table>");
653 
654 
655 
656 	return 0;
657 	}
658 
659 
660 
661 
662 	/*
663 	 * filetostdout
664 	 *
665 	 * prints a given file to stdout
666 	 *
667 	 */
filetostdout(char * fname)668 int filetostdout( char *fname ){
669 
670 	FILE *f = fopen(fname,"r");
671 	char achar;
672 
673 	/* if the file opened okay... */
674 	if (f) {
675 		while ( (achar = fgetc(f))!= EOF) fprintf(stdout,"%c",achar);
676 		fclose(f);
677 		}
678 	else {
679 		fprintf(stderr,"Error: could not open file %s\n",fname);
680 		}
681 
682 	return 0;
683 	}
684 
685 
686 
687 /*
688  * main
689  *
690  * The basic procedure is as follows...
691  *
692  * read in the input jpeg,
693  * x1,y1 -> x2, y2 coord's
694  * output file name, and
695  * the quality factor
696  *
697  * read in the required file
698  * copy the required "slice" into a new buffer
699  * write the new buffer to the new file name
700  *
701  */
main(int argc,char ** argv)702 int main( int argc, char **argv ) {
703 
704 	int quality;
705 	int aindex; /* argv index */
706 	char *infile=NULL, *outfile=NULL, *scriptfile=NULL, *headerfile=NULL, *footerfile=NULL;
707 
708 
709 /*	if (argc < 9) {
710 
711 		fprintf(stderr,"jslice v%s usage :\n %s -i <input jpeg> -p <output jpeg prefix> \
712 -c <cut list file> -q <output quality> \
713 [-h <header file>] [-f <footer file>]\n\n",_VERSION,argv[0]);
714 
715 		exit(1);
716 		}
717 	*/
718 	/*
719 	 * Get the command line parameters ...
720 	 */
721 	for ( aindex = 1; aindex < argc; aindex++ ){
722 
723 		if (argv[aindex][0] == '-'){
724 
725 			if ( argv[aindex][1] == 'i' ){
726 				infile = argv[aindex+1];
727 				}
728 			else
729 			if ( argv[aindex][1] == 'p' ){
730 				outfile = argv[aindex+1];
731 				}
732 			else
733 			if ( argv[aindex][1] == 'c' ){
734 				scriptfile = argv[aindex+1];
735 				}
736 			else
737 			if ( argv[aindex][1] == 'q' ){
738 				quality = atoi(argv[aindex+1]);
739 				}
740 			else
741 			if ( argv[aindex][1] == 'h' ){
742 				headerfile = argv[aindex+1];
743 				}
744 			else
745 			if ( argv[aindex][1] == 'f' ){
746 				footerfile = argv[aindex+1];
747 				}
748 			else
749 			if (strstr(argv[aindex],"help")){
750 				fprintf(stderr,_HELP);
751 				exit(1);
752 				}
753 			else {
754 			/* if nothing fitted... then dump HELP!! */
755 				fprintf(stderr,_HELP);
756 				exit(1);
757 				}
758 			} /* if this was a '-' argument */
759 
760 		} /* for */
761 
762 
763 	/*
764 	 * Check for errors in the input...
765 	 *
766 	 */
767 
768 	if (!infile) {
769 		fprintf(stderr,"Error: I -need- an input JPEG file, use the -i option\n");
770 		exit(1);
771 		}
772 
773 	if (!outfile) {
774 		fprintf(stderr,"Error: output file PREFIX required, use the -p option\n");
775 		exit(1);
776 		}
777 
778 	if (!scriptfile) {
779 		fprintf(stderr,"Error: cutlist file not specified, use the -c option\n");
780 		exit(1);
781 		}
782 
783 	if (!quality) {
784 		fprintf(stderr,"Warning: quality not specified, using %d%%\n",_QUALITY_DEFAULT);
785 		quality = _QUALITY_DEFAULT;
786 		}
787 
788 	if ((quality > 100)||(quality < 1)) {
789 		fprintf(stderr,"Invalid JPEG quality setting, please choose a value between 1 and 100\n");
790 		exit(1);
791 		}
792 
793 
794 	/* Now, let us read the input JPEG file to the buffer */
795 	read_JPEG_file(infile);
796 
797 	/* Test to see if this picture isn't too large for our jslice program
798 	 */
799 	if ((image_width >= MAX_WIDTH) || (image_height >= MAX_HEIGHT)){
800 		fprintf(stderr,"Sorry, but jslice has been compiled only to handle pictures up to %d x %d pixels\n",MAX_WIDTH,MAX_HEIGHT);
801 		exit(1);
802 		}
803 
804 	/*
805 	 * We've gotten this far... now lets actually produce some results
806 	 */
807 
808 	/*
809 	 * Print my message
810 	 *
811 	 */
812 	fprintf(stdout,_MESSAGE);
813 
814 
815 	if (headerfile) {
816 		filetostdout(headerfile);
817 		}
818 
819 	script_cut(scriptfile, outfile, quality);
820 
821 	if (footerfile) {
822 		filetostdout(footerfile);
823 		}
824 
825 	return 0;
826 	}
827