Mail Archives: djgpp/1994/01/18/12:21:43
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 -