www.pudn.com > pcx_c.zip > PCX.C


/*	PCX.c -  Graphic Routines that operate on PCX pictures 
*/ 
 
 
#include  
#include "lib.h" 
#include "pcx.h" 
 
 
int pcx_init(); 
int pcx_clear(); 
int pcx_set_point(); 
int pcx_clr_point(); 
int pcx_xor_point(); 
int pcx_write_row(); 
int pcx_select_plane(); 
int pcx_set_palette(); 
int pcx_mode(); 
int movmem(); 
int pokeb(); 
int peekb(); 
int pcx_get_point(); 
 
static int (*pcx_func[])() = { 
	pcx_init,      pcx_clear,     pcx_set_point, pcx_clr_point, 
	pcx_xor_point, pcx_get_point, pcx_write_row, pcx_select_plane, 
	pcx_set_palette,pcx_mode,     movmem, peekb, pokeb }; 
 
PCXPIC *pcx_cpic;      /* current picture   */ 
static int cplane;     /* current plane     */ 
int	pcx_md;        /* 1 if CGA-type picture, 0 for HERC/EGA */ 
 
 
int pcx_init() 
{ 
	movmem( pcx_func, vgr_func, sizeof(vgr_func) ); 
 
	VGR_NBPL = VGR_HRES = VGR_VRES = VGR_NCOLORS = cplane = 0; 
	if ( pcx_cpic ) 
	{  VGR_HRES    = pcx_cpic->hdr.hres; 
	   VGR_VRES    = pcx_cpic->hdr.vres; 
	   VGR_NBPL    = pcx_cpic->hdr.bpl; 
	   VGR_NCOLORS = pcx_cpic->hdr.bpp > 1 ?  
	                 0x01 << pcx_cpic->hdr.bpp : 
	                 0x01 << pcx_cpic->hdr.nplanes; 
	}; 
 
	return OK; 
} 
 
 
int pcx_select_plane( plane ) 
int plane; 
{ 
	return cplane = plane & 0x03; 
} 
 
 
int pcx_write_row( row, prow, nbytes ) 
int nbytes, row; 
char *prow; 
{ 
	int i; 
 
	i = pcx_cpic->hdr.hres / 8; 
	movmem( prow, (pcx_cpic->rows[cplane][row]),  
	               nbytes <= i ? nbytes : i ); 
} 
 
 
int pcx_clear() 
{ 
	int plane, row, nplanes, nrows, bytes; 
 
	nplanes =  pcx_cpic->hdr.nplanes; 
	nrows   =  pcx_cpic->hdr.y2 - pcx_cpic->hdr.y1 +1; 
	bytes   =  pcx_cpic->hdr.bpl; 
 
	for ( plane=0; plane < nplanes; plane ++ ) 
	   for ( row=0; row < bytes; row++ ) 
	      setmem( (pcx_cpic->rows[plane][row]), bytes, 0 ); 
} 
 
 
int pcx_mode( m ) 
int m; 
{ 
	switch ( m ) 
	{  case MODE_APA0:   /* 640x350x16 */ 
	   case MODE_APA1:   /* 720x348x02 */ 
	   case MODE_APA2:   /* 640x200x02 */ 
	      /* all these modes save color information 
	         1 bit per plane. 
	      */ 
	      pcx_md = 0; 
	      break; 
	   case MODE_APA3:   /* 320x200x04 */ 
	      /* this mode puts two bits per pixel into the 
	         same plane. 
	      */ 
	      pcx_md = 1; 
	      break; 
	   default:          /* invalid!   */ 
	      return ERROR; 
	}; 
 
	return OK; 
} 
 
 
int pcx_xor_point( x, y, color ) 
int x, y, color; 
{ 
	return pcx_set_point( x, y, pcx_get_point( x, y ) ^ color ); 
} 
 
 
int pcx_clr_point( x, y ) 
int x, y; 
{ 
	return pcx_set_point( x, y, 0 ); 
} 
 
 
int pcx_set_point( x, y, color ) 
int x, y, color; 
{ 
	register unsigned char *p; 
	unsigned char plane, b, o, mask; 
 
	if ( pcx_md ) 
	{  o = (x & 3) << 1; 
	   p = (unsigned char *)pcx_cpic->rows[0][y] + (x>>2); 
	   *p = (*p & ~(0xc0 >> o)) | ((color & 0x03) << (6-o)); 
	   return OK; 
	}; 
 
	o = x >> 3; 
	b = (unsigned int)0x80 >> (x & 0x07); 
 
	for ( mask=1,plane=0; plane < pcx_cpic->hdr.nplanes; plane++, mask<<=1 ) 
	{  p = (unsigned char *)pcx_cpic->rows[plane][y] + o; 
	   if ( color & mask ) 
	      *p |= b; 
	   else *p &= ~b; 
	}; 
 
	return OK; 
} 
 
 
int pcx_get_point( x, y ) 
int x, y; 
{ 
	unsigned char plane, b, o, color; 
 
	if ( pcx_md ) 
	{  b = (x & 3) << 1; 
	   return ( pcx_cpic->rows[0][y][x>>2] & (0xc0 >> b) ) >> (6-b); 
	}; 
 
	o = x >> 3; 
	b = (unsigned int)0x80 >> (x & 0x07); 
 
	for ( color=plane=0; plane < pcx_cpic->hdr.nplanes; plane++ ) 
	   color |= !!(pcx_cpic->rows[plane][y][o] & b) << plane; 
 
	return color; 
} 
 
 
/*	PCX Palette Settings. 
*/ 
 
