home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / sldtoppm.c < prev    next >
C/C++ Source or Header  |  1993-12-14  |  19KB  |  644 lines

  1. /*
  2.  
  3.       Convert an AutoCAD slide (.sld) file to PPM format
  4.  
  5.     An AutoCAD slide is a compressed sequence of  vectors  and    filled
  6.     polygons.    The  ppmdraw  package  is  used  to scan convert these
  7.     geometrical objects into a portable pixmap.
  8.  
  9.     Author:
  10.         John Walker
  11.         Autodesk SA
  12.         Avenue des Champs-Montants 14b
  13.         CH-2074 MARIN
  14.         Switzerland
  15.         Usenet: kelvin@Autodesk.com
  16.         Fax:    038/33 88 15
  17.         Voice:  038/33 76 33
  18.  
  19.     Permission    to  use, copy, modify, and distribute this software and
  20.     its documentation  for  any  purpose  and  without    fee  is  hereby
  21.     granted,  without any conditions or restrictions.  This software is
  22.     provided "as is" without express or implied warranty.
  23.  
  24. */
  25.  
  26. #include "ppm.h"
  27. #include "ppmdraw.h"
  28. #ifdef DEBUG
  29. #include <assert.h>
  30. #else
  31. #define assert(x)
  32. #endif
  33.  
  34. /*  Define a variable type accepting numbers -127 <= n <= 127.    But note
  35.     that we still expect it to act UNSIGNED. */
  36.  
  37. #define smallint unsigned char          /* Small integers */
  38.  
  39. #define TRUE     1
  40. #define FALSE     0
  41.  
  42. #define EOS     '\0'
  43.  
  44. /* Screen point */
  45.  
  46. struct spoint {
  47.     int x, y;
  48. };
  49.  
  50. /* Screen polygon */
  51.  
  52. struct spolygon { 
  53.     int npoints,              /* Number of points in polygon */
  54.           fill;              /* Fill type */
  55.     struct spoint pt[11];          /* Actual points */
  56. };
  57.  
  58. /* Screen vector */
  59.  
  60. struct svector {
  61.     struct spoint f;          /* From point */
  62.     struct spoint t;          /* To point */
  63. };
  64.  
  65. static int extend ARGS((smallint ch));
  66. static int sli ARGS((void));
  67. static int slib ARGS((void));
  68. static void vscale ARGS((int *px, int *py));
  69. static void slider ARGS((void (*slvec) ARGS((struct svector *vec, int colour)),
  70.                     void (*slflood) ARGS((struct spolygon *poly, int colour)) ));
  71. static void slidefind ARGS((char *sname, int dironly, int ucasen));
  72. static void draw ARGS((struct svector *vec, int colour));
  73. static void flood ARGS((struct spolygon *poly, int colour));
  74.  
  75. static int ixdots, iydots;          /* Screen size in dots */
  76. static FILE *slfile;              /* Slide file descriptor */
  77. static int blither = FALSE;          /* Dump slide file information ? */
  78. static int info = FALSE;          /* Print header information */
  79. static pixel **pixels;              /* Pixel map */
  80. static int pixcols, pixrows;          /* Pixel map size */
  81. #define pixmaxval 255              /* Largest pixel value */
  82. static double uscale = -1;          /* Uniform scale factor */
  83. static int sxsize = -1, sysize = -1;  /* Scale to X, Y size ? */
  84.  
  85. #include "autocad.h"                  /* AutoCAD standard colour assignments */
  86.  
  87. /*  Local variables  */
  88.  
  89. struct slhead {
  90.     char slh[17];              /* Primate-readable header */
  91.     char sntype;              /* Machine type (for number compat) */
  92.     char slevel;              /* Format type */
  93.     short sxdots, sydots;          /* Display X, Y dots */
  94.     double sdsar;              /* Display aspect ratio */
  95.     short shwfill;              /* Display hardware fill type */
  96.     char spad;                  /* Pad to even byte length */
  97. };
  98.  
  99. static int adjust = FALSE;          /* Adjust to correct aspect ratio ? */
  100. static struct slhead slfrof;          /* Slide file header */
  101. static long xfac, yfac;           /* Aspect ratio scale factors */
  102.  
  103. static int sdrawkcab;              /* Slide drawing kinematic conversion of
  104.                      ass-backwards data flag */
  105.  
  106. /*  EXTEND  --    Turn a smallint into an int with sign extension, whether
  107.         or not that happens automatically.  */
  108.  
  109. static int extend(ch)
  110.   smallint ch;
  111. {
  112.     return ((int) ((ch & 0x80) ? (ch | ~0xFF) : ch));
  113. }
  114.  
  115. /*  SLI  --  Input word from slide file  */
  116.  
  117. static int sli()
  118. {
  119.     short wd;
  120.  
  121.     if (fread(&wd, sizeof wd, 1, slfile) != 1) {
  122.         pm_error("error reading slide file");
  123.     } else {
  124.     if (sdrawkcab) {
  125.         wd = ((wd >> 8) & 0xFF) | (wd << 8);
  126.     }
  127.     }
  128.     return wd;
  129. }
  130.  
  131. /*  SLIB  --  Input byte from slide file  */
  132.  
  133. static int slib()
  134. {
  135.     smallint ch = 0;
  136.  
  137.     if (fread(&ch, sizeof ch, 1, slfile) != 1) {
  138.         pm_error("error reading slide file");
  139.     }
  140.     return extend(ch);
  141. }
  142.  
  143. /*  VSCALE -- scale screen coordinates for mismatched display.    */
  144.  
  145. static void vscale(px, py)
  146.   int *px, *py;
  147. {
  148.     *px = (((unsigned) *px) * xfac) >> 16;
  149.     *py = (((unsigned) *py) * yfac) >> 16;
  150. }
  151.  
  152. /*  SLIDER  --    Read slide file.  This is called with the name of the
  153.         file to be read and function pointers to the routines
  154.         which process vectors and polygon fill requests
  155.         respectively.
  156. */
  157.  
  158. static void slider(slvec, slflood)
  159.   void (*slvec) ARGS((struct svector *vec, int colour));
  160.   void (*slflood) ARGS((struct spolygon *poly, int colour));
  161. {
  162.     int i, rescale;
  163.     unsigned char ubfr[4];          /* Utility character buffer */
  164.     int lx, ly;               /* Last x and y point */
  165.     int slx, sly;              /* Last x and y scaled screen point */
  166.     struct svector vec;           /* Screen vector */
  167.     struct spolygon poly;          /* Screen polygon */
  168.     unsigned short cw;              /* Control word */
  169.     double dsar;              /* Screen aspect ratio */
  170.     long ldsar;               /* Scaled long DSAR */
  171.     short rtest;              /* Value to test byte reversal */
  172.     short btest = 0x1234;          /* Value to test byte-reversal */
  173.     static struct slhead slhi =       /* Master slide header sample */
  174.         {"AutoCAD Slide\r\n\32", 86,2, 0,0, 0.0, 0};
  175.     int curcolour = 7;              /* Current vector colour */
  176.     pixel rgbcolour;              /* Pixel used to clear pixmap */
  177.  
  178.     lx = ly = 32000;
  179.  
  180.     /* Process the header of the slide file.  */
  181.  
  182.     sdrawkcab = FALSE;              /* Initially guess byte order is OK */
  183.     fread(slfrof.slh, 17, 1, slfile);
  184.     fread(&slfrof.sntype, sizeof(char), 1, slfile);
  185.     fread(&slfrof.slevel, sizeof(char), 1, slfile);
  186.     fread(&slfrof.sxdots, sizeof(short), 1, slfile);
  187.     fread(&slfrof.sydots, sizeof(short), 1, slfile);
  188.     fread(ubfr, 4, 1, slfile);
  189.     fread(&slfrof.shwfill, sizeof(short), 1, slfile);
  190.     fread(&rtest, sizeof rtest, 1, slfile);
  191.  
  192.     /* Verify that slide format is compatible with this program. */
  193.  
  194.     if (strcmp(slfrof.slh, slhi.slh) != 0) {
  195.         pm_error("this is not an AutoCAD slide file.");
  196.     }
  197.  
  198.     /* Verify that the number format and file level in the header  are
  199.        compatible.  All slides written by versions of AutoCAD released
  200.        since September of 1987 are compatible with this format.  */
  201.  
  202.     if ((slfrof.sntype != slhi.sntype) || (slfrof.slevel != slhi.slevel)) {
  203.         pm_error("incompatible slide file format");
  204.     }
  205.  
  206.     /* Build SDSAR value from long scaled version. */
  207.  
  208.     ldsar = 0L;
  209.     for (i = 3; i >= 0; i--) {
  210.     ldsar = (ldsar << 8) | ubfr[i];
  211.     }
  212.     slfrof.sdsar = ((double) ldsar) / 1E7;
  213.  
  214.     /* Examine the byte order test value.   If it's backwards, set the
  215.        byte-reversal flag and correct all of the values we've read  in
  216.        so far. */
  217.  
  218.     if (btest != rtest) {
  219.     sdrawkcab = TRUE;
  220. #define rshort(x) x = ((x >> 8) & 0xFF) | (x << 8)
  221.     rshort(slfrof.sxdots);
  222.     rshort(slfrof.sydots);
  223.     rshort(slfrof.shwfill);
  224. #undef rshort
  225.     }
  226.  
  227.     /* Dump the header if we're blithering. */
  228.  
  229.     if (blither || info) {
  230.         pm_message("Slide file type %d, level %d, hwfill type %d.",
  231.         slfrof.sntype, slfrof.slevel, slfrof.shwfill);
  232.         pm_message("Original screen size %dx%d, aspect ratio %.3f.",
  233.         slfrof.sxdots + 1, slfrof.sydots + 1, slfrof.sdsar);
  234.         pm_message("Byte order is %s.",
  235.             sdrawkcab ? "being reversed" : "the same");
  236.     }
  237.  
  238.     /* If the display aspect ratio indicates that the  pixels  on  the
  239.        sending    screen    were  not  square,  adjust  the  size  of  the
  240.        generated bitmap to correct the    aspect    ratio  to  square  the
  241.        pixels.
  242.  
  243.        We  always  correct  the aspect ratio by adjusting the width of
  244.        the image.  This guarantees that output from the SHADE command,
  245.        which  is  essentially  scan-line  data written in vector form,
  246.        will not be corrupted. */
  247.  
  248.     dsar = ((double) slfrof.sxdots) / slfrof.sydots;
  249.     if (abs(slfrof.sdsar - dsar) > 0.0001) {
  250.     if (adjust) {
  251.         ixdots = slfrof.sxdots * (slfrof.sdsar / dsar) + 0.5;
  252.         iydots = slfrof.sydots;
  253.         dsar = ((double) ixdots) / iydots;
  254.     } else {
  255.             pm_message("Warning - pixels on source screen were non-square.");
  256.             pm_message("          Specifying -adjust will correct image width to compensate.");
  257.         ixdots = slfrof.sxdots;
  258.         iydots = slfrof.sydots;
  259.         dsar = slfrof.sdsar;
  260.     }
  261.     } else {
  262.     /* Source pixels were square. */
  263.     ixdots = slfrof.sxdots;
  264.     iydots = slfrof.sydots;
  265.     dsar = slfrof.sdsar;
  266.     adjust = FALSE;           /* Mark no adjustment needed */
  267.     }
  268.  
  269.     /* If there's a uniform scale factor specified, apply it. */
  270.  
  271.     if (uscale > 0) {
  272.     ixdots = (ixdots * uscale) + 0.5;
  273.     iydots = (iydots * uscale) + 0.5;
  274.     }
  275.  
  276.     /* If the image is to be stretched    to  a  given  width,  set  the
  277.        output  image  sizes accordingly.  If only a height or width is
  278.        given, scale the other direction proportionally to preserve the
  279.        aspect ratio. */
  280.  
  281.     if (sxsize > 0) {
  282.     if (sysize > 0) {
  283.         iydots = sysize - 1;
  284.     } else {
  285.         iydots = ((((long) iydots) * (sxsize - 1)) +
  286.               (iydots / 2)) / ixdots;
  287.     }
  288.     ixdots = sxsize - 1;
  289.     } else if (sysize > 0) {
  290.     if (sxsize > 0) {
  291.         ixdots = sxsize - 1;
  292.     } else {
  293.         ixdots = ((((long) ixdots) * (sysize - 1)) +
  294.               (ixdots / 2)) / iydots;
  295.     }
  296.     iydots = sysize - 1;
  297.     }
  298.  
  299.     if (adjust) {
  300.     pm_message(
  301.             "Resized from %dx%d to %dx%d to correct pixel aspect ratio.",
  302.         slfrof.sxdots + 1, slfrof.sydots + 1, ixdots + 1, iydots + 1);
  303.     }
  304.  
  305.     /* Allocate image buffer and clear it to black. */
  306.  
  307.     pixels = ppm_allocarray(pixcols = ixdots + 1, pixrows = iydots + 1);
  308.     PPM_ASSIGN(rgbcolour, 0, 0, 0);
  309.     ppmd_filledrectangle(pixels, pixcols, pixrows, pixmaxval, 0, 0,
  310.      pixcols, pixrows, PPMD_NULLDRAWPROC,
  311.      (char *) &rgbcolour);
  312.  
  313.     if ((rescale = slfrof.sxdots != ixdots ||
  314.     slfrof.sydots != iydots ||
  315.     slfrof.sdsar != dsar) != 0) {
  316.  
  317.         /* Rescale all coords. so they'll look (more or less)
  318.        right on this display.  */
  319.  
  320.     xfac = (ixdots + 1) * 0x10000L;
  321.     xfac /= (long) (slfrof.sxdots + 1);
  322.     yfac = (iydots + 1) * 0x10000L;
  323.     yfac /= (long) (slfrof.sydots + 1);
  324.     if (dsar < slfrof.sdsar) {
  325.         yfac = yfac * dsar / slfrof.sdsar;
  326.        } else {
  327.         xfac = xfac * slfrof.sdsar / dsar;
  328.     }
  329.     }
  330.  
  331.     poly.npoints = 0;              /* No flood in progress. */
  332.  
  333.     while ((cw = sli()) != 0xFC00) {
  334.     switch (cw & 0xFF00) {
  335.         case 0xFB00:          /*  Short vector compressed  */
  336.         vec.f.x = lx + extend(cw & 0xFF);
  337.         vec.f.y = ly + slib();
  338.         vec.t.x = lx + slib();
  339.         vec.t.y = ly + slib();
  340.         lx = vec.f.x;
  341.         ly = vec.f.y;
  342.         if (rescale) {
  343.             vscale(&vec.f.x, &vec.f.y);
  344.             vscale(&vec.t.x, &vec.t.y);
  345.         }
  346.         (*slvec)(&vec, curcolour);/* Draw vector on screen */
  347.         slx = vec.f.x;          /* Save scaled point */
  348.         sly = vec.f.y;
  349.         break;
  350.  
  351.         case 0xFC00:          /*  End of file  */
  352.         break;
  353.  
  354.         case 0xFD00:          /*  Flood command  */
  355.         vec.f.x = sli();
  356.         vec.f.y = sli();
  357.         if ((int) vec.f.y < 0) { /* start or end */
  358.             if (poly.npoints != 0) { /* end?  */
  359.             if (poly.npoints > 2 && poly.npoints < 11) {
  360.                 (*slflood)(&poly, curcolour);
  361.             } else {
  362.                             pm_error("Bad polygon vertex count (%d)",
  363.                    poly.npoints);
  364.             }
  365.             poly.npoints = 0;
  366.             } else {
  367.             poly.fill = -vec.f.y;  /* Start */
  368.             }
  369.         } else {          /* Polygon vertex */
  370.             if (poly.npoints < 10) {
  371.             if (rescale) {
  372.                 vscale(&vec.f.x, &vec.f.y);
  373.             }
  374.             poly.pt[poly.npoints].x = vec.f.x;
  375.             poly.pt[poly.npoints].y = vec.f.y;
  376.             }
  377.             poly.npoints++;
  378.         }
  379.         break;
  380.  
  381.         case 0xFE00:          /*  Common endpoint compressed  */
  382.         vec.f.x = lx + extend(cw & 0xFF);
  383.         vec.f.y = ly + slib();
  384.         lx = vec.f.x;
  385.         ly = vec.f.y;
  386.         vec.t.x = slx;
  387.         vec.t.y = sly;
  388.         if (rescale) {
  389.             vscale(&vec.f.x, &vec.f.y);
  390.         }
  391.         (*slvec)(&vec, curcolour);/* Draw vector */
  392.         slx = vec.f.x;          /* Save scaled point */
  393.         sly = vec.f.y;
  394.         break;
  395.  
  396.         case 0xFF00:          /*  Change colour  */
  397.         curcolour = cw & 0xFF;
  398.         break;
  399.  
  400.         default:              /*  Co-ordinates    */
  401.         lx = vec.f.x = cw;
  402.         ly = vec.f.y = sli();
  403.         vec.t.x = sli();
  404.         vec.t.y = sli();
  405.         if (rescale) {
  406.            vscale(&vec.f.x, &vec.f.y);
  407.            vscale(&vec.t.x, &vec.t.y);
  408.         }
  409.         (*slvec)(&vec, curcolour);
  410.         slx = vec.f.x;          /* Save scaled point */
  411.         sly = vec.f.y;
  412.         break;
  413.     }
  414.     }
  415. }
  416.  
  417. /*  SLIDEFIND  --  Find  a  slide  in  a  library  or,    if  DIRONLY is
  418.            nonzero, print a directory listing of the  library.
  419.            If  UCASEN  is nonzero, the requested slide name is
  420.            converted to upper case. */
  421.  
  422. static void slidefind(sname, dironly, ucasen)
  423.   char *sname;
  424.   int dironly, ucasen;
  425. {
  426.     char uname[32];
  427.     unsigned char libent[36];
  428.     long pos;
  429.  
  430.     if (dironly) {
  431.         pm_message("Slides in library:");
  432.     } else {
  433.     int i;
  434.     char *ip = sname;
  435.  
  436.     for (i = 0; i < 31; i++) {
  437.         char ch = *ip++;
  438.         if (ch == EOS) {
  439.         break;
  440.         }
  441.         if (ucasen && islower(ch)) {
  442.         ch = toupper(ch);
  443.         }
  444.         uname[i] = ch;
  445.     }
  446.     uname[i] = EOS;
  447.     }
  448.  
  449.     /* Read slide library header and verify. */
  450.  
  451.     if ((fread(libent, 32, 1, slfile) != 1) ||
  452.         (strcmp((char *)libent, "AutoCAD Slide Library 1.0\015\012\32") != 0)) {
  453.         pm_error("not an AutoCAD slide library file.");
  454.     }
  455.     pos = 32;
  456.  
  457.     /* Search for a slide with the requested name. */
  458.  
  459.     while (TRUE) {
  460.     if ((fread(libent, 36, 1, slfile) != 1) ||
  461.         (strlen((char *)libent) == 0)) {
  462.         if (dironly) {
  463.         return;
  464.         }
  465.             pm_error("slide %s not in library.", sname);
  466.     }
  467.     pos += 36;
  468.     if (dironly) {
  469.             pm_message("  %s", libent);
  470.     } else if (strcmp((char *)libent, uname) == 0) {
  471.         long dpos = (((((libent[35] << 8) | libent[34]) << 8) |
  472.                  libent[33]) << 8) | libent[32];
  473.         if ((slfile == stdin) || (fseek(slfile, dpos, 0) == -1)) {
  474.         dpos -= pos;
  475.  
  476.         while (dpos-- > 0) {
  477.             (void) getc(slfile);
  478.         }
  479.         }
  480.         break;
  481.     }
  482.     }
  483. }
  484.  
  485. /*  DRAW  --  Draw a vector in the given AutoCAD colour.  */
  486.  
  487. static void draw(vec, colour)
  488.   struct svector *vec;
  489.   int colour;
  490. {
  491.     pixel rgbcolour;
  492.  
  493.     if (blither) {
  494.         pm_message("Vector (%d, %d) - (%d, %d)  Colour %d",
  495.            vec->f.x, vec->f.y, vec->t.x, vec->t.y, colour);
  496.     }
  497.     assert(vec->f.x >= 0 && vec->f.x < pixcols);
  498.     assert(vec->f.y >= 0 && vec->f.y < pixrows);
  499.     assert(vec->t.x >= 0 && vec->t.x < pixcols);
  500.     assert(vec->t.y >= 0 && vec->t.y < pixrows);
  501.     PPM_ASSIGN(rgbcolour,
  502.            acadcol[colour][0], acadcol[colour][1], acadcol[colour][2]);
  503.     ppmd_line(pixels, pixcols, pixrows, pixmaxval,
  504.           vec->f.x, iydots - vec->f.y, vec->t.x, iydots - vec->t.y,
  505.           PPMD_NULLDRAWPROC,
  506.           (char *) &rgbcolour);
  507. }
  508.  
  509. /*  FLOOD  --  Draw a filled polygon.  */
  510.  
  511. static void flood(poly, colour)
  512.   struct spolygon *poly;
  513.   int colour;
  514. {
  515.     int i;
  516.     char *handle = ppmd_fill_init();
  517.     pixel rgbcolour;
  518.  
  519.     if (blither) {
  520.         pm_message("Polygon: %d points, fill type %d, colour %d",
  521.            poly->npoints, poly->fill, colour);
  522.     for (i = 0; i < poly->npoints; i++) {
  523.            pm_message("   Point %d:  (%d, %d)", i + 1,
  524.               poly->pt[i].x, poly->pt[i].y);
  525.     }
  526.     }
  527.  
  528.     PPM_ASSIGN(rgbcolour,
  529.            acadcol[colour][0], acadcol[colour][1], acadcol[colour][2]);
  530.     for (i = 0; i < poly->npoints; i++) {
  531.     assert(poly->pt[i].x >= 0 && poly->pt[i].x < pixcols);
  532.     assert(poly->pt[i].y >= 0 && poly->pt[i].y < pixrows);
  533.     ppmd_line(pixels, pixcols, pixrows, pixmaxval,
  534.           poly->pt[i].x, iydots - poly->pt[i].y, 
  535.           poly->pt[(i + 1) % poly->npoints].x,
  536.           iydots - poly->pt[(i + 1) % poly->npoints].y,
  537.           ppmd_fill_drawproc, handle);
  538.     }
  539.     ppmd_fill(pixels, pixcols, pixrows, pixmaxval,
  540.           handle, PPMD_NULLDRAWPROC, (char *) &rgbcolour);
  541. }
  542.  
  543. /*  Main program. */
  544.  
  545. int main(argc, argv)
  546.   int argc;
  547.   char *argv[];
  548. {
  549.     int argn;
  550.     char *usage = "[-verbose] [-info] [-adjust] [-scale <s>]\n\
  551.                  [-dir] [-lib|-Lib <name>]\n\
  552.                  [-xsize|-width <x>] [-ysize|-height <y>] [sldfile]";
  553.     int scalespec = FALSE, widspec = FALSE, hgtspec = FALSE, dironly = FALSE,
  554.     ucasen;
  555.     char *slobber = (char *) 0;          /* Slide library item */
  556.  
  557.  
  558.     ppm_init(&argc, argv);
  559.     argn = 1;
  560.  
  561.     while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
  562.         if (pm_keymatch(argv[argn], "-verbose", 2)) {
  563.         blither = TRUE;
  564.         } else if (pm_keymatch(argv[argn], "-adjust", 2)) {
  565.         adjust = TRUE;
  566.         } else if (pm_keymatch(argv[argn], "-dir", 2)) {
  567.         dironly = TRUE;
  568.         } else if (pm_keymatch(argv[argn], "-info", 2)) {
  569.         info = TRUE;
  570.         } else if (pm_keymatch(argv[argn], "-lib", 2)) {
  571.         if (slobber != (char *) 0) {
  572.                 pm_error("already specified a library item");
  573.         }
  574.             ucasen = argv[argn][1] != 'L';
  575.         argn++;
  576.         if (argn == argc) {
  577.         pm_usage(usage);
  578.         }
  579.         slobber = argv[argn];
  580.         } else if (pm_keymatch(argv[argn], "-scale", 2)) {
  581.         if (scalespec) {
  582.                 pm_error("already specified a scale factor");
  583.         }
  584.         argn++;
  585.             if ((argn == argc) || (sscanf(argv[argn], "%lf", &uscale) != 1))
  586.         pm_usage(usage);
  587.         if (uscale <= 0.0) {
  588.                 pm_error("scale factor must be greater than 0");
  589.         }
  590.         scalespec = TRUE;
  591.         } else if (pm_keymatch(argv[argn], "-xsize", 2) ||
  592.                    pm_keymatch(argv[argn], "-width", 2)) {
  593.         if (widspec) {
  594.                 pm_error("already specified a width/xsize");
  595.         }
  596.         argn++;
  597.             if ((argn == argc) || (sscanf(argv[argn], "%d", &sxsize) != 1))
  598.         pm_usage(usage);
  599.         widspec = TRUE;
  600.         } else if (pm_keymatch(argv[argn], "-ysize", 2) ||
  601.                    pm_keymatch(argv[argn], "-height", 2)) {
  602.         if (hgtspec) {
  603.                 pm_error("already specified a height/ysize");
  604.         }
  605.         argn++;
  606.             if ((argn == argc) || (sscanf(argv[argn], "%d", &sysize) != 1))
  607.         pm_usage(usage);
  608.         hgtspec = TRUE;
  609.     } else {
  610.         pm_usage(usage);
  611.     }
  612.     argn++;
  613.     }
  614.  
  615.     /* If a file name is specified, open it.  Otherwise read from
  616.        standard input. */
  617.  
  618.     if (argn < argc) {
  619.     slfile = pm_openr(argv[argn]);
  620.     argn++;
  621.     } else {
  622.     slfile = stdin;
  623.     }
  624.  
  625.     if (argn != argc) {           /* Extra bogus arguments ? */
  626.     pm_usage(usage);
  627.     }
  628.  
  629.     /* If we're extracting an item from a slide library, position the
  630.        input stream to the start of the chosen slide. */
  631.  
  632.     if (dironly || (slobber != (char *) 0)) {
  633.     slidefind(slobber, dironly, ucasen);
  634.     }
  635.  
  636.     if (!dironly) {
  637.     slider(draw, flood);
  638.     ppm_writeppm(stdout, pixels, pixcols, pixrows, pixmaxval, FALSE);
  639.     }
  640.     pm_close(slfile);
  641.     pm_close(stdout);
  642.     exit(0);
  643. }
  644.