//------------------------------------------------------------------- // shrunken.cpp (for Question V on Midterm Exam I) // // Here's a modification of 'shrinker.cpp' giving one possible // solution to Question V on Midterm Exam I as outlined below. // // ----------------------------------------------------------- // // This program presently displays the graphics image captured // in a file named "captured.img". Your job is to modify this // program so that the displayed image will be reduced in size // from 1024-by-768 to 512-by-384 (i.e., half as wide and half // as high as the original screen-image). You should draw the // smaller-sized image so that it is 'centered' on the screen. // // compile using: $ g++ shrinker.cpp int86.cpp -o shrinker // // NOTE: It is unnecessary to download the 'captured.img' file // from our class website when you are logged in to one of the // computer science department's workstations because the file // can be directly accessed via the local network file-system. // // programmer: ALLAN CRUSE // written on: 29 SEP 2005 //------------------------------------------------------------------- #include // for perror() #include // for open() #include // for exit() #include // for lseek() #include // for mmap() #include "int86.h" // for init8086(), int86() int *vram = (int*)0xA0000000; int vesa_mode = 0x4123, hres = 1024, vres = 768; struct vm86plus_struct vm; char imgname[] = "/home/web/cruse/cs686/captured.img"; int main( int argc, char **argv ) { // memory-map the image-data file into user-space int bmp = open( imgname, O_RDONLY ); if ( bmp < 0 ) { perror( imgname ); exit(1); } int sz = lseek( bmp, 0, SEEK_END ); int *img = (int*)mmap( NULL, sz, PROT_READ, MAP_PRIVATE, bmp, 0 ); if ( img == MAP_FAILED ) { perror( "mmap" ); exit(1); } // memory-map the video display-memory into user-space int vd = open( "/dev/vram", O_RDWR ); if ( vd < 0 ) { perror( "/dev/vram" ); exit(1); } int size = lseek( vd, 0, SEEK_END ); int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; if ( mmap( (void*)vram, size, prot, flag, vd, 0 ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } // enter graphics mode init8086(); vm.regs.eax = 0x4F02; vm.regs.ebx = vesa_mode; int86( 0x10, vm ); // here we transfer this memory-mapped image to the visible screen // (so this loop is where all of your code-modifications would go) // create a pointer to the reduced image's top-left corner int *dstn = vram + (vres/4)*hres + (hres/4); // loop through one-half the screen's row-numbers for (int y = 0; y < vres/2; y++) // loop through one-half the screen's column-numbers for (int x = 0; x < hres/2; x++) { // compute RGB color-average for 2-by-2 group int av_red = 0; // initialize red sum int av_green = 0; // initialize green sum int av_blue = 0; // initialize blue sum // fetch next pixel-group from the image-file for (int row = 0; row < 2; row++) for (int col = 0; col < 2; col++) { int src_index; src_index = (2*y+row)*hres + (2*x+col); int pel = img[ src_index ]; av_red += (pel>>16)&0xFF; // add red av_green += (pel>>8)&0xFF; // add green av_blue += (pel>>0)&0xFF; // add blue } av_red /= 4; // divide red sum by 4 av_green /= 4; // divide green sum by 4 av_blue /= 4; // divide blue sum by 4 int pel = 0; // initialize pixel pel |= (av_red<<16); // merge red average pel |= (av_green<<8); // merge green average pel |= (av_blue<<0); // merge blue average // store this pixel to video display memory int dst_index = y * hres + x; dstn[ dst_index ] = pel; } // wait until the user has finished viewing your displayed image getchar(); // leave graphics mode vm.regs.eax = 0x0003; int86( 0x10, vm ); printf( "\n" ); }