int pcx_set_palette( reg, red, green, blue ) 
unsigned char reg, red, green, blue; 
{ 
	if ( pcx_md ) 
	{  pcx_cpic->hdr.triple[reg].red = red; 
	   return OK; 
	}; 
 
	/* why do we multiply by 85? */ 
	pcx_cpic->hdr.triple[reg].red   = red   * 85; 
	pcx_cpic->hdr.triple[reg].green = green * 85; 
	pcx_cpic->hdr.triple[reg].blue  = blue  * 85; 
	return OK; 
} 
 
 
PCXPIC *pcx_init_pic( hres, vres, nplanes ) 
unsigned int hres, vres, nplanes; 
{ 
	int y, p, bpl; 
	PCXPIC *pic; 
	char *calloc(); 
	static TRIPLET ega_pal[] = {  /* copied from a        */ 
	      0x00, 0x00, 0x00,       /* PBRUSH picture file  */ 
	      0x00, 0x00, 0xaa, 
	      0x00, 0xaa, 0x00, 
	      0x00, 0xaa, 0xaa, 
	      0xaa, 0x00, 0x00, 
	      0xaa, 0x00, 0xaa, 
	      0xaa, 0xaa, 0x00, 
	      0xaa, 0xaa, 0xaa, 
	      0x55, 0x55, 0x55, 
	      0x55, 0x55, 0xff, 
	      0x55, 0xff, 0x55, 
	      0x55, 0xff, 0xff, 
	      0xff, 0x55, 0x55, 
	      0xff, 0x55, 0xff, 
	      0xff, 0xff, 0x55, 
	      0xff, 0xff, 0xff        }; 
 
	static TRIPLET cga_pal[] = { 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0, 
	        0,0,0, 255,0,0        }; 
 
	if ( !(pic = (PCXPIC *) calloc( 1, sizeof(PCXPIC) )) ) 
	   return NULL; /* out of memory */ 
 
	pic->hdr.x2 = hres -1; 
	pic->hdr.y2 = vres -1; 
 
	pic->hdr.maker     = 10; 
	pic->hdr.version   =  5; 
	pic->hdr.code      =  1; 
	pic->hdr.bpp       =  1 + pcx_md; 
	pic->hdr.bpl       = bpl = (hres * (1+pcx_md)) / 8; 
 
	VGR_HRES    = pic->hdr.hres    = hres; 
	VGR_VRES    = pic->hdr.vres    = vres; 
	VGR_NBPL    = bpl; 
	VGR_NCOLORS = 1 << (pic->hdr.nplanes = nplanes); 
 
	movmem( (pcx_md ? cga_pal : ega_pal),  
	         pic->hdr.triple, sizeof(pic->hdr.triple) ); 
 
	for ( p=0; p < nplanes; p++ ) 
	{  if ( ! (pic->rows[p] = (uchar **)calloc( 1, sizeof(char *) * vres)) ) 
	      return pcx_free_pic( pic ), (PCXPIC *)0; 
	   for ( y=0; y < vres; y++ ) 
	      if ( !(pic->rows[p][y] = (uchar *)calloc( 1, bpl )) ) 
	         return pcx_free_pic( pic ), (PCXPIC *)0; 
	}; 
 
	return pic; 
} 
 
 
int pcx_free_pic( pic ) 
PCXPIC *pic; 
{ 
	int row, plane, nrows, nplan; 
 
	nrows = pic->hdr.y2 - pic->hdr.y1 +1; 
	nplan = pic->hdr.nplanes; 
 
	VGR_MODE( MODE_TEXT0 ); 
	printf("At pcx_free_pic, probably out of memory...\n"); 
 
	for ( plane = 0; plane < nplan; plane++ ) 
	{  for ( row = 0; row < nrows; row++ ) 
	      allocf( pic->rows[plane][row] ); 
	   allocf( pic->rows[plane] ); 
	}; 
 
	allocf( pic ); 
	return NULL; 
} 
 
 
void map_not( map, len ) 
register unsigned int *map, len; 
{ 
	for ( ; len--; map++ ) 
	   *map = ~ *map; 
} 
 
 
void pcx_invert_pic( pic ) 
PCXPIC *pic; 
{ 
	int p, r, i; 
 
	for ( p=0; p < pic->hdr.nplanes; p++ ) 
	   for ( r=0; r < (pic->hdr.y2 - pic->hdr.y1); r++ ) 
	      map_not( pic->rows[p][r], pic->hdr.bpl / 2 ); 
} 
 
 
allocf( p ) 
char *p; 
{ 
	if ( !p ) 
	   return OK; 
 
	if ( free(p) == -1 ) 
	   CRASH( "heap munged" ); 
} 
 
