home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / gif_sun / gif2sun.c < prev    next >
C/C++ Source or Header  |  1989-09-09  |  19KB  |  731 lines

  1. /*********************************************
  2.  *             GIF viewer on SUNVIEW         *
  3.  *                                           *
  4.  *      March 23 1989 By Marcel J.E. Mol     *
  5.  *                                           *
  6.  * I hereby place this program               *
  7.  * in the public domain, i.e. there are no   *
  8.  * copying restrictions of any kind.         *
  9.  *********************************************/
  10.  
  11. /* 
  12.  * Here is a gif viewer for the SUN running suntools (or sunview).
  13.  * It is intended for color monitors (8 planes) and I don't
  14.  * know how it will react on a monochrome screen.
  15.  * It is rather slow because it uses call to sunview for 
  16.  * each pixel. Should be converted to use rasterfiles one day...
  17.  * 
  18.  * Little help:
  19.  *     left button: exit a picture being drawn, and starts the following
  20.  *                  picture, if any.
  21.  *     right button: exit program immediately.
  22.  *     middle button: when a picture is ready pressing the middle button
  23.  *                    will start the following picture, if any.
  24.  * 
  25.  * Usage:
  26.  *        gif2sun [-sn -ln -b] <gif-files>
  27.  * 
  28.  *       -sn : tries to expand a picture n times.
  29.  *       -ln : number of lines to hold for sunview batch mode.
  30.  *       -b  : disable optimization done by not drawing pixels in 
  31.  *             the background color.
  32.  * 
  33.  * Compile:
  34.  *          cc gif2sun.c -o gif2sun -lsuntool -lsunwindow -lpixrect
  35.  * 
  36.  */ 
  37.  
  38. #define FAST
  39.  
  40. #include <stdio.h>
  41. #include <suntool/sunview.h>
  42. #include <suntool/panel.h>
  43. #include <suntool/canvas.h>
  44.  
  45. /* Change event_action to event_id(event) for pre 4.0 */
  46. #ifndef event_action
  47. #define event_action event_id
  48. #define oldSunOS
  49. #endif
  50.  
  51. #ifndef oldSunOS
  52. #include <suntool/alert.h>    /* Only for SunOS 4 */
  53. #include <alloca.h>        /* Cannot find this on 3.5 */
  54. #endif
  55.  
  56. char *malloc();
  57. int strncmp();
  58.  
  59. #define FALSE 0
  60. #define TRUE 1
  61. #define COLSIZE 256
  62. #define PICSIZE 1;
  63. #define SHOWCOUNT 10;
  64.  
  65. #define BUTTONFONT "/usr/lib/fonts/fixedwidthfonts/gallant.r.19"
  66. static char *default_font =
  67.        "DEFAULT_FONT=/usr/lib/fonts/fixedwidthfonts/screen.r.13";
  68.  
  69. /*
  70.  * Sunview variables 
  71.  */
  72. static Frame fr;
  73. static Canvas cv;
  74. static Pixwin *pw;
  75. static Panel pn;
  76. static Pixfont *bf, *pf;
  77.  
  78. /*
  79.  * LZW structures and variables
  80.  */
  81. typedef int bool;
  82. unsigned char *stackp;
  83. unsigned int prefix[4096];
  84. unsigned char suffix[4096];
  85. unsigned char stack[4096];
  86. int datasize,codesize,codemask;     /* Decoder working variables */
  87. int clear,eoi;                      /* Special code values */
  88. int avail;
  89. int oldcode;
  90.  
  91. /*
  92.  * GIF variables
  93.  */
  94. FILE *infile;
  95. unsigned int screenwidth;           /* The dimensions of the screen */
  96. unsigned int screenheight;          /*   (not those of the image)   */
  97. bool global;                        /* Is there a global color map? */
  98. int globalbits;                     /* Number of bits of global colors */
  99. unsigned char globalmap[COLSIZE][3];/* RGB values for global color map */
  100. char bgcolor;                       /* background color */
  101. unsigned char *raster;              /* Decoded image data */
  102. unsigned left,top,width,height;
  103.  
  104. char *progname;
  105. char *filename;
  106. unsigned int windowwidth = 0;
  107. unsigned int windowheight = 0;
  108. unsigned int size;                  /* scale factor */
  109.  
  110. unsigned int initsize = PICSIZE;
  111. int endpicflag = FALSE;
  112. int drawflag;
  113. unsigned int showcount = SHOWCOUNT;
  114. int dobgflag = FALSE;
  115.  
  116. void convert();
  117. int  checksignature();
  118. void readscreen();
  119. int  readimage();
  120. void readextension();
  121. int  readraster();
  122. int  process();
  123. void outcode();
  124. void initsunview();
  125. void setupsunview();
  126. void initcolors();
  127. int  rasterize();
  128. void waitevent();
  129. void handlevent();
  130. void usage();
  131.  
  132.  
  133.  
  134.  
  135. main(argc,argv)
  136. int argc;
  137. char *argv[];
  138. {
  139.     extern int optind;
  140.     extern char *optarg;
  141.     int flag;
  142.  
  143.     progname = *argv;
  144.     while ((flag = getopt(argc, argv, "s:l:b")) != EOF) {
  145.         switch (flag) {
  146.             case 's' : if ((initsize = atoi(optarg)) <= 0) {
  147.                            initsize = PICSIZE;
  148.                            fprintf(stderr, "scale factor must more than 1\n");
  149.                        }
  150.                        break;
  151.             case 'l' : if ((showcount = atoi(optarg)) <= 0) {
  152.                            showcount = SHOWCOUNT;
  153.                            fprintf(stderr, "showcount must more than 1\n");
  154.                        }
  155.                        break;
  156.             case 'b' : dobgflag = TRUE;
  157.                        break;
  158.             default  : fprintf(stderr, "ignoring unknown flag %c\n", flag);
  159.                        usage();
  160.         }
  161.     }
  162.  
  163.     initsunview();
  164.     if (optind >= argc) {
  165.         filename = "stdin";
  166.         convert();
  167.     }
  168.     else
  169.         while (optind < argc) {
  170.             filename = argv[optind];
  171.             optind++;
  172.             if ((infile = fopen(filename,"r")) == NULL) {
  173.                 perror(filename);
  174.                 continue;
  175.             }
  176.             convert();
  177.             fclose(infile);
  178.         }
  179.  
  180.     if (drawflag)        /* wait for last picture if fully drawn */
  181.         waitevent();
  182.  
  183. } /* main */
  184.  
  185.  
  186.  
  187. void convert()
  188. {
  189.     char ch;
  190.  
  191.     printf("%s:\n", filename);
  192.     if (checksignature())
  193.         return;
  194.     readscreen();
  195.     size = initsize;
  196.     while ((ch = getc(infile)) != ';' && ch != EOF) {
  197.         switch (ch) {
  198.             case '\0':  break;  /* this kludge for non-standard files */
  199.             case ',':   if (readimage())
  200.                            return;
  201.                         break;
  202.             case '!':   readextension();
  203.                         break;
  204.             default:    printf(stderr, "illegal GIF block type\n");
  205.                         return;
  206.                         break;
  207.         }
  208.     }
  209.  
  210. } /* convert */
  211.  
  212.  
  213.  
  214. checksignature()
  215. {
  216.     char buf[6];
  217.  
  218.     fread(buf,1,6,infile);
  219.     if (strncmp(buf,"GIF",3)) {
  220.         fprintf(stderr, "file is not a GIF file\n");
  221.         return 1;
  222.     }
  223.     if (strncmp(&buf[3],"87a",3)) {
  224.         fprintf(stderr, "unknown GIF version number\n");
  225.         return 1;
  226.     }
  227.     return 0;
  228.  
  229. } /* checksignature */
  230.  
  231.  
  232.  
  233. /*
  234.  * Get information which is global to all the images stored in the file
  235.  */
  236.  
  237. void readscreen()
  238. {
  239.     unsigned char buf[7];
  240.  
  241.     fread(buf,1,7,infile);
  242.     screenwidth = buf[0] + (buf[1] << 8);
  243.     screenheight = buf[2] + (buf[3] << 8);
  244.     global = buf[4] & 0x80;
  245.     if (global) {
  246.         globalbits = (buf[4] & 0x07) + 1;
  247.         fread(globalmap,3,1<<globalbits,infile);
  248.     }
  249.     bgcolor = buf[5];
  250.     printf("    global screen: %dx%dx%d, backgroundcolor: %d\n",
  251.                 screenwidth, screenheight, 1<<globalbits, bgcolor);
  252.  
  253. } /* readscreen */
  254.  
  255.  
  256.  
  257.  
  258. readimage()
  259. {
  260.     unsigned char buf[9];
  261.     bool local, interleaved;
  262.     char localmap[256][3];
  263.     int localbits;
  264.     register row;
  265.     register i;
  266.     static int waitflag = FALSE;
  267.  
  268.     fread(buf, 1, 9, infile);
  269.     left = buf[0] + (buf[1] << 8);
  270.     top = buf[2] + (buf[3] << 8);
  271.     width = buf[4] + (buf[5] << 8);
  272.     height = buf[6] + (buf[7] << 8);
  273.     local = buf[8] & 0x80;
  274.     interleaved = buf[8] & 0x40;
  275.     printf("    image: %dx%d %s  org: %d,%d\n", width, height,
  276.               interleaved ? "interleaved" : "", left, top);
  277.     if (local == 0 && global == 0) {
  278.         fprintf(stderr, "no colormap present for image\n");
  279.         return 1;
  280.     }
  281.     if ((raster = (unsigned char*) malloc(width*height)) == NULL) {
  282.         fprintf(stderr, "not enough memory for image\n");
  283.         return 1;
  284.     }
  285.     if (readraster(width, height))
  286.         return 1;
  287.  
  288.     if (waitflag)         /* if first picture or previous picture is   */
  289.         waitevent();      /* interrupted, don't wait for a buttonpress */
  290.  
  291.     setupsunview(screenwidth, screenheight);
  292.     if (local) {
  293.         localbits = (buf[8] & 0x7) + 1;
  294.         printf("   local colors: %d\n", 1<<localbits);
  295.         fread(localmap, 3, 1<<localbits, infile);
  296.         initcolors(localmap, 1<<localbits, bgcolor);
  297.     } else if (global)
  298.         initcolors(globalmap, 1<<globalbits, bgcolor);
  299.  
  300.     waitflag = rasterize(interleaved, raster);
  301.     free(raster);
  302.  
  303.     return 0;
  304.  
  305. } /* readimage */
  306.  
  307.  
  308.  
  309. /*
  310.  * Read a GIF extension block (and do nothing with it).
  311.  */
  312.  
  313. void readextension()
  314. {
  315.     unsigned char code;
  316.     int count;
  317.     char buf[255];
  318.  
  319.     code = getc(infile);
  320.     while (count = getc(infile)) fread(buf, 1, count, infile);
  321.  
  322. } /* readextension */
  323.  
  324.  
  325.  
  326. /*
  327.  * Decode a raster image
  328.  */
  329.  
  330. readraster(width, height)
  331. unsigned width,height;
  332. {
  333.         unsigned char *fill = raster;
  334.         unsigned char buf[255];
  335.         register bits=0;
  336.         register unsigned datum=0;
  337.         register unsigned char *ch;
  338.         register int count, code;
  339.  
  340.         datasize = getc(infile);
  341.         clear = 1 << datasize;
  342.         eoi = clear + 1;
  343.         avail = clear + 2;
  344.         oldcode = -1;
  345.         codesize = datasize + 1;
  346.         codemask = (1 << codesize) - 1;
  347.         for (code = 0; code < clear; code++) {
  348.             prefix[code] = 0;
  349.             suffix[code] = code;
  350.         }
  351.         stackp = stack;
  352.         for (count = getc(infile); count > 0; count = getc(infile)) {
  353.             fread(buf,1,count,infile);
  354.             for (ch=buf; count-- > 0; ch++) {
  355.                 datum += *ch << bits;
  356.                 bits += 8;
  357.                 while (bits >= codesize) {
  358.                     code = datum & codemask;
  359.                     datum >>= codesize;
  360.                     bits -= codesize;
  361.                     if (code == eoi) {               /* This kludge put in */
  362. #if defined(DEBUG)
  363.                         printf("found eoi code\n");
  364. #endif
  365.                         goto exitloop;               /* because some GIF files */
  366.                     }                                /* aren't standard */
  367.                     if (process(code, &fill)) 
  368.                         goto exitloop;
  369.                 }
  370.             }
  371.             if (fill >= raster + width*height) {
  372.                 fprintf(stderr, "raster full before eoi code\n");
  373.                 goto exitloop;
  374.             }
  375.         }
  376. exitloop:
  377.         if (fill != raster + width*height)  {
  378.             fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
  379.                       (long) (fill-raster));
  380.             fprintf(stderr, "         instead of %ld bytes\n",
  381.                       (long) width*height);
  382.             return 0;  /* but try to show picture ... */
  383.         }
  384.  
  385.         return 0;
  386.  
  387. } /* readraster */
  388.  
  389.  
  390.  
  391.  
  392. /*
  393.  * Process a compression code.  "clear" resets the code table.  Otherwise
  394.  * make a new code table entry, and output the bytes associated with the
  395.  * code.
  396.  */
  397.  
  398. process(code, fill)
  399. register code;
  400. unsigned char **fill;
  401. {
  402.         int incode;
  403.         static unsigned char firstchar;
  404.  
  405.         if (code == clear) {
  406. #if defined(DEBUG)
  407.             fprintf(stderr, "clear encountered\n");
  408. #endif
  409.             codesize = datasize + 1;
  410.             codemask = (1 << codesize) - 1;
  411.             avail = clear + 2;
  412.             oldcode = -1;
  413.             return 0;
  414.         }
  415.  
  416.         if (code > avail) {
  417.             fprintf(stderr, "code %d to large for %d\n", code, avail);
  418.             code = avail;
  419.             return 1;  
  420.         }
  421.  
  422.         if (oldcode == -1) {
  423.             *(*fill)++ = suffix[code];
  424.             firstchar = oldcode = code;
  425.             return 0;
  426.         }
  427.  
  428.         incode = code;
  429.         if (code == avail) {      /* the first code is always < avail */
  430.             *stackp++ = firstchar;
  431.             code = oldcode;
  432.         }
  433.         while (code > clear) {
  434.             *stackp++ = suffix[code];
  435.             code = prefix[code];
  436.         }
  437.  
  438.         *stackp++ = firstchar = suffix[code];
  439.         prefix[avail] = oldcode;
  440.         suffix[avail] = firstchar;
  441. if (avail < 4096)
  442.         avail++;
  443.  
  444.         if (((avail & codemask) == 0) && (avail < 4096)) {
  445.             codesize++;
  446.             codemask += avail;
  447.         }
  448. #if defined(DEBUG)
  449.         if (avail >= 4096) {
  450.             fprintf(stderr, "tables full, avail = %d\n", avail);
  451.         }
  452. #endif
  453.  
  454.         oldcode = incode;
  455.         do {
  456.             *(*fill)++ = *--stackp;
  457.         } while (stackp > stack);
  458.  
  459.         return 0;
  460.  
  461. } /* process */
  462.  
  463.  
  464.  
  465. void initsunview()
  466. {
  467.  
  468.    (void) putenv(default_font);
  469.     bf = pf_open(BUTTONFONT);
  470.     pf = pf_default();
  471.  
  472. } /* initsunview */
  473.  
  474.  
  475.  
  476. void setupsunview(width, height)
  477. unsigned width, height;
  478. {
  479.     static havewin = FALSE;
  480.     char title[128];
  481.     unsigned rwidth;
  482.  
  483.     rwidth = width + width%2;    /* compensate for odd width */
  484.     while ((size*rwidth > 1000) && (size > 1))
  485.         size--;
  486.     rwidth *= size;
  487.     height *= size;
  488.     if ((windowwidth < rwidth) || (windowheight < height)) {
  489.         windowwidth = rwidth;
  490.         windowheight = height;
  491. /*        if (havewin)    DESTROYING WINDOWS RESULT IN SEGMENTATION FAULTS 
  492.             window_destroy(fr); */
  493.         fr = window_create(0, FRAME,
  494.              WIN_X, 5,
  495.              WIN_Y, 50,
  496.              WIN_SHOW, TRUE,
  497.              FRAME_LABEL, "Gif to Sun",
  498.              0);
  499.         havewin = TRUE;
  500.         pn = window_create(fr, PANEL, 0);
  501.         panel_create_item(pn, PANEL_MESSAGE,
  502.                            PANEL_ITEM_X, 5,
  503.                            PANEL_ITEM_Y, 5,
  504.                            PANEL_LABEL_STRING, "File:",
  505.                            0);
  506.         window_fit_height(pn);
  507.         cv = window_create(fr, CANVAS,
  508.                    WIN_WIDTH, windowwidth,
  509.                    WIN_HEIGHT, windowheight,
  510.                    WIN_CONSUME_PICK_EVENT, LOC_DRAG, 
  511.                    WIN_EVENT_PROC, handlevent, 
  512.                    0);
  513.  
  514.         window_fit(fr);
  515.         pw = canvas_pixwin(cv);
  516.         notify_interpose_destroy_func(fr, handlevent);
  517.         pw_setcmsname(pw, "gif colors");
  518.     }
  519.  
  520.     notify_dispatch();     /* show the correct window */
  521.     sprintf(title, "%-20s", filename);
  522.     panel_pw_text(pn, 50, 5+panel_fonthome(pf), PIX_SRC, pf, title);
  523.  
  524. } /* setupsunview */
  525.  
  526.  
  527.  
  528. /*
  529.  * Convert a color map (local or global) to arrays with R, G and B
  530.  * values. Pass colors to SUNVIEW and set the background color.
  531.  */
  532.  
  533. void initcolors(colormap, ncolors, bgcolor)
  534. unsigned char colormap[COLSIZE][3];
  535. int ncolors;
  536. int bgcolor;
  537. {
  538.     register i;
  539.     unsigned char red[COLSIZE];
  540.     unsigned char green[COLSIZE];
  541.     unsigned char blue[COLSIZE];
  542.  
  543. #if defined(DEBUG)
  544.     printf("            ");
  545. #endif
  546.     for (i = 0; i < ncolors; i++) {
  547.         red[i]   = colormap[i][0];
  548.         green[i] = colormap[i][1];
  549.         blue[i]  = colormap[i][2];
  550. #if defined(DEBUG)
  551.         printf("   %3u: %3u, %3u, %3u", i, red[i], green[i], blue[i]);
  552.         if (i%3 == 2)
  553.             printf("\n            ");
  554. #endif
  555.     }
  556.     pw_putcolormap(pw, 0, COLSIZE, red, green, blue);
  557.  
  558. #if defined(DEBUG)
  559.     printf("\n      Background: %3u: %3u, %3u, %3u\n", bgcolor,
  560.                           red[bgcolor], green[bgcolor], blue[bgcolor]);
  561. #endif
  562.     pw_writebackground(pw, 0, 0, windowwidth, windowheight,
  563.                            PIX_SET | PIX_COLOR(bgcolor));
  564.  
  565. } /* initcolors */
  566.  
  567.  
  568.  
  569. /*
  570.  * Read a row out of the raster image and write it to the screen
  571.  */
  572. #ifdef FAST
  573. rasterize(interleaved, raster)
  574. int interleaved;
  575. register unsigned char *raster;
  576. {
  577.     register row, col;
  578.     register unsigned char *rr;
  579.     unsigned char * newras;
  580.     Pixrect *picture;
  581.     int rwidth;
  582.     
  583. #define DRAWSEGMENT(offset, step)                             \
  584.         for (row = offset; row < height; row += step) {       \
  585.             rr = newras + row*rwidth;                          \
  586.             bcopy(raster, rr, rwidth);                         \
  587.             raster += width;                                  \
  588.         }
  589.  
  590.  
  591.     panel_pw_text(pn, 250, 5+panel_fonthome(pf), PIX_SRC, pf, "Drawing");
  592.     drawflag = TRUE;
  593.     rwidth = width + width%2;    /* compensate for odd width */
  594.         if ((newras = (unsigned char*) malloc(rwidth*height)) == NULL) {
  595.             fprintf(stderr, "not enough memory for image\n");
  596.             return 1;
  597.         }
  598.     if (interleaved) {
  599.         DRAWSEGMENT(0, 8);
  600.         DRAWSEGMENT(4, 8);
  601.         DRAWSEGMENT(2, 4);
  602.         DRAWSEGMENT(1, 2);
  603.     }
  604.     else 
  605.        DRAWSEGMENT(0, 1);
  606. /*        newras = raster; */
  607.  
  608.     picture = mem_point(screenwidth, screenheight, 8, newras);
  609.     pw_rop(pw, left, top, width, height,
  610.                 PIX_SRC, picture, 0, 0); 
  611.  
  612.     /*if (interleaved) */
  613.         free(newras);
  614.     panel_pw_text(pn, 250, 5+panel_fonthome(pf), PIX_SET, pf, "       ");
  615.     return drawflag;
  616.  
  617. } /* rasterize */
  618.  
  619. #else
  620.  
  621. rasterize(interleaved, raster)
  622. int interleaved;
  623. register unsigned char *raster;
  624. {
  625.     register row, col;
  626.     register c, lc;
  627.    
  628. fprintf(stderr, " you use the slow version\n");
  629.  
  630. #define DRAWSEGMENT(offset, step)                                        \
  631.         for (row = top+offset; row < top+height; row += step) {          \
  632.             notify_dispatch();                                           \
  633.             if (!drawflag)                                               \
  634.                 goto quitdraw;                                           \
  635.             for (col = left; col < left+width; col++)                    \
  636.               if ((c = *raster++) != bgcolor || dobgflag)                \
  637.                 pw_rop(pw, size*col, size*row, size, size,               \
  638.                            PIX_SRC | PIX_COLOR(c), (Pixrect *) 0, 0, 0); \
  639.             if (lc++ == showcount) {                                     \
  640.                 lc = 0;                                                  \
  641.                 pw_show(pw);                                             \
  642.             }                                                            \
  643.         }
  644.  
  645.  
  646.     panel_pw_text(pn, 250, 5+panel_fonthome(pf), PIX_SRC, pf, "Drawing");
  647.     pw_batch_on(pw);
  648.     drawflag = TRUE;
  649.     lc = 0;
  650.     if (interleaved) {
  651.         DRAWSEGMENT(0, 8);
  652.         DRAWSEGMENT(4, 8);
  653.         DRAWSEGMENT(2, 4);
  654.         DRAWSEGMENT(1, 2);
  655.     }
  656.     else {
  657.         DRAWSEGMENT(0, 1);
  658.     }
  659.  
  660. quitdraw:
  661.     pw_batch_off(pw);
  662.     panel_pw_text(pn, 250, 5+panel_fonthome(pf), PIX_SRC, pf, "       ");
  663.     return drawflag;
  664.  
  665. } /* rasterize */
  666.  
  667. #endif
  668.  
  669.  
  670. void waitevent()
  671. {
  672.  
  673.     while(endpicflag == FALSE) {
  674.         notify_dispatch();
  675.         usleep(50000);
  676.     }
  677.     endpicflag = FALSE;
  678.  
  679. } /* waitevent */
  680.  
  681.  
  682.  
  683. void handlevent(canvas, event, arg)
  684. Canvas *canvas;
  685. Event *event;
  686. char *arg;
  687. {
  688.  
  689.     switch (event_action(event)) {
  690.         case MS_RIGHT:
  691.                 if (event_is_down(event))
  692. #ifdef oldSunOS
  693.                 exit(0);    /* You won't miss the following fancy stuff.. */
  694. #else
  695.                     if (alert_prompt(fr, (Event *)0, ALERT_MESSAGE_STRINGS,
  696.                   "Please confirm:", "Do you know what you're doing??",
  697.                   0,
  698.                   ALERT_BUTTON_YES, "Of course, quit bugging me!",
  699.                   ALERT_BUTTON_NO, "Sorry, I hit the wrong button...",
  700.                   ALERT_MESSAGE_FONT, bf,
  701.                   ALERT_BUTTON_FONT, pf,
  702.                   0)
  703.                           == ALERT_YES) 
  704.                         exit(0);
  705.                     else
  706.                         notify_veto_destroy(fr);
  707. #endif
  708.                 break;
  709.         case MS_LEFT:
  710.                 if (event_is_down(event))
  711.                     drawflag = FALSE;
  712.                 break;
  713.         case MS_MIDDLE:
  714.                 if (event_is_down(event))
  715.                     endpicflag = TRUE;
  716.                 break;
  717.     }
  718.  
  719. } /* handlevent */
  720.  
  721.  
  722.  
  723. void usage()
  724. {
  725.  
  726.         fprintf(stderr, "usage: %s [-l<num] [-s<num>] [-b] gif-files\n",
  727.                         progname);
  728.  
  729. } /* usage */
  730.  
  731.