delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1994/01/18/12:21:43

Date: Tue, 18 Jan 94 10:30:50 CST
From: csaba AT vuse DOT vanderbilt DOT edu (Csaba A. Biegl)
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Subject: PCX dump routine

Here is the routine which can be used to dump a graphics screen to a 
.PCX file (remember, max 16 different colors on the screen!). See the
comments in "pcxdump.h" about usage.

Csaba Biegl
csaba AT vuse DOT vanderbilt DOT edu

----- CUT ---------------------- pcxdump.h --------------- CUT ------
/*
 * PCX DUMP routine. Always dumps whole screen (you must be using GRX and
 * be in a graphics mode. The GRX mode (16, 256 colors, etc..) does not
 * matter as long as the number of different colors on the screen does not
 * exceed 16. The 'pcxdump' routine takes one argument: the name of the PCX
 * file. If this is NULL, an internally generated name is used. It returns
 * an integer indicating completion status: 0 = failed, else success. The
 * output is put into sequentially numbered PCX files starting with
 * "DUMP0000.PCX"
 */

extern int pcxdump(char *fname);

----- CUT ---------------------- pcxdump.c --------------- CUT ------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grx.h>
#include <mousex.h>
#include <io.h>

typedef unsigned char  uchar;
typedef unsigned short ushort;

typedef struct {
    uchar   maker;
    uchar   version;
    uchar   code;
    uchar   bpp;				/* bits per pixel */
    ushort  x1,y1,x2,y2;			/* image position */
    ushort  hres,vres;				/* image size */
    struct  { uchar R,G,B; } cmap[16];		/* palette */
    uchar   vmode;				/* video mode to display it */
    uchar   nplanes;				/* number of planes */
    ushort  bpl;				/* bytes per scan line */
    char    filler[128 - 68];
} pcxhdr;

#if	defined(__GNUC__) && defined(__MSDOS__)
#define MAX_COLORS     32768	/* maximum color graphics mode supported */
#else
#define MAX_COLORS     256	/* maximum color graphics mode supported */
#endif
#define MAX_OUTCOLORS  16	/* max number of simultaneous colors */
#define MAX_WIDTH      1280	/* max horizontal image size */

static  int dumpCount = 0;