#ifdef MAIN 
 
/*	Manx 'C stack/heap size adjustment - 
	The vgr_fill() function uses an enourmous amount of stack, 
	and we're going to need enough heap space to allocate 
	4 bit maps for the EGA board. 
*/ 
uint	__STKLOW = 0, 
    	__STKSIZ = 4096, 
    	__HEAPSIZ = 8192; 
 
int 	cga_init(), ega_init(), herc_init(); 
int	board, (*board_init)(), md; 
 
/*	This structure is used here to facilitate drawing the 
	simple X and complex box that are used to test the 
	dot, line and fill functions. 
*/ 
typedef struct { 
   int x,y; 
} OBJ; 
 
static OBJ obj[] = {  
100, 100, 150, 200, 200, 100, 250, 150, 175, 250, 250, 350, 200, 400, 150, 300,  
100, 400,  50, 350, 125, 250,  50, 150, 100, 100 }; 
 
static OBJ obj2[] = { 
  0,  0,280,  0,280,140,240,140,240, 20,200, 20,200,280,240,280,240,160,  
280,160,280,300,  0,300,  0,160, 40,160, 40,280, 80,280, 80, 20, 40, 20,  
 40,140,  0,140,  0,  0 }; 
	    
static OBJ obj3[] = { 
	   120,20, 160,20, 160,280, 120,280, 120,20 }; 
 
 
