home *** CD-ROM | disk | FTP | other *** search
- /*
- pcxsave.c
-
- % Save a Z-soft pcx format image file from a pixel map structure.
-
- 7/29/89 By Ted.
-
- OWL-DIG 1.2
- Copyright (c) 1989 by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 3/28/90 jmd ansi-fied
- 12/19/90 ted set the pcx header colors to default PC colors, not 0's.
- */
-
- #include "oakhead.h"
- #include "disppriv.h"
- #include "frwdecl.h"
- #include "pcxdecl.h"
- #include "digutil.h"
-
- #define FRWBUFSIZE 1024
-
- OSTATIC boolean DIGPRIV pcx_savehdr(frw_type frw, pmap_type pmap, ocolmap_type cmap);
- OSTATIC boolean DIGPRIV pcx_savexcolmap(frw_type frw, ocolmap_type cmap);
- OSTATIC byte DIGPRIV newbyte(byte *obuf, unsigned ibyte, unsigned linebytes);
- /* -------------------------------------------------------------------------- */
-
- boolean DIGPRIV dig_savepcx(frw_type frw, pmap_type pmap, ocolmap_type cmap, pcxpack_fptr packpcx)
- {
- /* Save pcx file header */
- if (!pcx_savehdr(frw, pmap, cmap)) {
- return(FALSE);
- }
- /* Allocate Buffer */
- if (!frw_openbuf(frw, FRWBUFSIZE, FRW_WRITEMODE)) {
- return(FALSE);
- }
- /* Write out image */
- if (!(*packpcx)(frw, pmap)) {
- frw_closebuf(frw);
- return(FALSE);
- }
- /* Save extra colormap if needed */
- if (!pcx_savexcolmap(frw, cmap)) {
- frw_closebuf(frw);
- return(FALSE);
- }
- frw_closebuf(frw);
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- OSTATIC boolean DIGPRIV pcx_savehdr(frw_type frw, pmap_type pmap, ocolmap_type cmap)
- {
- pcxhdr_struct pcxhdr;
- int i;
- unsigned ncols;
-
- static byte defrgbs[16][3] = {
- {0x00,0x00,0x00},{0x00,0x00,0xAB},{0x00,0xAB,0x00},{0x00,0xAB,0xAB},
- {0xAB,0x00,0x00},{0xAB,0x00,0xAB},{0xAB,0x57,0x00},{0xAB,0xAB,0xAB},
- {0x57,0x57,0x57},{0x57,0x57,0xFF},{0x57,0xFF,0x57},{0x57,0xFF,0xFF},
- {0xFF,0x57,0x57},{0xFF,0x57,0xFF},{0xFF,0xFF,0x57},{0xFF,0xFF,0xFF}
- };
-
- /* Set up header structure */
- pcxhdr.mfgr = 10;
- pcxhdr.version = 5; /* Version 3 PCX file */
- pcxhdr.encoding = 1;
- pcxhdr.pixbits = disp_GetInfo()->pixbits;
-
- pcxhdr.xmin = 0;
- pcxhdr.ymin = 0;
- pcxhdr.xmax = pmap_GetWidth(pmap) - 1;
- pcxhdr.ymax = pmap_GetHeight(pmap) - 1;
-
- pcxhdr.hres = disp_GetPixWidth();
- pcxhdr.vres = disp_GetPixHeight();
-
- /* Set the pcx header color table colors */
- ncols = (cmap != NULL) ? (unsigned) cmap->nentries : 0;
- if (ncols <= 16) {
- /* First copy default PC colors in there */
- memmove ((VOID *) pcxhdr.rgb, (VOID *) defrgbs, 16*3);
-
- /* Then copy over with any custom colors that may be passed in. */
- for (i = 0; i < ncols; i++) {
- memmove((VOID *) pcxhdr.rgb[i],
- (VOID *) ocolmap_entry(cmap, cmap->firstpix + i), 3);
- }
- }
- else { /* we'll fill in the extended color table after doing the image */
- memset((VOID *) pcxhdr.rgb, 0, 16*3);
- }
-
- pcxhdr.reserved = 0;
- pcxhdr.nplanes = disp_GetInfo()->nplanes;
- pcxhdr.linebytes = (((pcxhdr.xmax+1) * pcxhdr.pixbits + 15) / 16) * 2;
- pcxhdr.paltype = 1 | 8;
- pcxhdr.ylines = pcxhdr.ymax + 1;
- memset((VOID *) pcxhdr.filler, 0, PCX_FILLER); /* clear out filler */
-
- pcx_hdrflip(&pcxhdr); /* Flip bytes in shorts if needed */
-
- /* Write out header */
- if (frw_write(frw, (VOID *) &pcxhdr, sizeof(pcxhdr_struct)) < sizeof(pcxhdr_struct)) {
- return(FALSE);
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- OSTATIC boolean DIGPRIV pcx_savexcolmap(frw_type frw, ocolmap_type cmap)
- /*
- Save extended 256 color color map after image if more than 16 colors used.
- */
- {
- opixval ncols, i;
-
- if (cmap == NULL) {
- return(TRUE);
- }
- ncols = (unsigned) cmap->nentries;
-
- if (ncols > 256) {
- ncols = 256;
- }
- if (ncols > 16) {
- if (!frw_writeb(frw, 12)) {
- return(FALSE);
- }
- /* Write out colors from color map */
- for (i = 0; i < ncols; i++) {
- if (frw_write(frw, (VOID *) ocolmap_entry(cmap, cmap->firstpix + i), 3) != 3) {
- return(FALSE);
- }
- }
- /* Write 0's for rest of colors up to 256 (if ncols was < 256) */
- for (i = ncols * 3 ; i < 256 * 3; i++) {
- if (!frw_writeb(frw, 0)) {
- return(FALSE);
- }
- }
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean DIGPRIV pcx_writeline(frw_type frw, byte *obuf, unsigned linebytes)
- /*
- Write one image plane scanline in pcx runlength format, making sure that
- an even number of bytes are written.
- */
- {
- unsigned ibyte;
- byte cbyte, nbyte;
- byte count;
- unsigned lastbyte;
-
- lastbyte = linebytes;
- if (lastbyte & 1) lastbyte++; /* Pad lastbyte out to an even number */
-
- /* For each code within a plane-line */
- ibyte = 0;
- cbyte = obuf[ibyte++];
- for (;;) {
- nbyte = newbyte(obuf, ibyte++, linebytes);
-
- if (nbyte != cbyte) {
- if((cbyte & 0xC0) == 0xC0) {
- if (!frw_writeb(frw, 0xC1)) return(FALSE); /* Quote it if needed */
- }
- if (!frw_writeb(frw, cbyte)) return(FALSE); /* Write the lone byte */
- }
- else { /* nbyte == cbyte */
- nbyte = newbyte(obuf, ibyte++, linebytes);
-
- if (cbyte == nbyte || (cbyte & 0xC0) == 0xC0) {
- count = 2;
- for (;;) {
- if (nbyte != cbyte) {
- break;
- }
- if (count == 0x3F) { /* 0x3F == ~0xC0 */
- break;
- }
- count++;
- nbyte = newbyte(obuf, ibyte++, linebytes);
- }
- if (!frw_writeb(frw, (byte) 0xC0 | count)) return(FALSE);
- if (!frw_writeb(frw, cbyte)) return(FALSE);
- }
- else { /* only 2; no repeat count */
- if (!frw_writeb(frw, cbyte)) return(FALSE);
- if (!frw_writeb(frw, cbyte)) return(FALSE);
- }
- }
- /* Note: if ibyte == lastbyte, nbyte is still valid because ibyte is post-incremented */
- if (ibyte > lastbyte) {
- break;
- }
- cbyte = nbyte;
- }
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static byte DIGPRIV newbyte(byte *obuf, unsigned ibyte, unsigned linebytes)
- {
- byte nbyte;
-
- if (ibyte < linebytes) {
- nbyte = obuf[ibyte]; /* Next byte from array */
- }
- else {
- nbyte = obuf[linebytes - 1]; /* Last array byte */
- /* if (FALSE) { */
- if (ibyte == linebytes && (linebytes & 1) == 1) {
- /* Use last array byte if padding to an even last byte */
- }
- else {
- /* Make a fake nbyte if out of array and not padding */
- nbyte = ~nbyte | 0xC0;
- }
- }
- return(nbyte);
- }
- /* -------------------------------------------------------------------------- */
-
-