int pcxdump(char *fname)
{
	GrContext save,xfer;
	pcxhdr hdr;
	uchar  rows[4][MAX_WIDTH / 8];
	char   colortable[MAX_COLORS];
	char   pcxfname[100];
	FILE  *pcxfile;
	int    numcolors,block,fast;
	int    ii,xx,yy,wdt,hgt;

	if(GrCurrentMode() < GR_320_200_graphics) return(0);
	if(GrNumColors() > MAX_COLORS) return(0);
	wdt = GrScreenX();
	hgt = GrScreenY();
	if(wdt > MAX_WIDTH) return(0);
	if(fname == NULL) for( ; ; ) {
	    /* find a new file name */
	    sprintf(pcxfname,"dump%04d.pcx",dumpCount);
	    if(access(pcxfname,0) != 0) {
		pcxfile = fopen(pcxfname,"wb");
		if(pcxfile == NULL) return(0);
		break;
	    }
	    if(++dumpCount >= 10000) return(0);
	}
	else {
	    strcpy(pcxfname,fname);
	    pcxfile = fopen(pcxfname,"wb");
	    if(pcxfile == NULL) return(0);
	}
	GrSaveContext(&save);
	GrCreateContext(wdt,1,NULL,&xfer);
	GrSetContext(&xfer);
	memset(&hdr,0,sizeof(pcxhdr));
	memset(colortable,-1,sizeof(colortable));
	hdr.maker   = 10;
	hdr.version = 5;
	hdr.code    = 1;
	hdr.x1	    = 0;
	hdr.y1	    = 0;
	hdr.x2	    = wdt - 1;
	hdr.y2	    = hgt - 1;
	hdr.hres    = wdt;
	hdr.vres    = hgt;
	hdr.bpp	    = 1;
	hdr.bpl	    = (wdt + 7) / 8;
	hdr.vmode   = 0x12;	    /* standard 640x480 16 color VGA ! */
	hdr.nplanes = 4;
	numcolors   = 0;
	fast  = (GrNumColors() == 256) ? 1 : 0;
	block = MouseCursorIsDisplayed();
	if(block) MouseEraseCursor();
	fwrite(&hdr,sizeof(pcxhdr),1,pcxfile);
	for(yy = 0; yy < hgt; yy++) {
	    uchar mask = 0x80;
	    int	  bytepos = 0;
	    int	  numbits = 0;
	    GrBitBlt(&xfer,0,0,&save,0,yy,wdt-1,yy,GrWRITE);
	    memset(rows,0,sizeof(rows));
	    for(xx = 0; xx < wdt; xx++) {
		int  color    = fast ? xfer.gc_baseaddr[xx] : GrPixel(xx,0);
		char outcolor = colortable[color];
		if(outcolor < 0) {	/* new color */
		    int r,g,b;
		    GrQueryColor(color,&r,&g,&b);
		    for(ii = 0; ii < numcolors; ii++) {
			if(hdr.cmap[ii].R != r) continue;
			if(hdr.cmap[ii].G != g) continue;
			if(hdr.cmap[ii].B != b) continue;
			outcolor = ii;
			break;
		    }
		    if(outcolor < 0) {
			if(numcolors >= MAX_OUTCOLORS) goto error;
			outcolor = ii = numcolors++;
			hdr.cmap[ii].R = r;
			hdr.cmap[ii].G = g;
			hdr.cmap[ii].B = b;
		    }
		    colortable[color] = outcolor;
		}
		if(outcolor & 1) rows[0][bytepos] |= mask;
		if(outcolor & 2) rows[1][bytepos] |= mask;
		if(outcolor & 4) rows[2][bytepos] |= mask;
		if(outcolor & 8) rows[3][bytepos] |= mask;
		mask >>= 1;
		if(++numbits == 8) {
		    mask    = 0x80;
		    numbits = 0;
		    bytepos++;
		}
	    }
	    for(ii = 0; ii < 4; ii++) {
		uchar *ptr    = rows[ii];
		uchar  pixval = *ptr;
		numbits = 0;
		for(bytepos = hdr.bpl; --bytepos >= 0; ptr++) {
		    if(pixval != *ptr) {
			while(numbits > 0x3f) {
			    putc((0xc0 | 0x3f),pcxfile);
			    putc(pixval,pcxfile);
			    numbits -= 0x3f;
			}
			if(numbits > 0) {
			    if((numbits > 1) || (pixval >= 0xc0))
				putc((0xc0 | numbits),pcxfile);
			    putc(pixval,pcxfile);
			}
			numbits = 0;
		    }
		    pixval = *ptr;
		    numbits++;
		}
		while(numbits > 0x3f) {
		    putc((0xc0 | 0x3f),pcxfile);
		    putc(pixval,pcxfile);
		    numbits -= 0x3f;
		}
		if(numbits > 0) {
		    if((numbits > 1) || (pixval >= 0xc0))
			putc((0xc0 | numbits),pcxfile);
		    putc(pixval,pcxfile);
		}
	    }
	}
	if(ferror(pcxfile)) goto error;
	if(block) MouseDisplayCursor();
	GrSetContext(&save);
	GrDestroyContext(&xfer);
	fseek(pcxfile,0L,0);
	fwrite(&hdr,sizeof(pcxhdr),1,pcxfile);
	fclose(pcxfile);
	return(1);
      error:
	if(block) MouseDisplayCursor();
	GrSetContext(&save);
	GrDestroyContext(&xfer);
	fclose(pcxfile);
	unlink(pcxfname);
	return(0);
}

----- CUT ------------------------------------------------ CUT ------

 

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019