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 #include #include #include #include #include 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 ------