home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / x / volume10 / xv / part04 < prev    next >
Encoding:
Text File  |  1990-12-10  |  32.3 KB  |  1,328 lines

  1. Path: uunet!cs.utexas.edu!sun-barr!newstop!exodus!appserv!halibut.cis.upenn.edu
  2. From: bradley@halibut.cis.upenn.edu (John Bradley)
  3. Newsgroups: comp.sources.x
  4. Subject: v10i082: xv - display and manipulate images, Part04/10
  5. Message-ID: <320@appserv.Eng.Sun.COM>
  6. Date: 27 Nov 90 20:08:20 GMT
  7. References: <csx-10i079:xv@uunet.UU.NET>
  8. Sender: news@exodus.Eng.Sun.COM
  9. Lines: 1311
  10. Approved: argv@sun.com
  11.  
  12. Submitted-by: bradley@halibut.cis.upenn.edu (John Bradley)
  13. Posting-number: Volume 10, Issue 82
  14. Archive-name: xv/part04
  15.  
  16. #!/bin/sh
  17. # to extract, remove the header and type "sh filename"
  18. if `test ! -s ./xvpbm.c`
  19. then
  20. echo "writting ./xvpbm.c"
  21. cat > ./xvpbm.c << '\BARFOO\'
  22. /*
  23.  * xvpbm.c - load routine for 'pm' format pictures
  24.  *
  25.  * LoadPBM(fname, numcols)  -  loads a PBM, PGM, or PPM file
  26.  * WritePBM(fp,pic,w,h,r,g,b,numcols,style,raw,cmt)
  27.  */
  28.  
  29. /*
  30.  * Copyright 1989, 1990 by the University of Pennsylvania
  31.  *
  32.  * Permission to use, copy, and distribute for non-commercial purposes,
  33.  * is hereby granted without fee, providing that the above copyright
  34.  * notice appear in all copies and that both the copyright notice and this
  35.  * permission notice appear in supporting documentation.
  36.  *
  37.  * The software may be modified for your own purposes, but modified versions
  38.  * may not be distributed.
  39.  *
  40.  * This software is provided "as is" without any express or implied warranty.
  41.  */
  42.  
  43.  
  44. #include "xv.h"
  45.  
  46.  
  47.  
  48. /* comments on error handling:
  49.    a truncated file is not considered a Major Error.  The file is loaded, the
  50.    rest of the pic is filled with 0's.
  51.  
  52.    a file with garbage characters in it is an unloadable file.  All allocated
  53.    stuff is tossed, and LoadPBM returns non-zero
  54.  
  55.    not being able to malloc is a Fatal Error.  The program is aborted. */
  56.  
  57.  
  58. #define TRUNCSTR "File appears to be truncated."
  59.  
  60. static int garbage;
  61. static long numgot, filesize;
  62.  
  63.  
  64. static int loadpbm(), loadpgm(), loadppm();
  65. static int getint(),  getbit(),  PBMerr();
  66.  
  67.  
  68. /*******************************************/
  69. int LoadPBM(fname,nc)
  70.      char *fname;
  71.      int   nc;
  72. /*******************************************/
  73. {
  74.   FILE  *fp;
  75.   int    c, c1;
  76.   int    w, h, maxv, rv;
  77.  
  78.   garbage = maxv = 0;
  79.  
  80.   /* open the stream, if necesary */
  81.   fp=fopen(fname,"r");
  82.   if (!fp) return 1;
  83.   
  84.   /* figure out the file size (for Informational Purposes Only) */
  85.   fseek(fp, 0L, 2);
  86.   filesize = ftell(fp);
  87.   fseek(fp, 0L, 0);
  88.  
  89.   /* read the first two bytes of the file to determine which format
  90.      this file is.  "P1" = ascii bitmap, "P2" = ascii greymap,
  91.      "P3" = ascii pixmap, "P4" = raw bitmap, "P5" = raw greymap,
  92.      "P6" = raw pixmap */
  93.  
  94.   c = getc(fp);  c1 = getc(fp);
  95.   if (c!='P' || c1<'1' || c1>'6') return(PBMerr("unknown format"));
  96.  
  97.   /* read in header information */
  98.   w = getint(fp);  h = getint(fp);
  99.  
  100.   /* if we're not reading a bitmap, read the 'max value' */
  101.   if ( !(c1=='1' || c1=='4')) {
  102.     maxv = getint(fp);
  103.     if (maxv < 1) garbage=1;    /* to avoid 'div by zero' probs */
  104.   }
  105.  
  106.  
  107.   if (garbage) {
  108.     if (fp!=stdin) fclose(fp);
  109.     return (PBMerr("Garbage characters in header."));
  110.   }
  111.  
  112.   rv = 0;
  113.  
  114.   /* call the appropriate subroutine to handle format-specific stuff */
  115.   if      (c1=='1' || c1=='4') rv = loadpbm(fp,w,h,       c1=='4' ? 1 : 0);
  116.   else if (c1=='2' || c1=='5') rv = loadpgm(fp,w,h, maxv, c1=='5' ? 1 : 0);
  117.   else if (c1=='3' || c1=='6') rv = loadppm(fp,w,h, maxv, c1=='6' ? 1 : 0, nc);
  118.  
  119.   if (fp!=stdin) fclose(fp);
  120.   return(rv);
  121. }  
  122.  
  123.  
  124.  
  125. /*******************************************/
  126. static int loadpbm(fp, w, h, raw)
  127. FILE *fp;
  128. int   w,h,raw;
  129. {
  130.   byte *pix;
  131.   int   i,j,bit;
  132.  
  133.  
  134.   SetISTR(ISTR_FORMAT,"PBM, %s format.  (%ld bytes)", 
  135.       (raw) ? "raw" : "ascii", filesize);
  136.  
  137.   /* load up the XV global variables */
  138.   pic = (byte *) calloc(w*h,1);
  139.   if (!pic) FatalError("couldn't malloc 'pic'");
  140.  
  141.   pWIDE = w;  pHIGH = h;
  142.  
  143.   /* B/W bitmaps have a two entry colormap */
  144.   r[0] = g[0] = b[0] = 255;   /* 0 = white */
  145.   r[1] = g[1] = b[1] = 0;     /* 1 = black */
  146.  
  147.   if (!raw) {
  148.     numgot = 0;
  149.     for (i=0, pix=pic; i<h; i++)
  150.       for (j=0; j<w; j++, pix++)
  151.     *pix = getbit(fp);
  152.  
  153.     if (numgot != w*h) PBMerr(TRUNCSTR);
  154.     if (garbage) {
  155.       free(pic);
  156.       return(PBMerr("Garbage characters in image data."));
  157.     }
  158.   }
  159.  
  160.  
  161.   else {   /* read raw bits */
  162.     int trunc = 0, k = 0;
  163.  
  164.     for (i=0, pix=pic; i<h; i++)
  165.       for (j=0,bit=0; j<w; j++, pix++, bit++) {
  166.  
  167.     bit &= 7;
  168.     if (!bit) {
  169.       k = getc(fp);
  170.       if (k==EOF) { trunc=1; k=0; }
  171.     }
  172.  
  173.     *pix = (k&0x80) ? 1 : 0;
  174.     k = k << 1;
  175.       }
  176.  
  177.     if (trunc) PBMerr(TRUNCSTR);
  178.   }
  179.  
  180.   return 0;
  181. }
  182.  
  183.  
  184. /*******************************************/
  185. static int loadpgm(fp, w, h, maxv, raw)
  186. FILE *fp;
  187. int   w,h,maxv,raw;
  188. {
  189.   byte *pix;
  190.   int   i,j,bitshift;
  191.  
  192.   SetISTR(ISTR_FORMAT,"PGM, %s format.  (%ld bytes)", 
  193.       (raw) ? "raw" : "ascii", filesize);
  194.  
  195.   /* load up the XV global variables */
  196.   pic = (byte *) calloc(w*h,1);
  197.   if (!pic) FatalError("couldn't malloc 'pic'");
  198.  
  199.   pWIDE = w;  pHIGH = h;
  200.  
  201.   /* if maxv>255, keep dropping bits until it's reasonable */
  202.   bitshift = 0;
  203.   while (maxv>255) { maxv = maxv>>1;  bitshift++; }
  204.  
  205.   /* fill in a greyscale colormap where maxv maps to 255 */
  206.   for (i=0; i<=maxv; i++)
  207.     r[i] = g[i] = b[i] = (i*255)/maxv;
  208.  
  209.   if (!raw) {
  210.     numgot = 0;
  211.     for (i=0, pix=pic; i<h; i++)
  212.       for (j=0; j<w; j++, pix++)
  213.     *pix = (getint(fp) >> bitshift);
  214.   }
  215.  
  216.   else numgot = fread(pic, 1, w*h, fp);   /* read raw data */
  217.  
  218.   if (numgot != w*h) PBMerr(TRUNCSTR);
  219.  
  220.   if (garbage) {
  221.     free(pic);
  222.     return (PBMerr("Garbage characters in image data."));
  223.   }
  224.  
  225.   return 0;
  226. }
  227.  
  228.  
  229. /*******************************************/
  230. static int loadppm(fp, w, h, maxv, raw, nc)
  231. FILE *fp;
  232. int   w,h,maxv,raw,nc;
  233. {
  234.   byte *pix, *pic24, scale[256];
  235.   int   i,j,bitshift;
  236.  
  237.   SetISTR(ISTR_FORMAT,"PPM, %s format.  (%ld bytes)", 
  238.       (raw) ? "raw" : "ascii", filesize);
  239.  
  240.   /* allocate 24-bit image */
  241.   pic24 = (byte *) calloc(w*h*3,1);
  242.   if (!pic24) FatalError("couldn't malloc 'pic24'");
  243.  
  244.   /* if maxv>255, keep dropping bits until it's reasonable */
  245.   bitshift = 0;
  246.   while (maxv>255) { maxv = maxv>>1;  bitshift++; }
  247.  
  248.   if (!raw) {
  249.     numgot = 0;
  250.     for (i=0, pix=pic24; i<h; i++)
  251.       for (j=0; j<w*3; j++, pix++)
  252.     *pix = (getint(fp) >> bitshift);
  253.   }
  254.  
  255.   else numgot = fread(pic24, 1, w*h*3, fp);    /* read raw data */
  256.  
  257.   if (numgot != w*h*3) PBMerr(TRUNCSTR);
  258.  
  259.   if (garbage) {
  260.     free(pic24);
  261.     return(PBMerr("Garbage characters in image data."));
  262.   }
  263.  
  264.   /* have to scale all RGB values up (Conv24to8 expects RGB values to
  265.      range from 0-255 */
  266.  
  267.   if (maxv<255) { 
  268.     for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
  269.  
  270.     for (i=0, pix=pic24; i<h; i++) 
  271.       for (j=0; j<w*3; j++, pix++) 
  272.     *pix = scale[*pix];
  273.   }
  274.  
  275.   i = Conv24to8(pic24,w,h,nc);
  276.   free(pic24);
  277.   return i;
  278. }
  279.  
  280.  
  281.  
  282. /*******************************************/
  283. static int getint(fp)
  284. FILE *fp;
  285. {
  286.   int c, i;
  287.  
  288.   /* skip forward to start of next number */
  289.   c = getc(fp);
  290.   while (1) {
  291.     /* eat comments */
  292.     if (c=='#') {   /* if we're at a comment, read to end of line */
  293.       while (c != '\n' && c != EOF) c=getc(fp);
  294.     }
  295.  
  296.     if (c==EOF) return 0;
  297.     if (c>='0' && c<='9') break;   /* we've found what we were looking for */
  298.  
  299.     /* see if we are getting garbage (non-whitespace) */
  300.     if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
  301.  
  302.     c = getc(fp);
  303.   }
  304.  
  305.  
  306.   /* we're at the start of a number, continue until we hit a non-number */
  307.   i = 0;
  308.   while (1) {
  309.     i = (i*10) + (c - '0');
  310.     c = getc(fp);
  311.     if (c==EOF) return i;
  312.     if (c<'0' || c>'9') break;
  313.   }
  314.  
  315.   numgot++;
  316.   return i;
  317. }
  318.  
  319.  
  320.  
  321. /*******************************************/
  322. static int getbit(fp)
  323. FILE *fp;
  324. {
  325.   int c;
  326.  
  327.   /* skip forward to start of next number */
  328.   c = getc(fp);
  329.   while (1) {
  330.     /* eat comments */
  331.     if (c=='#') {   /* if we're at a comment, read to end of line */
  332.       while (c != '\n' && c != EOF) c=getc(fp);
  333.     }
  334.  
  335.     if (c==EOF) return 0;
  336.     if (c=='0' || c=='1') break;   /* we've found what we were looking for */
  337.  
  338.     /* see if we are getting garbage (non-whitespace) */
  339.     if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=',') garbage=1;
  340.  
  341.     c = getc(fp);
  342.   }
  343.  
  344.  
  345.   numgot++;
  346.   return(c-'0');
  347. }
  348.  
  349.  
  350. /*******************************************/
  351. static int PBMerr(st)
  352. char *st;
  353. {
  354.   SetISTR(ISTR_WARNING,st);
  355.   return 1;
  356. }
  357.  
  358.  
  359.  
  360.  
  361.  
  362. /*******************************************/
  363. int WritePBM(fp,pic,w,h,rmap,gmap,bmap,numcols,colorstyle,raw)
  364. FILE *fp;
  365. byte *pic;
  366. int   w,h;
  367. byte *rmap, *gmap, *bmap;
  368. int   numcols, colorstyle, raw;
  369. {
  370.   /* writes a PBM/PGM/PPM file to the already open stream
  371.      if (raw), writes as RAW bytes, otherwise writes as ASCII 
  372.      'colorstyle' single-handedly determines the type of file written
  373.      if colorstyle==0, (Full Color) a PPM file is written
  374.      if colorstyle==1, (Greyscale)  a PGM file is written
  375.      if colorstyle==2, (B/W stipple) a PBM file is written */
  376.  
  377.   int   magic;
  378.   byte *pix;
  379.   int   i,j,len;
  380.  
  381.   /* calc the appropriate magic number for this file type */
  382.   magic = 0;
  383.   if      (colorstyle==0) magic = 3;
  384.   else if (colorstyle==1) magic = 2;
  385.   else if (colorstyle==2) magic = 1;
  386.  
  387.   if (raw && magic) magic+=3;
  388.  
  389.   if (!magic) return(PBMerr("WritePBM: unknown file format"));
  390.  
  391.   /* write the header info */
  392.   fprintf(fp,"P%d\n",magic);
  393.   fprintf(fp,"# created by 'xv %s'\n", namelist[curname]);
  394.   fprintf(fp,"%d %d\n",w,h);
  395.   if (colorstyle!=2) fprintf(fp,"255\n");
  396.  
  397.   if (ferror(fp)) return -1;
  398.  
  399.   /* write the image data */
  400.  
  401.   if (colorstyle==0) {                  /* 24bit RGB, 3 bytes per pixel */
  402.     for (i=0, pix=pic, len=0; i<h; i++)
  403.       for (j=0; j<w; j++,pix++) {
  404.     if (raw) {
  405.       putc(r[*pix],fp);  
  406.       putc(g[*pix],fp);  
  407.       putc(b[*pix],fp);
  408.     }
  409.     else {
  410.       fprintf(fp,"%3d %3d %3d ",r[*pix], g[*pix], b[*pix]);
  411.       len+=12;
  412.       if (len>58) { fprintf(fp,"\n");  len=0; }
  413.     }
  414.       }
  415.   }
  416.  
  417.   else if (colorstyle==1) {             /* 8-bit greyscale */
  418.     byte rgb[256];
  419.     for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
  420.     for (i=0, pix=pic, len=0; i<w*h; i++,pix++) {
  421.       if (raw) putc(rgb[*pix],fp);
  422.       else {
  423.     fprintf(fp,"%3d ",rgb[*pix]);
  424.     len += 4;
  425.     if (len>66) { fprintf(fp,"\n");  len=0; }
  426.       }
  427.     }
  428.   }
  429.  
  430.   else if (colorstyle==2) {             /* 1-bit B/W stipple */
  431.     int bit,k;
  432.     for (i=0, pix=pic, len=0; i<h; i++) {
  433.       for (j=0, bit=0, k=0; j<w; j++, pix++) {
  434.     if (raw) {
  435.       k = (k << 1) | *pix;
  436.       bit++;
  437.       if (bit==8) {
  438.         fputc(~k,fp);
  439.         bit = k = 0;
  440.       }
  441.     }
  442.     else {
  443.       if (*pix) fprintf(fp,"0 ");
  444.            else fprintf(fp,"1 ");
  445.       len+=2;
  446.       if (len>68) { fprintf(fp,"\n"); len=0; }
  447.     }
  448.       } /* j */
  449.       if (raw && bit) {
  450.     k = k << (8-bit);
  451.     fputc(~k,fp);
  452.       }
  453.     }
  454.   }
  455.  
  456.   if (ferror(fp)) return -1;
  457.  
  458.   return 0;
  459. }
  460.  
  461.  
  462.       
  463.       
  464.  
  465.  
  466.  
  467. \BARFOO\
  468. else
  469.   echo "will not over write ./xvpbm.c"
  470. fi
  471. if `test ! -s ./xvpm.c`
  472. then
  473. echo "writting ./xvpm.c"
  474. cat > ./xvpm.c << '\BARFOO\'
  475. /*
  476.  * xvpm.c - load routine for 'pm' format pictures
  477.  *
  478.  * LoadPM(fname, numcols)  -  loads a PM pic, does 24to8 code if nec.
  479.  * WritePM(fp, pic, w, h, r,g,b, numcols, style)
  480.  * WriteRaw(fp, pic, w, h, r,g,b, numcols, style)
  481.  */
  482.  
  483. /*
  484.  * Copyright 1989, 1990 by the University of Pennsylvania
  485.  *
  486.  * Permission to use, copy, and distribute for non-commercial purposes,
  487.  * is hereby granted without fee, providing that the above copyright
  488.  * notice appear in all copies and that both the copyright notice and this
  489.  * permission notice appear in supporting documentation.
  490.  *
  491.  * The software may be modified for your own purposes, but modified versions
  492.  * may not be distributed.
  493.  *
  494.  * This software is provided "as is" without any express or implied warranty.
  495.  */
  496.  
  497.  
  498. #include "xv.h"
  499. #include "pm.h"
  500.  
  501. pmpic  thePic;
  502.  
  503. static int PMError();
  504. static void flipl();
  505.  
  506. /*******************************************/
  507. int LoadPM(fname,nc)
  508.      char *fname;
  509.      int   nc;
  510. /*******************************************/
  511. {
  512.   FILE  *fp;
  513.   int    isize,i,flipit,w,h,rv;
  514.  
  515.   rv = 0;
  516.   thePic.pm_image = NULL;
  517.  
  518.   /* read in the PM picture */
  519.   fp=fopen(fname,"r");
  520.   if (!fp) return( PMError("unable to open file") );
  521.   
  522.   flipit = 0;
  523.   fread(&thePic,PM_IOHDR_SIZE,1,fp);
  524.   if (thePic.pm_id != PM_MAGICNO) {
  525.     flipl( (byte *) &thePic.pm_id);
  526.     if (thePic.pm_id == PM_MAGICNO) flipit = 1;
  527.     else flipl( (byte *) &thePic.pm_id);
  528.   }
  529.   if (thePic.pm_id != PM_MAGICNO) return( PMError("not a PM file") );
  530.  
  531.   if (flipit) {
  532.     flipl((byte *) &thePic.pm_np);      flipl((byte *) &thePic.pm_nrow);
  533.     flipl((byte *) &thePic.pm_ncol);    flipl((byte *) &thePic.pm_nband);
  534.     flipl((byte *) &thePic.pm_form);    flipl((byte *) &thePic.pm_cmtsize);
  535.     }
  536.           
  537.   /* make sure that the input picture can be dealt with */
  538.   if ( thePic.pm_nband!=1 || 
  539.       (thePic.pm_form!=PM_I && thePic.pm_form!=PM_C) ||
  540.       (thePic.pm_form==PM_I && thePic.pm_np>1) ||
  541.       (thePic.pm_form==PM_C && (thePic.pm_np==2 || thePic.pm_np>4)) ) {
  542.     fprintf(stderr,"PM picture not in a displayable format.\n");
  543.     fprintf(stderr,"(ie, 1-plane PM_I, or 1-, 3-, or 4-plane PM_C)\n");
  544.     return 1;
  545.     }    
  546.  
  547.   w = thePic.pm_ncol;  h = thePic.pm_nrow;
  548.  
  549.   isize = pm_isize(&thePic);
  550.  
  551.   if (DEBUG) 
  552.     fprintf(stderr,"%s: LoadPM() - loading a %dx%d %s pic, %d planes\n",
  553.         cmd, w, h, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C", 
  554.         thePic.pm_np);
  555.  
  556.   SetISTR(ISTR_FORMAT,"PM, %s.  (%d plane %s)  (%d bytes)",
  557.       (thePic.pm_form==PM_I || thePic.pm_np>1) ? 
  558.          "24-bit color" : "8-bit greyscale",
  559.       thePic.pm_np, (thePic.pm_form==PM_I) ? "PM_I" : "PM_C",
  560.       isize + PM_IOHDR_SIZE + thePic.pm_cmtsize);
  561.  
  562.   /* allocate memory for picture and read it in */
  563.   thePic.pm_image = (char *) malloc(isize);
  564.   if (thePic.pm_image == NULL) 
  565.     return( PMError("unable to malloc PM picture") );
  566.  
  567.   if (fread(thePic.pm_image, (unsigned) isize, 1, fp) != 1) 
  568.     return( PMError("file read error") );
  569.   if (fp!=stdin) fclose(fp);
  570.  
  571.   if (DEBUG) fprintf(stderr,"loadpm 1\n");
  572.  
  573.   /* convert PM picture to 'pic' (8 bit) format */
  574.   if (thePic.pm_form == PM_I) {
  575.     int  *intptr;
  576.     byte *pic24, *picptr;
  577.  
  578.     if ((pic24 = (byte *) malloc(w*h*3))==NULL) 
  579.       return( PMError("unable to malloc 24-bit picture") );
  580.       
  581.     intptr = (int *) thePic.pm_image;
  582.     picptr = pic24;
  583.  
  584.     if (flipit) {    /* if flipit, integer is RRGGBBAA instead of AABBGGRR */
  585.       for (i=w*h; i>0; i--, intptr++) {
  586.     *picptr++ = (*intptr>>24) & 0xff;
  587.     *picptr++ = (*intptr>>16) & 0xff;
  588.     *picptr++ = (*intptr>>8)  & 0xff;
  589.       }
  590.     }
  591.     else {
  592.       for (i=w*h; i>0; i--, intptr++) {
  593.     *picptr++ = (*intptr)     & 0xff;
  594.     *picptr++ = (*intptr>>8)  & 0xff;
  595.     *picptr++ = (*intptr>>16) & 0xff;
  596.       }
  597.     }
  598.  
  599.     if (DEBUG) fprintf(stderr,"loadpm 2\n");
  600.  
  601.     free(thePic.pm_image);
  602.     rv=Conv24to8(pic24,w,h,nc);
  603.     free(pic24);
  604.   }
  605.  
  606.  
  607.   else if (thePic.pm_form == PM_C && thePic.pm_np>1) {
  608.     byte *pic24, *picptr, *rptr, *gptr, *bptr;
  609.  
  610.     if ((pic24 = (byte *) malloc(w*h*3))==NULL) 
  611.       return( PMError("unable to malloc 24-bit picture") );
  612.  
  613.     rptr = (byte *) thePic.pm_image;
  614.     gptr = rptr + w*h;
  615.     bptr = rptr + w*h*2;
  616.     picptr = pic24;
  617.     for (i=w*h; i>0; i--) {
  618.       *picptr++ = *rptr++;
  619.       *picptr++ = *gptr++;
  620.       *picptr++ = *bptr++;
  621.     }
  622.     free(thePic.pm_image);
  623.     rv=Conv24to8(pic24,w,h,nc);
  624.     free(pic24);
  625.   }
  626.   
  627.   else if (thePic.pm_form == PM_C && thePic.pm_np==1) {
  628.     /* don't have to convert, just point pic at thePic.pm_image */
  629.     pic = (byte *) thePic.pm_image;
  630.     pWIDE = w;  pHIGH = h;  
  631.     for (i=0; i<256; i++) r[i]=g[i]=b[i]=i;  /* and build mono colortable */
  632.     rv = 0;
  633.   }
  634.  
  635.   return rv;
  636. }
  637.  
  638.  
  639. /*******************************************/
  640. int WritePM(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
  641. FILE *fp;
  642. byte *pic;
  643. int   w,h;
  644. byte *rmap, *gmap, *bmap;
  645. int   numcols, colorstyle;
  646. {
  647.   /* writes a PM file to the already open stream
  648.      'colorstyle' single-handedly determines the type of PM pic written
  649.      if colorstyle==0, (Full Color) a 3-plane PM_C pic is written
  650.      if colorstyle==1, (Greyscal) a 1-plane PM_C pic is written
  651.      if colorstyle==0, (B/W stipple) a 1-plane PM_C pic is written */
  652.  
  653.   char  foo[256];
  654.   int   i;
  655.   byte *p;
  656.  
  657.   /* create 'comment' field */
  658.   sprintf(foo,"created by 'xv %s'\n", namelist[curname]);
  659.  
  660.   /* fill in fields of a pmheader */
  661.   thePic.pm_id = PM_MAGICNO;
  662.   thePic.pm_np = (colorstyle==0) ? 3 : 1;
  663.   thePic.pm_ncol = w;
  664.   thePic.pm_nrow = h;
  665.   thePic.pm_nband = 1;
  666.   thePic.pm_form  = PM_C;
  667.   thePic.pm_cmtsize = strlen(foo);
  668.  
  669.   if (fwrite(&thePic, PM_IOHDR_SIZE, 1, fp) != 1) return -1;
  670.  
  671.   /* write the picture data */
  672.   if (colorstyle == 0) {         /* 24bit RGB, organized as 3 8bit planes */
  673.     for (i=0,p=pic; i<w*h; i++, p++)
  674.       putc(rmap[*p], fp);
  675.     for (i=0,p=pic; i<w*h; i++, p++)
  676.       putc(gmap[*p], fp);
  677.     for (i=0,p=pic; i<w*h; i++, p++)
  678.       putc(bmap[*p], fp);
  679.   }
  680.  
  681.   else if (colorstyle == 1) {    /* GreyScale: 8 bits per pixel */
  682.     byte rgb[256];
  683.     for (i=0; i<numcols; i++) rgb[i] = MONO(rmap[i],gmap[i],bmap[i]);
  684.     for (i=0, p=pic; i<w*h; i++, p++)
  685.       putc(rgb[*p],fp);
  686.   }
  687.  
  688.   else /* (colorstyle == 2) */ { /* B/W stipple.  pic is 1's and 0's */
  689.     for (i=0, p=pic; i<w*h; i++, p++)
  690.       putc(*p ? 255 : 0,fp);
  691.   }
  692.  
  693.   if (fputs(foo,fp)==EOF) return -1;
  694.  
  695.   return 0;
  696. }
  697.  
  698.  
  699. /*****************************/
  700. static int PMError(st)
  701. char *st;
  702. {
  703.   SetISTR(ISTR_WARNING,"LoadPM() - %s",cmd,st);
  704.   Warning();
  705.   if (thePic.pm_image != NULL) free(thePic.pm_image);
  706.   return -1;
  707. }
  708.  
  709.  
  710. /*****************************/
  711. static void flipl(p)
  712.      byte *p;
  713. {
  714.   byte t; 
  715.   t = p[0];  p[0]=p[3];  p[3] = t;
  716.   t = p[1];  p[1]=p[2];  p[2] = t;
  717. }
  718.  
  719.  
  720.  
  721. \BARFOO\
  722. else
  723.   echo "will not over write ./xvpm.c"
  724. fi
  725. if `test ! -s ./xvscrl.c`
  726. then
  727. echo "writting ./xvscrl.c"
  728. cat > ./xvscrl.c << '\BARFOO\'
  729. /* 
  730.  * xvscrl.c - Scroll Bar handling functions
  731.  *
  732.  * callable functions:
  733.  *
  734.  *   SCCreate()   -  creates the Scroll Bar window.
  735.  *   SCSetRange() -  sets min/max/current values of control
  736.  *   SCSetVal()   -  sets value of control 
  737.  *   SCRedraw()   -  redraws scroll bar
  738.  *   SCTrack()    -  called when clicked.  Operates control 'til mouseup
  739.  */
  740.  
  741. /*
  742.  * Copyright 1989, 1990 by the University of Pennsylvania
  743.  *
  744.  * Permission to use, copy, and distribute for non-commercial purposes,
  745.  * is hereby granted without fee, providing that the above copyright
  746.  * notice appear in all copies and that both the copyright notice and this
  747.  * permission notice appear in supporting documentation.
  748.  *
  749.  * The software may be modified for your own purposes, but modified versions
  750.  * may not be distributed.
  751.  *
  752.  * This software is provided "as is" without any express or implied warranty.
  753.  */
  754.  
  755.  
  756. #include "xv.h"
  757. #include "bitmaps.h"
  758.  
  759.  
  760. static Pixmap upPix,  downPix;   /* up/down arrows */
  761. static Pixmap up1Pix, down1Pix;  /* up/down arrows (lit up) */
  762. static Pixmap sgray;             /* gray stipple for lit scrollbar */
  763. static int    pixmaps_built=0;   /* true if pixmaps created already */
  764.  
  765.  
  766. /* scroll regions */
  767. #define UPLINE 0
  768. #define UPPAGE 1
  769. #define DNLINE 2
  770. #define DNPAGE 3
  771. #define THUMB  4
  772.  
  773. #define SCRLWAIT 150   /* milliseconds to wait between scrolls */
  774.  
  775. /* local functions */
  776. #ifdef __STDC__
  777. static int  whereInScrl(SCRL *, int, int);
  778. static void drawArrow(SCRL *, int);
  779. #else
  780. static int  whereInScrl();
  781. static void drawArrow();
  782. #endif
  783.  
  784.  
  785. /***************************************************/
  786. void SCCreate(sp, parent, x, y, vert, len, minv, maxv, curv, page, 
  787.               fg, bg, func)
  788. SCRL         *sp;
  789. Window        parent;
  790. int           x,y,vert,len,minv,maxv,curv,page;
  791. unsigned long fg,bg;
  792. void          (*func)();
  793. {
  794.  
  795.  
  796.   if (!pixmaps_built) {
  797.     upPix    = XCreatePixmapFromBitmapData(theDisp, parent, 
  798.         up_bits, up_width, up_height, fg, bg, dispDEEP);
  799.     downPix  = XCreatePixmapFromBitmapData(theDisp, parent, 
  800.             down_bits, down_width, down_height, fg, bg, dispDEEP);
  801.     up1Pix   = XCreatePixmapFromBitmapData(theDisp, parent, 
  802.                 up1_bits, up1_width, up1_height, fg, bg, dispDEEP);
  803.     down1Pix = XCreatePixmapFromBitmapData(theDisp, parent, 
  804.             down1_bits, down1_width, down1_height,fg,bg,dispDEEP);
  805.     sgray    = XCreatePixmapFromBitmapData(theDisp, parent,
  806.             scrlgray_bits, scrlgray_width, scrlgray_height,fg,bg,dispDEEP);
  807.   }
  808.  
  809.   sp->vert = vert;
  810.   sp->len  = len;
  811.   sp->fg   = fg;
  812.   sp->bg   = bg;
  813.   sp->uplit = sp->dnlit = 0;
  814.  
  815.   if (vert) 
  816.     sp->win = XCreateSimpleWindow(theDisp, parent,x,y,up_width-2,len,1,fg,bg);
  817.   else FatalError("don't know HOW to make horizontal scrollbar");
  818.  
  819.   if (!sp->win) FatalError("can't create scrollbar window");
  820.  
  821.   sp->tsize  =  up_width-2;      /* really only if vertical */
  822.   sp->tmin   =  up_height-1;
  823.   sp->tmax   =  len - (up_height-1) - sp->tsize;
  824.   sp->drawobj = func;
  825.  
  826.   SCSetRange(sp, minv, maxv, curv, page);
  827.   XSelectInput(theDisp, sp->win, ExposureMask | ButtonPressMask);
  828. }
  829.  
  830.  
  831. /***************************************************/
  832. void SCSetRange(sp, minv, maxv, curv, page)
  833. SCRL *sp;
  834. int   minv, maxv, curv, page;
  835. {
  836.   if (maxv<minv) maxv=minv;
  837.   sp->min = minv;    sp->max = maxv;    sp->page = page;
  838.   sp->active =  (minv < maxv);
  839.  
  840.   /* adjust scroll bar background */
  841.   if (sp->active) XSetWindowBackgroundPixmap(theDisp, sp->win, sgray);
  842.              else XSetWindowBackground(theDisp, sp->win, sp->bg);
  843.  
  844.   SCSetVal(sp, curv);
  845. }
  846.  
  847.  
  848. /***************************************************/
  849. void SCSetVal(sp, curv)
  850. SCRL *sp;
  851. int   curv;
  852. {
  853.   RANGE(curv, sp->min, sp->max);   /* make sure curv is in-range */
  854.   sp->val = curv;
  855.  
  856.   if (sp->active) 
  857.     sp->tpos = sp->tmin + ((sp->tmax - sp->tmin)*(curv - sp->min))
  858.                         / (sp->max - sp->min);
  859.   SCRedraw(sp);
  860.   (sp->drawobj)();     /* redraw whatever the scrollbar controls */
  861.   XFlush(theDisp);
  862. }
  863.  
  864.  
  865. /***************************************************/
  866. void SCRedraw(sp)
  867. SCRL *sp;
  868. {
  869.   XSetForeground(theDisp, theGC, sp->fg);
  870.   XSetBackground(theDisp, theGC, sp->bg);
  871.  
  872.   XClearWindow(theDisp, sp->win);
  873.   
  874.   if (sp->vert) {    /* draw up/down arrows */
  875.     drawArrow(sp,UPLINE);
  876.     drawArrow(sp,DNLINE);
  877.  
  878.     if (sp->active) {   /* a thumb is necessary */
  879.       XSetForeground(theDisp, theGC, sp->bg);
  880.       XFillRectangle(theDisp, sp->win, theGC,
  881.              1, sp->tpos+1, sp->tsize-2, sp->tsize-2);
  882.       XSetForeground(theDisp, theGC, sp->fg);
  883.       XDrawRectangle(theDisp, sp->win, theGC,
  884.              0, sp->tpos, sp->tsize-1, sp->tsize-1);
  885.     }
  886.   }
  887. }
  888.  
  889.  
  890.  
  891. /***************************************************/
  892. static int whereInScrl(sp,x,y)
  893. SCRL *sp;
  894. int x,y;
  895. {
  896.   int v;
  897.  
  898.   /* returns region # that x,y is in.  Returns '-1' if none */
  899.  
  900.   v=0;
  901.   if (sp->vert) {
  902.     if (x<0 || x>up_width-2 || y<0 || y>sp->len) return -1;
  903.     v = y;
  904.   }
  905.  
  906.   /* once we know it's in scroll bar, only have to check 'v' versus len */
  907.   if (v < sp->tmin)               return UPLINE;
  908.   if (sp->active) {
  909.     if (v <  sp->tpos)             return UPPAGE;
  910.     if (v <  sp->tpos + sp->tsize) return THUMB;
  911.     if (v <= sp->tmax + sp->tsize) return DNPAGE;
  912.   }
  913.   if (v > sp->tmax+sp->tsize)    return DNLINE;
  914.  
  915.   return -1;
  916. }
  917.  
  918.  
  919. /***************************************************/
  920. static void drawArrow(sp,arr)
  921. SCRL *sp;
  922. int arr;
  923. {
  924.   /* only if vertical */
  925.   if (arr == UPLINE) {
  926.     if (sp->uplit) 
  927.       XCopyArea(theDisp, up1Pix,  sp->win,theGC,0,0,up_width,up_height,-1,-1);
  928.     else
  929.       XCopyArea(theDisp, upPix,   sp->win,theGC,0,0,up_width,up_height,-1,-1);
  930.   }
  931.  
  932.   else if (arr == DNLINE) {
  933.     if (sp->dnlit) 
  934.       XCopyArea(theDisp, down1Pix,sp->win,theGC,0,0,up_width,up_height,
  935.         -1, sp->len-(up_height-1));
  936.     else
  937.       XCopyArea(theDisp, downPix, sp->win,theGC,0,0,up_width,up_height,
  938.         -1, sp->len-(up_height-1));
  939.   }
  940.  
  941.   XFlush(theDisp);
  942. }
  943.  
  944.  
  945. /***************************************************/
  946. void SCTrack(sp,mx,my)
  947. SCRL *sp;
  948. int mx,my;
  949. {
  950.   Window       rW,cW;
  951.   int          rx,ry, x,y, ipos, pos, lit, ty, tyoff, ty1;
  952.   unsigned int mask;
  953.  
  954.   /* determine in which of the five regions of the scroll bar the mouse
  955.      was clicked (upline, downline, uppage, downpage, thumb) */
  956.  
  957.   ty = tyoff = 0;
  958.  
  959.   XSetForeground(theDisp, theGC, sp->fg);
  960.   XSetBackground(theDisp, theGC, sp->bg);
  961.  
  962.   /* light up appropriate bit of scroll bar */
  963.   ipos = whereInScrl(sp,mx,my);
  964.   lit = 1;
  965.  
  966.   switch (ipos) {
  967.   case UPLINE:  sp->uplit = 1;
  968.                 if (sp->val > sp->min) SCSetVal(sp,sp->val-1);                
  969.                 Timer(SCRLWAIT);
  970.                 break;
  971.  
  972.   case DNLINE:  sp->dnlit = 1;
  973.                 if (sp->val < sp->max) SCSetVal(sp,sp->val+1);
  974.                 Timer(SCRLWAIT);
  975.                 break;
  976.  
  977.   case UPPAGE:  SCSetVal(sp,sp->val - sp->page);  break;
  978.   case DNPAGE:  SCSetVal(sp,sp->val + sp->page);  break;
  979.   case THUMB:   tyoff = sp->tpos - my;
  980.                 ty = sp->tpos;
  981.                 XSetState(theDisp, theGC, sp->fg, sp->bg, GXinvert, 
  982.               sp->fg ^ sp->bg);
  983.                 XDrawRectangle(theDisp,sp->win,theGC,
  984.                    0, sp->tpos, sp->tsize-1, sp->tsize-1);
  985.                 break;
  986.   }
  987.  
  988.   /* VERTICAL CODE ONLY */
  989.   while (XQueryPointer(theDisp,sp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
  990.     if (!(mask & Button1Mask)) break;    /* button released */
  991.  
  992.     switch (ipos) {
  993.  
  994.     case THUMB:
  995.       /* do thumb tracking */
  996.       if (x<-16 || x>16+sp->tsize) {   /* outside tracking range */
  997.     if (lit) {
  998.       lit = 0;
  999.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  1000.     }
  1001.       }
  1002.  
  1003.       else {                           /* inside tracking range */
  1004.     if (!lit) {  /* not lit, just turn on */
  1005.       lit = 1;
  1006.       ty = y + tyoff;
  1007.       RANGE(ty, sp->tmin, sp->tmax);
  1008.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  1009.     }
  1010.     else { /* already lit, more the thumb */
  1011.       ty1 = y+tyoff;
  1012.       RANGE(ty1, sp->tmin, sp->tmax);
  1013.       if (ty != ty1) {    /* but only if mouse has moved */
  1014.         XDrawRectangle(theDisp, sp->win, theGC, 
  1015.                0,ty,sp->tsize-1,sp->tsize-1);
  1016.         ty = ty1;
  1017.         XDrawRectangle(theDisp, sp->win, theGC, 
  1018.                0,ty,sp->tsize-1,sp->tsize-1);
  1019.       }
  1020.     }
  1021.       }
  1022.       break;
  1023.  
  1024.  
  1025.     case UPLINE:
  1026.     case DNLINE:                     /* arrows */
  1027.       pos = whereInScrl(sp,x,y);
  1028.       if (pos == ipos) {
  1029.     if (!lit) { 
  1030.       lit = 1; 
  1031.       if (ipos == UPLINE) { sp->uplit = 1;  drawArrow(sp,UPLINE); }
  1032.                      else { sp->dnlit = 1;  drawArrow(sp,DNLINE); }
  1033.     }
  1034.  
  1035.     else {
  1036.       if (sp->val > sp->min && pos==UPLINE) {
  1037.         SCSetVal(sp, sp->val-1);
  1038.         Timer(SCRLWAIT);
  1039.       }
  1040.       else if (sp->val < sp->max && pos==DNLINE) {
  1041.         SCSetVal(sp, sp->val+1);
  1042.         Timer(SCRLWAIT);
  1043.       }
  1044.     }
  1045.       }
  1046.       
  1047.       else {
  1048.     if (lit) { 
  1049.       lit = 0; 
  1050.       if (ipos == UPLINE) { sp->uplit = 0;  drawArrow(sp,UPLINE); }
  1051.                      else { sp->dnlit = 0;  drawArrow(sp,DNLINE); }
  1052.     }
  1053.       }
  1054.       break;
  1055.       
  1056.     }
  1057.   }
  1058.  
  1059.  
  1060.   if (ipos == THUMB) {
  1061.     if (lit)    /* turn off */
  1062.       XDrawRectangle(theDisp,sp->win,theGC,0,ty,sp->tsize-1,sp->tsize-1);
  1063.  
  1064.     XSetState(theDisp, theGC, sp->fg, sp->bg, GXcopy, AllPlanes);
  1065.  
  1066.     if (lit && ty != sp->tpos) {    /* if thumb was moved, ROUND to new val */
  1067.       int dt, dv;
  1068.       dt = sp->tmax - sp->tmin;
  1069.       dv = sp->max  - sp->min;
  1070.       SCSetVal(sp, sp->min + (dv*(ty - sp->tmin)+dt/2) / dt);
  1071.     }
  1072.   }
  1073.  
  1074.   if (lit && ipos == UPLINE) { sp->uplit = 0; drawArrow(sp, UPLINE); }
  1075.   if (lit && ipos == DNLINE) { sp->dnlit = 0; drawArrow(sp, DNLINE); }
  1076. }
  1077.  
  1078.  
  1079.  
  1080.  
  1081. \BARFOO\
  1082. else
  1083.   echo "will not over write ./xvscrl.c"
  1084. fi
  1085. if `test ! -s ./xvxbm.c`
  1086. then
  1087. echo "writting ./xvxbm.c"
  1088. cat > ./xvxbm.c << '\BARFOO\'
  1089. /*
  1090.  * xvxbm.c - load routine for X11 Bitmap format pictures
  1091.  *
  1092.  * LoadXBM(fname)  -  loads an X11 Bitmap file\
  1093.  * WriteXBM(fp, pic, w, h)
  1094.  */
  1095.  
  1096. /*
  1097.  * Copyright 1989, 1990 by the University of Pennsylvania
  1098.  *
  1099.  * Permission to use, copy, and distribute for non-commercial purposes,
  1100.  * is hereby granted without fee, providing that the above copyright
  1101.  * notice appear in all copies and that both the copyright notice and this
  1102.  * permission notice appear in supporting documentation.
  1103.  *
  1104.  * The software may be modified for your own purposes, but modified versions
  1105.  * may not be distributed.
  1106.  *
  1107.  * This software is provided "as is" without any express or implied warranty.
  1108.  */
  1109.  
  1110.  
  1111. #include "xv.h"
  1112.  
  1113.  
  1114.  
  1115. /*
  1116.  * File Format:
  1117.  *   (format identifier:  "#define" as first couple chars in file)
  1118.  *
  1119.  * looks for first line beginning with '#define'
  1120.  *   reads "#define identifier width"  (identifier is ignored)
  1121.  * looks for next line beginning with '#define'
  1122.  *   reads "#define identifier height" (identifier is ignored)
  1123.  * looks for next occurence of characters '0x'
  1124.  *   read next two chars as two hex digits
  1125.  *   move forward to next occurence of '0x'
  1126.  *   repeat
  1127.  */
  1128.  
  1129.  
  1130. static int XBMError();
  1131.  
  1132.  
  1133. /*******************************************/
  1134. int LoadXBM(fname,nc)
  1135.      char *fname;
  1136.      int   nc;
  1137. /*******************************************/
  1138. {
  1139.   FILE  *fp;
  1140.   int    c, c1;
  1141.   int    i, j, k, bit, w, h;
  1142.   byte  *pix;
  1143.   long   filesize;
  1144.   char   line[256];
  1145.   byte   hex[256];
  1146.  
  1147.   k = 0;
  1148.  
  1149.   fp=fopen(fname,"r");
  1150.   if (!fp) return 1;
  1151.  
  1152.   /* figure out the file size (for Informational Purposes Only) */
  1153.   fseek(fp, 0L, 2);
  1154.   filesize = ftell(fp);
  1155.   fseek(fp, 0L, 0);
  1156.  
  1157.  
  1158.   /* read width:  skip lines until we hit a #define */
  1159.   while (1) {
  1160.     if (!fgets(line,256,fp)) 
  1161.       return(XBMError("EOF reached in header info."));
  1162.  
  1163.     if (strncmp(line,"#define",7)==0) {
  1164.       if (sscanf(line,"#define %*s %d", &w) != 1) 
  1165.     return(XBMError("Unable to read 'width'"));
  1166.       else break;
  1167.     }
  1168.   }
  1169.  
  1170.  
  1171.   /* read height:  skip lines until we hit another #define */
  1172.   while (1) {
  1173.     if (!fgets(line,256,fp)) 
  1174.       return(XBMError("EOF reached in header info."));
  1175.  
  1176.     if (strncmp(line,"#define",7)==0) {
  1177.       if (sscanf(line,"#define %*s %d", &h) != 1) 
  1178.     return(XBMError("Unable to read 'height'"));
  1179.       else break;
  1180.     }
  1181.   }
  1182.  
  1183.  
  1184.  
  1185.   /* scan forward until we see the first '0x' */
  1186.   c = getc(fp);  c1 = getc(fp);
  1187.   while (c1!=EOF && !(c=='0' && c1=='x') ) { c = c1;  c1 = getc(fp); }
  1188.  
  1189.   if (c1==EOF) 
  1190.     return(XBMError("No bitmap data found"));
  1191.  
  1192.  
  1193.   /* load up the stuff XV expects us to load up */
  1194.  
  1195.   SetISTR(ISTR_FORMAT,"X11 Bitmap  (%ld bytes)", filesize);
  1196.  
  1197.   pic = (byte *) calloc(w*h,1);
  1198.   if (!pic) FatalError("couldn't malloc 'pic'");
  1199.  
  1200.   pWIDE = w;  pHIGH = h;
  1201.  
  1202.   /* B/W bitmaps have a two entry colormap */
  1203.   r[0] = g[0] = b[0] = 255;     /* 0 = white */
  1204.   r[1] = g[1] = b[1] = 0;       /* 1 = black */
  1205.  
  1206.  
  1207.   /* initialize the 'hex' array for zippy ASCII-hex -> int conversion */
  1208.  
  1209.   for (i=0; i<256; i++) hex[i]=0;
  1210.   for (i='0'; i<='9'; i++) hex[i] = i - '0';
  1211.   for (i='a'; i<='f'; i++) hex[i] = i + 10 - 'a';
  1212.   for (i='A'; i<='F'; i++) hex[i] = i + 10 - 'A';
  1213.  
  1214.   /* read/convert the image data */
  1215.  
  1216.   for (i=0, pix=pic; i<h; i++)
  1217.     for (j=0,bit=0; j<w; j++, pix++, bit = ++bit&7) {
  1218.  
  1219.       if (!bit) {
  1220.     /* get next byte from file.  we're already positioned at it */
  1221.     c = getc(fp);  c1 = getc(fp);
  1222.     if (c<0 || c1<0) { 
  1223.       /* EOF: break out of loop */      
  1224.       c=c1='0'; i=h; j=w;
  1225.       XBMError("The file would appear to be truncated.");
  1226.     }
  1227.  
  1228.     k = (hex[c] << 4) + hex[c1];
  1229.  
  1230.     /* advance to next '0x' */
  1231.     c = getc(fp);  c1 = getc(fp);
  1232.     while (c1!=EOF && !(c=='0' && c1=='x') ) { c = c1;  c1 = getc(fp); }
  1233.       }
  1234.  
  1235.       *pix = (k&1) ? 1 : 0;
  1236.       k = k >> 1;
  1237.     }
  1238.  
  1239.   fclose(fp);
  1240.  
  1241.   return 0;
  1242. }  
  1243.  
  1244.  
  1245.  
  1246. /*******************************************/
  1247. static int XBMError(st)
  1248. char *st;
  1249. {
  1250.   SetISTR(ISTR_WARNING,st);
  1251.   return 1;
  1252. }
  1253.  
  1254.  
  1255. /*******************************************/
  1256. int WriteXBM(fp, pic, w, h, fname)
  1257. FILE *fp;
  1258. byte *pic;
  1259. int   w,h;
  1260. char *fname;
  1261. {
  1262.   /* pic is expected to be an array of w*h bytes.  '0' is considered 'black'
  1263.      non-zero is considered white.  Some sort of stippling algorithm should've
  1264.      been called already to produce pic, otherwise the output won't be at all
  1265.      useful */
  1266.  
  1267.   int   i,j,k,bit,len,nbytes;
  1268.   byte *pix;
  1269.   char name[256], *foo;
  1270.  
  1271.   /* figure out a reasonable basename */
  1272.   strcpy(name,fname);
  1273.   foo = strchr(name,'.');
  1274.   if (foo) *foo='\0';                 /* truncated name at first '.' */
  1275.  
  1276.   fprintf(fp,"#define %s_width %d\n",name,w);  
  1277.   fprintf(fp,"#define %s_height %d\n",name,h);
  1278.   fprintf(fp,"static char %s_bits[] = {\n",name);
  1279.  
  1280.   fprintf(fp," ");
  1281.  
  1282.   nbytes = h * ((w+7)/8);   /* # of bytes to write */
  1283.  
  1284.   for (i=0, len=1, pix=pic; i<h; i++) {
  1285.     for (j=bit=k=0; j<w; j++,pix++) {
  1286.       k = (k>>1);
  1287.       if (*pix) k |= 0x80;
  1288.       bit++;
  1289.       if (bit==8) {
  1290.     fprintf(fp,"0x%02x",(byte) ~k);
  1291.     nbytes--;  len += 4;
  1292.     if (nbytes) { fprintf(fp,",");  len++; }
  1293.     if (len>72) { fprintf(fp,"\n ");  len=1; }
  1294.     bit = k = 0;
  1295.       }
  1296.     }
  1297.  
  1298.     if (bit) {
  1299.       k = k >> (8-bit);
  1300.       fprintf(fp,"0x%02x",(byte) ~k);
  1301.       nbytes--;  len += 4;
  1302.       if (nbytes) { fprintf(fp,",");  len++; }
  1303.       if (len>72) { fprintf(fp,"\n ");  len=1; }
  1304.     }
  1305.   }
  1306.  
  1307.   fprintf(fp,"};\n");
  1308.  
  1309.   if (ferror(fp)) return -1;
  1310.   return 0;
  1311. }
  1312. \BARFOO\
  1313. else
  1314.   echo "will not over write ./xvxbm.c"
  1315. fi
  1316. echo "Finished archive 4 of 10"
  1317. exit
  1318.  
  1319. dan
  1320. ----------------------------------------------------
  1321. O'Reilly && Associates   argv@sun.com / argv@ora.com
  1322. Opinions expressed reflect those of the author only.
  1323. --
  1324. dan
  1325. ----------------------------------------------------
  1326. O'Reilly && Associates   argv@sun.com / argv@ora.com
  1327. Opinions expressed reflect those of the author only.
  1328.