home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c185 / 2.ddi / OWLSRC.EXE / CSCAPE / SOURCE / PCXSAVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-06  |  5.9 KB  |  233 lines

  1. /*
  2.     pcxsave.c
  3.  
  4.     % Save a Z-soft pcx format image file from a pixel map structure.
  5.  
  6.     7/29/89 By Ted.
  7.  
  8.     OWL 1.1
  9.     Copyright (c) 1989 by Oakland Group, Inc.
  10.     ALL RIGHTS RESERVED.
  11.  
  12.     Revision History:
  13.     -----------------
  14. */
  15.  
  16. #include "oakhead.h"
  17. #include "disppriv.h"
  18. #include "frwdecl.h"
  19. #include "pcxdecl.h"
  20. #include "digutil.h"
  21.  
  22. #define FRWBUFSIZE        1024
  23.  
  24. OSTATIC boolean DIGPRIV pcx_savehdr(_arg3(frw_type frw, pmap_type pmap, ocolmap_type cmap));
  25. OSTATIC boolean DIGPRIV pcx_savexcolmap(_arg2(frw_type frw, ocolmap_type cmap));
  26. OSTATIC byte    DIGPRIV newbyte(_arg3(byte *obuf, unsigned ibyte, unsigned linebytes));
  27. /* -------------------------------------------------------------------------- */
  28.  
  29. boolean DIGPRIV dig_savepcx(frw, pmap, cmap, packpcx)
  30.     frw_type frw;
  31.     pmap_type pmap;
  32.     ocolmap_type cmap;
  33.     pcxpack_fptr packpcx;
  34. {
  35.     /* Save pcx file header */
  36.     if (!pcx_savehdr(frw, pmap, cmap)) {
  37.         return(FALSE);
  38.     }
  39.     /* Allocate Buffer */
  40.     if (!frw_openbuf(frw, FRWBUFSIZE, FRW_WRITEMODE)) {
  41.         return(FALSE);
  42.     }
  43.     /* Write out image */
  44.     if (!(*packpcx)(frw, pmap)) {
  45.         frw_closebuf(frw);
  46.         return(FALSE);
  47.     }
  48.     /* Save extra colormap if needed */
  49.     if (!pcx_savexcolmap(frw, cmap)) {
  50.         frw_closebuf(frw);
  51.         return(FALSE);
  52.     }
  53.     frw_closebuf(frw);
  54.     return(TRUE);
  55. }
  56. /* -------------------------------------------------------------------------- */
  57.  
  58. OSTATIC boolean DIGPRIV pcx_savehdr(frw, pmap, cmap)
  59.     frw_type frw;
  60.     pmap_type pmap;
  61.     ocolmap_type cmap;
  62. {
  63.     pcxhdr_struct pcxhdr;
  64.     int i;
  65.     unsigned ncols;
  66.  
  67.     /* Set up header structure */
  68.     pcxhdr.mfgr = 10;
  69.     pcxhdr.version = 5;        /* Version 3 PCX file */
  70.     pcxhdr.encoding = 1;
  71.     pcxhdr.pixbits = disp_GetInfo()->pixbits;
  72.  
  73.     pcxhdr.xmin = 0;
  74.     pcxhdr.ymin = 0;
  75.     pcxhdr.xmax = pmap_GetWidth(pmap) - 1;
  76.     pcxhdr.ymax = pmap_GetHeight(pmap) - 1;
  77.  
  78.     pcxhdr.hres = disp_GetPixWidth();
  79.     pcxhdr.vres = disp_GetPixHeight();
  80.  
  81.     memset((VOID *) pcxhdr.rgb, 0, 16*3);    /* first clear out color table */
  82.     ncols = (cmap != NULL) ? (unsigned) cmap->nentries : 0;
  83.     if (ncols <= 16) {
  84.         for (i = 0; i < ncols; i++) {
  85.             memmove((VOID *) pcxhdr.rgb[i],
  86.                     (VOID *) ocolmap_entry(cmap, cmap->firstpix + i), 3);
  87.         }
  88.     }
  89.     /* else we'll fill in the extended color table after doing the image */
  90.  
  91.     pcxhdr.reserved = 0;
  92.     pcxhdr.nplanes = disp_GetInfo()->nplanes;
  93.     pcxhdr.linebytes = (((pcxhdr.xmax+1) * pcxhdr.pixbits + 15) / 16) * 2;
  94.     pcxhdr.paltype = 1 | 8;
  95.     pcxhdr.ylines = pcxhdr.ymax + 1;
  96.     memset((VOID *) pcxhdr.filler, 0, PCX_FILLER);    /* clear out filler */
  97.  
  98.     pcx_hdrflip(&pcxhdr);    /* Flip bytes in shorts if needed */
  99.  
  100.     /* Write out header */
  101.     if (frw_write(frw, (VOID *) &pcxhdr, sizeof(pcxhdr_struct)) < sizeof(pcxhdr_struct)) {
  102.         return(FALSE);
  103.     }
  104.     return(TRUE);
  105. }
  106. /* -------------------------------------------------------------------------- */
  107.  
  108. OSTATIC boolean DIGPRIV pcx_savexcolmap(frw, cmap)
  109.     frw_type frw;
  110.     ocolmap_type cmap;
  111. /*
  112.     Save extended 256 color color map after image if more than 16 colors used.
  113. */
  114. {
  115.     opixval ncols, i;
  116.  
  117.     if (cmap == NULL) {
  118.         return(TRUE);
  119.     }
  120.     ncols = (unsigned) cmap->nentries;
  121.  
  122.     if (ncols > 256) {
  123.         ncols = 256;
  124.     }
  125.     if (ncols > 16) {
  126.         if (!frw_writeb(frw, 12)) {
  127.             return(FALSE);
  128.         }
  129.         /* Write out colors from color map */
  130.         for (i = 0; i < ncols; i++) {
  131.             if (frw_write(frw, (VOID *) ocolmap_entry(cmap, cmap->firstpix + i), 3) != 3) {
  132.                 return(FALSE);
  133.             }
  134.         }
  135.         /* Write 0's for rest of colors up to 256 (if ncols was < 256) */
  136.         for (i = ncols * 3 ; i < 256 * 3; i++) {
  137.             if (!frw_writeb(frw, 0)) {
  138.                 return(FALSE);
  139.             }
  140.         }
  141.     }
  142.     return(TRUE);
  143. }
  144. /* -------------------------------------------------------------------------- */
  145.  
  146. boolean DIGPRIV pcx_writeline(frw, obuf, linebytes)
  147.     frw_type frw;
  148.     byte *obuf;
  149.     unsigned linebytes;
  150. /*
  151.     Write one image plane scanline in pcx runlength format, making sure that
  152.     an even number of bytes are written.
  153. */
  154. {
  155.     unsigned ibyte;
  156.     byte cbyte, nbyte;
  157.     byte count;
  158.     unsigned lastbyte;
  159.  
  160.     lastbyte = linebytes;
  161.     if (lastbyte & 1) lastbyte++;    /* Pad lastbyte out to an even number */
  162.  
  163.     /* For each code within a plane-line */
  164.     ibyte = 0;
  165.     cbyte = obuf[ibyte++];
  166.     for (;;) {
  167.         nbyte = newbyte(obuf, ibyte++, linebytes);
  168.  
  169.         if (nbyte != cbyte) {
  170.             if((cbyte & 0xC0) == 0xC0) {
  171.                 if (!frw_writeb(frw, 0xC1)) return(FALSE); /* Quote it if needed */
  172.             }
  173.             if (!frw_writeb(frw, cbyte)) return(FALSE);    /* Write the lone byte */
  174.         }
  175.         else {    /* nbyte == cbyte */
  176.             nbyte = newbyte(obuf, ibyte++, linebytes);
  177.  
  178.             if (cbyte == nbyte || (cbyte & 0xC0) == 0xC0) {
  179.                 count = 2;
  180.                 for (;;) {
  181.                     if (nbyte != cbyte) {
  182.                         break;
  183.                     }
  184.                     if (count == 0x3F) {    /* 0x3F == ~0xC0 */
  185.                         break;
  186.                     }
  187.                     count++;
  188.                     nbyte = newbyte(obuf, ibyte++, linebytes);
  189.                 }
  190.                 if (!frw_writeb(frw, (byte) 0xC0 | count)) return(FALSE);
  191.                 if (!frw_writeb(frw, cbyte)) return(FALSE);
  192.             }
  193.             else {    /* only 2; no repeat count */
  194.                 if (!frw_writeb(frw, cbyte)) return(FALSE);
  195.                 if (!frw_writeb(frw, cbyte)) return(FALSE);
  196.             }
  197.         }
  198.         /* Note: if ibyte == lastbyte, nbyte is still valid because ibyte is post-incremented */
  199.         if (ibyte > lastbyte) {
  200.             break;
  201.         }
  202.         cbyte = nbyte;
  203.     }
  204.     return(TRUE);
  205. }
  206. /* -------------------------------------------------------------------------- */
  207.  
  208. static byte DIGPRIV newbyte(obuf, ibyte, linebytes)
  209.     byte *obuf;
  210.     unsigned ibyte;
  211.     unsigned linebytes;
  212. {
  213.     byte nbyte;
  214.  
  215.     if (ibyte < linebytes) {
  216.         nbyte = obuf[ibyte];    /* Next byte from array */
  217.     }
  218.     else {
  219.         nbyte = obuf[linebytes - 1];    /* Last array byte */
  220. /*        if (FALSE) { */
  221.         if (ibyte == linebytes && (linebytes & 1) == 1) {
  222.             /* Use last array byte if padding to an even last byte */
  223.         }
  224.         else {
  225.             /* Make a fake nbyte if out of array and not padding */
  226.             nbyte = ~nbyte | 0xC0;
  227.         }
  228.     }
  229.     return(nbyte);
  230. }
  231. /* -------------------------------------------------------------------------- */
  232.  
  233.