main( argc, argv ) 
char **argv; 
int argc; 
{ 
	void pcx_showpic(); 
	FILE *fp, *fopen(); 
	int c, h, v, p; 
 
	printf("PCX test routine.\n"); 
	if ( argc == 1 ) 
	   printf("Try \"PCX xx\" for help\n" ); 
 
	board = vgr_get_board(); 
 
	if ( argc >= 2 ) 
	{       if ( !strcmp(argv[1], "ega") ) 
	           board = TYPE_EGA; 
	   else if ( !strcmp(argv[1], "cga") ) 
	           board = TYPE_CGA; 
	   else if ( !strcmp(argv[1], "herc") ) 
	           board = TYPE_HERC; 
	   else if ( !strcmp(argv[1], "cga2") ) 
	           board = 9; 
	   else {  printf("\ 
usage: PCX\n\ 
or     PCX \n\ 
or     PCX  \n\n\ 
 func: Excercises the board & PCX routines.\n\ 
        may be one of:\n\ 
       	   cga - 640x200x2 CGA\n\ 
       	   cga2- 320x200x4 CGA\n\ 
       	   herc- Hercules Hi-Res\n\ 
       	   ega - 640x350x16 EGA\n\ 
        may be any file name,\n\ 
       although an extension of .PCX is\n\ 
       appropriate.\n" ); 
 	           exit(1); 
 	        }; 
	}; 
 
	switch( board ) 
	{  case TYPE_UNKNOWN: 
	   case TYPE_MDA: 
	      CRASH("unable to detect a HERC, CGA or EGA board"); 
	   case TYPE_CGA: 
	      printf("CGA board detected\n"); 
	      board_init = cga_init; 
	      md = MODE_APA2, c = 1, h = 640, v=200, p=1; 
	      break; 
	   case 9: 
	      printf("CGA/APA3 Selected\n"); 
	      board_init = cga_init; 
	      md = MODE_APA3, c = 2, h = 320, v=200, p=1; 
	      break; 
	   case TYPE_EGA: 
	      printf("EGA board detected\n"); 
	      board_init = ega_init; 
	      md = MODE_APA0, c = 9, h = 640, v=350, p=4; 
	      break; 
	   case TYPE_HERC: 
	      printf("HERC board detected\n"); 
	      board_init = herc_init; 
	      md = MODE_APA1, c = 1, h = 720, v=348, p=1; 
	      break; 
	   default: 
	      CRASH("bug: invalid board type number"); 
	}; 
 
	printf("Hit return to continue:"); 
	getchar(); 
 
	/* pcx_init_pic needs to know what mode it's in 
	*/ 
	pcx_init(); 
	pcx_mode( md );    
	if ( !(pcx_cpic = pcx_init_pic( h, v, p )) ) 
	   CRASH("out of memory"); 
 
	pcx_init(); 
	if ( VGR_MODE( md ) ) 
	   CRASH( "error in mode selection" ); 
 
	printf("HRES=%d, VRES=%d, NCOLORS=%d, NPLANES=%d, pcx_md=%d\n", 
	      VGR_HRES, VGR_VRES, VGR_NCOLORS, p, pcx_md ); 
 
	draw_it( (OBJ *)&obj,  NELEMS(obj) , 3, 3,   0, 0, c ); 
	printf("."); 
	draw_it( (OBJ *)&obj2, NELEMS(obj2), 3, 3, 150, 0, c ); 
	printf("."); 
	draw_it( (OBJ *)&obj3, NELEMS(obj3), 3, 3, 150, 0, c ); 
	printf("."); 
 
	vgr_fill(  33, 40, c ); 
	printf("."); 
	vgr_fill( 179, 19, c ); 
 
	printf("\nhit return to continue, then hit return again:"); 
	getchar(); 
 
	if ( (*board_init)() ) 
	   CRASH( "board init failed" ); 
	if ( VGR_MODE( md ) ) 
	   CRASH( "error in mode selection" ); 
 
	pcx_showpic( pcx_cpic, 0, 0, 0 ); 
 
	getchar(); 
 
	VGR_MODE( MODE_TEXT0 ); 
 
	if ( argc == 3 ) 
	{  if ( !(fp = fopen( argv[2], "w" )) ) 
	      CRASH( "error opening picture file" ); 
	   if ( pcx_write_pic( pcx_cpic, fp ) ) 
	      CRASH( "error writing picture file" ); 
	   fclose(fp); 
	}; 
 
	exit(0); 
} 
 
 
draw_it( obj, n, divx, divy, ox, oy, c ) 
OBJ *obj; 
int n, divx, divy; 
{ 
	int x; 
 
	vgr_point( obj[0].x / divx + ox, obj[0].y / divy + oy, -1 ); 
	for ( x=1; x < n; x++ ) 
	   vgr_point( obj[x].x / divx + ox, obj[x].y / divy + oy, c ); 
} 
 
 
#endif