// I N C L U D E S /////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include "graph3.h" // our graphics functions from day 3 // S T R U C T U R E S /////////////////////////////////////////////////////// typedef struct pcx_header_typ { char manufacturer; char version; char encoding; char bits_per_pixel; int x,y; int width,height; int horz_res; int vert_res; char ega_palette[48]; char reserved; char num_color_planes; int bytes_per_line; int palette_type; char padding[58]; } pcx_header, *pcx_header_ptr; typedef struct pcx_picture_typ { pcx_header header; RGB_color palette[256]; char far *buffer; } pcx_picture, *pcx_picture_ptr; // P R O T O T Y P E S /////////////////////////////////////////////////////// void PCX_Init(pcx_picture_ptr image); void PCX_Load(char *filename, pcx_picture_ptr image,int enable_palette); void PCX_Delete(pcx_picture_ptr image); void PCX_Show_Buffer(pcx_picture_ptr image); // F U N C T I O N S ///////////////////////////////////////////////////////// void PCX_Init(pcx_picture_ptr image) { // this function allocates the buffer region needed to load a pcx file if (!(image->buffer = (char far *)_fmalloc(SCREEN_WIDTH * SCREEN_HEIGHT + 1))) printf("\ncouldn't allocate screen buffer"); } // end PCX_Init ////////////////////////////////////////////////////////////////////////////// void PCX_Load(char *filename, pcx_picture_ptr image,int enable_palette) { // this function loads a pcx file into a picture structure, the actual image // data for the pcx file is decompressed and expanded into a secondary buffer // within the picture structure, the separate images can be grabbed from this // buffer later. also the header and palette are loaded FILE *fp; int num_bytes,index; long count; unsigned char data; char far *temp_buffer; // open the file fp = fopen(filename,"rb"); // load the header temp_buffer = (char far *)image; for (index=0; index<128; index++) { temp_buffer[index] = (char)getc(fp); } // end for index // load the data and decompress into buffer count=0; while(count<=SCREEN_WIDTH * SCREEN_HEIGHT) { // get the first piece of data data = (unsigned char)getc(fp); // is this a rle? if (data>=192 && data<=255) { // how many bytes in run? num_bytes = data-192; // get the actual data for the run data = (unsigned char)getc(fp); // replicate data in buffer num_bytes times while(num_bytes-->0) { image->buffer[count++] = data; } // end while } // end if rle else { // actual data, just copy it into buffer at next location image->buffer[count++] = data; } // end else not rle } // end while // move to end of file then back up 768 bytes i.e. to begining of palette fseek(fp,-768L,SEEK_END); // load the pallete into the palette for (index=0; index<256; index++) { // get the red component image->palette[index].red = (unsigned char)(getc(fp) >> 2); // get the green component image->palette[index].green = (unsigned char)(getc(fp) >> 2); // get the blue component image->palette[index].blue = (unsigned char)(getc(fp) >> 2); } // end for index fclose(fp); // change the palette to newly loaded palette if commanded to do so if (enable_palette) { // for each palette register set to the new color values for (index=0; index<256; index++) { Set_Palette_Register(index,(RGB_color_ptr)&image->palette[index]); } // end for index } // end if change palette } // end PCX_Load ////////////////////////////////////////////////////////////////////////////// void PCX_Delete(pcx_picture_ptr image) { // this function de-allocates the buffer region used for the pcx file load _ffree(image->buffer); } // end PCX_Delete ////////////////////////////////////////////////////////////////////////////// void PCX_Show_Buffer(pcx_picture_ptr image) { // just copy he pcx buffer into the video buffer char far *data; data = image->buffer; _asm { push ds ; save the data segment les di, video_buffer ; point es:di to video buffer lds si, data ; point ds:si to data area mov cx,320*200/2 ; move 32000 words cld ; set direction to foward rep movsw ; do the string operation pop ds ; restore the data segment } } // end PCX_Show_Buffer // M A I N /////////////////////////////////////////////////////////////////// void main(int argc, char **argv) { long index; // loop counter pcx_picture background_pcx; // this pcx structure holds background imagery FILE *fp; // used to see if file exists // make sure there is a file name if (argc<2) { printf("\nUsuage: pcxshow filename.PCX"); return; } // end if // test if the file exist, but not for the .PCX extension if (!fopen(argv[1],"rb")) { printf("\nFile:%s - not found!",argv[1]); return(1); } // end if not found else { fclose(fp); } // end else found // set video mode to 320x200 256 color mode Set_Video_Mode(VGA256); // load in background PCX_Init((pcx_picture_ptr)&background_pcx); PCX_Load(argv[1], (pcx_picture_ptr)&background_pcx,1); PCX_Show_Buffer((pcx_picture_ptr)&background_pcx); PCX_Delete((pcx_picture_ptr)&background_pcx); // wait for user to hit keyboard while(!kbhit()){} // disolve the screen...in one line I might add! for (index=0; index<=300000; index++,Plot_Pixel_Fast(rand()%320, rand()%200, 0)); // go back to text mode Set_Video_Mode(TEXT_MODE); } // end main