// // Test program for Fl_Anim_GIF_Image::copy(). // #include #include #include #include #include #include #include #include static Fl_Anim_GIF_Image *orig = 0; static bool draw_grid = true; static int events(int event_) { if (event_ == FL_SHORTCUT && Fl::first_window()) { if (Fl::event_key()=='g') { draw_grid = !draw_grid; printf("grid: %s\n", (draw_grid ? "ON" : "OFF")); } else if (Fl::event_key()=='b') { if (Fl_Image::scaling_algorithm() != FL_RGB_SCALING_BILINEAR) Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR); else Fl_Image::scaling_algorithm(FL_RGB_SCALING_NEAREST); printf("bilenear: %s\n", (Fl_Image::scaling_algorithm() != FL_RGB_SCALING_BILINEAR ? "OFF" : "ON")); } else return 0; Fl::first_window()->redraw(); } return 1; } class Canvas : public Fl_Box { typedef Fl_Box Inherited; public: Canvas(int x, int y, int w, int h) : Inherited(x, y, w, h) {} void draw() FL_OVERRIDE { if (draw_grid) { // draw a transparency grid as background static const Fl_Color C1 = fl_rgb_color(0xcc, 0xcc, 0xcc); static const Fl_Color C2 = fl_rgb_color(0x88, 0x88, 0x88); static const int SZ = 8; for (int y = 0; y < h(); y += SZ) { for (int x = 0; x < w(); x += SZ) { fl_color(x%(SZ * 2) ? y%(SZ * 2) ? C1 : C2 : y%(SZ * 2) ? C2 : C1); fl_rectf(x, y, 32, 32); } } } // draw the current image frame over the grid Inherited::draw(); } void do_resize(int W, int H) { if (image() && (image()->w() != W || image()->h() != H)) { Fl_Anim_GIF_Image *animgif = (Fl_Anim_GIF_Image *)image(); animgif->stop(); image(0); // delete already copied images if (animgif != orig ) { delete animgif; } Fl_Anim_GIF_Image *copied = (Fl_Anim_GIF_Image *)orig->copy(W, H); if (!copied->valid()) { // check success of copy Fl::warning("Fl_Anim_GIF_Image::copy() %d x %d failed", W, H); } else { printf("resized to %d x %d\n", copied->w(), copied->h()); } copied->canvas(this, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS); } window()->cursor(FL_CURSOR_DEFAULT); } static void do_resize_cb(void *d) { Canvas *c = (Canvas *)d; c->do_resize(c->w(), c->h()); } void resize(int x, int y, int w, int h) FL_OVERRIDE { Inherited::resize(x, y, w, h); // decouple resize event from actual resize operation // to avoid lockups.. Fl::remove_timeout(do_resize_cb, this); Fl::add_timeout(0.1, do_resize_cb, this); window()->cursor(FL_CURSOR_WAIT); } }; int main(int argc, char *argv[]) { // setup play parameters from args const char *fileName = 0; bool bilinear = false; bool optimize = false; bool uncache = false; bool debug = false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "-b")) // turn bilinear scaling on bilinear = true; else if (!strcmp(argv[i], "-o")) // turn optimize on optimize = true; else if (!strcmp(argv[i], "-g")) // disable grid draw_grid = false; else if (!strcmp(argv[i], "-u")) // uncache uncache = true; else if (!strcmp(argv[i], "-d")) // debug debug = true; else if (argv[i][0] != '-' && !fileName) { fileName = argv[i]; } else if (argv[i][0] == '-') { printf("Invalid argument: '%s'\n", argv[i]); exit(1); } } if (!fileName) { fprintf(stderr, "Test program for animated copy.\n"); fprintf(stderr, "Usage: %s fileName [-b]ilinear [-o]ptimize [-g]rid [-u]ncache\n", argv[0]); exit(0); } Fl_Anim_GIF_Image::min_delay = 0.1; // set a minumum delay for playback Fl_Double_Window win(640, 480); // prepare a canvas for the animation // (we want to show it in the center of the window) Canvas canvas(0, 0, win.w(), win.h()); win.resizable(win); win.size_range(1, 1); win.end(); win.show(); // create/load the animated gif and start it immediately. // We use the 'DONT_RESIZE_CANVAS' flag here to tell the // animation not to change the canvas size (which is the default). int flags = Fl_Anim_GIF_Image::Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS; if (optimize) { flags |= Fl_Anim_GIF_Image::OPTIMIZE_MEMORY; printf("Using memory optimization (if image supports)\n"); } if (debug) { flags |= Fl_Anim_GIF_Image::DEBUG_FLAG; } orig = new Fl_Anim_GIF_Image(/*name_=*/ fileName, /*canvas_=*/ &canvas, /*flags_=*/ flags ); // check if loading succeeded printf("%s: valid: %d frames: %d uncache: %d\n", orig->name(), orig->valid(), orig->frames(), orig->frame_uncache()); if (orig->valid()) { win.copy_label(fileName); // print information about image optimization int n = 0; for (int i = 0; i < orig->frames(); i++) { if (orig->frame_x(i) != 0 || orig->frame_y(i) != 0) n++; } printf("image has %d optimized frames\n", n); Fl_Image::scaling_algorithm(FL_RGB_SCALING_NEAREST); if (bilinear) { Fl_Image::scaling_algorithm(FL_RGB_SCALING_BILINEAR); printf("Using bilinear scaling - can be slow!\n"); // NOTE: this can be *really* slow with large sizes, if FLTK // has to resize on its own without hardware scaling enabled. } orig->frame_uncache(uncache); if (uncache) { printf("Caching disabled - watch cpu load!\n"); } // set initial size to fit into window double ratio = orig->valid() ? (double)orig->w() / orig->h() : 1; int W = win.w() - 40; int H = (double)W / ratio; printf("original size: %d x %d\n", orig->w(), orig->h()); win.size(W, H); Fl::add_handler(events); return Fl::run(); } }