/* * Lineviewer - An extremely simple line viewing application * Copyright (C) 1999,2000 Mark R. Stevens * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ // standard c++ includes #include #include #include #include // opengl includes #include // I am going to assume that the points are in X1 Y1 X2 Y2 format typedef struct { float x1, y1, x2, y2; } line; // we will need a collection of these lines vector lines; // A hack to store the image data unsigned int imageWidth; unsigned int imageHeight; unsigned char *imageData; // the window dimensions unsigned int windowWidth; unsigned int windowHeight; /**********************************************************************/ void parseLineFile(const char *lineFile) { // we will need a temporary line to read line l; // open the stream and check ifstream inFile(lineFile); if (inFile.bad()) { cerr << "\nError:\n"; cerr << "\tOcurred in (parseLineFile)\n"; cerr << "\tCould not open file (" << lineFile << ")\n"; abort(); } // continue to read lines until the end while (! inFile.eof()) { inFile >> l.x1; inFile >> l.y1; inFile >> l.x2; inFile >> l.y2; lines.push_back(l); } // will close on destruction but who cares inFile.close(); } /**********************************************************************/ /**********************************************************************/ void parseImageFile(const char *imageFile) { // open the stream and check ifstream inFile(imageFile); if (inFile.bad()) { cerr << "\nError:\n"; cerr << "\tOcurred in (parseImageFile)\n"; cerr << "\tCould not open file (" << imageFile << ")\n"; abort(); } // get the header string header; inFile >> header; // check format if (header != "P5") { cerr << "\nError:\n"; cerr << "\tOcurred in (parseImageFile)\n"; cerr << "\tImage header incorrect. Was (" << header << ") must be P5\n"; abort(); } // skim over the comments that can be here char comment[1024]; inFile.getline(comment, 1024, '\n'); streampos bc; do { bc = inFile.tellg(); inFile.getline(comment, 1024, '\n'); } while (comment[0] == '#'); inFile.seekg(bc); // get the image dimensions inFile >> imageWidth >> imageHeight; // read over the maximum bit pattern: assume 255 unsigned int bitMax; inFile >> bitMax; // store the window dimensions windowWidth = imageWidth; windowHeight = imageHeight; // create the image data and verify imageData = new unsigned char[imageWidth * imageHeight]; if (imageData == static_cast(0)) { cerr << "\nError:\n"; cerr << "\tOcurred in (parseImageFile)\n"; cerr << "\tCould not allocate ("; cerr << imageWidth * imageHeight << " bytes for image.\n"; abort(); } // mass read the image data inFile.read(imageData, imageWidth * imageHeight); // unfortunately pgm files have a different coordinate system from opengl for (unsigned int y = 0; y < (imageHeight / 2); y++) { for (unsigned int x = 0; x < imageWidth; x++) { swap(imageData[(imageHeight - y - 1) * imageWidth + x], imageData[y * imageWidth + x]); } } // will close on destruction but who cares inFile.close(); } /**********************************************************************/ /**********************************************************************/ void render() { // fill the screen with the image glDrawPixels (imageWidth, imageHeight, GL_LUMINANCE, GL_UNSIGNED_BYTE, static_cast(imageData)); // set up for drawing line segments glBegin(GL_LINES); // visit each line and render for (vector::iterator i = lines.begin(); i < lines.end(); i++) { glVertex2f(i->x1, i->y1); glVertex2f(i->x2, i->y2); } // finish up drawing the line list glEnd(); // make sure things get flushed properly glFlush(); // swap the buffer to front glutSwapBuffers(); } /**********************************************************************/ /**********************************************************************/ static void init(void) { // inefficient but easy to set the color here glClearColor(0.0, 0.0, 0.0, 0.0); // set up the transformation matrix glMatrixMode (GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, imageWidth, 0, imageHeight); // set up the modeling matrix glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // set up the viewport glViewport(0, 0, windowWidth, windowHeight); // set up for drawing the image glPixelStorei (GL_UNPACK_ALIGNMENT, sizeof(unsigned char)); glWindowPos2sMESA(0, 0); // draw the lines in a visible color glColor3ub(255, 0, 0); // compute and set the pixel zoom factors float zoomx = (static_cast(windowWidth) / static_cast(imageWidth)); float zoomy = (static_cast(windowHeight) / static_cast(imageHeight)); glPixelZoom(zoomx, zoomy); } /**********************************************************************/ /**********************************************************************/ static void resize(int newWidth, int newHeight) { // adjust the window dimensions windowWidth = newWidth; windowHeight = newHeight; // call the init window to update things init(); } /**********************************************************************/ /**********************************************************************/ int main(int argc, char *argv[]) { // verify that there are two arguments if (argc != 3) { cerr << "\nError (" << argc << "):\n"; cerr << "\tOcurred in (main)\n"; cerr << "\tUsage: lineViewer lineFile.txt imageFile.pgm\n"; abort(); } // load the line segments parseLineFile(argv[1]); // load the image parseImageFile(argv[2]); // popup a window the dimension of the image glutInitWindowPosition(0, 0); glutInitWindowSize(windowWidth, windowHeight); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); // make sure the window gets created properly if (glutCreateWindow("lineViewer") == GL_FALSE) { cerr << "\nError:\n"; cerr << "\tOcurred in (main)\n"; cerr << "\tCould not open glut window: glutCreateWindow failed\n"; abort(); } // call the initialization init(); // what happens when the window is resized glutReshapeFunc(resize); // set up the routine to render glutDisplayFunc(render); // enter the event loop glutMainLoop(); // done return (1); } /**********************************************************************/