// Starter code for image mosaicing assignment, 15-869 // by Steve Seitz // This code displays an image in a scrollable FLTK window // The image is displayed using OpenGL commands // Clicking the mouse tells you where in the image the mouse is #include #include #include #include #include #include #include #include #include #include // Define subclass of GL window class mosaic_window : public Fl_Gl_Window { void draw(); int handle(int event); Pic *img; public: mosaic_window(int w,int h,const char *l=0); void setImage(Pic *image); float xoff, yoff, scale; }; // Global variables Fl_Window *win; mosaic_window *pane; Fl_Scrollbar *hscroll, *vscroll; // Constructor mosaic_window::mosaic_window(int w,int h,const char *l) : Fl_Gl_Window(0,0,w,h,l) { img = NULL; xoff = yoff = 0.0; scale = 1.0; } // Draw Open GL pane--all drawing code should go here void mosaic_window::draw() { // the valid() property may be used to avoid reinitializing your // GL transformation for each redraw: if (!valid()) { valid(1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Specify window size // Don't know why I need to do it this way... the commented out // version should work, not this! // glViewport(0,0,w(),h()); glViewport(-int(xoff),0,w()-int(xoff),h()); // Specify coordinate mapping // gluOrtho2D(xoff, w()+xoff, h()+yoff, yoff); gluOrtho2D(0, w(), h()+yoff, yoff); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPixelZoom(1.0,1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); // Update scrollers int slidestep = 5; int slidex = img->nx-w(); int slidey = img->ny-h(); if (slidex < 0) slidex = 0; if (slidey < 0) slidey = 0; hscroll->range(0, slidex); hscroll->slider_size(slidestep/(float)slidex); vscroll->range(0, slidey); vscroll->slider_size(slidestep/(float)slidey); } /* draw image, one scanline at a time */ glClear(GL_COLOR_BUFFER_BIT); if (img) { for (int y = 0; y < img->ny; y++) { glRasterPos2i(0, y); glDrawPixels(img->nx, 1, GL_RGB, GL_UNSIGNED_BYTE, &(PIC_PIXEL(img, 0, y, 0)) ); } } Fl_Gl_Window::draw(); glFlush(); } // Handle events int mosaic_window::handle(int event) { float ev_x, ev_y; switch(event) { case FL_PUSH: ev_x = Fl::event_x() + xoff; ev_y = Fl::event_y() + yoff; fprintf(stderr, "Mouse click at: (%.2f, %.2f)\n", ev_x, ev_y); break; case FL_KEYBOARD: fprintf(stderr, "Key press: %c\n", Fl::event_key()); switch (Fl::event_key()) { case '.': scale *= 2.0; invalidate(); redraw(); break; case ',': scale /= 2.0; invalidate(); redraw(); break; } break; default: ; } Fl_Gl_Window::handle(event); return 1; } void mosaic_window::setImage(Pic *image) { img = image; redraw(); } // Scroller callbacks void hscrollcb(Fl_Scrollbar* scroll) { pane->xoff = (float)scroll->value(); pane->invalidate(); pane->redraw(); } void vscrollcb(Fl_Scrollbar* scroll) { pane->yoff = (float)scroll->value(); pane->invalidate(); pane->redraw(); } int main (int argc, char **argv) { win = new Fl_Window(660, 500, "Mosaic"); hscroll = new Fl_Scrollbar(0, 480, 640, 20); hscroll->type(1); hscroll->callback((Fl_Callback*)hscrollcb); hscroll->step(5); vscroll = new Fl_Scrollbar(640, 0, 20, 480); vscroll->type(0); vscroll->callback((Fl_Callback*)vscrollcb); hscroll->step(5); pane = new mosaic_window(640, 480, "pane"); // Read in input image if (argc > 1) { Pic *img = tiff_read(argv[1], NULL); if(!img) { printf("Unable to open input file '%s'\n", argv[1]); } else { printf("Read a %dx%d TIFF image (%d bytes per pixel)\n", img->nx, img->ny, img->bpp); pane->setImage(img); } } else { fprintf(stderr, "Usage: mosaic img.tif\n"); exit(1); } win->resizable(pane); win->end(); win->show(); return Fl::run(); }