home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / fbm / part06 / flpcx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-06-08  |  8.9 KB  |  310 lines

  1. /*****************************************************************
  2.  * flpcx.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  5.  * use this file in whole or in part provided that you do not sell it
  6.  * for profit and that this copyright notice is retained unchanged.
  7.  *
  8.  * flpcx.c: 
  9.  *
  10.  * CONTENTS
  11.  *    write_pcx (image, stream)
  12.  *    read_pcx (image, stream, mstr, mlen)
  13.  *
  14.  * EDITLOG
  15.  *    LastEditDate = Tue Mar  7 19:57:24 1989 - Michael Mauldin
  16.  *    LastFileName = /usr2/mlm/src/misc/fbm/flpcx.c
  17.  *
  18.  * HISTORY
  19.  * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  20.  *    Beta release (version 0.9) mlm@cs.cmu.edu
  21.  *
  22.  * 12-Nov-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  23.  *    Created.
  24.  *****************************************************************/
  25.  
  26. # include <stdio.h>
  27. # include <math.h>
  28. # include <ctype.h>
  29. # include "fbm.h"
  30.  
  31. /****************************************************************
  32.  * pcx.h: Paintbrush file format header, as per "ZSoft Technical
  33.  *    Reference Manual for Publisher's Paintbrush, PC Paintbrush Plus,
  34.  *    PC Paintbrush and Frieze Graphics.", 1988,  ZSoft corporation,
  35.  *
  36.  *    450 Franklin Rd. Suite 100 / Marietta, GA  30067 / 404-428-0008
  37.  *
  38.  * HISTORY
  39.  * {1}     1-Sep-87  Michael L. Mauldin (mlm) at cognac
  40.  *     Created.
  41.  * 
  42.  ****************************************************************/
  43.  
  44. # define UBYTE    unsigned char    /*  8 bits unsigned        */
  45. # define WORD    short        /* 16 bits signed        */
  46.  
  47. typedef struct pcxstruct {
  48.   UBYTE    Manufacturer;        /* 10 == ZSoft PCX        */
  49.   UBYTE    Version;        /* Version Information        */
  50.                 /*    0 == ver 2.5        */
  51.                 /*    2 == ver 2.8 w/pallete    */
  52.                 /*    3 == 2.8 w/o pallete    */
  53.                 /*    5 == ver 3.0 w/pallete    */
  54.   UBYTE    Encoding;        /* 01 == PCX run-length encoding */
  55.   UBYTE    BitsPerPixel;        /* 8/number of pixels per byte    */
  56.   WORD    Window[4];        /* xmin, ymin, xmax, ymax    */
  57.   WORD    Hres;            /* Horizontal resolution    */
  58.   WORD    Vres;            /* Vertical resolution        */
  59.   UBYTE    Colormap[16][3];    /* Color Pallete, RGB in 0..255    */
  60.   UBYTE    Reserved;        /* Reserved            */
  61.   UBYTE NPlanes;        /* Number of Color Planes    */
  62.   WORD    BytesPerLine;        /* Number of bytes per scan line */
  63.   WORD    Palette;        /* 1 = color/BW, 2 = grayscale  */
  64.   UBYTE    Filler[58];        /* Pad header to 128 bytes    */
  65. } PCXHDR;
  66.  
  67. # define XMIN 0
  68. # define YMIN 1
  69. # define XMAX 2
  70. # define YMAX 3
  71.  
  72. # define CNTMSK 0xc0
  73. # define MAXCNT 0x3f
  74.  
  75. # define swapword(X) ((((X)&0xff) << 8) | (((X) & 0xff00) >> 8))
  76.  
  77. /****************************************************************
  78.  * write_pcx: Write PC Paintbrush format
  79.  ****************************************************************/
  80.  
  81. #ifndef lint
  82. static char *fbmid =
  83.     "$FBM flpcx.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  84. #endif
  85.  
  86. write_pcx (image, stream)
  87. FBM *image;
  88. FILE *stream;
  89. {  
  90.   fprintf (stderr, "PCX support not yet available\n");
  91.  
  92.   return (0);
  93. }
  94.  
  95. /****************************************************************
  96.  * read_pcx: Read PC Paintbrush format
  97.  ****************************************************************/
  98.  
  99. read_pcx (image, rfile, mstr, mlen)
  100. FBM *image;
  101. FILE *rfile;
  102. char *mstr;
  103. int mlen;
  104. { PCXHDR phdr;
  105.   char *hp;
  106.   register unsigned char *bmp, *scan;
  107.   register int k, r, c, bit, byte, mask, width, height, rowlen;
  108.   int depth, ptype, color, enc, clrlen, totalbytes;
  109.   unsigned char *buf, *tail;
  110.  
  111.   /* Read PCX file header */
  112.   hp = (char *) &phdr;
  113.  
  114.   if (mlen > 0) strncpy (hp, mstr, mlen);
  115.  
  116.   if (! fread (hp+mlen, sizeof (phdr) - mlen, 1, rfile))
  117.   { perror ("read_fbm (header)"); return (0); }
  118.  
  119.   if (phdr.Manufacturer != PCX_MAGIC)
  120.   { fprintf (stderr,
  121.          "Error, file is not a PCX file, magic %02x is not 0a\n",
  122.           phdr.Manufacturer);
  123.     return (0);
  124.   }
  125.   
  126.   /* PCX uses Little Indian byte order, swap on SUNS, RTs, ... */
  127.   if (machine_byte_order () == BIG)
  128.   { phdr.Window[0] =     swapword (phdr.Window[0]);
  129.     phdr.Window[1] =     swapword (phdr.Window[1]);
  130.     phdr.Window[2] =     swapword (phdr.Window[2]);
  131.     phdr.Window[3] =     swapword (phdr.Window[3]);
  132.     phdr.Hres =          swapword (phdr.Hres);
  133.     phdr.Vres =          swapword (phdr.Vres);
  134.     phdr.BytesPerLine =  swapword (phdr.BytesPerLine);
  135.     phdr.Palette =  swapword (phdr.Palette);
  136.   }
  137.   
  138. # ifdef DEBUG
  139.   fprintf (stderr, "Manufacturer        %d\n", phdr.Manufacturer);
  140.   fprintf (stderr, "Version             %d\n", phdr.Version);
  141.   fprintf (stderr, "Encoding            %d\n", phdr.Encoding);
  142.   fprintf (stderr, "BitsPerPixel        %d\n", phdr.BitsPerPixel);
  143.   fprintf (stderr, "Window0             %d\n", phdr.Window[0]);
  144.   fprintf (stderr, "Window1             %d\n", phdr.Window[1]);
  145.   fprintf (stderr, "Window2             %d\n", phdr.Window[2]);
  146.   fprintf (stderr, "Window3             %d\n", phdr.Window[3]);
  147.   fprintf (stderr, "Hres                %d\n", phdr.Hres);
  148.   fprintf (stderr, "Vres                %d\n", phdr.Vres);
  149.   fprintf (stderr, "Reserved            %d\n", phdr.Reserved);
  150.   fprintf (stderr, "NPlanes             %d\n", phdr.NPlanes);
  151.   fprintf (stderr, "BytesPerLine        %d\n", phdr.BytesPerLine);
  152.   fprintf (stderr, "Palette             %d\n", phdr.Palette);
  153. # endif
  154.  
  155.   /* Now extract relevant features of PCX file header */
  156.   width =  phdr.Window[XMAX] - phdr.Window[XMIN] + 1;
  157.   height = phdr.Window[YMAX] - phdr.Window[YMIN] + 1;
  158.   depth =  phdr.NPlanes;
  159.   ptype =  phdr.Version;
  160.   color =  (ptype == 2) || (ptype == 5);
  161.   enc =    phdr.Encoding;
  162.  
  163.   if (phdr.BitsPerPixel != 1)
  164.   { fprintf (stderr, "%s %d bits per pixel with %d planes\n", 
  165.          "Error in PCX file, can't handle", 
  166.          phdr.BitsPerPixel, depth);
  167.     return (0);
  168.   }
  169.  
  170.   /* Initialize image header */
  171.   image->hdr.cols = width;
  172.   image->hdr.rows = height;
  173.   image->hdr.planes = 1;
  174.   image->hdr.bits = (color || depth > 1) ? 8 : 1;
  175.   image->hdr.physbits = 8;
  176.   image->hdr.rowlen = rowlen = 16 * ((width + 15) / 16);
  177.   image->hdr.plnlen = rowlen * height;
  178.   image->hdr.clrlen = clrlen = color ? (16 * 3) : 0;
  179.   image->hdr.aspect = 1.0;
  180.   image->hdr.title[0] = '\0';
  181.   image->hdr.credits[0] = '\0';
  182.  
  183.   /* Describe what we are doing */
  184.   fprintf (stderr, "Reading PCX file [%dx%d]", width, height);
  185.   if (phdr.BitsPerPixel > 1)
  186.     fprintf (stderr, ", %d bits per pixel", phdr.BitsPerPixel);
  187.   if (depth > 1)
  188.     fprintf (stderr, ", %d planes", depth);
  189.   if (clrlen > 0)
  190.     fprintf (stderr, ", %d colors", clrlen/3);
  191.   fprintf (stderr, "\n");
  192.  
  193.   /* Allocate space */
  194.   alloc_fbm (image);
  195.  
  196.   /* Read colormap if need be */
  197.   if (clrlen > 0)
  198.   { for (c=0; c<16; c++)
  199.     { image->cm[c]    = phdr.Colormap[c][0];
  200.       image->cm[c+16] = phdr.Colormap[c][1];
  201.       image->cm[c+32] = phdr.Colormap[c][2];
  202.     }
  203.   }
  204.  
  205.   /* Zero out the bits */
  206.   bmp = image->bm;
  207.   tail = bmp + image->hdr.plnlen;
  208.  
  209.   while (bmp < tail) { *bmp++ = 0; }
  210.   
  211.   /* Bytes per scan line */
  212.   totalbytes = depth * phdr.BytesPerLine;
  213.   buf = (unsigned char *) malloc (totalbytes);
  214.  
  215.   /* Now read bits */
  216.   for (r=0; r<height; r++)
  217.   { bmp = &(image->bm[r * rowlen]);
  218.   
  219.     /* Read a scan line */
  220.     if (pcxline_read (enc, buf, totalbytes, rfile) == 0)
  221.     { fprintf (stderr, "Premature EOF in row %d, totalbytes %d\n",
  222.         r, totalbytes);
  223. # ifdef REAL
  224.       free_fbm (image);
  225.       return (0);
  226. # else
  227.       return (1);
  228. # endif
  229.     }
  230.         
  231.     /* Decode scan line into row of image */
  232.     if (depth == 1)
  233.     { bmp = &(image->bm[r * rowlen]);
  234.       scan = buf;
  235.  
  236.       for (c=0; c<width; c++)
  237.       { byte = c>>3;
  238.     mask = 0x80 >> (c&7);
  239.     *bmp++ = (buf[byte] & mask) ? WHITE : BLACK;
  240.       }
  241.     }
  242.     else
  243.     { for (k=0; k<depth; k++)
  244.       { bmp = &(image->bm[r * rowlen]);
  245.         scan = &buf[k * phdr.BytesPerLine];
  246.     bit = 1 << k;
  247.  
  248.         for (c=0; c<width; c++)
  249.     { byte = c>>3;
  250.       mask = 0x80 >> (c&7);
  251.  
  252.       *bmp++ |= (buf[byte] & mask) ? bit : 0;
  253.         }
  254.       }
  255.     }
  256.   }
  257.  
  258.   if (depth > 1)
  259.   { fprintf (stderr, "Read %d planes successfully\n", depth);
  260.   }
  261.  
  262.   return (1);
  263. }
  264.  
  265. /****************************************************************
  266.  * encget (pbyt, pcnt, fid)    Page 10 of ZSoft Manual
  267.  ****************************************************************/
  268.  
  269. encget (pbyt, pcnt, fid)
  270. int *pbyt;    /* Where to place data */
  271. int *pcnt;    /* Where to place count */
  272. FILE *fid;    /* Image file stream */
  273. { register int i;
  274.  
  275.   *pcnt = 1;        /* Safety play */
  276.   if (EOF == (i = getc (fid))) return (EOF);
  277.   if (CNTMSK == (CNTMSK & i))
  278.   { *pcnt = MAXCNT & i;
  279.     if (EOF == (i = getc (fid))) return (EOF);
  280.   }
  281.   *pbyt = i;
  282.   return (0);
  283. }
  284.  
  285. /****************************************************************
  286.  * pcxline_read
  287.  ****************************************************************/
  288. pcxline_read (enc, buf, total, fid)
  289. unsigned char *buf;    /* Output buffer */
  290. int total;        /* Bytes in one scan line */
  291. FILE *fid;        /* Input stream */
  292. { int data, count, len=0;
  293.  
  294.   if (enc != 1)
  295.   { return (fread (buf, 1, total, fid)); }
  296.  
  297.   while (len < total)
  298.   { if (EOF == encget (&data, &count, fid))
  299.       return (len);
  300.     while (count > 0) { *buf++ = data; len++; count--; }
  301.   }
  302.   
  303.   if (count > 0)
  304.   { fprintf (stderr, "%s, after %d bytes, lost %d bytes of %02x\n",
  305.          "Error in reading scan lines", total, count, data);
  306.   }
  307.  
  308.   return (len);
  309. }
  310.