/************************************************************ * file: pan.cc * Visualization Course, Fall 2001 * Author: Chee Yap * * A basic demo of panning an image. * This program reads from several bmp files, each stored in * an instance of "RGBpixmap" class. * * Technical details of panning: * -- need double buffering * -- new implementation of "RGBpixmap::draw(int x, int y)" * to draw image at new position (x,y) instead of (0,0). * -- use of glPixelStorei(GL_UNPACK_SKIP_ROWS, r) * to skip r initial rows of image * -- use of glPixelStorei(GL_UNPACK_SKIP_PIXELS, c); * to skip c initial pixels of each row of image * -- use of glPixelStorei(GL_UNPACK_ROW_LENGTH, C); * to specify that the FULL image rows has C column * * Keyboard commands: * q = quit * s = switch to the next pixmap for display * w = write the current buffer out to a file "out.bmp" * o = read from out.bmp file into current pixmap * f = re-read input file of current pixmap * x/X = pan right/left * y/Y = pan up/down * (ALTERNATIVELY, use vi's Keystrokes: * l = left, h = right, j = down, k = up) * g = reads into pixmap a 200x200 portion of screen at * current raster position (set with Left-mouse click, * see below) * * Mouse actions: * Mouse drag = current image is dragged along * Right-click = clears the screen. * * Adapted from pixmap.cc ************************************************************/ #include // needed for use of cout #include // needed for math functions exp(x), etc #ifdef _WINDOZ #include #include #else #include #endif #include "app3.cc" // grab bag of routines from Appendix 3 of book, // but many functions omitted (do not compile) ///////////////////////////////////////////////////////////// // Constants ///////////////////////////////////////////////////////////// int screenWidth = 640; int screenHeight = 480; // names of bmp files to read: const int numPics = 3; // number of pictures to show char * fname[numPics+1] = { "/home/yap/public_html/data/edges/MVC-001F.bmp", "/home/yap/public_html/data/edges/MVC-002F.bmp", "/home/yap/public_html/data/edges/MVC-004F.bmp", "out.bmp"}; // out.bmp is for output, not for reading! RGBpixmap pic[numPics]; // create numPics global pixmaps int whichPic = 0; // current pixmap to display // position for panning IntPoint rasterPos(0,0); // rasterPos for drawing image IntPoint lastMousePos(0,0); // differential position for mouse motion int speed = 1; // speed for keyboard panning //<<<<<<<<<<<<<<<<<<<<<<<<< myMouse >>>>>>>>>>>>>>>>>>>>>>>> void myMouse(int button, int state, int mx, int my) { // set raster position with a left click if(button == GLUT_LEFT_BUTTON) { lastMousePos.x = mx; lastMousePos.y = my; } else { glutPostRedisplay(); } } //<<<<<<<<<<<<<<<<<<<<<<<<< mouseMove >>>>>>>>>>>>>>>>> void mouseMove(int mx, int my) { // set raster position with mouse motion rasterPos.x -= mx - lastMousePos.x; rasterPos.y -= lastMousePos.y - my; lastMousePos.x = mx; lastMousePos.y = my; glutPostRedisplay(); }// mouseMove //<<<<<<<<<<<<<<<<<<<<<<<<<< myReshape >>>>>>>>>>>>>>>>>>> void myReshape(int w, int h) { screenWidth = w; screenHeight = h; }// myReshape //<<<<<<<<<<<<<<<<<<<<<<< myDisplay >>>>>>>>>>>>>>>>>>>>>>>>>> void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); RGBpixmap pm = pic[whichPic]; pm.draw(rasterPos.x, rasterPos.y); glFlush(); glutSwapBuffers(); } //<<<<<<<<<<<<<<<<<<<<<<<< myKeys >>>>>>>>>>>>>>>>>>>>>> void myKeys(unsigned char key, int x, int y) { RGBpixmap pm; RGBpixmap * outpm; switch(key) { case 27: case 'q': exit(0); break; case 's': // switch image whichPic++; if (whichPic >= numPics) whichPic=0; glPixelStorei(GL_UNPACK_ROW_LENGTH, pic[whichPic].nCols); rasterPos.x = 0; rasterPos.y = 0; glutPostRedisplay(); break; case 'g': // grab a piece pic[whichPic].read(rasterPos.x, rasterPos.y, rasterPos.x+200, rasterPos.y+200); break; case 'w': // write current buffer to out.bmp file pm = pic[whichPic]; outpm = new RGBpixmap(pm.nRows, pm.nCols); glReadPixels(0,0, pm.nCols, pm.nRows, GL_RGB, GL_UNSIGNED_BYTE, outpm->pixel); outpm->writeBMPFile("out.bmp"); break; case 'o': // read file again pic[whichPic].readBMPFile(fname[numPics]); //fname[numPics]="out.bmp" glPixelStorei(GL_UNPACK_ROW_LENGTH, pic[whichPic].nCols); break; case 'f': // read current file again pic[whichPic].readBMPFile(fname[whichPic]); //re-read file glPixelStorei(GL_UNPACK_ROW_LENGTH, pic[whichPic].nCols); break; case 'r': // reset rasterPos.x = 0; rasterPos.y = 0; glutPostRedisplay(); break; case 'l': case 'x': // translate x rasterPos.x += speed; break; case 'k': case 'y': // translate y rasterPos.y += speed; break; case 'h': case 'X': // translate -x rasterPos.x -= speed; break; case 'j': case 'Y': // translate -y rasterPos.y -= speed; break; case 'a': // accelerate speed += 1; break; case 'A': // accelerate speed -= 1; if (speed == 0) speed = 1; break; } glutPostRedisplay(); } //<<<<<<<<<<<<<<<<<<<<<< main >>>>>>>>>>>>>>>>>>>>>>>>> int main(int argc, char **argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(screenWidth, screenHeight); glutInitWindowPosition(30, 30); glutCreateWindow("Panning Images"); // the next three lines are essential for the // glRasterPos2i(x,y) to work properly! glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, (GLdouble)screenWidth, 0.0, (GLdouble)screenHeight); glMatrixMode(GL_MODELVIEW); glutKeyboardFunc(myKeys); glutMouseFunc(myMouse); // mouse button down or up glutMotionFunc(mouseMove); // mouse motion with any button down glutDisplayFunc(myDisplay); glutReshapeFunc(myReshape); glClearColor(0.9f, 0.9f, 0.9f, 0.0); //background color glClear(GL_COLOR_BUFFER_BIT); // initialize images for (int i=0; i< numPics; i++) pic[i].readBMPFile(fname[i]); //make a pixmap // Need to control the pixel-storage mode in a per image basis! // See the key board commands for panning // glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_UNPACK_ROW_LENGTH, pic[whichPic].nCols); glutMainLoop(); }