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