home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / popi / part03 < prev    next >
Text File  |  1991-08-22  |  61KB  |  2,319 lines

  1. Newsgroups: comp.sources.misc
  2. From: Rich Burridge <richb@Aus.Sun.COM>
  3. Subject:  v22i042:  popi - The Digital Darkroom, Part03/09
  4. Message-ID: <1991Aug22.165620.17321@sparky.IMD.Sterling.COM>
  5. X-Md4-Signature: aee1769fdbd1d4b66e51f73eedbf4110
  6. Date: Thu, 22 Aug 1991 16:56:20 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: Rich Burridge <richb@Aus.Sun.COM>
  10. Posting-number: Volume 22, Issue 42
  11. Archive-name: popi/part03
  12. Environment: Xlib, Xview, SunView
  13. Supersedes: popi: Volume 9, Issue 47-55
  14.  
  15. #! /bin/sh
  16. # 1. Remove everything above the #! /bin/sh line
  17. # 2. Save the resulting text in a file.
  18. # 3. Execute the file with /bin/sh to create the files:
  19. #    libpbm.c
  20. #    libpbm.h
  21. #    run.c
  22. #    special.c
  23. #    popi.icon
  24. # This archive created: Wed Aug 21 10:35:53 EST 1991
  25. #
  26. #
  27. export PATH; PATH=/bin:$PATH
  28. #
  29. if [ -f libpbm.c ]
  30. then
  31. echo shar: will not over-write existing file libpbm.c
  32. else
  33. echo shar: extracting 'libpbm.c',    15728 characters
  34. cat > libpbm.c <<'Funky_Stuff'
  35.  
  36. /*  @(#)libpbm.c 1.4 91/01/17
  37.  *
  38.  *  PBM/PGM/PPM routines used by the popi program.
  39.  *
  40.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  41.  *  This version is based on the code in his Prentice Hall book,
  42.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  43.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
  44.  *
  45.  *  Permission is given to distribute these extensions, as long as these
  46.  *  introductory messages are not removed, and no monies are exchanged.
  47.  *
  48.  *  No responsibility is taken for any errors or inaccuracies inherent
  49.  *  either to the comments or the code of this program, but if reported
  50.  *  (see README file) then an attempt will be made to fix them.
  51.  */
  52.  
  53. /*  Based on routines from the PBMPLUS utility libraries.
  54.  *
  55.  *  Copyright (C) 1989 by Jef Poskanzer.
  56.  *
  57.  *  Permission to use, copy, modify, and distribute this software and its
  58.  *  documentation for any purpose and without fee is hereby granted, provided
  59.  *  that the above copyright notice appear in all copies and that both that
  60.  *  copyright notice and this permission notice appear in supporting
  61.  *  documentation.  This software is provided "as is" without express or
  62.  *  implied warranty.
  63.  */
  64.  
  65. #include <stdio.h>
  66. #include "popi.h"
  67. #include "libpbm.h"
  68.  
  69. static bit   pbm_getbit P(( FILE * )) ;
  70. static char  pbm_getc   P(( FILE * )) ;
  71.  
  72. static unsigned char pbm_getrawbyte P(( FILE * )) ;
  73.  
  74. static int pbm_getint           P(( FILE * )) ;
  75. static int pbm_readmagicnumber  P(( FILE * )) ;
  76.  
  77. static void pbm_readpbminitrest P(( FILE *, int *, int *)) ;
  78. static void pgm_readpgminitrest P(( FILE *, int *, int *, gray * )) ;
  79. static void ppm_readppminitrest P(( FILE *, int *, int *, pixval * )) ; 
  80.  
  81. static void pm_error   P(( char *, char *, char *, char *, char *, char * )) ;
  82. static void pm_message P(( char *, char *, char *, char *, char *, char * )) ;
  83. static void pm_perror  P(( char * )) ;
  84.  
  85. static void pbm_readpbmrow       P(( FILE *, bit *,   int, int)) ;
  86.  
  87. static void pgm_writepgmrowraw   P(( FILE *, gray *,  int, gray)) ;
  88. static void pgm_writepgmrowplain P(( FILE *, gray *,  int, gray)) ;
  89. static void ppm_writeppmrowraw   P(( FILE *, pixel *, int, pixval)) ;
  90. static void ppm_writeppmrowplain P(( FILE *, pixel *, int, pixval)) ;
  91.  
  92. static char *pm_progname ;
  93.  
  94. static bit  *bitrow ;
  95. static gray *grayrow ;
  96.  
  97. int pm_iserror = FALSE ;
  98.  
  99.  
  100. static bit
  101. pbm_getbit(file)
  102. FILE *file ;
  103. {
  104.   register char ch ;
  105.  
  106.   do
  107.     {
  108.       ch = pbm_getc(file) ;
  109.     }
  110.   while (ch == ' ' || ch == '\t' || ch == '\n') ;
  111.  
  112.   if (ch != '0' && ch != '1')
  113.     pm_error("junk in file where bits should be",
  114.              (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  115.  
  116.   return((ch == '1') ? 1 : 0) ;
  117. }
  118.  
  119.  
  120. static char
  121. pbm_getc(file)
  122. FILE *file ;
  123. {
  124.   register int ich ;
  125.   register char ch ;
  126.  
  127.   ich = getc(file) ;
  128.   if (ich == EOF)
  129.     pm_error("premature EOF",
  130.              (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  131.   ch = (char) ich ;
  132.  
  133.   if (ch == '#')
  134.     {
  135.       do
  136.         {
  137.           ich = getc(file) ;
  138.           if (ich == EOF)
  139.             pm_error("premature EOF", (char *) 0, (char *) 0,
  140.                                       (char *) 0, (char *) 0, (char *) 0) ;
  141.           ch = (char) ich ;
  142.         }
  143.       while ( ch != '\n' );
  144.     }
  145.   return(ch) ;
  146. }
  147.  
  148.  
  149. static unsigned char
  150. pbm_getrawbyte(file)
  151. FILE *file ;
  152. {
  153.   register int iby ;
  154.      
  155.   iby = getc(file) ;
  156.   if (iby == EOF)
  157.     pm_error("premature EOF",
  158.              (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  159.   return((unsigned char) iby) ;
  160. }
  161.  
  162.  
  163. static int
  164. pbm_getint(file)
  165. FILE *file ;
  166. {
  167.   register char ch ;
  168.   register int i ;
  169.  
  170.   do
  171.     {
  172.       ch = pbm_getc(file) ;
  173.       if (pm_iserror == TRUE) return(0) ;
  174.     }
  175.   while (ch == ' ' || ch == '\t' || ch == '\n') ;
  176.  
  177.   if (ch < '0' || ch > '9')
  178.     {
  179.       pm_error("junk in file where an integer should be",
  180.                (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  181.       return(0) ;
  182.     }
  183.  
  184.   i = 0 ;
  185.   do
  186.     {
  187.       i = i * 10 + ch - '0' ;
  188.       ch = pbm_getc(file) ;
  189.       if (pm_iserror == TRUE) return(0) ;
  190.     }
  191.   while (ch >= '0' && ch <= '9') ;
  192.  
  193.   return(i) ;
  194. }
  195.  
  196.  
  197. static int
  198. pbm_readmagicnumber(file)
  199. FILE *file ;
  200. {
  201.   int ich1, ich2 ;
  202.      
  203.   ich1 = getc(file) ;
  204.   if (ich1 == EOF)
  205.     pm_error("premature EOF reading magic number",
  206.              (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  207.   ich2 = getc(file) ;
  208.   if (ich2 == EOF)
  209.     pm_error("premature EOF reading magic number",
  210.               (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  211.   return(ich1 * 256 + ich2) ;
  212. }
  213.  
  214.  
  215. static void
  216. pbm_readpbminitrest(file, colsP, rowsP)
  217. FILE *file ;
  218. int *colsP, *rowsP ;
  219. {
  220.   *colsP = pbm_getint(file) ;      /* Read size. */
  221.   *rowsP = pbm_getint(file) ;
  222. }
  223.  
  224.  
  225. static void
  226. pbm_readpbmrow(file, bitrow, cols, format)
  227. FILE *file ;
  228. bit *bitrow ;
  229. int cols, format ;
  230. {
  231.   register int col, bitshift ;
  232.   register unsigned char item ;
  233.   register bit *bP ;
  234.  
  235.   switch (format)
  236.     {
  237.       case PBM_FORMAT  : for (col = 0, bP = bitrow; col < cols; col++, bP++)
  238.                            *bP = pbm_getbit(file) ;
  239.                          break ;
  240.  
  241.       case RPBM_FORMAT : bitshift = -1 ;
  242.                          for (col = 0, bP = bitrow; col < cols; col++, bP++)
  243.                            {
  244.                              if (bitshift == -1)
  245.                                {
  246.                                  item = pbm_getrawbyte(file) ;
  247.                                  bitshift = 7 ;
  248.                                }
  249.                              *bP = (item >> bitshift) & 1 ;
  250.                              bitshift-- ;
  251.                            }
  252.                          break ;
  253.  
  254.       default          : pm_error("can't happen", (char *) 0, (char *) 0,
  255.                                       (char *) 0, (char *) 0, (char *) 0) ;
  256.     }
  257. }
  258.  
  259.  
  260. static void
  261. pgm_readpgminitrest(file, colsP, rowsP, maxvalP)
  262. FILE *file ;
  263. int *colsP, *rowsP ;
  264. gray *maxvalP ;
  265. {
  266.   *colsP = pbm_getint(file) ;         /* Read size. */
  267.   *rowsP = pbm_getint(file) ;
  268.  
  269.   *maxvalP = pbm_getint(file) ;       /* Read maxval. */
  270.   if (*maxvalP > PGM_MAXMAXVAL)
  271.     pm_error("maxval too large - %d > %d\n",
  272.              (char *) *maxvalP, (char *) PGM_MAXMAXVAL,
  273.              (char *) 0, (char *) 0, (char *) 0) ;
  274. }
  275.  
  276.  
  277. /*ARGSUSED*/
  278. void
  279. pgm_readpgmrow(file, grayrow, cols, maxval, format)
  280. FILE *file ;
  281. gray *grayrow ;
  282. int cols, format ;
  283. gray maxval ;
  284. {
  285.   register int col ;
  286.   register gray *gP ;
  287.   register bit *bP ;
  288.  
  289.   switch (format)
  290.     {
  291.       case PGM_FORMAT  : for (col = 0, gP = grayrow; col < cols; col++, gP++)
  292.                            {
  293.                              *gP = pbm_getint(file) ;
  294.                              if (pm_iserror == TRUE) return ;
  295.                            }
  296.                          break ;
  297.  
  298.       case RPGM_FORMAT : for (col = 0, gP = grayrow; col < cols; col++, gP++)
  299.                            {
  300.                              *gP = pbm_getrawbyte(file) ;
  301.                              if (pm_iserror == TRUE) return ;
  302.                            }
  303.                          break ;
  304.  
  305.       case PBM_FORMAT  :
  306.       case RPBM_FORMAT : pbm_readpbmrow(file, bitrow, cols, format) ;
  307.                          gP = grayrow ;
  308.                          bP = bitrow ;
  309.                          for (col = 0; col < cols; col++, gP++, bP++)
  310.                            *gP = (*bP == PBM_WHITE) ? maxval : 0 ;
  311.                          break ;
  312.  
  313.       default          : pm_error("can't happen", (char *) 0, (char *) 0,
  314.                                       (char *) 0, (char *) 0, (char *) 0) ;
  315.     }
  316. }
  317.  
  318.  
  319. void
  320. pgm_writepgminit(file, cols, rows, maxval)
  321. FILE *file ;
  322. int cols, rows ;
  323. gray maxval ;
  324. {
  325.   if (maxval <= 255)
  326.     FPRINTF(file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, RPGM_MAGIC2,
  327.             cols, rows, maxval) ;
  328.   else
  329.     FPRINTF(file, "%c%c\n%d %d\n%d\n", PGM_MAGIC1, PGM_MAGIC2,
  330.             cols, rows, maxval) ;
  331. }
  332.  
  333.  
  334. void
  335. pgm_writepgmrow(file, grayrow, cols, maxval)
  336. FILE *file ;
  337. gray *grayrow ;
  338. int cols ;
  339. gray maxval ;
  340. {
  341.   if (maxval <= 255) pgm_writepgmrowraw(file,   grayrow, cols, maxval) ;
  342.   else               pgm_writepgmrowplain(file, grayrow, cols, maxval) ;
  343. }
  344.  
  345.  
  346. /*ARGSUSED*/
  347. static void
  348. pgm_writepgmrowraw(file, grayrow, cols, maxval)
  349. FILE *file ;
  350. gray *grayrow ;
  351. int cols ;
  352. gray maxval ;
  353. {
  354.   register int col ;
  355.   register gray *gP ;
  356.  
  357.   for (col = 0, gP = grayrow; col < cols; col++, gP++)
  358.     if (putc((char) *gP, file) == EOF) pm_perror((char *) 0) ;
  359. }
  360.  
  361.  
  362. /*ARGSUSED*/
  363. static void
  364. pgm_writepgmrowplain(file, grayrow, cols, maxval)
  365. FILE *file ;
  366. gray *grayrow ;
  367. int cols ;
  368. gray maxval ;
  369. {
  370.   register int col, charcount ;
  371.   register gray *gP ;
  372.  
  373.   charcount = 0 ;
  374.   for (col = 0, gP = grayrow; col < cols; col++, gP++)
  375.     {
  376.       if (charcount >= 70)
  377.         {
  378.           if (putc('\n', file) == EOF) pm_perror((char *) 0) ;
  379.           charcount = 0 ;
  380.         }
  381.       if (putus((unsigned int) *gP, file) == EOF) pm_perror((char *) 0) ;
  382.       if (putc(' ', file) == EOF) pm_perror((char *) 0) ;
  383.       charcount += 4 ;
  384.     }    
  385.   if (putc('\n', file) == EOF) pm_perror((char *) 0) ;
  386. }
  387.  
  388.  
  389. char *
  390. pm_allocrow(cols, size)
  391. int cols ;
  392. {    
  393.   register char *itrow ;
  394.  
  395.   itrow = (char *) malloc((unsigned int) (cols * size)) ;
  396.   if (itrow == (char *) 0)
  397.     pm_error("out of memory allocating a row",
  398.              (char *) 0, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  399.   return(itrow) ;
  400. }
  401.  
  402.  
  403. static void
  404. pm_error(fmt, v1, v2, v3, v4, v5)
  405. char *fmt, *v1, *v2, *v3, *v4, *v5 ;
  406. {
  407.   pm_message(fmt, v1, v2, v3, v4, v5) ;
  408.   pm_iserror = TRUE ;
  409. }
  410.  
  411.  
  412. void
  413. pm_freerow(itrow)
  414. char *itrow ;
  415. {
  416.   FREE(itrow) ;
  417. }
  418.  
  419.  
  420. static void
  421. pm_message(fmt, v1, v2, v3, v4, v5)
  422. char *fmt, *v1, *v2, *v3, *v4, *v5 ;
  423. {
  424.   FPRINTF(stderr, "%s: ", pm_progname) ;
  425.   FPRINTF(stderr, fmt, v1, v2, v3, v4, v5) ;
  426.   FPUTC('\n', stderr) ;
  427. }
  428.  
  429.  
  430. static void
  431. pm_perror(reason)
  432. char *reason ;
  433. {
  434.   extern char *sys_errlist[] ;
  435.   extern int errno ;
  436.   char *e ;
  437.  
  438.   if (errno == 0) e = "end of file" ;        /* Not particularly kosher. */
  439.   else            e = sys_errlist[errno] ;
  440.  
  441.   if (reason != 0 && reason[0] != '\0')
  442.     pm_error("%s - %s", reason, e, (char *) 0, (char *) 0, (char *) 0) ;
  443.   else
  444.     pm_error("%s", e, (char *) 0, (char *) 0, (char *) 0, (char *) 0) ;
  445. }
  446.  
  447.  
  448. void
  449. ppm_readppminit(file, colsP, rowsP, maxvalP, formatP)
  450. FILE *file ;
  451. int *colsP, *rowsP, *formatP ;
  452. pixval *maxvalP ;
  453. {
  454.   *formatP = pbm_readmagicnumber(file) ;      /* Check magic number. */
  455.   switch (*formatP)
  456.     {
  457.       case PPM_FORMAT  :
  458.       case RPPM_FORMAT : ppm_readppminitrest(file, colsP, rowsP, maxvalP) ;
  459.                          break ;
  460.  
  461.       case PGM_FORMAT  :
  462.       case RPGM_FORMAT : pgm_readpgminitrest(file, colsP, rowsP, maxvalP) ;
  463.                          grayrow = pgm_allocrow(*colsP) ;
  464.                          break ;
  465.  
  466.       case PBM_FORMAT  :
  467.       case RPBM_FORMAT : pbm_readpbminitrest(file, colsP, rowsP) ;
  468.                          *maxvalP = PPM_PBMMAXVAL ;
  469.                          bitrow = pbm_allocrow(*colsP) ;
  470.                          break ;
  471.  
  472.       default          : *formatP = OLD_POPI_FORMAT ;  /* Let's hope it is. */
  473.                          rewind(file) ;
  474.     }
  475. }
  476.  
  477.  
  478. static void
  479. ppm_readppminitrest(file, colsP, rowsP, maxvalP)
  480. FILE *file ;
  481. int *colsP, *rowsP ;
  482. pixval *maxvalP ;
  483. {
  484.   *colsP = pbm_getint(file) ;      /* Read size. */
  485.   *rowsP = pbm_getint(file) ;
  486.  
  487.   *maxvalP = pbm_getint(file) ;    /* Read maxval. */
  488.   if (*maxvalP > PPM_MAXMAXVAL)
  489.     pm_error("maxval too large - %d > %d",
  490.              (char *) *maxvalP, (char *) PPM_MAXMAXVAL,
  491.              (char *) 0, (char *) 0, (char *) 0) ;
  492. }
  493.  
  494.  
  495. void
  496. ppm_readppmrow(file, pixelrow, cols, maxval, format)
  497. FILE *file ;
  498. pixel *pixelrow ;
  499. int cols, format ;
  500. pixval maxval ;
  501. {
  502.   register int col ;
  503.   register pixel *pP ;
  504.   register pixval r, g, b ;
  505.   register gray *gP ;
  506.  
  507.   switch (format)
  508.     {
  509.       case PPM_FORMAT  : for (col = 0, pP = pixelrow; col < cols; col++, pP++)
  510.                            {
  511.                              r = pbm_getint(file) ;
  512.                              g = pbm_getint(file) ;
  513.                              b = pbm_getint(file) ;
  514.                              if (pm_iserror == TRUE) return ;
  515.                              PPM_ASSIGN(*pP, r, g, b) ;
  516.                            }
  517.                          break ;
  518.  
  519.       case RPPM_FORMAT : for (col = 0, pP = pixelrow; col < cols; col++, pP++)
  520.                            {
  521.                              r = pbm_getrawbyte(file) ;
  522.                              g = pbm_getrawbyte(file) ;
  523.                              b = pbm_getrawbyte(file) ;
  524.                              if (pm_iserror == TRUE) return ;
  525.                              PPM_ASSIGN(*pP, r, g, b) ;
  526.                            }
  527.                          break ;
  528.  
  529.       case PGM_FORMAT  :
  530.       case RPGM_FORMAT : pgm_readpgmrow(file, grayrow, cols, maxval, format) ;
  531.                          gP = grayrow ;
  532.                          pP = pixelrow ;
  533.                          for (col = 0; col < cols; col++, gP++, pP++)
  534.                            {
  535.                              r = *gP ;
  536.                              if (pm_iserror == TRUE) return ;
  537.                              PPM_ASSIGN(*pP, r, r, r) ;
  538.                            }
  539.                          break ;
  540.  
  541.       default          : pm_error("can't happen", (char *) 0, (char *) 0,
  542.                                       (char *) 0, (char *) 0, (char *) 0) ;
  543.     }
  544. }
  545.  
  546.  
  547. void
  548. ppm_writeppminit(file, cols, rows, maxval)
  549. FILE *file ;
  550. int cols, rows ;
  551. pixval maxval ;
  552. {
  553.   if (maxval <= 255)
  554.     FPRINTF(file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, RPPM_MAGIC2,
  555.             cols, rows, maxval) ;
  556.   else
  557.     FPRINTF(file, "%c%c\n%d %d\n%d\n", PPM_MAGIC1, PPM_MAGIC2,
  558.             cols, rows, maxval) ;
  559. }
  560.  
  561.  
  562. void
  563. ppm_writeppmrow(file, pixelrow, cols, maxval)
  564. FILE *file ;
  565. pixel *pixelrow ;
  566. int cols ;
  567. pixval maxval ;
  568. {
  569.   if (maxval <= 255) ppm_writeppmrowraw(file, pixelrow, cols, maxval) ;
  570.   else               ppm_writeppmrowplain(file, pixelrow, cols, maxval) ;
  571. }
  572.  
  573.  
  574. /*ARGSUSED*/
  575. static void
  576. ppm_writeppmrowraw(file, pixelrow, cols, maxval)
  577. FILE *file ;
  578. pixel *pixelrow ;
  579. int cols ;
  580. pixval maxval ;
  581. {
  582.   register int col ;
  583.   register pixel *pP ;
  584.   register pixval val ;
  585.  
  586.   for (col = 0, pP = pixelrow; col < cols; col++, pP++)
  587.     {
  588.       val = PPM_GETR(*pP) ;
  589.       if (putc((char) val, file) == EOF) pm_perror((char *) 0) ;
  590.       val = PPM_GETG(*pP) ;
  591.       if (putc((char) val, file) == EOF) pm_perror((char *) 0) ;
  592.       val = PPM_GETB(*pP) ;
  593.       if (putc((char) val, file) == EOF) pm_perror((char *) 0) ;
  594.     }
  595. }
  596.  
  597.  
  598. /*ARGSUSED*/
  599. static void
  600. ppm_writeppmrowplain(file, pixelrow, cols, maxval)
  601. FILE *file ;
  602. pixel *pixelrow ;
  603. int cols;
  604. pixval maxval ;
  605. {
  606.   register int col, charcount ;
  607.   register pixel *pP ;
  608.   register pixval val ;
  609.  
  610.   charcount = 0 ;
  611.   for (col = 0, pP = pixelrow; col < cols; col++, pP++)
  612.     {
  613.       if (charcount >= 70)
  614.         {
  615.           if (putc('\n', file) == EOF) pm_perror((char *) 0) ;
  616.           charcount = 0 ;
  617.         }
  618.       val = PPM_GETR(*pP) ;
  619.       if (putus(val, file) == EOF) pm_perror((char *) 0) ;
  620.       if (putc(' ', file)  == EOF) pm_perror((char *) 0) ;
  621.       val = PPM_GETG(*pP) ;
  622.       if (putus(val, file) == EOF) pm_perror((char *) 0) ;
  623.       if (putc(' ', file)  == EOF) pm_perror((char *) 0) ;
  624.       val = PPM_GETB(*pP) ;
  625.       if (putus(val, file) == EOF) pm_perror((char *) 0) ;
  626.       if (putc(' ', file)  == EOF) pm_perror((char *) 0) ;
  627.       if (putc(' ', file)  == EOF) pm_perror((char *) 0) ;
  628.       charcount += 13 ;
  629.     }
  630.   if (putc('\n', file) == EOF) pm_perror((char *) 0) ;
  631. }
  632.  
  633.  
  634. static int
  635. putus(n, file)
  636. unsigned int n ;
  637. FILE *file ;
  638. {
  639.   if (n >= 10)
  640.     if (putus(n / 10, file) == EOF) return(EOF) ;
  641.   return(putc((char) (n % 10 + '0'), file)) ;
  642. }
  643. Funky_Stuff
  644. len=`wc -c < libpbm.c`
  645. if [ $len !=    15728 ] ; then
  646. echo error: libpbm.c was $len bytes long, should have been    15728
  647. fi
  648. fi # end of overwriting check
  649. if [ -f libpbm.h ]
  650. then
  651. echo shar: will not over-write existing file libpbm.h
  652. else
  653. echo shar: extracting 'libpbm.h',     3227 characters
  654. cat > libpbm.h <<'Funky_Stuff'
  655.  
  656. /*  @(#)libpbm.h 1.4 91/01/17
  657.  *
  658.  *  PBM/PGM/PPM definitions used by the popi program.
  659.  *
  660.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  661.  *  This version is based on the code in his Prentice Hall book,
  662.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  663.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc.
  664.  *
  665.  *  Permission is given to distribute these extensions, as long as these
  666.  *  introductory messages are not removed, and no monies are exchanged.
  667.  *
  668.  *  No responsibility is taken for any errors or inaccuracies inherent
  669.  *  either to the comments or the code of this program, but if reported
  670.  *  (see README file) then an attempt will be made to fix them.
  671.  */
  672.  
  673. /*  Based on definitions from the PBMPLUS utility libraries.
  674.  *
  675.  *  Copyright (C) 1989 by Jef Poskanzer.
  676.  *
  677.  *  Permission to use, copy, modify, and distribute this software and its
  678.  *  documentation for any purpose and without fee is hereby granted, provided
  679.  *  that the above copyright notice appear in all copies and that both that
  680.  *  copyright notice and this permission notice appear in supporting
  681.  *  documentation.  This software is provided "as is" without express or
  682.  *  implied warranty.
  683.  */
  684.  
  685. typedef unsigned char bit ;
  686. typedef unsigned char gray ;
  687. typedef gray          pixval ;
  688.  
  689. typedef struct {
  690.   pixval r, g, b ;
  691. } pixel ;
  692.  
  693. #define  OLD_POPI_FORMAT  -1
  694.  
  695. #define  PBM_WHITE      0
  696. #define  PBM_BLACK      1
  697.  
  698. #define  PBM_MAGIC1     'P'
  699. #define  PBM_MAGIC2     '1'
  700. #define  RPBM_MAGIC2    '4'
  701. #define  PBM_FORMAT     (PBM_MAGIC1 * 256 + PBM_MAGIC2)
  702. #define  RPBM_FORMAT    (PBM_MAGIC1 * 256 + RPBM_MAGIC2) 
  703. #define  PPM_PBMMAXVAL  1
  704.  
  705. #define  PGM_MAGIC1     'P'
  706. #define  PGM_MAGIC2     '2'
  707. #define  RPGM_MAGIC2    '5'
  708. #define  PGM_FORMAT     (PGM_MAGIC1 * 256 + PGM_MAGIC2)
  709. #define  RPGM_FORMAT    (PGM_MAGIC1 * 256 + RPGM_MAGIC2)
  710. #define  PGM_MAXMAXVAL  255
  711.  
  712. #define  PPM_MAGIC1     'P'
  713. #define  PPM_MAGIC2     '3'
  714. #define  RPPM_MAGIC2    '6'
  715. #define  PPM_FORMAT     (PPM_MAGIC1 * 256 + PPM_MAGIC2)
  716. #define  RPPM_FORMAT    (PPM_MAGIC1 * 256 + RPPM_MAGIC2)
  717. #define  PPM_MAXMAXVAL  PGM_MAXMAXVAL
  718.  
  719. #define  pbm_allocrow(cols)     ((bit *)   pm_allocrow(cols, sizeof(bit)))
  720. #define  pgm_allocrow(cols)     ((gray *)  pm_allocrow(cols, sizeof(gray)))
  721. #define  ppm_allocrow(cols)     ((pixel *) pm_allocrow(cols, sizeof(pixel)))
  722.  
  723. #define  pgm_freerow(grayrow)   pm_freerow((char *) grayrow)
  724. #define  ppm_freerow(pixelrow)  pm_freerow((char *) pixelrow)
  725.  
  726. #define  PPM_GETR(p)            ((p).r)
  727. #define  PPM_GETG(p)            ((p).g)
  728. #define  PPM_GETB(p)            ((p).b)
  729. #define  PPM_ASSIGN(p, red, grn, blu) \
  730.          do { (p).r = (red) ; (p).g = (grn) ; (p).b = (blu) ; } while (0)
  731.  
  732. char *pm_allocrow P(( int, int )) ;
  733.  
  734. void pgm_readpgmrow   P(( FILE *, gray *, int, gray, int )) ;
  735. void pgm_writepgminit P(( FILE *, int, int, gray )) ;
  736. void pgm_writepgmrow  P(( FILE *, gray *, int, gray )) ;
  737. void pm_freerow       P(( char * )) ;
  738. void ppm_readppminit  P(( FILE *, int *, int *, pixval *, int * )) ;
  739. void ppm_readppmrow   P(( FILE *, pixel *, int, pixval, int )) ;
  740. void ppm_writeppminit P(( FILE *, int, int, pixval )) ;
  741. void ppm_writeppmrow  P(( FILE *, pixel *, int, pixval )) ;
  742.  
  743. Funky_Stuff
  744. len=`wc -c < libpbm.h`
  745. if [ $len !=     3227 ] ; then
  746. echo error: libpbm.h was $len bytes long, should have been     3227
  747. fi
  748. fi # end of overwriting check
  749. if [ -f run.c ]
  750. then
  751. echo shar: will not over-write existing file run.c
  752. else
  753. echo shar: extracting 'run.c',    14422 characters
  754. cat > run.c <<'Funky_Stuff'
  755.  
  756. /*  @(#)run.c 1.4 91/08/21
  757.  *
  758.  *  Run time interpreter used by the popi program.
  759.  *
  760.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  761.  *  This version is based on the code in his Prentice Hall book,
  762.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  763.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
  764.  *
  765.  *  Permission is given to distribute these extensions, as long as these
  766.  *  introductory messages are not removed, and no monies are exchanged.
  767.  *
  768.  *  No responsibility is taken for any errors or inaccuracies inherent
  769.  *  either to the comments or the code of this program, but if reported
  770.  *  (see README file) then an attempt will be made to fix them.
  771.  */
  772.  
  773. #include <ctype.h>
  774. #include "popi.h"
  775.  
  776. #if        SEQPAR
  777. #include <parallel/microtask.h>
  778. #endif  /* SEQPAR */
  779.  
  780. #define  STACKSIZE  128
  781.  
  782. #define  dop(OP)    a = *--sp ; tp = sp-1 ; *tp = (*tp OP (stack_t) a)
  783.  
  784. /* Local function prototypes */
  785.  
  786. void prun P((void)) ;
  787.  
  788.  
  789. void
  790. SwapOldNew()
  791. {
  792.   struct SRC *tmp ;
  793.  
  794.   tmp = CurOld ;
  795.   CurOld = CurNew ;
  796.   CurNew = tmp ;
  797. }
  798.  
  799.  
  800. static void
  801. prun()
  802. {
  803.   long *ParseEnd ;     /* After end of parse string */
  804.   int color ;
  805.   int x ;
  806.   int y ;              /* Coordinates */
  807.   int nrange = 0 ;     /* No. range errors */
  808.  
  809.   ParseEnd = &parsed[prs] ;
  810.  
  811. #ifndef NDEBUG
  812.   if (Debug)
  813.     {
  814.       register long *CurrParse ;  /* Pointer to current item in parse string */
  815.  
  816.       FPRINTF(Debug, "Parse string\n") ;
  817.       for (CurrParse = parsed; CurrParse != ParseEnd; ++CurrParse)
  818.         FPRINTF(Debug, "'%c' (%ld)\n", (char) *CurrParse, *CurrParse) ;
  819.       FPRINTF(Debug, "---\n") ;
  820.     }
  821. #endif /* NDEBUG */
  822.  
  823. /*  Warning: Microsoft Quick C generates incorrect code for the following
  824.  *  loop when optimisation is turned on.
  825.  */
  826.  
  827. #ifndef SEQPAR
  828.     for (y = 0; y < Ysize; ++y)
  829. #else  /* ! SEQPAR */
  830.     for (y = m_myid; y < Ysize; y += m_numprocs)
  831. #endif  /* ! SEQPAR */
  832.       {
  833.         short *ap ;    /* Precalculated polar angles */
  834.         short *rp ;    /* Precalculated polar radius */
  835.         register pixel_t *pixp ;    /* Default destination */
  836.  
  837.         ap = &avals[y * Xsize] ;
  838.         rp = &rvals[y * Xsize] ;
  839.  
  840.         for (color = 0; color < colors; ++color)
  841.           {
  842.             pixp = CurNew->pix[y][color] ;
  843.  
  844.             DEBUG((Debug, "y = %d\n", y)) ;
  845.             for (x = 0; x < Xsize; ++x, ++pixp)
  846.               {
  847.                 stack_t Stack[STACKSIZE] ;   /* The stack */
  848.                 register stack_t *sp ;       /* Stack pointer (top of stack) */
  849.                 register stack_t *tp ;       /* Temp stack pointer */
  850.                 stack_t a ;
  851.                 stack_t b ;
  852.                 int c ;                      /* Scratch */
  853.                 register pixel_t *u ;        /* Explicit destination */
  854.                 register long *CurrParse ;   /* Pointer to current item */
  855.                                              /* in parse string */
  856.  
  857.                 for (CurrParse = parsed, sp = Stack; CurrParse != ParseEnd;
  858.                      ++CurrParse)
  859.                   {
  860.                     switch ((int) *CurrParse)
  861.                       {
  862.  
  863.         case OP_VALUE : *sp++ = (stack_t) *++CurrParse ;
  864.                         continue ;
  865.  
  866.         case OP_AT    : --sp ;
  867.                         if (Truncate)
  868.                           {
  869.                                  if (*sp > Zmax) *sp = Zmax ;
  870.                             else if (*sp < 0) *sp = 0 ;
  871.                           }
  872.                         *pixp = (pixel_t) *sp ;
  873.                         continue ;
  874.  
  875.         case OP_PLUS  : dop(+) ;
  876.                         break ;
  877.  
  878.         case OP_MINUS : dop(-) ;
  879.                         break ;
  880.  
  881.         case OP_MUL   : dop(*) ;
  882.                         break ;
  883.  
  884.         case OP_DIV   : a = *--sp ;
  885.                         tp = sp-1 ;
  886.                         if (a == 0) *tp = Zmax ;
  887.                         else *tp = (*tp / (stack_t) a) ;
  888.                         break ;
  889.  
  890.         case OP_MOD   : a = *--sp ;
  891.                         tp = sp-1 ;
  892.                         if (a == 0) *tp = 0 ;
  893.                         else *tp = (*tp % (stack_t) a) ;
  894.                         break ;
  895.  
  896.         case OP_GT    : dop(>) ;
  897.                         break ;
  898.  
  899.         case OP_LT    : dop(<) ;
  900.                         break ;
  901.  
  902.         case OP_GE    : dop(>=) ;
  903.                         break ;
  904.  
  905.         case OP_LE    : dop(<=) ;
  906.                         break ;
  907.  
  908.         case OP_EQ    : dop(==) ;
  909.                         break ;
  910.  
  911.         case OP_NE    : dop(!=) ;
  912.                         break ;
  913.  
  914.         case OP_CAND  : dop(&&) ;
  915.                         break ;
  916.  
  917.         case OP_COR   : dop(||) ;
  918.                         break ;
  919.  
  920.         case OP_XOR   : dop(^) ;
  921.                         break ;
  922.  
  923.         case OP_OR    : dop(|) ;
  924.                         break ;
  925.  
  926.         case OP_AND   : dop(&) ;
  927.                         break ;
  928.  
  929.         case OP_X     : *sp++ = (stack_t) x ;
  930.                         break ;
  931.  
  932.         case OP_Y     : *sp++ = (stack_t) y ;
  933.                         break ;
  934.  
  935.         case OP_UMIN  : tp = sp-1 ;
  936.                         *tp = -(*tp) ;
  937.                         break ;
  938.  
  939.         case OP_NOT   : tp = sp-1 ;
  940.                         *tp = !(*tp) ;
  941.                         break ;
  942.  
  943.         case OP_ASGN  : a = *--sp ;
  944.                         u = (pixel_t *) *--sp ;
  945.                         if (Truncate)
  946.                           {
  947.                                  if (a > Zmax) a = Zmax ;
  948.                             else if (a < 0) a = 0 ;
  949.                           }
  950.                         *u = (pixel_t) a ;
  951.                         break ;
  952.  
  953.         case OP_CRVAL : a = *--sp ;              /* y */
  954.                         b = *--sp ;              /* x */
  955.                         tp = sp-1 ;
  956.                         c = (int) *tp ;
  957.                         if (RangeCheck &&
  958.                             (a > Xsize - 1 || a < 0 ||
  959.                              b > Ysize - 1 || b < 0))
  960.                           {
  961.                             if (nrange++ == 0)
  962.                               FPRINTF(stderr,
  963.                                       "Range err at (%d,%d) => %s[%d, %d]\n",
  964.                                       x, y, Images[c].str, b, a) ;
  965.                           }
  966.                         if (a >= Ysize) a = Ysize - 1 ;
  967.                         if (a < 0)      a = 0 ;
  968.                         if (b >= Xsize) b = Xsize - 1 ;
  969.                         if (b < 0)      b = 0 ;
  970.                         *tp = (stack_t) Images[c].pix[a][color][b] ;
  971.                         break ;
  972.  
  973.         case OP_CLVAL : a = *--sp ;              /* y */
  974.                         b = *--sp ;              /* x */
  975.                         tp = sp-1 ;
  976.                         c = (int) *tp ;
  977.                         if (RangeCheck &&
  978.                             (a > Xsize - 1 || a < 0 ||
  979.                              b > Ysize - 1 || b < 0))
  980.                           {
  981.                             if (nrange++ == 0)
  982.                               FPRINTF(stderr,
  983.                                       "Range err at (%d,%d) => %s[%d, %d]\n",
  984.                                       x, y, Images[c].str, b, a) ;
  985.                           }
  986.                         if (a >= Ysize) a = Ysize - 1 ;
  987.                         if (a < 0)      a = 0 ;
  988.                         if (b >= Xsize) b = Xsize - 1 ;
  989.                         if (b < 0)      b = 0 ;
  990.                         *tp = (stack_t)
  991.                               &(Images[c].pix[a][color][b]) ;
  992.                         break ;
  993.  
  994.         case OP_PRVAL : {
  995.                           int xval ;
  996.                           int yval ;
  997.     
  998.                           a = *--sp ;    /* Angle */
  999.                           b = *--sp ;    /* Radius */
  1000.  
  1001.                           xval = (int) (b * cos((double) DtoR(a)) +
  1002.                                         Xsize / 2.0) ;
  1003.                           yval = (int) (- b * sin((double) DtoR(a)) +
  1004.                                         Ysize / 2.0) ;
  1005.  
  1006.                           tp = sp - 1 ;
  1007.                           c = (int) *tp ;
  1008.  
  1009.                           if (RangeCheck &&
  1010.                               (xval < 0 || xval >= Xsize ||
  1011.                                yval < 0 || yval >= Ysize))
  1012.                             {
  1013.                               if (nrange++ == 0)
  1014.                                 FPRINTF(stderr,
  1015.                                  "Range err at (%d,%d) => %s{%d,%d} [%d,%d]\n",
  1016.                                  x, y, Images[c].str, b, a, xval, yval) ;
  1017.                             }
  1018.  
  1019.                           if (xval < 0)      xval = 0 ;
  1020.                           if (xval >= Xsize) xval = Xsize - 1 ;
  1021.                           if (yval < 0)      yval = 0 ;
  1022.                           if (yval >= Ysize) yval = Ysize - 1 ;
  1023.  
  1024.                           *tp = (stack_t) Images[c].pix[yval][color][xval] ;
  1025.                         }
  1026.                         break ;
  1027.  
  1028.         case OP_PLVAL : {
  1029.                           int xval ;
  1030.                           int yval ;
  1031.  
  1032.                           a = *--sp ;    /* Angle */
  1033.                           b = *--sp ;    /* Radius */
  1034.  
  1035.                           xval = (int) (b * cos((double) DtoR(a)) +
  1036.                                         Xsize / 2.0) ;
  1037.                           yval = (int) (- b * sin((double) DtoR(a)) +
  1038.                                         Ysize / 2.0) ;
  1039.  
  1040.                           tp = sp - 1 ;
  1041.                           c = (int) *tp ;
  1042.  
  1043.                           if (RangeCheck &&
  1044.                               (xval < 0 || xval >= Xsize ||
  1045.                                yval < 0 || yval >= Ysize))
  1046.                             {
  1047.                               if (nrange++ == 0)
  1048.                                 FPRINTF(stderr,
  1049.                                   "Range err at (%d,%d) => %s{%d,%d} [%d,%d]\n",
  1050.                                   x, y, Images[c].str, b, a, xval, yval) ;
  1051.                             }
  1052.  
  1053.                           if (xval < 0)      xval = 0 ;
  1054.                           if (xval >= Xsize) xval = Xsize - 1 ;
  1055.                           if (yval < 0)      yval = 0 ;
  1056.                           if (yval >= Ysize) yval = Ysize - 1 ;
  1057.  
  1058.                           *tp = (stack_t) &(Images[c].pix[yval][color][xval]) ;
  1059.                         }
  1060.                         break ;
  1061.  
  1062.         case OP_POW   : a = *--sp ;     /* Exponent */
  1063.                         tp = sp-1 ;
  1064.                         *tp = (stack_t)
  1065.                               pow((double) *tp, (double) a) ;
  1066.                         break ;
  1067.  
  1068.         case OP_A     :
  1069. #if        NOMEM
  1070.                         *sp++ = (stack_t)
  1071.                                 RtoD(atan2((double) y, (double) x)) + 0.5 ;
  1072. #else  /* !NOMEM */
  1073.                         *sp++ = (stack_t) *ap ;
  1074. #endif  /* !NOMEM */
  1075.                         break ;
  1076.  
  1077.         case OP_R     : *sp++ = (stack_t) *rp ;
  1078.                         break ;
  1079.  
  1080.         case OP_SIN   : tp = sp-1 ;
  1081.                         *tp = (stack_t)
  1082.                               (sin((double) DtoR(*tp)) * (double) Zmax) ;
  1083.                         break ;
  1084.  
  1085.         case OP_COS   : tp = sp-1 ;
  1086.                         *tp = (stack_t)
  1087.                               (cos((double) DtoR(*tp)) * (double) Zmax) ;
  1088.                         break ;
  1089.  
  1090.         case OP_ATAN  : a = *--sp ;
  1091.                         tp = sp-1 ;
  1092.                         *tp = (stack_t)
  1093.                               RtoD(atan2((double) *tp, (double) a)) ;
  1094.                         break ;
  1095.  
  1096.         case OP_HYPOT : a = *--sp ;
  1097.                         tp = sp - 1 ;
  1098.                         *tp = (stack_t) hypot((double) *tp, (double) a) ;
  1099.                         break ;
  1100.  
  1101.         case OP_ABS   : tp = sp-1 ;
  1102.                         *tp = *tp < 0 ? - *tp : *tp ;
  1103.                         break ;
  1104.  
  1105.         case OP_LOG   : tp = sp-1 ;
  1106.                         *tp = (stack_t) log((double) *tp) ;
  1107.                         break ;
  1108.  
  1109.         case OP_SQRT  : tp = sp-1 ;
  1110.                         *tp = (stack_t) sqrt((double) *tp) ;
  1111.                         break ;
  1112.  
  1113.         case OP_RAND  : *sp++ = (stack_t) RANDOM ;
  1114.                         break ;
  1115.  
  1116.         case OP_LSHIFT : dop(<<) ;
  1117.                          break ;
  1118.  
  1119.         case OP_RSHIFT : dop(>>) ;
  1120.                          break ;
  1121.  
  1122.         case OP_CONDIT : a = *--sp ;
  1123.                          CurrParse++ ;
  1124.                          if (!a)
  1125.                            CurrParse = &parsed[*CurrParse] ;
  1126.                          break ;
  1127.  
  1128.         case OP_COLON  : CurrParse = &parsed[CurrParse[1]] ;
  1129.                          break ;
  1130.  
  1131.         default        : if (*CurrParse < 127 && isprint(*CurrParse))
  1132.                            SPRINTF(ErrBuf, "run: unknown operator '%c' (%d)",
  1133.                                    *CurrParse, *CurrParse) ;
  1134.                          else
  1135.                            SPRINTF(ErrBuf, "run: unknown operator %d",
  1136.                                    *CurrParse) ;
  1137.                          error(ERR_SNARK) ;
  1138.                          return ;
  1139.                       }
  1140.                   }
  1141.                 ++ap ;
  1142.                 ++rp ;
  1143.               }
  1144.           }
  1145.  
  1146. #if  SEQPAR
  1147.         if (m_myid == 0)
  1148. #endif  /* SEQPAR */
  1149.           disp_percentdone(y * 100 / (Ysize-1)) ;
  1150.       }
  1151. }
  1152.  
  1153.  
  1154. void
  1155. run()
  1156. {
  1157.   int y ;
  1158.   pixel_t ***linep ;
  1159.  
  1160. #if  SEQPAR
  1161.   static int parked = 0 ;
  1162.  
  1163.   if (parked)
  1164.     m_rele_procs() ;
  1165.   m_fork(prun) ;
  1166.   m_kill_procs() ;     /* For some reason, parking doesn't work properly ...
  1167.   m_park_procs() ;
  1168.   parked = 1 ;         /* so it can be released above */
  1169. #else  /* ! SEQPAR */
  1170.   prun() ;
  1171. #endif  /* ! SEQPAR */
  1172.  
  1173.   disp_percentdone(100) ;  /* Can rely on '100' to terminate */
  1174.  
  1175.   if (disp_active)
  1176.     {
  1177.       disp_imgstart() ;
  1178.       for (linep = CurNew->pix, y = 0; y != Ysize; ++linep, ++y)
  1179.         disp_putline(*linep, y) ;
  1180.       disp_imgend() ;
  1181.     }
  1182.  
  1183.   SwapOldNew() ;
  1184. }
  1185.  
  1186.  
  1187. /*  Convert the three RGB lines into one NTSC luma line, for display
  1188.  *  on grayscale devices.  (Just pass pointer along if colors == 1)
  1189.  */
  1190.  
  1191. pixel_t*
  1192. ntsc_luma(lines)
  1193. pixel_t **lines ;
  1194. {
  1195.   int x ;
  1196.   static pixel_t *p = 0 ;
  1197.  
  1198.   if (colors == 1) return(lines[0]) ;
  1199.  
  1200.   if (p == NULL)
  1201.     p = (pixel_t *) Emalloc((unsigned)Xsize * sizeof(pixel_t)) ;
  1202.  
  1203.   for (x = 0; x < Xsize; x++)
  1204.     p[x] = lines[0][x] * 0.299 +       /* R */
  1205.            lines[1][x] * 0.587 +       /* G */
  1206.            lines[2][x] * 0.114 ;       /* B */
  1207.  
  1208.   return(p) ;
  1209. }
  1210. Funky_Stuff
  1211. len=`wc -c < run.c`
  1212. if [ $len !=    14422 ] ; then
  1213. echo error: run.c was $len bytes long, should have been    14422
  1214. fi
  1215. fi # end of overwriting check
  1216. if [ -f special.c ]
  1217. then
  1218. echo shar: will not over-write existing file special.c
  1219. else
  1220. echo shar: extracting 'special.c',    23621 characters
  1221. cat > special.c <<'Funky_Stuff'
  1222.  
  1223. /*  @(#)special.c 1.5 91/08/20
  1224.  *
  1225.  *  Special transformations used by the popi program.
  1226.  *
  1227.  *  Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
  1228.  *  This version is based on the code in his Prentice Hall book,
  1229.  *  "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
  1230.  *  which is copyright (c) 1988 by Bell Telephone Laboratories, Inc. 
  1231.  *
  1232.  *  Permission is given to distribute these extensions, as long as these
  1233.  *  introductory messages are not removed, and no monies are exchanged.
  1234.  *
  1235.  *  No responsibility is taken for any errors or inaccuracies inherent
  1236.  *  either to the comments or the code of this program, but if reported
  1237.  *  (see README file) then an attempt will be made to fix them.
  1238.  */
  1239.  
  1240. /*  Special transformations from chapter 6 of BP.
  1241.  *
  1242.  *  The way this is done is fairly nasty at the moment, but it does work.
  1243.  */
  1244.  
  1245. #include <sys/types.h>
  1246. #include <ctype.h>
  1247. #include <time.h>
  1248.  
  1249. #ifdef      BSD
  1250. #include <sys/timeb.h>
  1251. #endif   /* BSD */
  1252.  
  1253. #include "popi.h"
  1254. #include "lex.h"
  1255.  
  1256. #define  GAMMA     7.5    /* Default gamma for matte() */
  1257. #define  TILESIZE  25     /* Default tile size for tile() */
  1258. #define  N         3      /* Default blur size for oil() */
  1259.  
  1260. #define  New      (CurNew->pix)
  1261.  
  1262. /* ANSI prototypes for local functions */
  1263.  
  1264. struct SRC *parseimg P((void)) ;
  1265.  
  1266. bool parsefname P((void)) ;
  1267.  
  1268. void CloseLog P((FILE **)) ;
  1269. void displayimg P((void)) ;
  1270. void debug P((void)) ;
  1271. void dolog P((void)) ;
  1272. void dosigned P((void)) ;
  1273. void freeimg P((void)) ;
  1274. void genepson P((void)) ;
  1275. void genps P((void)) ;
  1276. void imtrunc P((void)) ;
  1277. void list P((void)) ;
  1278. void matte P((void)) ;
  1279. void melt P((void)) ;
  1280. void oil P((void)) ;
  1281. void ofmt P((void)) ;
  1282. void readimg P((void)) ;
  1283. void shear P((void)) ;
  1284. void slice P((void)) ;
  1285. void tile P((void)) ;
  1286. void undo P((void)) ;
  1287. void verbose P((void)) ;
  1288. void writeimg P((void)) ;
  1289.  
  1290. struct SpecialOp
  1291. {
  1292.   char *name, *notes ;
  1293.   void (*func) P((void)) ;
  1294. } ;
  1295.  
  1296. static struct SpecialOp SpecialOps[] = {   /* Also update popi.1 */
  1297.   { "debug",          "",                         debug },
  1298.   { "display",        "[+|-|image]",              displayimg },
  1299.   { "free",           "image",                    freeimg },
  1300.   { "genepson",       "\"filename\" [image]",     genepson },
  1301.   { "genps",          "\"filename\" [image]",     genps },
  1302.   { "help",           "",                         help },
  1303.   { "list",           "",                         list },
  1304.   { "logfile",        "[+|-|\"filename\"]",       dolog },
  1305.   { "matte",          "[image [gamma]]",          matte },
  1306.   { "melt",           "[image]",                  melt },
  1307.   { "ofmt",           "[+|-]",                    ofmt },
  1308.   { "oil",            "[image]",                  oil },
  1309.   { "read",           "\"filename\" [image]",     readimg },
  1310.   { "shear",          "[image]",                  shear },
  1311.   { "signed",         "[+|-]",                    dosigned },
  1312.   { "slice",          "[image]",                  slice },
  1313.   { "tile",           "[image]",                  tile },
  1314.   { "truncate",       "[+|-]",                    imtrunc },
  1315.   { "undo",           "",                         undo },
  1316.   { "verbose",        "[+|-]",                    verbose },
  1317.   { "version",        "",                         version },
  1318.   { "write",          "\"filename\" [image]",     writeimg },
  1319.   { (char *) 0,       (char *) 0,                 (void (*) P((void)) ) 0 }
  1320. } ;
  1321.  
  1322.  
  1323. /* Convenience function, since most of these routines have
  1324.  * an image as their 1st parameter.
  1325.  */
  1326.  
  1327. static struct SRC *
  1328. parseimg()
  1329. {
  1330.   lex() ;
  1331.  
  1332.   if (lat == '\n' || lat == ')')
  1333.     {
  1334.       pushback(lat) ;
  1335.       return CurOld ;
  1336.     }
  1337.  
  1338.   if (lat != T_INAME)
  1339.     {
  1340.       SPRINTF(ErrBuf, "Expected image name") ;
  1341.       error(ERR_PARSE) ;
  1342.       return (struct SRC *) 0 ;
  1343.     }
  1344.  
  1345.   return &Images[lexval] ;
  1346. }
  1347.  
  1348.  
  1349. static bool
  1350. parsefname()
  1351. {
  1352.   lex() ;
  1353.  
  1354.   if (lat == '\n') pushback(lat) ;
  1355.  
  1356.   if (lat != T_FNAME)
  1357.     {
  1358.       SPRINTF(ErrBuf, "Expected file name") ;
  1359.       error(ERR_PARSE) ;
  1360.       return FALSE ;
  1361.     }
  1362.   return TRUE ;
  1363. }
  1364.  
  1365.  
  1366. static void
  1367. oil()
  1368. {
  1369.   register int color, x, y ;
  1370.   register int dx, dy ;
  1371.   pixel_t mfp ;
  1372.   static int *histo = 0 ;
  1373.   struct SRC *srcp ;
  1374.   pixel_t ***img ;
  1375.  
  1376.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1377.   img = srcp->pix ;
  1378.  
  1379.   if (histo == (int *) 0 &&
  1380.       (histo = (int *)
  1381.        LINT_CAST(Emalloc((unsigned)Zsize * sizeof (int)))) == (int *) 0)
  1382.     return ;
  1383.  
  1384.   if (disp_active) disp_imgstart() ;
  1385.  
  1386.   for (y = N; y < Ysize-N; y++)
  1387.     {
  1388.       for (x = N; x < Xsize-N; x++)
  1389.         {
  1390.           for (dx = 0; dx < Zsize; dx++) histo[dx] = 0 ;
  1391.           for (dy = y-N; dy <= y+N; dy++)
  1392.             for (dx = x-N; dx <= x+N; dx++)
  1393.               for (color = 0; color < colors; ++color)
  1394.                 histo[img[dy][color][dx]]++ ;
  1395.  
  1396.           for (dx = dy = 0; dx < Zsize; dx++)
  1397.             if (histo[dx] > dy)
  1398.               {
  1399.                 dy = histo[dx] ;
  1400.                 mfp = (pixel_t) dx ;
  1401.               }
  1402.           New[y][color][x] = mfp ;
  1403.         }
  1404.  
  1405.       if (disp_active) disp_putline(New[y], y) ;
  1406.       disp_percentdone(y * 100 / (Ysize-1)) ;
  1407.     }
  1408.  
  1409.   if (disp_active) disp_imgend() ;
  1410.   SwapOldNew() ;
  1411. }
  1412.  
  1413.  
  1414. static void
  1415. shear()
  1416. {
  1417.   register int color, x, y, r ;
  1418.   int dx, dy ;
  1419.   static int *yshift = 0 ;
  1420.   struct SRC *srcp ;
  1421.   pixel_t ***img ;
  1422.  
  1423.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1424.  
  1425.   img = srcp->pix ;
  1426.  
  1427.   if (yshift == 0 &&
  1428.       (yshift = (int *)
  1429.       LINT_CAST(Emalloc((unsigned)Xsize * sizeof(int)))) == 0)
  1430.     return ;
  1431.  
  1432.   if (disp_active) disp_imgstart() ;
  1433.  
  1434.   for (x = r = 0; x < Xsize; x++)
  1435.     {
  1436.       if (RANDOM % Zsize < 128) r-- ;
  1437.       else                      r++ ;
  1438.       yshift[x] = r ;
  1439.     }
  1440.  
  1441.   for (y = 0; y < Ysize; y++)
  1442.     {
  1443.       for (color = 0; color < colors; color++)
  1444.         {
  1445.           if (RANDOM % Zsize < 128) r-- ;
  1446.           else                      r++ ;
  1447.  
  1448.           for (x = 0; x < Xsize; x++)
  1449.             {
  1450.               dx = x + r ;
  1451.               dy = y + yshift[x] ;
  1452.               if (dx >= Xsize || dy >= Ysize || dx < 0 || dy < 0)
  1453.                 continue ;
  1454.               New[y][color][x] = img[dy][color][dx] ;
  1455.             }
  1456.         }
  1457.  
  1458.       if (disp_active) disp_putline(New[y], y) ;
  1459.       disp_percentdone(y * 100 / (Ysize-1)) ;
  1460.     }
  1461.  
  1462.   if (disp_active) disp_imgend() ;
  1463.   SwapOldNew() ;
  1464. }
  1465.  
  1466.  
  1467. static void
  1468. slice()
  1469. {
  1470.   register int color, x, y, r ;
  1471.   int dx, dy ;
  1472.   struct SRC *srcp ;
  1473.   pixel_t ***img ;
  1474.   static int *xshift = 0 ;
  1475.   static int *yshift = 0 ;
  1476.  
  1477.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1478.   img = srcp->pix ;
  1479.  
  1480.   if (xshift == 0 &&
  1481.       (xshift = (int *)
  1482.       LINT_CAST(Emalloc((unsigned)Ysize * sizeof (int)))) == 0)
  1483.     return ;
  1484.  
  1485.   if (yshift == 0 &&
  1486.       (yshift = (int *)
  1487.       LINT_CAST(Emalloc((unsigned)Xsize * sizeof (int)))) == 0)
  1488.     return ;
  1489.  
  1490.   if (disp_active) disp_imgstart() ;
  1491.  
  1492.   for (x = dx = 0 ; x < Xsize; x++)
  1493.     {
  1494.       if (dx == 0)
  1495.         {
  1496.           r = (RANDOM & 63) - 32 ;
  1497.           dx = 8 + RANDOM & 31 ;
  1498.         }
  1499.       else dx-- ;
  1500.       yshift[x] = r ;
  1501.     }
  1502.  
  1503.   for (y = dy = 0; y < Ysize; y++)
  1504.     {
  1505.       if (dy == 0)
  1506.         {
  1507.           r = (RANDOM & 63) - 32 ;
  1508.           dy = 8 + RANDOM & 31 ;
  1509.         }
  1510.       else dy-- ;
  1511.       xshift[y] = r ;
  1512.     }
  1513.  
  1514.   for (y = 0; y < Ysize; y++)
  1515.     {
  1516.       for (color = 0; color < colors; color++)
  1517.         for (x = 0; x < Xsize; x++)
  1518.           {
  1519.             dx = x + xshift[y] ;
  1520.             dy = y + yshift[x] ;
  1521.             if (dx < Xsize && dy < Ysize && dx >= 0 && dy >= 0)
  1522.               New[y][color][x] = img[dy][color][dx] ;
  1523.           }
  1524.  
  1525.       if (disp_active) disp_putline(New[y], y) ;
  1526.       disp_percentdone(y * 100 / (Ysize-1)) ;
  1527.     }
  1528.  
  1529.   if (disp_active) disp_imgend() ;
  1530.   SwapOldNew() ;
  1531. }
  1532.  
  1533.  
  1534. static void
  1535. tile()
  1536. {
  1537.   register int color, x, y, dx, dy ;
  1538.   int ox, oy, nx, ny ;
  1539.   int TileSize = TILESIZE ;
  1540.   struct SRC *srcp ;
  1541.   pixel_t ***img ;
  1542.  
  1543.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1544.   img = srcp->pix ;
  1545.  
  1546.   for (y = 0; y < Ysize-TileSize; y += TileSize)
  1547.     {
  1548.       for (color = 0; color < colors; color++)
  1549.         for (x = 0; x < Xsize-TileSize; x += TileSize)
  1550.           {
  1551.             ox = (RANDOM & 31) - 16 ;       /* Displacement. */
  1552.             oy = (RANDOM & 31) - 16 ;
  1553.  
  1554.             for (dy = y; dy < y+TileSize; dy++)
  1555.               for (dx = x; dx < x+TileSize; dx++)
  1556.                 {
  1557.                   nx = dx + ox ;
  1558.                   ny = dy + oy ;
  1559.                   if (nx >= Xsize || ny >= Ysize || nx < 0 || ny < 0)
  1560.                     continue ;
  1561.                   New[ny][color][nx] = img[dy][color][dx] ;
  1562.                 }
  1563.           }
  1564.       disp_percentdone(y * 100 / (Ysize-1)) ;
  1565.     }
  1566.  
  1567.   if (disp_active)
  1568.     {
  1569.       disp_imgstart() ;
  1570.       for (y = 0; y < Ysize; y++) disp_putline(New[y], y) ;
  1571.       disp_imgend() ;
  1572.     }
  1573.   SwapOldNew() ;
  1574. }
  1575.  
  1576.  
  1577. /*  Note: affects source image in situ.
  1578.  *  Buffers not swapped after processing.
  1579.  */
  1580.  
  1581. static void
  1582. melt()
  1583. {
  1584.   register int color, x, y, k, NumPixels ;
  1585.   pixel_t val ;
  1586.   struct SRC *srcp ;
  1587.   pixel_t ***img ;
  1588.  
  1589.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1590.   img = srcp->pix ;
  1591.  
  1592.   NumPixels = Xsize * Ysize ;
  1593.   for (k = 0; k < NumPixels; k++)
  1594.     {
  1595.       x = RANDOM % Xsize ;
  1596.       y = RANDOM % (Ysize - 1) ;
  1597.  
  1598.       for (color = 0; color < colors; color++)
  1599.         while (y < Ysize-1 && img[y][x] <= img[y+1][x])
  1600.           {
  1601.             val                = img[y][color][x] ;
  1602.             img[y][color][x]   = img[y+1][color][x] ;
  1603.             img[y+1][color][x] = val ;
  1604.             y++ ;
  1605.           }
  1606.       disp_percentdone(k * 100 / (NumPixels-1)) ;
  1607.     }
  1608.   if (disp_active)
  1609.     {
  1610.       disp_imgstart() ;
  1611.       for (y = 0; y < Ysize; y++)
  1612.         disp_putline(img[y], y) ;
  1613.       disp_imgend() ;
  1614.     }
  1615. }
  1616.  
  1617.  
  1618. static void
  1619. matte()
  1620. {
  1621.   struct SRC *srcp ;
  1622.   pixel_t ***img ;
  1623.   double gamma ;
  1624.   register color, x, y ;
  1625.   static pixel_t *lookup = (pixel_t *) 0 ;
  1626.   static double lastgamma = 0.0 ;
  1627.  
  1628.   DEBUG((Debug, "matte()\n")) ;
  1629.  
  1630.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1631.   img = srcp->pix ;
  1632.  
  1633.   lex() ;
  1634.   if (lat == '\n' || lat == ')')
  1635.     {
  1636.       gamma = GAMMA ;
  1637.       pushback(lat) ;
  1638.     }
  1639.   else gamma = lexval + lexfract ;
  1640.  
  1641.   if (lookup == 0 &&
  1642.       (lookup = (pixel_t *) Emalloc((unsigned) Zsize)) == (pixel_t *) 0)
  1643.     return ;
  1644.  
  1645.   if (lastgamma != gamma)
  1646.     {
  1647.       for (x = 0; x < Zsize; ++x)
  1648.         lookup[x] = ((double)Zmax * pow(x / (double)Zmax, gamma) < 3.0)
  1649.                     ? Zmax : 0 ;
  1650.       lastgamma = gamma ;
  1651.     }
  1652.  
  1653.   if (disp_active) disp_imgstart() ;
  1654.   for (y = 0; y < Ysize; y++)
  1655.     {
  1656.       for (color = 0; color < colors; color++)
  1657.         for (x = 0; x < Xsize; x++)
  1658.           New[y][color][x] = lookup[img[y][color][x]] ;
  1659.       if (disp_active) disp_putline(New[y], y) ;
  1660.       disp_percentdone(y * 100 / (Ysize-1)) ;
  1661.     }
  1662.   if (disp_active) disp_imgend() ;
  1663. }
  1664.  
  1665.  
  1666. static void
  1667. genps()
  1668. {
  1669.   int x, y ;
  1670.   FILE *ostr ;
  1671.   struct SRC *srcp ;
  1672.   pixel_t ***img, *ip ;
  1673.   time_t time P((time_t *)) ;
  1674.   time_t clock ;
  1675. #if       unix
  1676.   char *getlogin P((void)) ;
  1677. #endif /* unix */
  1678.  
  1679.   if (!parsefname()) return ;
  1680.  
  1681.   if ((ostr = EfopenW(text)) == NULL) return ;
  1682.  
  1683.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1684.  
  1685.   img = srcp->pix ;
  1686.   clock = time((time_t *) 0) ;
  1687.     
  1688.   FPRINTF(ostr, "%%!PS-Adobe-1.0\n") ;
  1689.   FPRINTF(ostr, "%%%%Title: popi bit image '%s'\n", srcp->str) ;
  1690.   FPRINTF(ostr, "%%%%DocumentFonts:\n") ;
  1691.   FPRINTF(ostr, "%%%%Creator: popi\n") ;
  1692.   FPRINTF(ostr, "%%%%CreationDate: %s", ctime(&clock)) ;    /* Includes \n */
  1693.   FPRINTF(ostr, "%%%%Pages: 1\n") ;
  1694.  
  1695. #if        unix
  1696.   FPRINTF(ostr, "%%%%For: %s\n", getlogin()) ;
  1697. #endif  /* unix */
  1698.  
  1699.   FPRINTF(ostr, "%%%%EndComments\n") ;
  1700.   FPRINTF(ostr, "clippath pathbbox pop pop translate\n") ;
  1701.   FPRINTF(ostr, "clippath pathbbox pop exch pop exch sub dup scale\n") ;
  1702.   FPRINTF(ostr, "/picstr %d string def\n", Xsize) ;
  1703.   FPRINTF(ostr, "/doimage {\n") ;
  1704.   FPRINTF(ostr, "%d %d %d [ %d 0 0 -%d 0 %d ]\n",
  1705.                  Xsize, Ysize, BITSPERPIXEL, Xsize, Ysize, Ysize) ;
  1706.   FPRINTF(ostr, "{currentfile picstr readhexstring pop}image}bind def\n") ;
  1707.   FPRINTF(ostr, "%%%%EndProlog\n%%%%Page 0 0\ndoimage\n") ;
  1708.  
  1709.   for (y = 0; y < Ysize; ++y)
  1710.     {
  1711.       ip = ntsc_luma((pixel_t **) &img[y]) ;
  1712.       for (x = 0; x < Xsize; ++x)
  1713.         {
  1714.           if (x % 40 == 0)    /* Formatting only */
  1715.             PUTC('\n', ostr) ;
  1716.           FPRINTF(ostr, "%02x", *ip++) ;
  1717.         }
  1718.       PUTC('\n', ostr) ;
  1719.     }
  1720.  
  1721.   FPRINTF(ostr, "showpage\n") ;
  1722.   Efclose(ostr) ;
  1723. }
  1724.  
  1725.  
  1726. /* Although this is set up to use one particular graphics mode
  1727.  * of a 24-pin printer, everything should be generic enough
  1728.  * that it can be changed to work with a different graphics
  1729.  * mode on an 8-pin printer, just by changing a few numbers.
  1730.  */
  1731.  
  1732. static void
  1733. genepson()
  1734. {
  1735.   struct SRC *srcp ;
  1736.   char *PinVals ;
  1737.   pixel_t *PinThresh, ThreshStep ;
  1738.   FILE *ostr ;
  1739.   register int x ;
  1740.   register pixel_t ***img ;
  1741.   int y, yn ;
  1742.   int pin ;
  1743.   int BytesPerChunk, PinsPerPixel, BytesPerColumn ;
  1744.   int yPixelsPerByte, xPinsPerPixel, yPinsPerPixel ;
  1745.  
  1746.   if (parsefname() == 0) return ;
  1747.  
  1748.   if ((ostr = EfopenW(text)) == NULL) return ;
  1749.  
  1750.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1751.  
  1752.   img = srcp->pix ;
  1753.  
  1754. /* Printer specific */
  1755.  
  1756.   xPinsPerPixel  = 2 ;
  1757.   yPinsPerPixel  = 2 ;
  1758.   BytesPerColumn = 24 / BITSINBYTE ;
  1759.  
  1760.   PinsPerPixel   = xPinsPerPixel * yPinsPerPixel ;
  1761.   BytesPerChunk  = xPinsPerPixel * BytesPerColumn ;
  1762.   yPixelsPerByte = BITSINBYTE / yPinsPerPixel ;
  1763.  
  1764. /* Must be whole number of pixels (y direction) per  byte. */
  1765.  
  1766.   assert(yPinsPerPixel * yPixelsPerByte == BITSINBYTE) ;
  1767.  
  1768. /* Reallocate these each time, as changing the print mode
  1769.  * may change the sizes of these arrays.
  1770.  */
  1771.  
  1772.   if ((PinVals = Emalloc((unsigned)BytesPerChunk)) == 0 ||
  1773.       (PinThresh = (pixel_t *)
  1774.       Emalloc((unsigned) PinsPerPixel * sizeof(pixel_t))) == 0)
  1775.     return ;
  1776.  
  1777.   ThreshStep = (pixel_t) (Zsize / (PinsPerPixel + 1)) ;
  1778.   for (pin = 0; pin <  PinsPerPixel; ++pin)
  1779.     PinThresh[pin] = (pixel_t) ((pin + 1) * ThreshStep) ;
  1780.  
  1781.   for (y = 0;  y < Ysize; y = yn)
  1782.     {
  1783.  
  1784. /* Printer specific */
  1785.  
  1786. /* This print line is width Xsize pixels, and (Xsize * xPinsPerPixel)
  1787.  * pin positions (dots on the page).
  1788.  * No. of dots vertical  is (BytesPerColumn * BITSINBYTE)
  1789.  * which is yPinsPerPixel times  the no.  of image scanlines.
  1790.  */
  1791.  
  1792.       FPRINTF(ostr, "\033*%c%c%c",
  1793.               39,                             /* 180 dpi in both directions */
  1794.               (Xsize * xPinsPerPixel) % 256,
  1795.               (Xsize * xPinsPerPixel) / 256) ;
  1796.  
  1797.       for (x = 0; x <  Xsize; ++x)
  1798.         {
  1799.           register int  ycur ;
  1800.           int ByteCount, xpin ;
  1801.           char *dp ;
  1802.  
  1803. /* Clear the PinVals array */
  1804.  
  1805.           for (ByteCount = 0, dp = PinVals; ByteCount < BytesPerChunk;
  1806.                ++ByteCount)
  1807.             *dp++ = 0 ;
  1808.  
  1809.           dp = PinVals ;
  1810.  
  1811. /* For each byte-sized row of the print head, collect 1 pixel width of data. */
  1812.  
  1813.           for (ByteCount = 0, dp = PinVals, ycur = y;
  1814.                ByteCount < BytesPerColumn; ++ByteCount, dp  += xPinsPerPixel)
  1815.             {
  1816.               register unsigned char  bit ;
  1817.  
  1818.               yn = ycur + yPixelsPerByte ;
  1819.               if (yn > Ysize) yn = Ysize ;
  1820.  
  1821. /*  For the current byte row of the print-head (ie. yPixelsPerByte image
  1822.  *  scanlines), collect a pixel width of data.
  1823.  */
  1824.  
  1825.               for (bit = 0x80; ycur <  yn; ++ycur)
  1826.                 {
  1827.                   pixel_t val ;
  1828.                   int ypin ;
  1829.  
  1830.                   if (colors == 1) val = img[ycur][0][x] ;  /* Grey level */
  1831.                   else                             /* Calculate NTSC luma */
  1832.                     val = img[ycur][0][x] * 0.299 +       /* R */
  1833.                           img[ycur][1][x] * 0.587 +       /* G */
  1834.                           img[ycur][2][x] * 0.114 ;       /* B */
  1835.  
  1836. /* Now use an appropriate no. of pins to simulate the greyscale value. */
  1837.  
  1838.                   for (ypin = 0, pin =  0; ypin < yPinsPerPixel; ++ypin)
  1839.                     {
  1840.                       for (xpin = 0; xpin < xPinsPerPixel; ++xpin, ++pin)
  1841.                         if (val < PinThresh[pin]) dp[xpin] |= bit ;
  1842.                       bit >>=  1 ;
  1843.                     }
  1844.                 }
  1845.             }
  1846.  
  1847. /*  We have set up enough columns for a single pixel in the x direction.
  1848.  *  Now print them in the correct order.
  1849.  */
  1850.  
  1851.           for (xpin = 0; xpin < xPinsPerPixel; ++xpin)
  1852.             {
  1853.               for (ByteCount = 0; ByteCount < BytesPerColumn; ++ByteCount)
  1854.                 PUTC(PinVals[ByteCount * xPinsPerPixel + xpin], ostr) ;
  1855.             }
  1856.         }
  1857.  
  1858. /* Printer specific */
  1859.  
  1860.       FPRINTF(ostr, "\033J%c\r", 24);
  1861.     }
  1862.  
  1863.   Efclose(ostr) ;
  1864.   free(PinVals) ;
  1865.   free((char *) PinThresh) ;
  1866. }
  1867.  
  1868.  
  1869. static void
  1870. list()
  1871. {
  1872.   showfiles() ;
  1873. }
  1874.  
  1875.  
  1876. /* :read "filename" [imagename] */
  1877.  
  1878. static void
  1879. readimg()
  1880. {
  1881.   char filename[512] ;
  1882.   char *imgname = (char *) 0 ;
  1883.  
  1884.   if (parsefname() == 0) return ;
  1885.  
  1886.   STRCPY(filename, text) ;
  1887.  
  1888.   lex() ;
  1889.  
  1890.   if (lat == '\n' || lat == ')')
  1891.     {
  1892.       pushback(lat) ;
  1893.     }
  1894.   else if (lat != T_NAME && lat != T_INAME)
  1895.     {
  1896.       SPRINTF(ErrBuf, "Expected image name") ;
  1897.       error(ERR_PARSE) ;
  1898.     }
  1899.   else imgname = text ;
  1900.  
  1901.   getpix(filename, imgname) ;
  1902. }
  1903.  
  1904.  
  1905. static void
  1906. newimg()
  1907. {
  1908.   struct SRC *img ;
  1909.  
  1910.   lex() ;
  1911.  
  1912.   if (lat == T_INAME)
  1913.     {
  1914.       SPRINTF(ErrBuf, "Image named '%s' already exists", text) ;
  1915.       error(ERR_PARSE) ;
  1916.       return ;
  1917.     }
  1918.  
  1919.   if (lat != T_NAME)
  1920.     {
  1921.       SPRINTF(ErrBuf, "Expected name of new image") ;
  1922.       error(ERR_PARSE) ;
  1923.       return ;
  1924.     }
  1925.  
  1926. /* Find an empty slot in the image array */
  1927.  
  1928.   for (img = Images; img->pix != (pixel_t ***) 0; ++img) continue ;
  1929.  
  1930.   if (img == &Images[nimages]) ++nimages ;
  1931.  
  1932.   if ((img->pix = ImgAlloc()) == (pixel_t ***) 0 ||
  1933.      (img->str = (char *)
  1934.      Emalloc((unsigned int) (strlen(text)+1))) == (char *) 0)
  1935.     {
  1936.       img->pix = (pixel_t ***) 0 ;
  1937.       return ;
  1938.     }
  1939.  
  1940.   STRCPY(img->str, text) ;
  1941.  
  1942. /* Swap newly created image with old */
  1943.  
  1944.   {
  1945.     pixel_t ***tmp ;
  1946.  
  1947.     tmp         = CurOld->pix ;
  1948.     CurOld->pix = img->pix ;
  1949.     img->pix    = tmp ;
  1950.   }
  1951. }
  1952.  
  1953.  
  1954. static void
  1955. writeimg()
  1956. {
  1957.   struct SRC *img ;
  1958.  
  1959.   if (parsefname() == 0) return ;
  1960.  
  1961.   if ((img = parseimg()) == (struct SRC *) 0) return ;
  1962.  
  1963.   putpix(img, text) ;
  1964. }
  1965.  
  1966.  
  1967. static void
  1968. freeimg()
  1969. {
  1970.   struct SRC *srcp ;
  1971.  
  1972.   if ((srcp = parseimg()) == (struct SRC *) 0) return ;
  1973.     
  1974.   if (srcp == CurOld || srcp == CurNew)
  1975.     {
  1976.       SPRINTF(ErrBuf, "Cannot free 'old' or 'new'") ;
  1977.       error(0) ;
  1978.       return ;
  1979.     }
  1980.  
  1981.   ImgFree(srcp) ;
  1982. }
  1983.  
  1984.  
  1985. static void
  1986. displayimg()
  1987. {
  1988.   pixel_t ***img ;
  1989.   int y ;
  1990.  
  1991.   lex() ;
  1992.  
  1993.   if (lat == '+')
  1994.     {
  1995.       disp_active = 1 ;
  1996.       return ;
  1997.     }
  1998.   if (lat == '-')
  1999.     {
  2000.       disp_active = 0 ;
  2001.       return ;
  2002.     }
  2003.   if (lat == '\n')
  2004.     {
  2005.       pushback(lat) ;
  2006.       img = CurOld->pix ;
  2007.     }
  2008.   else if (lat == T_INAME) img = Images[lexval].pix ;
  2009.   else if (lat == T_NEW)   img = CurNew->pix ;
  2010.   else
  2011.     {
  2012.       SPRINTF(ErrBuf, "Expected +, - or image name") ;
  2013.       error(ERR_PARSE) ;
  2014.       return ;
  2015.     }
  2016.  
  2017.   disp_imgstart() ;
  2018.  
  2019.   for (y = 0; y < Ysize; y++) disp_putline(img[y], y) ;
  2020.  
  2021.   disp_imgend() ;
  2022. }
  2023.  
  2024.  
  2025. static void
  2026. CloseLog(filep)
  2027. FILE **filep ;
  2028. {
  2029.   if (*filep == NULL) return ;
  2030.  
  2031.   FPRINTF(*filep, "\n---\n") ;
  2032.   FCLOSE(*filep) ;
  2033.   *filep = NULL ;
  2034. }
  2035.  
  2036.  
  2037. void
  2038. OpenLog(filep)
  2039. FILE **filep ;
  2040. {
  2041.   time_t time() ;
  2042.   time_t clock ;
  2043.  
  2044.   CloseLog(filep) ;
  2045.  
  2046.   if ((*filep = fopen(LogFile, "a")) == NULL)
  2047.     {
  2048.       SPRINTF(ErrBuf,
  2049.               "Can't open log file '%s' - logging is off", LogFile) ;
  2050.       error(ERR_SYS) ;
  2051.       return ;
  2052.     }
  2053.  
  2054.   clock = time((time_t *) 0) ;
  2055.   FPRINTF(*filep, "==>> %s", ctime(&clock)) ;    /* Includes '\n' */
  2056. }
  2057.  
  2058.  
  2059. static void
  2060. dolog()
  2061. {
  2062.   static char *buf = (char *) 0 ;
  2063.  
  2064.   lex() ;
  2065.  
  2066.        if (lat == '+') OpenLog(&LogStr) ;
  2067.   else if (lat == '-') CloseLog(&LogStr) ;
  2068.   else if (lat == T_FNAME)
  2069.     {
  2070.       if (buf == (char *) 0 &&
  2071.           (buf = Emalloc((unsigned int) 512)) == (char *) 0)
  2072.         return ;
  2073.       STRCPY(buf, text) ;
  2074.       LogFile = buf ;
  2075.       OpenLog(&LogStr) ;
  2076.     }
  2077.   else pushback(lat) ;
  2078.     
  2079.   if (LogStr) PRINTF("Logging is active on file '%s'\n", LogFile) ;
  2080.   else        PRINTF("Logging is off\n") ;
  2081. }
  2082.  
  2083.  
  2084. static void
  2085. debug()
  2086. {
  2087.   static char *buf = (char *) 0 ;
  2088.  
  2089.   lex() ;
  2090.  
  2091.        if (lat == '+') OpenLog(&Debug) ;
  2092.   else if (lat == '-') CloseLog(&Debug) ;
  2093.   else if (lat == T_FNAME)
  2094.     {
  2095.       if (buf == (char *) 0 &&
  2096.           (buf = Emalloc((unsigned int) 512)) == (char *) 0)
  2097.         return ;
  2098.       STRCPY(buf, text) ;
  2099.       LogFile = buf ;
  2100.       OpenLog(&Debug) ;
  2101.     }
  2102.   else pushback(lat) ;
  2103.  
  2104.   if (Debug) PRINTF("Logging is active on file '%s'\n", LogFile) ;
  2105.   else       PRINTF("Logging is off\n") ;
  2106. }
  2107.  
  2108.  
  2109. static char *HelpMsg[] = {
  2110.   "binary ops:   ** * /  % + - << >> < > >= <= == != & ^ | && ||",
  2111.   "funcs:        sin(deg) cos(deg) atan(y, x) hypot(x, y)",
  2112.   "              log(val) sqrt(val) abs(val) rand()",
  2113.   "values:       x y r a X Y R A Z",
  2114.   "special funcs",
  2115.   "\t:list",
  2116.   "\t:read \"filename\"",
  2117.   "\t:write \"filename\"",
  2118.   "\t:genps \"filename\" [image]",
  2119.   "\t:genepson \"filename\" [image]",
  2120.   "\t:create image",
  2121.   "\t:free image",
  2122.   "\t:display [image]",
  2123.   "\t:display +|-",
  2124.   "\t:ofmt +|-",
  2125.   "\t:truncate +|-",
  2126.   "\t:signed +|-",
  2127.   "\t:undo",
  2128.   "\t:run \"filename\"",
  2129.   "\t:logfile \"filename\"",
  2130.   "\t:version",
  2131.   "\t:quit (also `q' and `exit')",
  2132.   (char *) 0
  2133. } ;
  2134.  
  2135.  
  2136. void
  2137. help()
  2138. {
  2139.   int i ;
  2140.  
  2141.   PrStrs(HelpMsg) ;
  2142.   FPRINTF(stderr, "\t?\n") ;
  2143.   FPRINTF(stderr, "\tq\n") ;
  2144.   FPRINTF(stderr, "\n") ;
  2145.   for (i = 0; SpecialOps[i].name; i++)
  2146.     FPRINTF(stderr, "\t:%-10s  %s\n",
  2147.             SpecialOps[i].name, SpecialOps[i].notes) ;
  2148. }
  2149.  
  2150.  
  2151. static void
  2152. undo()
  2153. {
  2154.   SwapOldNew() ;
  2155. }
  2156.  
  2157.  
  2158. static void
  2159. verbose()
  2160. {
  2161.   lex() ;
  2162.  
  2163.        if (lat == '+') Verbose = 1 ;
  2164.   else if (lat == '-') Verbose = 0 ;
  2165.   else                 pushback(lat) ;
  2166.     
  2167.   PRINTF("Verbose is %s\n", Verbose ? "on" : "off") ;
  2168. }
  2169.  
  2170.  
  2171. static void
  2172. imtrunc()
  2173. {
  2174.   lex() ;
  2175.  
  2176.        if (lat == '+') Truncate = 1 ;
  2177.   else if (lat == '-') Truncate = 0 ;
  2178.   else                 pushback(lat) ;
  2179.  
  2180.   PRINTF("Truncation is %s\n", Truncate ? "on" : "off") ;
  2181. }
  2182.  
  2183.  
  2184. static void
  2185. dosigned() 
  2186. {
  2187.   lex() ;
  2188.  
  2189.        if (lat == '+') signed_io = 1 ;
  2190.   else if (lat == '-') signed_io = 0 ;
  2191.   else                 pushback(lat) ;
  2192.  
  2193.   PRINTF("Signed I/O is %s\n", signed_io ? "on" : "off") ;
  2194. }
  2195.  
  2196.  
  2197. static void
  2198. ofmt() 
  2199. {
  2200.   lex() ;
  2201.  
  2202.        if (lat == '+') oldfmt = 1 ;
  2203.   else if (lat == '-') oldfmt = 0 ;
  2204.   else                 pushback(lat) ;
  2205.  
  2206.   PRINTF("Old output format is %s\n", oldfmt ? "on" : "off") ;
  2207. }
  2208.  
  2209.  
  2210. void
  2211. special()
  2212. {
  2213.   int i, cnt, len ;
  2214.   struct SpecialOp *sp ;
  2215.  
  2216.   DEBUG((Debug, "special\n")) ;
  2217.   lex() ;
  2218.  
  2219.   for (cnt = i = 0; SpecialOps[i].name; i++)
  2220.     if (strncmp(text, SpecialOps[i].name, strlen(text)) == 0)
  2221.       {  
  2222.         sp = &SpecialOps[i] ;
  2223.         cnt++ ;
  2224.       }
  2225.  
  2226.   if (cnt > 1)
  2227.     {
  2228.       SPRINTF(ErrBuf, "Special operation '%s' ambiguous (", text) ;
  2229.       for (i = 0; SpecialOps[i].name; i++)
  2230.         if (strncmp(text, SpecialOps[i].name, strlen(text)) == 0)
  2231.           {
  2232.             strcat(ErrBuf, SpecialOps[i].name) ;
  2233.             strcat(ErrBuf, ", ") ;
  2234.           }
  2235.       len = strlen(ErrBuf);
  2236.       ErrBuf[len-2] = ')';
  2237.       ErrBuf[len-1] = '\n';
  2238.       error(ERR_PARSE) ;
  2239.       while (lat != '\n')      /* !!! KLUDGE !!! */
  2240.         lex() ;
  2241.       return ;
  2242.     }
  2243.  
  2244.   if (cnt < 1)
  2245.     {
  2246.       SPRINTF(ErrBuf, "Special operation '%s' unrecognised", text) ;
  2247.       error(ERR_PARSE) ;
  2248.       while (lat != '\n')      /* !!! KLUDGE !!! */
  2249.         lex();
  2250.       return ;
  2251.     }
  2252.  
  2253.   DEBUG((Debug, "calling func '%s'\n", sp->name)) ;
  2254.   (*(sp->func))() ;
  2255.  
  2256.   if (lat != '\n') lex() ;
  2257.  
  2258.   if (lat != '\n')
  2259.     {
  2260.       SPRINTF(ErrBuf, "Tokens after special command ignored") ;
  2261.       error(ERR_WARN) ;
  2262.     }
  2263.  
  2264.   assert(lat == '\n') ;
  2265. }
  2266. Funky_Stuff
  2267. len=`wc -c < special.c`
  2268. if [ $len !=    23621 ] ; then
  2269. echo error: special.c was $len bytes long, should have been    23621
  2270. fi
  2271. fi # end of overwriting check
  2272. if [ -f popi.icon ]
  2273. then
  2274. echo shar: will not over-write existing file popi.icon
  2275. else
  2276. echo shar: extracting 'popi.icon',     1933 characters
  2277. cat > popi.icon <<'Funky_Stuff'
  2278. /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16
  2279.  */
  2280.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0001,0x0001,
  2281.     0x8000,0x0000,0x0001,0x7F81,0x8000,0x0000,0x0001,0x30C1,
  2282.     0x8000,0x0000,0x0001,0x3061,0x8000,0x0000,0x0001,0x3061,
  2283.     0x8000,0x0000,0x0001,0x3061,0x8000,0x0000,0x0001,0x30C1,
  2284.     0x8000,0x7600,0x0001,0x3781,0x8000,0xDF80,0x0001,0x3001,
  2285.     0x8001,0x76E8,0x0001,0x3001,0x8001,0xFF00,0x0001,0x3001,
  2286.     0x8002,0x7BFC,0x0001,0x3001,0x8002,0xDE03,0x0001,0x3001,
  2287.     0x800A,0xD5F8,0x0001,0x3001,0x804A,0xBF45,0xC001,0x7801,
  2288.     0x801A,0xE97C,0x0001,0x0001,0x81D3,0xAFEB,0x6001,0x0001,
  2289.     0x823F,0xFBBE,0x1001,0x0F81,0x82EF,0xEAFF,0xF401,0x11C1,
  2290.     0x857F,0xABFF,0x8401,0x20E1,0x857F,0xE87F,0xF801,0x6061,
  2291.     0x87FF,0x007F,0xFE01,0x6061,0x8BFF,0x000F,0xF801,0x6061,
  2292.     0x8FFC,0x0005,0xFE01,0x6061,0x87FE,0x01FF,0xFF01,0x7041,
  2293.     0x8FFB,0xF37F,0xFE01,0x3881,0x87EF,0xF1E0,0xFF81,0x1F01,
  2294.     0x8FF8,0xF1FE,0xFF81,0x0001,0x8FFF,0xB110,0x5D01,0x0001,
  2295.     0x87E2,0xD0C4,0x5FC1,0x0001,0x8FEA,0x0010,0x3FC1,0x77C1,
  2296.     0x87A0,0xA045,0x1FC1,0x38E1,0x87F4,0xA030,0x5F81,0x3071,
  2297.     0x87D2,0x8001,0x3F81,0x3031,0x85D6,0xC014,0xBF81,0x3031,
  2298.     0x87F0,0x39C5,0xBF01,0x3031,0x87DE,0x8F85,0xFE01,0x3031,
  2299.     0x83EA,0x3FF4,0x3E01,0x3021,0x83FC,0xA85D,0xF801,0x3841,
  2300.     0x81F7,0xFFE5,0xB801,0x3F81,0x81FE,0xA005,0xF801,0x3001,
  2301.     0x807E,0x9007,0xF001,0x3001,0x807F,0x96C3,0xF801,0x3001,
  2302.     0x80FE,0x8A8F,0xFC01,0x3001,0x80FF,0xCBA2,0xFE01,0x7801,
  2303.     0x80FF,0xD69F,0xFF01,0x0001,0x807F,0xD5D7,0xFC01,0x0001,
  2304.     0x81FF,0xF77F,0xFC01,0x0601,0x80FF,0xFDDF,0xFE01,0x0601,
  2305.     0x80FF,0xEFFE,0xFE01,0x0001,0x81FE,0xFFFD,0xFF81,0x0001,
  2306.     0x87FE,0xFFFD,0xFFC1,0x1E01,0x9FEF,0xBFF5,0xABF1,0x0601,
  2307.     0xBFFB,0x7FDF,0xFFFD,0x0601,0xFFCF,0xD7F3,0xC7FF,0x0601,
  2308.     0xFFFF,0xFFDF,0xFFFF,0x0601,0xFFFF,0x6FF7,0xFFFF,0x0601,
  2309.     0xFFFF,0xFFFF,0xFFFF,0x0601,0xFFFF,0xEFCF,0xFFFF,0x0601,
  2310.     0xFFFF,0xFFFF,0xFFFF,0x0601,0xFFFF,0xFFFF,0xFFFF,0x1F81,
  2311.     0xFFFF,0xFFFF,0xFFFF,0x0001,0xFFFF,0xFFFF,0xFFFF,0xFFFF
  2312. Funky_Stuff
  2313. len=`wc -c < popi.icon`
  2314. if [ $len !=     1933 ] ; then
  2315. echo error: popi.icon was $len bytes long, should have been     1933
  2316. fi
  2317. fi # end of overwriting check
  2318. exit 0 # Just in case...
  2319.