Animated GIF support (Fl_Anim_GIF_Image class) (#375)
This commit is contained in:
parent
1fc269b0d4
commit
2ddfd9d949
185
FL/Fl_Anim_GIF_Image.H
Normal file
185
FL/Fl_Anim_GIF_Image.H
Normal file
@ -0,0 +1,185 @@
|
||||
//
|
||||
// Fl_Anim_GIF_Image class header for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 2016-2022 by Christian Grabner <wcout@gmx.net>.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
// file is missing or damaged, see the license at:
|
||||
//
|
||||
// https://www.fltk.org/COPYING.php
|
||||
//
|
||||
// Please see the following page on how to report bugs and issues:
|
||||
//
|
||||
// https://www.fltk.org/bugs.php
|
||||
//
|
||||
|
||||
#ifndef Fl_Anim_Gif_Image_H
|
||||
#define Fl_Anim_Gif_Image_H
|
||||
|
||||
// forward declarations
|
||||
class Fl_Image;
|
||||
class Fl_Widget;
|
||||
|
||||
#include <FL/Fl_GIF_Image.H>
|
||||
|
||||
// Load and display animater GIF images
|
||||
class FL_EXPORT Fl_Anim_GIF_Image : public Fl_GIF_Image {
|
||||
|
||||
class FrameInfo; // internal helper class
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
When opening an Fl_Anim_GIF_Image there are some options
|
||||
that can be passed in a `flags` value.
|
||||
*/
|
||||
enum Flags {
|
||||
/**
|
||||
This flag indicates to the loader that it should not start
|
||||
the animation immediately after successful load, which is
|
||||
the default.
|
||||
It can be started later using the \ref start() method.
|
||||
*/
|
||||
DONT_START = 1,
|
||||
/**
|
||||
This flag indicates to the loader that it should not
|
||||
resize the canvas widget of the animation to the dimensions
|
||||
of the animation, which is the default.
|
||||
Needed for special use cases.
|
||||
*/
|
||||
DONT_RESIZE_CANVAS = 2,
|
||||
/**
|
||||
This flag indicates to the loader that it should not
|
||||
set the animation as \ref image() member of the canvas widget,
|
||||
which is the default.
|
||||
Needed for special use cases.
|
||||
*/
|
||||
DONT_SET_AS_IMAGE = 4,
|
||||
/**
|
||||
Often frames change just a small area of the animation canvas.
|
||||
This flag indicates to the loader to try using less memory
|
||||
by storing frame data not as canvas-sized images but use the
|
||||
sizes defined in the GIF file.
|
||||
The drawbacks are higher cpu usage during playback and maybe
|
||||
minor artefacts when resized.
|
||||
*/
|
||||
OPTIMIZE_MEMORY = 8,
|
||||
/**
|
||||
This flag can be used to print informations about the
|
||||
decoding process to the console.
|
||||
*/
|
||||
LOG_FLAG = 64,
|
||||
/**
|
||||
This flag can be used to print even more informations about
|
||||
the decoding process to the console.
|
||||
*/
|
||||
DEBUG_FLAG = 128
|
||||
};
|
||||
|
||||
// -- constructors and destructor
|
||||
Fl_Anim_GIF_Image(const char *filename, Fl_Widget *canvas = 0, unsigned short flags = 0);
|
||||
Fl_Anim_GIF_Image(const char* imagename, const unsigned char *data,
|
||||
const size_t length, Fl_Widget *canvas = 0,
|
||||
unsigned short flags = 0);
|
||||
Fl_Anim_GIF_Image();
|
||||
~Fl_Anim_GIF_Image() FL_OVERRIDE;
|
||||
|
||||
// -- file handling
|
||||
bool load(const char *name, const unsigned char *imgdata=NULL, size_t imglength=0);
|
||||
bool valid() const;
|
||||
|
||||
// -- getters and setters
|
||||
void frame_uncache(bool uncache);
|
||||
bool frame_uncache() const;
|
||||
double delay(int frame_) const;
|
||||
void delay(int frame, double delay);
|
||||
void canvas(Fl_Widget *canvas, unsigned short flags = 0);
|
||||
Fl_Widget *canvas() const;
|
||||
int canvas_w() const;
|
||||
int canvas_h() const;
|
||||
bool is_animated() const;
|
||||
const char *name() const;
|
||||
void speed(double speed);
|
||||
double speed() const;
|
||||
|
||||
// -- animation
|
||||
int frames() const;
|
||||
void frame(int frame);
|
||||
int frame() const;
|
||||
Fl_Image *image() const;
|
||||
Fl_Image *image(int frame) const;
|
||||
bool start();
|
||||
bool stop();
|
||||
bool next();
|
||||
|
||||
/** Return if the animation is currently running or stopped.
|
||||
\return true if the animation is running
|
||||
*/
|
||||
bool playing() const { return valid() && Fl::has_timeout(cb_animate, (void *)this); }
|
||||
|
||||
// -- image data
|
||||
Fl_Anim_GIF_Image& resize(int w, int h);
|
||||
Fl_Anim_GIF_Image& resize(double scale);
|
||||
int frame_x(int frame) const;
|
||||
int frame_y(int frame) const;
|
||||
int frame_w(int frame) const;
|
||||
int frame_h(int frame) const;
|
||||
|
||||
// -- overriden methods
|
||||
void color_average(Fl_Color c, float i) FL_OVERRIDE;
|
||||
Fl_Image *copy(int W, int H) const FL_OVERRIDE;
|
||||
Fl_Image *copy() const { return Fl_Pixmap::copy(); }
|
||||
void desaturate() FL_OVERRIDE;
|
||||
void draw(int x, int y, int w, int h, int cx = 0, int cy = 0) FL_OVERRIDE;
|
||||
void uncache() FL_OVERRIDE;
|
||||
|
||||
// -- debugging and logging
|
||||
int debug() const;
|
||||
|
||||
// -- static methods
|
||||
static int frame_count(const char *name, const unsigned char *imgdata = NULL, size_t imglength = 0);
|
||||
|
||||
/**
|
||||
The loop flag can be used to (dis-)allow loop count.
|
||||
If set (which is the default), the animation will be
|
||||
stopped after the number of repeats specified in the
|
||||
GIF file (typically this count is set to 'forever' anyway).
|
||||
If cleared the animation will always be 'forever',
|
||||
regardless of what is specified in the GIF file.
|
||||
*/
|
||||
static bool loop;
|
||||
|
||||
/**
|
||||
The min_delay value can be used to set a minimum value
|
||||
for the frame delay for playback. This is to prevent
|
||||
CPU hogs caused by images with very low delay rates.
|
||||
This is a global value for all Fl_Anim_GIF_Image objects.
|
||||
*/
|
||||
static double min_delay;
|
||||
|
||||
protected:
|
||||
|
||||
bool next_frame();
|
||||
void clear_frames();
|
||||
void set_frame(int frame);
|
||||
|
||||
static void cb_animate(void *d);
|
||||
void scale_frame();
|
||||
void set_frame();
|
||||
void on_frame_data(Fl_GIF_Image::GIF_FRAME &f) FL_OVERRIDE;
|
||||
void on_extension_data(Fl_GIF_Image::GIF_FRAME &f) FL_OVERRIDE;
|
||||
|
||||
private:
|
||||
|
||||
char *name_;
|
||||
unsigned short flags_;
|
||||
Fl_Widget *canvas_;
|
||||
bool uncache_;
|
||||
bool valid_;
|
||||
int frame_; // current frame
|
||||
double speed_;
|
||||
FrameInfo *fi_;
|
||||
};
|
||||
|
||||
#endif // Fl_Anim_Gif_Image_H
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// GIF image header file for the Fast Light Tool Kit (FLTK).
|
||||
//
|
||||
// Copyright 1998-2021 by Bill Spitzak and others.
|
||||
// Copyright 1998-2022 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -36,10 +36,51 @@ public:
|
||||
// constructor with length (since 1.4.0)
|
||||
Fl_GIF_Image(const char* imagename, const unsigned char *data, const size_t length);
|
||||
|
||||
static bool is_animated(const char *name_);
|
||||
/** Sets how the shared image core routine should treat animated GIF files.
|
||||
The default is to treat them as ordinary GIF's e.g. it creates a Fl_GIF_Image object.
|
||||
If this variable is set, then an animated GIF object Fl_Anim_GIF_Image is created.
|
||||
*/
|
||||
static bool animate;
|
||||
|
||||
protected:
|
||||
|
||||
void load_gif_(class Fl_Image_Reader &rdr);
|
||||
// Proteced constructors needed for animated GIF support through Fl_Anim_GIF_Image.
|
||||
Fl_GIF_Image(const char* filename, bool anim);
|
||||
Fl_GIF_Image(const char* imagename, const unsigned char *data, const size_t length, bool anim);
|
||||
// Protected default constructor needed for Fl_Anim_GIF_Image.
|
||||
Fl_GIF_Image();
|
||||
|
||||
void load_gif_(class Fl_Image_Reader &rdr, bool anim=false);
|
||||
|
||||
void load(const char* filename, bool anim);
|
||||
void load(const char* imagename, const unsigned char *data, const size_t length, bool anim);
|
||||
|
||||
// Internal structure to "glue" animated GIF support into Fl_GIF_Image.
|
||||
// This data is passed during decoding to the Fl_Anim_GIF_Image class.
|
||||
struct GIF_FRAME {
|
||||
int ifrm, width, height, x, y, w, h,
|
||||
clrs, bkgd, trans,
|
||||
dispose, delay;
|
||||
const uchar *bptr;
|
||||
const struct CPAL {
|
||||
uchar r, g, b;
|
||||
} *cpal;
|
||||
GIF_FRAME(int frame, uchar *data) : ifrm(frame), bptr(data) {}
|
||||
GIF_FRAME(int frame, int W, int H, int fx, int fy, int fw, int fh, uchar *data) :
|
||||
ifrm(frame), width(W), height(H), x(fx), y(fy), w(fw), h(fh), bptr(data) {}
|
||||
void disposal(int mode, int delay) { dispose = mode; this->delay = delay; }
|
||||
void colors(int nclrs, int bg, int tp) { clrs = nclrs; bkgd = bg; trans = tp; }
|
||||
};
|
||||
|
||||
// Internal virtual methods, which are called during decoding to pass data
|
||||
// to the Fl_Anim_GIF_Image class.
|
||||
virtual void on_frame_data(GIF_FRAME &gf) {}
|
||||
virtual void on_extension_data(GIF_FRAME &gf) {}
|
||||
|
||||
private:
|
||||
|
||||
void lzw_decode(Fl_Image_Reader &rdr, uchar *Image, int Width, int Height, int CodeSize, int ColorMapSize, int Interlace);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -272,6 +272,9 @@ public:
|
||||
|
||||
An internal copy is made of the original image before
|
||||
changes are applied, to avoid modifying the original image.
|
||||
|
||||
\note The RGB color of \ref FL_BACKGROUND_COLOR may change when the
|
||||
connection to the display is made. See fl_open_display().
|
||||
*/
|
||||
void inactive() { color_average(FL_GRAY, .33f); }
|
||||
virtual void desaturate();
|
||||
|
@ -81,6 +81,10 @@ set (FLUID_SOURCES
|
||||
############################################################
|
||||
|
||||
set (IMAGE_SOURCES
|
||||
animgifimage
|
||||
animgifimage-play
|
||||
animgifimage-resize
|
||||
animgifimage-simple
|
||||
howto-simple-svg
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,11 @@ SHELL = /bin/sh
|
||||
.SILENT:
|
||||
|
||||
# Executables
|
||||
ALL = browser-simple$(EXEEXT) \
|
||||
ALL = animgifimage$(EXEEXT) \
|
||||
animgifimage-play$(EXEEXT) \
|
||||
animgifimage-simple$(EXEEXT) \
|
||||
animgifimage-resize$(EXEEXT) \
|
||||
browser-simple$(EXEEXT) \
|
||||
cairo-draw-x$(EXEEXT) \
|
||||
chart-simple$(EXEEXT) \
|
||||
draggable-group$(EXEEXT) \
|
||||
|
237
examples/animgifimage-play.cxx
Normal file
237
examples/animgifimage-play.cxx
Normal file
@ -0,0 +1,237 @@
|
||||
//
|
||||
// Demonstrates how to play an animated GIF file
|
||||
// under application control frame by frame if
|
||||
// this is needed.
|
||||
// Also demonstrates how to use a single animation
|
||||
// object to load multiple animations.
|
||||
//
|
||||
// animgifimage <file> [-r] [-s speed_factor]
|
||||
//
|
||||
// Multiple files can be specified e.g. testsuite/*
|
||||
//
|
||||
// Use keys '+'/'-'/Enter to change speed, ' ' to pause.
|
||||
// Right key changes to next frame in paused mode.
|
||||
// 'n' changes to next file, 'r' toggles reverse play.
|
||||
//
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static double speed_factor = 1.; // slow down/speed up playback by factor
|
||||
static bool reverse = false; // true = play animation backwards
|
||||
static bool paused = false; // flag for paused animation
|
||||
static bool frame_info = false; // flag to update current frame info in title
|
||||
static Fl_Anim_GIF_Image animgif; // the animation object
|
||||
static char **Argv = 0; // copy of main() argv[]
|
||||
static int Argc = 0; // copy of main() argc
|
||||
static int current_arg = 0; // current index in argv[]
|
||||
|
||||
static int next_arg() {
|
||||
while (1) {
|
||||
current_arg++;
|
||||
if (current_arg >= Argc) {
|
||||
current_arg = 1;
|
||||
}
|
||||
if (Argv[current_arg]) break;
|
||||
}
|
||||
return current_arg;
|
||||
}
|
||||
|
||||
static const char *next_file() {
|
||||
while (Argv[next_arg()][0] == '-') ;
|
||||
return Argv[current_arg];
|
||||
}
|
||||
|
||||
static void set_title() {
|
||||
char buf[200];
|
||||
char fi[50];
|
||||
if (frame_info)
|
||||
snprintf(fi, sizeof(fi), "frame %d/%d", animgif.frame() + 1, animgif.frames());
|
||||
else
|
||||
snprintf(fi, sizeof(fi), "%d frames", animgif.frames());
|
||||
snprintf(buf, sizeof(buf), "%s (%s) x %3.2f %s%s",
|
||||
Argv[current_arg], fi,
|
||||
speed_factor, reverse ? "reverse" : "",
|
||||
paused ? " PAUSED" : "");
|
||||
|
||||
Fl::first_window()->copy_label(buf);
|
||||
}
|
||||
|
||||
static void cb_anim(void *d_) {
|
||||
Fl_Anim_GIF_Image *animgif = (Fl_Anim_GIF_Image *)d_;
|
||||
int frame(animgif->frame());
|
||||
|
||||
// switch to next/previous frame
|
||||
if (reverse) {
|
||||
animgif->canvas()->window()->redraw();
|
||||
frame--;
|
||||
if (frame < 0) {
|
||||
frame = animgif->frames() - 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
frame++;
|
||||
if (frame >= animgif->frames()) {
|
||||
frame = 0;
|
||||
}
|
||||
}
|
||||
// set the frame (and update canvas)
|
||||
animgif->frame(frame);
|
||||
|
||||
// setup timer for next frame
|
||||
if (!paused && animgif->delay(frame)) {
|
||||
Fl::repeat_timeout(animgif->delay(frame) / speed_factor, cb_anim, d_);
|
||||
}
|
||||
if (frame_info)
|
||||
set_title();
|
||||
}
|
||||
|
||||
static void next_frame() {
|
||||
cb_anim(&animgif);
|
||||
}
|
||||
|
||||
static void toggle_pause() {
|
||||
paused = !paused;
|
||||
set_title();
|
||||
if (paused)
|
||||
Fl::remove_timeout(cb_anim, &animgif);
|
||||
else
|
||||
next_frame();
|
||||
set_title();
|
||||
}
|
||||
|
||||
static void toggle_info() {
|
||||
frame_info = !frame_info;
|
||||
set_title();
|
||||
}
|
||||
|
||||
static void toggle_reverse() {
|
||||
reverse = !reverse;
|
||||
set_title();
|
||||
}
|
||||
|
||||
static void zoom(bool out) {
|
||||
int W = animgif.w();
|
||||
int H = animgif.h();
|
||||
// Note: deliberately no range check (use key 'N' to reset)
|
||||
static const double f = 1.05;
|
||||
if (out)
|
||||
animgif.resize((double)W/f, (double)H/f);
|
||||
else
|
||||
animgif.resize(f*W, f*H);
|
||||
}
|
||||
|
||||
static void change_speed(int dir_) {
|
||||
if (dir_> 0) {
|
||||
speed_factor += (speed_factor < 1) ? 0.01 : 0.1;
|
||||
if (speed_factor > 100)
|
||||
speed_factor = 100.;
|
||||
}
|
||||
else if (dir_ < 0) {
|
||||
speed_factor -= (speed_factor > 1) ? 0.1 : 0.01;
|
||||
if (speed_factor < 0.01)
|
||||
speed_factor = 0.01;
|
||||
}
|
||||
else {
|
||||
speed_factor = 1.;
|
||||
}
|
||||
set_title();
|
||||
}
|
||||
|
||||
static void load_next() {
|
||||
Fl::remove_timeout(cb_anim, &animgif);
|
||||
paused = false;
|
||||
animgif.load(next_file());
|
||||
animgif.canvas()->window()->redraw();
|
||||
// check if loading succeeded
|
||||
printf("valid: %d frames: %d\n", animgif.valid(), animgif.frames());
|
||||
if (animgif.valid()) {
|
||||
printf("play '%s'%s with %3.2f x speed\n", animgif.name(),
|
||||
(reverse ? " reverse" : ""), speed_factor);
|
||||
animgif.frame(reverse ? animgif.frames() - 1 : 0);
|
||||
// setup first timeout, but check for zero-delay (normal GIF)!
|
||||
if (animgif.delay(animgif.frame())) {
|
||||
Fl::add_timeout(animgif.delay(animgif.frame()) / speed_factor, cb_anim, &animgif);
|
||||
}
|
||||
}
|
||||
set_title();
|
||||
}
|
||||
|
||||
static int events(int event_) {
|
||||
if (event_ == FL_SHORTCUT && Fl::first_window()) {
|
||||
switch (Fl::event_key()) {
|
||||
case '+': change_speed(1); break;
|
||||
case '-': change_speed(-1); break;
|
||||
case FL_Enter: change_speed(0); break;
|
||||
case 'n': load_next(); break;
|
||||
case 'z': zoom(Fl::event_shift()); break;
|
||||
case 'i': toggle_info(); break; // Note: this can raise cpu usage considerably!
|
||||
case 'r': toggle_reverse(); break;
|
||||
case ' ': toggle_pause(); break;
|
||||
case FL_Right:
|
||||
if (paused && Fl::get_key(FL_Right)) next_frame();
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
Fl::first_window()->redraw();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// setup play parameters from args
|
||||
Argv = argv;
|
||||
Argc = argc;
|
||||
int n = 0;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-r"))
|
||||
reverse = !reverse;
|
||||
else if (!strcmp(argv[i], "-s") && i + 1 < argc) {
|
||||
i++;
|
||||
speed_factor = atof(argv[i]);
|
||||
argv[i] = 0;
|
||||
}
|
||||
else if (argv[i][0] != '-') {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
printf("Invalid argument: '%s'\n", argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (!n) {
|
||||
fprintf(stderr, "Test program for application controlled GIF animation.\n");
|
||||
fprintf(stderr, "Please specify one or more image files!\n");
|
||||
exit(0);
|
||||
}
|
||||
if (speed_factor < 0.01 || speed_factor > 100)
|
||||
speed_factor = 1.;
|
||||
|
||||
Fl_Double_Window win(800, 600);
|
||||
|
||||
// prepare a canvas for the animation
|
||||
// (we want to show it in the center of the window)
|
||||
Fl_Box canvas(0, 0, win.w(), win.h());
|
||||
Fl_Box help(0, win.h()-20, win.w(), 20, "Keys: N=next file, I=toggle info, R=play reverse, +/-/Enter/Space=change speed, Z=Zoom");
|
||||
win.resizable(win);
|
||||
|
||||
win.end();
|
||||
win.show();
|
||||
Fl::add_handler(events);
|
||||
|
||||
// use the 'DONT_RESIZE_CANVAS' flag to tell the animation
|
||||
// not to change the canvas size (which is the default).
|
||||
unsigned short flags = Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS;
|
||||
// flags |= Fl_Anim_GIF_Image::DEBUG_FLAG|Fl_Anim_GIF_Image::LOG_FLAG;
|
||||
animgif.canvas(&canvas, flags);
|
||||
|
||||
load_next();
|
||||
return Fl::run();
|
||||
}
|
185
examples/animgifimage-resize.cxx
Normal file
185
examples/animgifimage-resize.cxx
Normal file
@ -0,0 +1,185 @@
|
||||
//
|
||||
// Test program for Fl_Anim_GIF_Image::copy().
|
||||
//
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include <FL/Fl_Image.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_draw.H>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
40
examples/animgifimage-simple.cxx
Normal file
40
examples/animgifimage-simple.cxx
Normal file
@ -0,0 +1,40 @@
|
||||
//
|
||||
// Minimal program for displaying an animated GIF file
|
||||
// with the Fl_Anim_GIF_Image class.
|
||||
//
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Box.H>
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include <FL/Fl.H>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Fl_Double_Window win(400, 300, "Fl_Anim_GIF_Image demo");
|
||||
|
||||
// prepare a canvas (widget) for the animation
|
||||
Fl_Box canvas(20, 40, win.w()-40, win.h()-80, "Hello from FLTK GIF-animation!");
|
||||
canvas.align(FL_ALIGN_TOP|FL_ALIGN_IMAGE_BACKDROP);
|
||||
canvas.labelsize(20);
|
||||
|
||||
win.resizable(win);
|
||||
win.end();
|
||||
win.show(1, argv);
|
||||
|
||||
// Create and load the animated gif as image
|
||||
// of the `canvas` widget 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).
|
||||
const char *default_image = "../test/pixmaps/fltk_animated.gif";
|
||||
Fl_Anim_GIF_Image animgif(/*name_=*/ argv[1] ? argv[1] : default_image,
|
||||
/*canvas_=*/ &canvas,
|
||||
/*flags_=*/ Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
|
||||
// resize animation to canvas size
|
||||
animgif.scale(canvas.w(), canvas.h(), /*can_expand*/1, /*proportional*/1);
|
||||
|
||||
// check if loading succeeded
|
||||
printf("%s: ld=%d, valid=%d, frames=%d, size=%dx%d\n",
|
||||
animgif.name(), animgif.ld(), animgif.valid(),
|
||||
animgif.frames(), animgif.canvas_w(), animgif.canvas_h());
|
||||
if (animgif.valid())
|
||||
return Fl::run();
|
||||
}
|
303
examples/animgifimage.cxx
Normal file
303
examples/animgifimage.cxx
Normal file
@ -0,0 +1,303 @@
|
||||
//
|
||||
// Test program for displaying animated GIF files using the
|
||||
// Fl_Anim_GIF_Image class.
|
||||
//
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_Tiled_Image.H>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int g_good_count = 0, g_bad_count = 0, g_frame_count = 0;
|
||||
|
||||
static const Fl_Color BackGroundColor = FL_GRAY; // use e.g. FL_RED to see
|
||||
// transparent parts better
|
||||
static const double RedrawDelay = 1./20; // interval [sec] for forced redraw
|
||||
|
||||
static void quit_cb(Fl_Widget* w_, void*) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void set_title(Fl_Window *win, Fl_Anim_GIF_Image *animgif) {
|
||||
char buf[200];
|
||||
snprintf(buf, sizeof(buf), "%s (%d frames) %2.2fx", fl_filename_name(animgif->name()),
|
||||
animgif->frames(), animgif->speed());
|
||||
if (animgif->frame_uncache())
|
||||
strcat(buf, " U");
|
||||
win->copy_label(buf);
|
||||
win->copy_tooltip(buf);
|
||||
}
|
||||
|
||||
static void cb_forced_redraw(void *d) {
|
||||
Fl_Window *win = Fl::first_window();
|
||||
while (win) {
|
||||
if (!win->menu_window())
|
||||
win->redraw();
|
||||
win = Fl::next_window(win);
|
||||
}
|
||||
if (Fl::first_window())
|
||||
Fl::repeat_timeout(RedrawDelay, cb_forced_redraw);
|
||||
}
|
||||
|
||||
Fl_Window *openFile(const char *name, char *flags, bool close = false) {
|
||||
// determine test options from 'flags'
|
||||
bool uncache = strchr(flags, 'u');
|
||||
char *d = flags - 1;
|
||||
int debug = 0;
|
||||
while ((d = strchr(++d, 'd'))) debug++;
|
||||
bool optimize_mem = strchr(flags, 'm');
|
||||
bool desaturate = strchr(flags, 'D');
|
||||
bool average = strchr(flags, 'A');
|
||||
bool test_tiles = strchr(flags, 'T');
|
||||
bool test_forced_redraw = strchr(flags, 'f');
|
||||
char *r = strchr(flags, 'r');
|
||||
bool resizable = r && !test_tiles;
|
||||
double scale = 1.0;
|
||||
if (r && resizable) scale = atof(r+1);
|
||||
if (scale <= 0.1 || scale > 5)
|
||||
scale = resizable ? 0.7 : 1.0;
|
||||
|
||||
// setup window
|
||||
Fl::remove_timeout(cb_forced_redraw);
|
||||
Fl_Double_Window *win = new Fl_Double_Window(300, 300);
|
||||
win->color(BackGroundColor);
|
||||
if (close)
|
||||
win->callback(quit_cb);
|
||||
printf("Loading '%s'%s%s ... ", name,
|
||||
uncache ? " (uncached)" : "",
|
||||
optimize_mem ? " (optimized)" : "");
|
||||
|
||||
// create a canvas for the animation
|
||||
Fl_Box *canvas = test_tiles ? 0 : new Fl_Box(0, 0, 0, 0); // canvas will be resized by animation
|
||||
Fl_Box *canvas2 = 0;
|
||||
unsigned short gif_flags = debug ? Fl_Anim_GIF_Image::LOG_FLAG : 0;
|
||||
if (debug > 1)
|
||||
gif_flags |= Fl_Anim_GIF_Image::DEBUG_FLAG;
|
||||
if (optimize_mem)
|
||||
gif_flags |= Fl_Anim_GIF_Image::OPTIMIZE_MEMORY;
|
||||
|
||||
// create animation, specifying this canvas as display widget
|
||||
Fl_Anim_GIF_Image *animgif = new Fl_Anim_GIF_Image(name, canvas, gif_flags);
|
||||
bool good( animgif->ld() == 0 && animgif->valid() );
|
||||
printf("%s: %d x %d (%d frames) %s\n",
|
||||
animgif->name(), animgif->w(), animgif->h(), animgif->frames(), good ? "OK" : "ERROR");
|
||||
// for the statistics (when run on testsuite):
|
||||
g_good_count += good;
|
||||
g_bad_count += !good;
|
||||
g_frame_count += animgif->frames();
|
||||
|
||||
win->user_data(animgif); // store address of image (see note in main())
|
||||
|
||||
// exercise the optional tests on the animation
|
||||
animgif->frame_uncache(uncache);
|
||||
if (scale != 1.0) {
|
||||
animgif->resize(scale);
|
||||
printf("TEST: resized %s by %.2f to %d x %d\n", animgif->name(), scale, animgif->w(), animgif->h());
|
||||
}
|
||||
if (average) {
|
||||
printf("TEST: color_average %s\n", animgif->name());
|
||||
animgif->color_average(FL_GREEN, 0.5); // currently hardcoded
|
||||
}
|
||||
if (desaturate) {
|
||||
printf("TEST: desaturate %s\n", animgif->name());
|
||||
animgif->desaturate();
|
||||
}
|
||||
int W = animgif->w();
|
||||
int H = animgif->h();
|
||||
if (animgif->frames()) {
|
||||
if (test_tiles) {
|
||||
// demonstrate a way how to use the animation with Fl_Tiled_Image
|
||||
printf("TEST: use %s as tiles\n", animgif->name());
|
||||
W *= 2;
|
||||
H *= 2;
|
||||
Fl_Tiled_Image *tiled_image = new Fl_Tiled_Image(animgif);
|
||||
Fl_Group *group = new Fl_Group(0, 0, win->w(), win->h());
|
||||
group->image(tiled_image);
|
||||
group->align(FL_ALIGN_INSIDE);
|
||||
animgif->canvas(group, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS | Fl_Anim_GIF_Image::DONT_SET_AS_IMAGE );
|
||||
win->resizable(group);
|
||||
} else {
|
||||
// demonstrate a way how to use same animation in another canvas simultaneously:
|
||||
// as the current implementation allows only automatic redraw of one canvas..
|
||||
if (test_forced_redraw) {
|
||||
if (W < 400) {
|
||||
printf("TEST: open %s in another animation with application redraw\n", animgif->name());
|
||||
canvas2 = new Fl_Box(W, 0, animgif->w(), animgif->h()); // another canvas for animation
|
||||
canvas2->image(animgif); // is set to same animation!
|
||||
W *= 2;
|
||||
Fl::add_timeout(RedrawDelay, cb_forced_redraw); // force periodic redraw
|
||||
}
|
||||
}
|
||||
}
|
||||
// make window resizable (must be done before show())
|
||||
if (resizable && canvas && !test_tiles) {
|
||||
win->resizable(win);
|
||||
}
|
||||
win->size(W, H); // change to actual size of canvas
|
||||
// start the animation
|
||||
win->end();
|
||||
win->show();
|
||||
win->wait_for_expose();
|
||||
set_title(win, animgif);
|
||||
if (resizable && !test_tiles) {
|
||||
// need to reposition the widgets (have been moved by setting resizable())
|
||||
if (canvas && canvas2) {
|
||||
canvas->resize(0, 0, W/2, canvas->h());
|
||||
canvas2->resize(W/2, 0, W/2, canvas2->h());
|
||||
}
|
||||
else if (canvas) {
|
||||
canvas->resize(0, 0, animgif->canvas_w(), animgif->canvas_h());
|
||||
}
|
||||
}
|
||||
win->init_sizes(); // IMPORTANT: otherwise weird things happen at Ctrl+/- scaling
|
||||
} else {
|
||||
delete win;
|
||||
return 0;
|
||||
}
|
||||
if (debug >=3) {
|
||||
// open each frame in a separate window
|
||||
for (int i = 0; i < animgif->frames(); i++) {
|
||||
char buf[200];
|
||||
snprintf(buf, sizeof(buf), "Frame #%d", i + 1);
|
||||
Fl_Double_Window *win = new Fl_Double_Window(animgif->w(), animgif->h());
|
||||
win->copy_tooltip(buf);
|
||||
win->copy_label(buf);
|
||||
win->color(BackGroundColor);
|
||||
int w = animgif->image(i)->w();
|
||||
int h = animgif->image(i)->h();
|
||||
// in 'optimize_mem' mode frames must be offsetted to canvas
|
||||
int x = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_x(i);
|
||||
int y = (w == animgif->w() && h == animgif->h()) ? 0 : animgif->frame_y(i);
|
||||
Fl_Box *b = new Fl_Box(x, y, w, h);
|
||||
// get the frame image
|
||||
b->image(animgif->image(i));
|
||||
win->end();
|
||||
win->show();
|
||||
}
|
||||
}
|
||||
return win;
|
||||
}
|
||||
|
||||
#include <FL/filename.H>
|
||||
bool openDirectory(const char *dir, char *flags) {
|
||||
dirent **list;
|
||||
int nbr_of_files = fl_filename_list(dir, &list, fl_alphasort);
|
||||
if (nbr_of_files <= 0)
|
||||
return false;
|
||||
int cnt = 0;
|
||||
for (int i = 0; i < nbr_of_files; i++) {
|
||||
char buf[512];
|
||||
const char *name = list[i]->d_name;
|
||||
if (!strcmp(name, ".") || !strcmp(name, "..")) continue;
|
||||
const char *p = strstr(name, ".gif");
|
||||
if (!p) p = strstr(name, ".GIF");
|
||||
if (!p) continue;
|
||||
if (*(p+4)) continue; // is no extension!
|
||||
snprintf(buf, sizeof(buf), "%s/%s", dir, name);
|
||||
if (strstr(name, "debug")) // hack: when name contains 'debug' open single frames
|
||||
strcat(flags, "d");
|
||||
if (openFile(buf, flags, cnt == 0))
|
||||
cnt++;
|
||||
}
|
||||
return cnt != 0;
|
||||
}
|
||||
|
||||
static void change_speed(double delta) {
|
||||
Fl_Widget *below = Fl::belowmouse();
|
||||
if (below && below->image()) {
|
||||
Fl_Anim_GIF_Image *animgif = 0;
|
||||
// Q: is there a way to determine Fl_Tiled_Image without using dynamic cast?
|
||||
Fl_Tiled_Image *tiled = dynamic_cast<Fl_Tiled_Image *>(below->image());
|
||||
animgif = tiled ?
|
||||
dynamic_cast<Fl_Anim_GIF_Image *>(tiled->image()) :
|
||||
dynamic_cast<Fl_Anim_GIF_Image *>(below->image());
|
||||
if (animgif && animgif->playing()) {
|
||||
double speed = animgif->speed();
|
||||
if (!delta) speed = 1.;
|
||||
else speed += delta;
|
||||
if (speed < 0.1) speed = 0.1;
|
||||
if (speed > 10) speed = 10;
|
||||
animgif->speed(speed);
|
||||
set_title(below->window(), animgif);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int events(int event) {
|
||||
if (event == FL_SHORTCUT) {
|
||||
if (Fl::event_key() == '+')
|
||||
change_speed(0.1);
|
||||
else if (Fl::event_key() == '-')
|
||||
change_speed(-0.1);
|
||||
else if (Fl::event_key() == '0')
|
||||
change_speed(0);
|
||||
else
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char testsuite[] = "testsuite";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
fl_register_images();
|
||||
Fl::add_handler(events);
|
||||
char *openFlags = (char *)calloc(1024, 1);
|
||||
if (argc > 1) {
|
||||
// started with argumemts
|
||||
if (strstr(argv[1], "-h")) {
|
||||
printf("Usage:\n"
|
||||
" -t [directory] [-{flags}] open all files in directory (default name: %s) [with options]\n"
|
||||
" filename [-{flags}] open single file [with options] \n"
|
||||
" No arguments open a fileselector\n"
|
||||
" {flags} can be: d=debug mode, u=uncached, D=desaturated, A=color averaged, T=tiled\n"
|
||||
" m=minimal update, r[scale factor]=resize by 'scale factor'\n"
|
||||
" Use keys '+'/'-/0' to change speed of the active image (belowmouse).\n", testsuite);
|
||||
exit(1);
|
||||
}
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-')
|
||||
strcat(openFlags, &argv[i][1]);
|
||||
}
|
||||
if (strchr(openFlags, 't')) { // open all GIF-files in a given directory
|
||||
const char *dir = testsuite;
|
||||
for (int i = 2; i < argc; i++)
|
||||
if (argv[i][0] != '-')
|
||||
dir = argv[i];
|
||||
openDirectory(dir, openFlags);
|
||||
printf("Summary: good=%d, bad=%d, frames=%d\n", g_good_count, g_bad_count, g_frame_count);
|
||||
} else { // open given file(s)
|
||||
for (int i = 1; i < argc; i++)
|
||||
if (argv[i][0] != '-')
|
||||
openFile(argv[i], openFlags, strchr(openFlags, 'd'));
|
||||
}
|
||||
} else {
|
||||
// started without arguments: choose file
|
||||
Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser)
|
||||
while (1) {
|
||||
Fl::add_timeout(0.1, cb_forced_redraw); // animate images in chooser
|
||||
const char *filename = fl_file_chooser("Select a GIF image file","*.{gif,GIF}", NULL);
|
||||
Fl::remove_timeout(cb_forced_redraw);
|
||||
if (!filename)
|
||||
break;
|
||||
Fl_Window *win = openFile(filename, openFlags);
|
||||
Fl::run();
|
||||
// delete last window (which is now just hidden) to test destructors
|
||||
// NOTE: it is essential that *before* doing this also the
|
||||
// animated image is destroyed, otherwise it will crash
|
||||
// because it's canvas will be gone.
|
||||
// In order to keep this demo simple, the adress of the
|
||||
// Fl_Anim_GIF_Image has been stored in the window's user_data.
|
||||
// In a real-life application you will probably store
|
||||
// it somewhere in the window's or canvas' object and destroy
|
||||
// the image in the window's or canvas' destructor.
|
||||
if (win && win->user_data())
|
||||
delete ((Fl_Anim_GIF_Image *)win->user_data());
|
||||
delete win;
|
||||
}
|
||||
}
|
||||
return Fl::run();
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
#include <FL/fl_utf8.h> // fl_fopen()
|
||||
#include <FL/Fl_File_Chooser.H>
|
||||
#include <FL/Fl_SVG_Image.H>
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include "../src/flstring.h"
|
||||
|
||||
#include <stdio.h>
|
||||
@ -51,6 +52,7 @@ static int image_header_written = 0;
|
||||
static int jpeg_header_written = 0;
|
||||
static int png_header_written = 0;
|
||||
static int gif_header_written = 0;
|
||||
static int animated_gif_header_written = 0;
|
||||
static int bmp_header_written = 0;
|
||||
static int svg_header_written = 0;
|
||||
|
||||
@ -134,8 +136,19 @@ void Fluid_Image::write_static(int compressed) {
|
||||
if (!img) return;
|
||||
const char *idata_name = unique_id(this, "idata", fl_filename_name(name()), 0);
|
||||
function_name_ = unique_id(this, "image", fl_filename_name(name()), 0);
|
||||
// TODO: GIF, ICO, BMP
|
||||
if (compressed && strcmp(fl_filename_ext(name()), ".gif")==0) {
|
||||
|
||||
if (is_animated_gif_) {
|
||||
// Write animated gif image data...
|
||||
write_c("\n");
|
||||
if (animated_gif_header_written != write_number) {
|
||||
write_c("#include <FL/Fl_Anim_GIF_Image.H>\n");
|
||||
animated_gif_header_written = write_number;
|
||||
}
|
||||
write_c("static const unsigned char %s[] =\n", idata_name);
|
||||
size_t nData = write_static_binary("AnimGIF");
|
||||
write_c(";\n");
|
||||
write_initializer("Fl_Anim_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
||||
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".gif")==0) {
|
||||
// Write gif image data...
|
||||
write_c("\n");
|
||||
if (gif_header_written != write_number) {
|
||||
@ -146,7 +159,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||
size_t nData = write_static_binary("GIF");
|
||||
write_c(";\n");
|
||||
write_initializer("Fl_GIF_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
||||
} else if (compressed && strcmp(fl_filename_ext(name()), ".bmp")==0) {
|
||||
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".bmp")==0) {
|
||||
// Write bmp image data...
|
||||
write_c("\n");
|
||||
if (bmp_header_written != write_number) {
|
||||
@ -198,7 +211,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||
write_cdata(img->data()[0], ((img->w() + 7) / 8) * img->h());
|
||||
write_c(";\n");
|
||||
write_initializer( "Fl_Bitmap", "%s, %d, %d, %d", idata_name, ((img->w() + 7) / 8) * img->h(), img->w(), img->h());
|
||||
} else if (compressed && strcmp(fl_filename_ext(name()), ".jpg")==0) {
|
||||
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".jpg")==0) {
|
||||
// Write jpeg image data...
|
||||
write_c("\n");
|
||||
if (jpeg_header_written != write_number) {
|
||||
@ -209,7 +222,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||
size_t nData = write_static_binary("JPEG");
|
||||
write_c(";\n");
|
||||
write_initializer("Fl_JPEG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
||||
} else if (compressed && strcmp(fl_filename_ext(name()), ".png")==0) {
|
||||
} else if (compressed && fl_ascii_strcasecmp(fl_filename_ext(name()), ".png")==0) {
|
||||
// Write png image data...
|
||||
write_c("\n");
|
||||
if (png_header_written != write_number) {
|
||||
@ -220,7 +233,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||
size_t nData = write_static_binary("PNG");
|
||||
write_c(";\n");
|
||||
write_initializer("Fl_PNG_Image", "\"%s\", %s, %d", fl_filename_name(name()), idata_name, nData);
|
||||
} else if (strcmp(fl_filename_ext(name()), ".svg")==0 || strcmp(fl_filename_ext(name()), ".svgz")==0) {
|
||||
} else if (fl_ascii_strcasecmp(fl_filename_ext(name()), ".svg")==0 || fl_ascii_strcasecmp(fl_filename_ext(name()), ".svgz")==0) {
|
||||
bool gzipped = (strcmp(fl_filename_ext(name()), ".svgz") == 0);
|
||||
// Write svg image data...
|
||||
if (compressed) {
|
||||
@ -242,7 +255,7 @@ void Fluid_Image::write_static(int compressed) {
|
||||
}
|
||||
} else {
|
||||
// if FLUID runs from the command line, make sure that the image is not
|
||||
// only loade but also rasterized, so we can write the RGB image data
|
||||
// only loaded but also rasterized, so we can write the RGB image data
|
||||
Fl_RGB_Image* rgb_image = NULL;
|
||||
Fl_SVG_Image* svg_image = NULL;
|
||||
if (img->d()>0)
|
||||
@ -279,6 +292,8 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
write_c("static Fl_Image *%s() {\n", function_name_);
|
||||
if (is_animated_gif_)
|
||||
write_c("%sFl_GIF_Image::animate = true;\n", indent(1));
|
||||
write_c("%sstatic Fl_Image *image = NULL;\n", indent(1));
|
||||
write_c("%sif (!image)\n", indent(1));
|
||||
write_c("%simage = new %s(", indent(2), type_name);
|
||||
@ -292,7 +307,11 @@ void Fluid_Image::write_initializer(const char *type_name, const char *format, .
|
||||
void Fluid_Image::write_code(int bind, const char *var, int inactive) {
|
||||
/* Outputs code that attaches an image to an Fl_Widget or Fl_Menu_Item.
|
||||
This code calls a function output before by Fluid_Image::write_initializer() */
|
||||
if (img) write_c("%s%s->%s%s( %s() );\n", indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
|
||||
if (img) {
|
||||
write_c("%s%s->%s%s( %s() );\n", indent(), var, bind ? "bind_" : "", inactive ? "deimage" : "image", function_name_);
|
||||
if (is_animated_gif_)
|
||||
write_c("%s((Fl_Anim_GIF_Image*)(%s()))->canvas(%s, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);\n", indent(), function_name_, var);
|
||||
}
|
||||
}
|
||||
|
||||
void Fluid_Image::write_inline(int inactive) {
|
||||
@ -355,11 +374,20 @@ Fluid_Image* Fluid_Image::find(const char *iname) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
Fluid_Image::Fluid_Image(const char *iname) {
|
||||
Fluid_Image::Fluid_Image(const char *iname)
|
||||
: is_animated_gif_(false)
|
||||
{
|
||||
name_ = fl_strdup(iname);
|
||||
written = 0;
|
||||
refcount = 0;
|
||||
img = Fl_Shared_Image::get(iname);
|
||||
if (img && iname) {
|
||||
const char *ext = fl_filename_ext(iname);
|
||||
if (fl_ascii_strcasecmp(ext, ".gif")==0) {
|
||||
int fc = Fl_Anim_GIF_Image::frame_count(iname);
|
||||
if (fc > 0) is_animated_gif_ = true;
|
||||
}
|
||||
}
|
||||
function_name_ = NULL;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
|
||||
class Fluid_Image {
|
||||
bool is_animated_gif_;
|
||||
const char *name_;
|
||||
int refcount;
|
||||
Fl_Shared_Image *img;
|
||||
|
@ -21,236 +21,127 @@ void show_help(const char *name);
|
||||
|
||||
Fl_Double_Window *about_panel=(Fl_Double_Window *)0;
|
||||
|
||||
#include <FL/Fl_Pixmap.H>
|
||||
static const char *idata_fluid[] = {
|
||||
"96 96 32 1",
|
||||
" \tc None",
|
||||
".\tc #000100",
|
||||
"+\tc #031F3F",
|
||||
"@\tc #00366C",
|
||||
"#\tc #2E302D",
|
||||
"$\tc #0058AC",
|
||||
"%\tc #0060BF",
|
||||
"&\tc #4E504D",
|
||||
"*\tc #14659F",
|
||||
"=\tc #006DDC",
|
||||
"-\tc #2C7087",
|
||||
";\tc #0080FF",
|
||||
">\tc #407B74",
|
||||
",\tc #0F85F9",
|
||||
"\'\tc #268CCD",
|
||||
")\tc #7C7E7B",
|
||||
"!\tc #2D92EC",
|
||||
"~\tc #4498A9",
|
||||
"{\tc #2F94FE",
|
||||
"]\tc #5BA18C",
|
||||
"^\tc #6BA674",
|
||||
"/\tc #7DAD62",
|
||||
"(\tc #93BD53",
|
||||
"_\tc #A4A6A2",
|
||||
":\tc #6CB6FF",
|
||||
"<\tc #ABCC3F",
|
||||
"[\tc #C4DA2A",
|
||||
"}\tc #CACCC9",
|
||||
"|\tc #DCE913",
|
||||
"1\tc #BBDEFF",
|
||||
"2\tc #FDFE00",
|
||||
"3\tc #FDFFFC",
|
||||
" \
|
||||
",
|
||||
" \
|
||||
",
|
||||
" \
|
||||
",
|
||||
" ........... \
|
||||
",
|
||||
" ...................... \
|
||||
",
|
||||
" ........................ \
|
||||
",
|
||||
" ........#&#&#&#&##...... \
|
||||
",
|
||||
" ....)__}33333333333}_... \
|
||||
",
|
||||
" ...&33333333333333333... \
|
||||
",
|
||||
" ...#33311133333333333... \
|
||||
",
|
||||
" ...&33!,{,;:333333333... \
|
||||
",
|
||||
" ...&3:,{{{{,13333333}... \
|
||||
",
|
||||
" ...&3!{{!{{,13333333}... \
|
||||
",
|
||||
" ...&3:!{{!{;13333333}... \
|
||||
",
|
||||
" ...&3{{{{{{;133333333... \
|
||||
",
|
||||
" ...&31,{{{;,33333333}... \
|
||||
",
|
||||
" ...&331{{{:133333333}... \
|
||||
",
|
||||
" ...&3333333333333333_... \
|
||||
",
|
||||
" ...&3333333333333333}... \
|
||||
",
|
||||
" ...&3333333333333333_... \
|
||||
",
|
||||
" ...&3333333333333333}... \
|
||||
",
|
||||
" ...&3333333333333333_... \
|
||||
",
|
||||
" ...&3333333333333333}... \
|
||||
",
|
||||
" ...&3333333333333333_... \
|
||||
",
|
||||
" ...&3333333331!,,;:3}... \
|
||||
",
|
||||
" ...&333333333{{{{{;:_... \
|
||||
",
|
||||
" ...&333333331,{!{!{{}... \
|
||||
",
|
||||
" ...&333333331{{{{{{,_... \
|
||||
",
|
||||
" ...)333333331{{!{{{{_... \
|
||||
",
|
||||
" ...)333333333{{{!{;:_... \
|
||||
",
|
||||
" ...)3333333331{;;;:3_... \
|
||||
",
|
||||
" ...)3333333333331333_... \
|
||||
",
|
||||
" ...)3333333333333333_... \
|
||||
",
|
||||
" ...)3333333333333333_... \
|
||||
",
|
||||
" ..._3333333333333333_... \
|
||||
",
|
||||
" ..._3333333333333333_... \
|
||||
",
|
||||
" ..._3333333333333333_... \
|
||||
",
|
||||
" ..._3333333333333333}.... \
|
||||
",
|
||||
" ...._33333333333333333#... \
|
||||
",
|
||||
" ....&333333333333333333_.... \
|
||||
",
|
||||
" ....&33333333333333333333).... \
|
||||
",
|
||||
" ....333333333333333333333}&.... \
|
||||
",
|
||||
" ...._33333333333333333333333.... \
|
||||
",
|
||||
" ....&333333333331:11333333333_.... \
|
||||
",
|
||||
" ....#33333333333:,,,;:333333333&.... \
|
||||
",
|
||||
" ....}3333333333:,!{{{;1333333333&.... \
|
||||
",
|
||||
" ....}33333333333{{{!{{,!3333333333.... \
|
||||
",
|
||||
" ....)333333333333{{{{!{{{3333333333_.... \
|
||||
",
|
||||
" ....#3333333333333!{{{{{,:33333333333&.... \
|
||||
",
|
||||
" ...._33333333333331{{!{,;1333333333333#.... \
|
||||
",
|
||||
" ...._333333333333333:;,;,13333333333333_.... \
|
||||
",
|
||||
" ...._333333333333333333113333333333333333_.... \
|
||||
",
|
||||
" ....&33333333333333333333333333331::1333333&.... \
|
||||
",
|
||||
" ...._333333333333333333333333333{,{{;{133333#... \
|
||||
",
|
||||
" ...._3333333333333333333333333331,{!{{,:33333}.... \
|
||||
",
|
||||
" ....&3333333333133333333333333333:{{{{{{:333333).... \
|
||||
",
|
||||
" ...#333333331{,,;:333333333333333:{!{!{{:3333333&.... \
|
||||
",
|
||||
" ....}33333333,{{{{;:333333333333331,{!{{;:33333333#... \
|
||||
",
|
||||
" ...._333333331,!{!{{,333333333333333{,{{;{1333333333.... \
|
||||
",
|
||||
" ....&3333333331{{{{{{{3333333333333333::::33333333333)....\
|
||||
",
|
||||
" ....+!:::::::::{{{{!{{;::::::::::::::::::::::::::!:::::+...\
|
||||
. ",
|
||||
" ...+=;;;;;;;;;;;;{{{{;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;=...\
|
||||
. ",
|
||||
" ....%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;%..\
|
||||
.. ",
|
||||
" ....@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;$.\
|
||||
... ",
|
||||
" ...+%;;;;;;!!!;;;;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;!=;;;+\
|
||||
.... ",
|
||||
" ....%;;;;;!([<|^~]^([%;;;;;;;;;;;;;;;;;,(<\'=;;;;;;;!^/<[|\'=;\
|
||||
;=+... ",
|
||||
" ....$;;;;;\'|2>]22<|22[%=;;;;;;;;;;;;;;;;^22[%=;;;;;;!][22|%=;;\
|
||||
;$.... ",
|
||||
" ....@;;;;;;[2[%^2|*[22(%=;;;;;;;;;;;;;;;,/22|$=;;;;;;;;<22<%=;;;\
|
||||
;$.... ",
|
||||
" ....+=;;;;;~22^$%]~$|22>%=;;;;;;;;;;;;;;;;\'||^%=;;;;;;;,[22^$=;;\
|
||||
;;;+.... ",
|
||||
" ....%;;;;;,[22-%===\'22|*==;;;;;;;;;;;;;;;;;;=%=;;;;;;;;\'22|*%=;\
|
||||
;;;;=+... ",
|
||||
" ....$;;;;;;!22|$%;,;^22<$=;;;;;;;;;;;;;;;;;;===;;;;;;;;;^22|$==;;;\
|
||||
;;;%.... ",
|
||||
" ....@;;;;;\'](22[^]=;;<22^$==!~]/~=;!]]~;;;;{\'~]==;;;;~<<]<22($=;;\
|
||||
;;;;;;@.... ",
|
||||
" ....@;;;;;;]<|22|[<%;!|22-%\'[2222*=;/22(%;~|222(=;;;!<2|^[222>$=;;;\
|
||||
;;;;;;+.... ",
|
||||
" ....=;;;;;;;,[22>$===~22|$==,[22[%=;[22]%=,!|22]%=;![2|*%]22|*==;;;;\
|
||||
;;;;;%+... ",
|
||||
" ....@;;;;;;;;!|22*$=;;/22($=;,[22/$=\'222*%=;!|22-%;;<22>%=]22[$%;;;;\
|
||||
;;;;;;;=.... ",
|
||||
" ....@;;;;;;;;;~22[*==;;[22>%=;\'22|-%,^22[$=;,~22[$%;]22<$%=(22/$=;;;;\
|
||||
;;;;;;;;@.... ",
|
||||
" ....+;;;;;;;;;;^22<$=;;!222*$=;]22[$==[22/$=;;(22/$=![22]$=;|22-%=;;;;;\
|
||||
;;;;;;;;+... ",
|
||||
" ....;;;;;;;;;;;<22^%=;;]22[$=;;(22/$=~222-%=;;[22>%=]22|$%;~22|$==;;;;;\
|
||||
;;;;;;;;;.... ",
|
||||
" ....%;;;;;;;;;;;|22-%=;;(22/$=;{|22-%=<22|$%;;\'22|*%;<22<$==(22<$=;=;;;\
|
||||
;;;;;;;;;;$.... ",
|
||||
" ....+;;;;;;;;;;;!222$==;,|22>%=;~22|$=]|22($=;;]22[$%,|22^%=!|22^$=;;;;;;\
|
||||
;;;;;;;;;;@.... ",
|
||||
" ....+=;;;;;;;;;;;~22[$%;;\'22|*-/;]22($*[<22^$^=;(22/$(-222>$=(222->~;;;;;\
|
||||
;;;;;;;;;;;=+.... ",
|
||||
" ...+;;;;;;;;;;;;;(22/$=;;]22|*<\'=(22/*[~[22>(]=;|22>//=|22/$^(|2|-[%=;;;;\
|
||||
;;;;;;;;;;;;=.... ",
|
||||
" ....$;;;;;;;;;;;;;<22>%=;;]222|>==(222|^=|22|<%=;|222<%=(222|<-222|-==;;;;;\
|
||||
;;;;;;;;;;;;$.... ",
|
||||
" ....@;;;;;;;;;;;;;!|2|$=;;;\'[2[>%=;\'|2[]%=/2|/$==;^2|(*%=!(2|($%<2[-%=;;;;\
|
||||
;;;;;;;;;;;;;;;@.... ",
|
||||
"....@;;;;;;;;;;;;;;\'22($%;;;;=%%==;;;=%%%==;=%%==;;;=%===;;==%%====%%=,;;;;;\
|
||||
;;;;;;;;;;;;;;;+... ",
|
||||
"...+=;;;;;;;;;;!\'=,]22-%=;;;;;;==;=;;;===;=;;===;;;;;===;;;;=;=,;;,=;=;;;;;;\
|
||||
;;;;;;;;;;;;;;;=....",
|
||||
"...+;;;;;;;;;;;[2^=<2<$==;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;;;+...",
|
||||
"...+;;;;;;;;;;;22(\'2|*%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;;;;+...",
|
||||
"...+;;;;;;;;;;;^|<[[-%=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;;;+...",
|
||||
"...+;;;;;;;;;;;;*~*%===;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;;;@...",
|
||||
"...+;;;;;;;;;;;;;====;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;;;+...",
|
||||
"....$=;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\
|
||||
;;;;;;;;;;;;;=$....",
|
||||
" .....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\
|
||||
+++++++++++++..... ",
|
||||
" ............................................................................\
|
||||
................. ",
|
||||
" ...........................................................................\
|
||||
................. ",
|
||||
" ........................................................................\
|
||||
.............. "
|
||||
};
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
static const unsigned char idata_fluid[] =
|
||||
{71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80,
|
||||
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,
|
||||
0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91,
|
||||
161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108,
|
||||
182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69,
|
||||
84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0,
|
||||
0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223,
|
||||
120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201,
|
||||
91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147,
|
||||
241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28,
|
||||
93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143,
|
||||
90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153,
|
||||
142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64,
|
||||
188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120,
|
||||
25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231,
|
||||
105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218,
|
||||
161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193,
|
||||
232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254,
|
||||
81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121,
|
||||
51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163,
|
||||
237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109,
|
||||
100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72,
|
||||
177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78,
|
||||
83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195,
|
||||
61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107,
|
||||
246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250,
|
||||
234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208,
|
||||
216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103,
|
||||
106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191,
|
||||
255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16,
|
||||
70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195,
|
||||
0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98,
|
||||
192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122,
|
||||
120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88,
|
||||
129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2,
|
||||
110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118,
|
||||
120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2,
|
||||
16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39,
|
||||
76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42,
|
||||
150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138,
|
||||
46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65,
|
||||
145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225,
|
||||
48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182,
|
||||
90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224,
|
||||
131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154,
|
||||
23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18,
|
||||
186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64,
|
||||
154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10,
|
||||
192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187,
|
||||
234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6,
|
||||
42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0,
|
||||
235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38,
|
||||
224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224,
|
||||
157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125,
|
||||
71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62,
|
||||
112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38,
|
||||
2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252,
|
||||
1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78,
|
||||
111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159,
|
||||
235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10,
|
||||
120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82,
|
||||
185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12,
|
||||
89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148,
|
||||
226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146,
|
||||
147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163,
|
||||
32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40,
|
||||
96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121,
|
||||
34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201,
|
||||
202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73,
|
||||
76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0,
|
||||
57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103,
|
||||
223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71,
|
||||
227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95,
|
||||
151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111,
|
||||
100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102,
|
||||
56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168,
|
||||
148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100,
|
||||
163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117,
|
||||
163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189,
|
||||
191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36,
|
||||
219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128,
|
||||
61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225,
|
||||
130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202,
|
||||
224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227,
|
||||
178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42,
|
||||
167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156,
|
||||
57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130,
|
||||
134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127,
|
||||
112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177,
|
||||
76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92,
|
||||
197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120,
|
||||
102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241,
|
||||
240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0,
|
||||
5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243,
|
||||
26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167,
|
||||
106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208,
|
||||
51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123,
|
||||
124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144,
|
||||
141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164,
|
||||
154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79,
|
||||
111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217,
|
||||
218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238,
|
||||
239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39,
|
||||
142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125,
|
||||
139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106,
|
||||
181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223,
|
||||
111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68,
|
||||
135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118,
|
||||
122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167,
|
||||
53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120,
|
||||
162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39,
|
||||
215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186,
|
||||
229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17,
|
||||
99,199,176,225,186,61,16,35,74,220,19,2,0,59};
|
||||
static Fl_Image *image_fluid() {
|
||||
static Fl_Image *image = new Fl_Pixmap(idata_fluid);
|
||||
Fl_GIF_Image::animate = true;
|
||||
static Fl_Image *image = NULL;
|
||||
if (!image)
|
||||
image = new Fl_Anim_GIF_Image("fluid.animated.gif", idata_fluid, 2545);
|
||||
return image;
|
||||
}
|
||||
|
||||
@ -275,6 +166,8 @@ Fl_Double_Window* make_about_panel() {
|
||||
about_panel->hotspot(about_panel);
|
||||
{ Fl_Box* o = new Fl_Box(10, 10, 115, 120);
|
||||
o->image( image_fluid() );
|
||||
((Fl_Anim_GIF_Image*)(image_fluid()))->canvas(o, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
|
||||
((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f);
|
||||
} // Fl_Box* o
|
||||
{ Fl_Box* o = new Fl_Box(135, 10, 205, 75, "FLTK User\nInterface Designer\nVersion x.x.x");
|
||||
o->color((Fl_Color)12);
|
||||
|
@ -36,11 +36,12 @@ if (!cbuf[0]) {
|
||||
}} {}
|
||||
Fl_Window about_panel {
|
||||
label {About FLUID} open
|
||||
xywh {449 217 345 180} type Double color 50 selection_color 47 hide hotspot
|
||||
code0 {\#include "../src/flstring.h"} non_modal
|
||||
xywh {449 217 345 180} type Double color 50 selection_color 47 hotspot
|
||||
code0 {\#include "../src/flstring.h"} non_modal visible
|
||||
} {
|
||||
Fl_Box {} {
|
||||
image {icons/fluid-96.xpm} xywh {10 10 115 120}
|
||||
Fl_Box {} {selected
|
||||
image {icons/fluid.animated.gif} compress_image 1 xywh {10 10 115 120}
|
||||
code0 {((Fl_Anim_GIF_Image*)(o->image()))->speed(0.5f);}
|
||||
}
|
||||
Fl_Box {} {
|
||||
label {FLTK User
|
||||
@ -59,7 +60,7 @@ Version x.x.x}
|
||||
}
|
||||
Fl_Button {} {
|
||||
label {View License...}
|
||||
callback {show_help("license.html");} selected
|
||||
callback {show_help("license.html");}
|
||||
xywh {115 145 123 25} labelcolor 136
|
||||
}
|
||||
Fl_Return_Button {} {
|
||||
|
BIN
fluid/icons/fluid.animated.gif
Normal file
BIN
fluid/icons/fluid.animated.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
@ -471,6 +471,7 @@ set (IMGCPPFILES
|
||||
Fl_BMP_Image.cxx
|
||||
Fl_File_Icon2.cxx
|
||||
Fl_GIF_Image.cxx
|
||||
Fl_Anim_GIF_Image.cxx
|
||||
Fl_Help_Dialog.cxx
|
||||
Fl_ICO_Image.cxx
|
||||
Fl_JPEG_Image.cxx
|
||||
|
1279
src/Fl_Anim_GIF_Image.cxx
Normal file
1279
src/Fl_Anim_GIF_Image.cxx
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
//
|
||||
// Fl_GIF_Image routines.
|
||||
//
|
||||
// Copyright 1997-2021 by Bill Spitzak and others.
|
||||
// Copyright 1997-2023 by Bill Spitzak and others.
|
||||
//
|
||||
// This library is free software. Distribution and use rights are outlined in
|
||||
// the file "COPYING" which should have been included with this file. If this
|
||||
@ -73,6 +73,16 @@
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
Internally used structure to hold GIF color map data
|
||||
during decoding.
|
||||
*/
|
||||
struct ColorMap {
|
||||
uchar Red[256];
|
||||
uchar Green[256];
|
||||
uchar Blue[256];
|
||||
};
|
||||
|
||||
/*
|
||||
This small helper function checks for read errors or end of file
|
||||
and does some cleanup if an error was found.
|
||||
@ -137,8 +147,8 @@ Fl_GIF_Image::Fl_GIF_Image(const char *filename) :
|
||||
|
||||
Construct an image from a block of memory inside the application. Fluid offers
|
||||
"binary data" chunks as a great way to add image data into the C++ source code.
|
||||
\p imagename can be NULL. If a name is given, the image is added to the list of
|
||||
shared images and will be available by that name.
|
||||
\p imagename can be \c NULL. If a name is given, the image is added to the
|
||||
list of shared images and will be available by that name.
|
||||
|
||||
If a GIF image is animated, Fl_GIF_Image will only read and display the
|
||||
first frame of the animation.
|
||||
@ -205,193 +215,49 @@ Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data) :
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
This method reads GIF image data and creates an RGB or RGBA image. The GIF
|
||||
format supports only 1 bit for alpha. The final image data is stored in
|
||||
a modified XPM format (Fl_GIF_Image is a subclass of Fl_Pixmap).
|
||||
To avoid code duplication, we use an Fl_Image_Reader that reads data from
|
||||
either a file or from memory.
|
||||
*/
|
||||
void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
Fl_GIF_Image::Fl_GIF_Image(const char *filename, bool anim) :
|
||||
Fl_Pixmap((char *const*)0)
|
||||
{
|
||||
char **new_data; // Data array
|
||||
uchar *Image = 0L; // internal temporary image data array
|
||||
w(0); h(0);
|
||||
|
||||
// printf("\nFl_GIF_Image::load_gif_ : %s\n", rdr.name());
|
||||
|
||||
{char b[6] = { 0 };
|
||||
for (int i=0; i<6; ++i) b[i] = rdr.read_byte();
|
||||
if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
|
||||
Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", rdr.name());
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
|
||||
Fl::warning("%s is version %c%c%c.",rdr.name(),b[3],b[4],b[5]);
|
||||
}
|
||||
|
||||
int Width = rdr.read_word();
|
||||
int Height = rdr.read_word();
|
||||
|
||||
uchar ch = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
char HasColormap = ((ch & 0x80) != 0);
|
||||
int BitsPerPixel = (ch & 7) + 1;
|
||||
int ColorMapSize;
|
||||
if (HasColormap) {
|
||||
ColorMapSize = 2 << (ch & 7);
|
||||
Fl_Image_Reader rdr;
|
||||
if (rdr.open(filename) == -1) {
|
||||
Fl::error("Fl_GIF_Image: Unable to open %s!", filename);
|
||||
ld(ERR_FILE_ACCESS);
|
||||
} else {
|
||||
ColorMapSize = 0;
|
||||
load_gif_(rdr, anim);
|
||||
}
|
||||
// int OriginalResolution = ((ch>>4)&7)+1;
|
||||
// int SortedTable = (ch&8)!=0;
|
||||
ch = rdr.read_byte(); // Background Color index
|
||||
ch = rdr.read_byte(); // Aspect ratio is N/64
|
||||
CHECK_ERROR
|
||||
}
|
||||
|
||||
// Read in global colormap:
|
||||
uchar transparent_pixel = 0;
|
||||
char has_transparent = 0;
|
||||
uchar Red[256], Green[256], Blue[256]; /* color map */
|
||||
if (HasColormap) {
|
||||
for (int i=0; i < ColorMapSize; i++) {
|
||||
Red[i] = rdr.read_byte();
|
||||
Green[i] = rdr.read_byte();
|
||||
Blue[i] = rdr.read_byte();
|
||||
}
|
||||
Fl_GIF_Image::Fl_GIF_Image(const char *imagename, const unsigned char *data, const size_t length, bool anim) :
|
||||
Fl_Pixmap((char *const*)0)
|
||||
{
|
||||
Fl_Image_Reader rdr;
|
||||
if (rdr.open(imagename, data, length) == -1) {
|
||||
ld(ERR_FILE_ACCESS);
|
||||
} else {
|
||||
load_gif_(rdr, anim);
|
||||
}
|
||||
CHECK_ERROR
|
||||
}
|
||||
|
||||
int CodeSize; /* Code size, init from GIF header, increases... */
|
||||
char Interlace;
|
||||
/**
|
||||
The default constructor creates an empty GIF image.
|
||||
|
||||
// Main parser loop: parse "blocks" until an image is found or error
|
||||
*/
|
||||
Fl_GIF_Image::Fl_GIF_Image() :
|
||||
Fl_Pixmap((char *const*)0)
|
||||
{
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
int i = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
int blocklen;
|
||||
/*
|
||||
Internally used method to read from the LZW compressed data
|
||||
stream 'rdr' and decode it to 'Image' buffer.
|
||||
|
||||
if (i == 0x21) { // a "gif extension"
|
||||
ch = rdr.read_byte(); // extension type
|
||||
blocklen = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
|
||||
if (ch == 0xF9 && blocklen == 4) { // Graphic Control Extension
|
||||
// printf("Graphic Control Extension at offset %ld\n", rdr.tell()-2);
|
||||
char bits = rdr.read_byte(); // Packed Fields
|
||||
rdr.read_word(); // Delay Time
|
||||
transparent_pixel = rdr.read_byte(); // Transparent Color Index
|
||||
blocklen = rdr.read_byte(); // Block Terminator (must be zero)
|
||||
CHECK_ERROR
|
||||
if (bits & 1) has_transparent = 1;
|
||||
}
|
||||
else if (ch == 0xFF) { // Application Extension
|
||||
// printf("Application Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
else if (ch == 0xFE) { // Comment Extension
|
||||
// printf("Comment Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
else if (ch == 0x01) { // Plain Text Extension
|
||||
// printf("Plain Text Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
else {
|
||||
Fl::warning("%s: unknown GIF extension 0x%02x at offset %ld, length = %d",
|
||||
rdr.name(), ch, rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
} else if (i == 0x2c) { // an image: Image Descriptor follows
|
||||
// printf("Image Descriptor at offset %ld\n", rdr.tell());
|
||||
rdr.read_word(); // Image Left Position
|
||||
rdr.read_word(); // Image Top Position
|
||||
Width = rdr.read_word(); // Image Width
|
||||
Height = rdr.read_word(); // Image Height
|
||||
ch = rdr.read_byte(); // Packed Fields
|
||||
CHECK_ERROR
|
||||
Interlace = ((ch & 0x40) != 0);
|
||||
if (ch & 0x80) { // image has local color table
|
||||
// printf("Local Color Table at offset %ld\n", rdr.tell());
|
||||
BitsPerPixel = (ch & 7) + 1;
|
||||
ColorMapSize = 2 << (ch & 7);
|
||||
for (i=0; i < ColorMapSize; i++) {
|
||||
Red[i] = rdr.read_byte();
|
||||
Green[i] = rdr.read_byte();
|
||||
Blue[i] = rdr.read_byte();
|
||||
}
|
||||
}
|
||||
CHECK_ERROR
|
||||
break; // okay, this is the image we want
|
||||
} else if (i == 0x3b) { // Trailer (end of GIF data)
|
||||
// printf("Trailer found at offset %ld\n", rdr.tell());
|
||||
Fl::error("%s: no image data found.", rdr.name());
|
||||
ld(ERR_NO_IMAGE); // this GIF file is "empty" (no image)
|
||||
return; // terminate
|
||||
} else {
|
||||
Fl::error("%s: unknown GIF code 0x%02x at offset %ld", rdr.name(), i, rdr.tell()-1);
|
||||
ld(ERR_FORMAT); // broken file
|
||||
return; // terminate
|
||||
}
|
||||
CHECK_ERROR
|
||||
|
||||
// skip all data (sub)blocks:
|
||||
while (blocklen > 0) {
|
||||
rdr.skip(blocklen);
|
||||
blocklen = rdr.read_byte();
|
||||
}
|
||||
// printf("End of data (sub)blocks at offset %ld\n", rdr.tell());
|
||||
}
|
||||
|
||||
// read image data
|
||||
|
||||
// printf("Image Data at offset %ld\n", rdr.tell());
|
||||
|
||||
CodeSize = rdr.read_byte() + 1; // LZW Minimum Code Size
|
||||
CHECK_ERROR
|
||||
|
||||
if (BitsPerPixel >= CodeSize) { // Workaround for broken GIF files...
|
||||
BitsPerPixel = CodeSize - 1;
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
}
|
||||
|
||||
// Fix images w/o color table. The standard allows this and lets the
|
||||
// decoder choose a default color table. The standard recommends the
|
||||
// first two color table entries should be black and white.
|
||||
|
||||
if (ColorMapSize == 0) { // no global and no local color table
|
||||
Fl::warning("%s does not have a color table, using default.\n", rdr.name());
|
||||
BitsPerPixel = CodeSize - 1;
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
Red[0] = Green[0] = Blue[0] = 0; // black
|
||||
Red[1] = Green[1] = Blue[1] = 255; // white
|
||||
for (int i = 2; i < ColorMapSize; i++) {
|
||||
Red[i] = Green[i] = Blue[i] = (uchar)(255 * i / (ColorMapSize - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Fix transparent pixel index outside ColorMap (Issue #271)
|
||||
if (has_transparent && transparent_pixel >= ColorMapSize) {
|
||||
for (int k = ColorMapSize; k <= transparent_pixel; k++)
|
||||
Red[k] = Green[k] = Blue[k] = 0xff; // white (color is irrelevant)
|
||||
ColorMapSize = transparent_pixel + 1;
|
||||
}
|
||||
|
||||
#if (0) // TEST/DEBUG: fill color table to maximum size
|
||||
for (int i = ColorMapSize; i < 256; i++) {
|
||||
Red[i] = Green[i] = Blue[i] = 0; // black
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_ERROR
|
||||
|
||||
// now read the LZW compressed image data
|
||||
|
||||
Image = new uchar[Width*Height];
|
||||
NOTE: This methode has been extracted from load_gif_()
|
||||
in order to make the code more read/hand-able.
|
||||
|
||||
*/
|
||||
void Fl_GIF_Image::lzw_decode(Fl_Image_Reader &rdr, uchar *Image,
|
||||
int Width, int Height, int CodeSize, int ColorMapSize, int Interlace) {
|
||||
int YC = 0, Pass = 0; /* Used to de-interlace the picture */
|
||||
uchar *p = Image;
|
||||
uchar *eol = p+Width;
|
||||
@ -419,10 +285,10 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
for (;;) {
|
||||
|
||||
/* Fetch the next code from the raster data stream. The codes can be
|
||||
* any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
|
||||
* maintain our location as a pointer and a bit offset.
|
||||
* In addition, GIF adds totally useless and annoying block counts
|
||||
* that must be correctly skipped over. */
|
||||
* any length from 3 to 12 bits, packed into 8-bit bytes, so we have to
|
||||
* maintain our location as a pointer and a bit offset.
|
||||
* In addition, GIF adds totally useless and annoying block counts
|
||||
* that must be correctly skipped over. */
|
||||
int CurCode = thisbyte;
|
||||
if (frombit+CodeSize > 7) {
|
||||
if (blocklen <= 0) {
|
||||
@ -455,8 +321,11 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CurCode == EOFCode)
|
||||
if (CurCode == EOFCode) {
|
||||
rdr.skip(blocklen);
|
||||
blocklen = rdr.read_byte(); // Block-Terminator must follow!
|
||||
break;
|
||||
}
|
||||
|
||||
uchar OutCode[4097]; // temporary array for reversing codes
|
||||
uchar *tp = OutCode;
|
||||
@ -515,47 +384,52 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
}
|
||||
OldCode = CurCode;
|
||||
}
|
||||
}
|
||||
|
||||
// We are done reading the image, now convert to xpm
|
||||
|
||||
w(Width);
|
||||
h(Height);
|
||||
d(1);
|
||||
/*
|
||||
Internally used function to convert raw 'Image' data
|
||||
to XPM format in an allocated buffer 'new_data'.
|
||||
|
||||
NOTE: This function has been extracted from load_gif_()
|
||||
in order to make the code more read/hand-able.
|
||||
|
||||
*/
|
||||
static char ** convert_to_xpm(uchar *Image, int Width, int Height, ColorMap &CMap, int ColorMapSize, int transparent_pixel) {
|
||||
// allocate line pointer arrays:
|
||||
new_data = new char*[Height+2];
|
||||
char **new_data = new char*[Height+2];
|
||||
|
||||
// transparent pixel must be zero, swap if it isn't:
|
||||
if (has_transparent && transparent_pixel != 0) {
|
||||
if (transparent_pixel > 0) {
|
||||
// swap transparent pixel with zero
|
||||
p = Image+Width*Height;
|
||||
uchar *p = Image+Width*Height;
|
||||
while (p-- > Image) {
|
||||
if (*p==transparent_pixel) *p = 0;
|
||||
else if (!*p) *p = transparent_pixel;
|
||||
}
|
||||
uchar t;
|
||||
t = Red[0];
|
||||
Red[0] = Red[transparent_pixel];
|
||||
Red[transparent_pixel] = t;
|
||||
t = CMap.Red[0];
|
||||
CMap.Red[0] = CMap.Red[transparent_pixel];
|
||||
CMap.Red[transparent_pixel] = t;
|
||||
|
||||
t = Green[0];
|
||||
Green[0] = Green[transparent_pixel];
|
||||
Green[transparent_pixel] = t;
|
||||
t = CMap.Green[0];
|
||||
CMap.Green[0] = CMap.Green[transparent_pixel];
|
||||
CMap.Green[transparent_pixel] = t;
|
||||
|
||||
t = Blue[0];
|
||||
Blue[0] = Blue[transparent_pixel];
|
||||
Blue[transparent_pixel] = t;
|
||||
t = CMap.Blue[0];
|
||||
CMap.Blue[0] = CMap.Blue[transparent_pixel];
|
||||
CMap.Blue[transparent_pixel] = t;
|
||||
}
|
||||
|
||||
// find out what colors are actually used:
|
||||
uchar used[256]; uchar remap[256];
|
||||
int i;
|
||||
for (i = 0; i < ColorMapSize; i++) used[i] = 0;
|
||||
p = Image+Width*Height;
|
||||
uchar *p = Image+Width*Height;
|
||||
while (p-- > Image) used[*p] = 1;
|
||||
|
||||
// remap them to start with printing characters:
|
||||
int base = has_transparent && used[0] ? ' ' : ' '+1;
|
||||
int base = transparent_pixel >= 0 && used[0] ? ' ' : ' '+1;
|
||||
int numcolors = 0;
|
||||
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
||||
remap[i] = (uchar)(base++);
|
||||
@ -563,6 +437,7 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
}
|
||||
|
||||
// write the first line of xpm data (use suffix as temp array):
|
||||
uchar Suffix[4096];
|
||||
int length = snprintf((char*)(Suffix), sizeof(Suffix),
|
||||
"%d %d %d %d",Width,Height,-numcolors,1);
|
||||
new_data[0] = new char[length+1];
|
||||
@ -572,9 +447,9 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
new_data[1] = (char*)(p = new uchar[4*numcolors]);
|
||||
for (i = 0; i < ColorMapSize; i++) if (used[i]) {
|
||||
*p++ = remap[i];
|
||||
*p++ = Red[i];
|
||||
*p++ = Green[i];
|
||||
*p++ = Blue[i];
|
||||
*p++ = CMap.Red[i];
|
||||
*p++ = CMap.Green[i];
|
||||
*p++ = CMap.Blue[i];
|
||||
}
|
||||
|
||||
// remap the image data:
|
||||
@ -588,9 +463,344 @@ void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr)
|
||||
new_data[i + 2][Width] = 0;
|
||||
}
|
||||
|
||||
data((const char **)new_data, Height + 2);
|
||||
alloc_data = 1;
|
||||
return new_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
This method reads GIF image data and creates an RGB or RGBA image. The GIF
|
||||
format supports only 1 bit for alpha. The final image data is stored in
|
||||
a modified XPM format (Fl_GIF_Image is a subclass of Fl_Pixmap).
|
||||
To avoid code duplication, we use an Fl_Image_Reader that reads data from
|
||||
either a file or from memory.
|
||||
|
||||
wcout 2022/01/20 - Added animated GIF support:
|
||||
If the load_gif_() method is called with 'anim=true', then not only the first
|
||||
image is decoded (as with Fl_GIF_Image), but all contained images are read.
|
||||
The new Fl_Anim_GIF_Image class is derived from Fl_GIF_Image and utilises this
|
||||
feature in order to avoid code duplication of the GIF decoding routines.
|
||||
The first image is in this case (additionally) stored in the usual way as described
|
||||
above (making the Fl_Anim_GIF_Image a normal Fl_GIF_Image too).
|
||||
All subsequent images are only decoded (and not converted to XPM) and passed
|
||||
to Fl_Anim_GIF_Image, which stores them on its own (in RGBA format).
|
||||
*/
|
||||
void Fl_GIF_Image::load_gif_(Fl_Image_Reader &rdr, bool anim/*=false*/)
|
||||
{
|
||||
uchar *Image = 0L; // internal temporary image data array
|
||||
int frame = 0;
|
||||
|
||||
// Needed for proper decoding of *all* images in file (Fl_Anim_GIF_Image)
|
||||
uchar background_color_index = 0;
|
||||
GIF_FRAME::CPAL GlobalColorTable[256];
|
||||
bool HasGlobalColorTable = false;
|
||||
GIF_FRAME::CPAL LocalColorTable[256];
|
||||
bool HasLocalColorTable = false;
|
||||
|
||||
w(0); h(0);
|
||||
|
||||
// printf("\nFl_GIF_Image::load_gif_ : %s\n", rdr.name());
|
||||
|
||||
{char b[6] = { 0 };
|
||||
for (int i=0; i<6; ++i) b[i] = rdr.read_byte();
|
||||
if (b[0]!='G' || b[1]!='I' || b[2] != 'F') {
|
||||
Fl::error("Fl_GIF_Image: %s is not a GIF file.\n", rdr.name());
|
||||
ld(ERR_FORMAT);
|
||||
return;
|
||||
}
|
||||
if (b[3]!='8' || b[4]>'9' || b[5]!= 'a')
|
||||
Fl::warning("%s is version %c%c%c.",rdr.name(),b[3],b[4],b[5]);
|
||||
}
|
||||
|
||||
int ScreenWidth = rdr.read_word();
|
||||
int ScreenHeight = rdr.read_word();
|
||||
int Width = ScreenWidth;
|
||||
int Height = ScreenHeight;
|
||||
|
||||
uchar ch = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
char HasColormap = ((ch & 0x80) != 0);
|
||||
HasGlobalColorTable = HasColormap;
|
||||
memset(GlobalColorTable, 0, sizeof(GlobalColorTable));
|
||||
int BitsPerPixel = (ch & 7) + 1;
|
||||
int ColorMapSize = HasColormap ? 2 << (ch & 7) : 0;
|
||||
// int OriginalResolution = ((ch>>4)&7)+1;
|
||||
// int SortedTable = (ch&8)!=0;
|
||||
background_color_index = rdr.read_byte(); // Background Color index
|
||||
ch = rdr.read_byte(); // Aspect ratio is N/64
|
||||
CHECK_ERROR
|
||||
|
||||
// Read in global colormap:
|
||||
uchar transparent_pixel = 0;
|
||||
char has_transparent = 0;
|
||||
char user_input = 0;
|
||||
int delay = 0;
|
||||
int dispose = 0;
|
||||
int XPos = 0;
|
||||
int YPos = 0;
|
||||
struct ColorMap CMap; /* color map */
|
||||
if (HasColormap) {
|
||||
for (int i=0; i < ColorMapSize; i++) {
|
||||
CMap.Red[i] = rdr.read_byte();
|
||||
CMap.Green[i] = rdr.read_byte();
|
||||
CMap.Blue[i] = rdr.read_byte();
|
||||
// store away for reading of further images in file (Fl_Anim_GIF_Image)
|
||||
// because the values are changed during processing.
|
||||
GlobalColorTable[i].r = CMap.Red[i];
|
||||
GlobalColorTable[i].g = CMap.Green[i];
|
||||
GlobalColorTable[i].b = CMap.Blue[i];
|
||||
}
|
||||
}
|
||||
CHECK_ERROR
|
||||
|
||||
char Interlace = 0;
|
||||
|
||||
// Main parser loop: parse "blocks" until an image is found or error
|
||||
|
||||
for (;;) {
|
||||
|
||||
int i = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
int blocklen = 0;
|
||||
|
||||
if (i == 0x21) { // a "gif extension"
|
||||
ch = rdr.read_byte(); // extension type
|
||||
blocklen = rdr.read_byte();
|
||||
CHECK_ERROR
|
||||
|
||||
if (ch == 0xF9 && blocklen == 4) { // Graphic Control Extension
|
||||
// printf("Graphic Control Extension at offset %ld\n", rdr.tell()-2);
|
||||
uchar bits = rdr.read_byte(); // Packed Fields xxxDDDUT
|
||||
dispose = (bits >> 2) & 7;
|
||||
delay = rdr.read_word(); // Delay Time
|
||||
transparent_pixel = rdr.read_byte(); // Transparent Color Index
|
||||
blocklen = rdr.read_byte(); // Block Terminator (must be zero)
|
||||
CHECK_ERROR
|
||||
has_transparent = (bits & 1) ? 1 : 0;
|
||||
user_input = (bits & 2) ? 1 : 0;
|
||||
}
|
||||
else if (ch == 0xFF) { // Application Extension
|
||||
// printf("Application Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
uchar buf[512];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
for (i=0; i<blocklen; i++) buf[i] = rdr.read_byte();
|
||||
blocklen = rdr.read_byte(); // read next Data Sub-block too for NETSCAPE ext.
|
||||
CHECK_ERROR
|
||||
if (blocklen) {
|
||||
while (blocklen--) buf[i++] = rdr.read_byte();
|
||||
blocklen = rdr.read_byte();
|
||||
}
|
||||
CHECK_ERROR
|
||||
|
||||
// Notify derived class on loaded extension data
|
||||
|
||||
GIF_FRAME f(frame, buf);
|
||||
on_extension_data(f);
|
||||
}
|
||||
else if (ch == 0xFE) { // Comment Extension
|
||||
// printf("Comment Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
else if (ch == 0x01) { // Plain Text Extension
|
||||
// printf("Plain Text Extension at offset %ld, length = %d\n", rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
else {
|
||||
Fl::warning("%s: unknown GIF extension 0x%02x at offset %ld, length = %d",
|
||||
rdr.name(), ch, rdr.tell()-3, blocklen);
|
||||
; // skip data
|
||||
}
|
||||
} else if (i == 0x2c) { // an image: Image Descriptor follows
|
||||
// printf("Image Descriptor at offset %ld\n", rdr.tell());
|
||||
XPos = rdr.read_word(); // Image Left Position
|
||||
YPos = rdr.read_word(); // Image Top Position
|
||||
Width = rdr.read_word(); // Image Width
|
||||
Height = rdr.read_word(); // Image Height
|
||||
ch = rdr.read_byte(); // Packed Fields
|
||||
CHECK_ERROR
|
||||
Interlace = ((ch & 0x40) != 0);
|
||||
HasLocalColorTable = ch & 0x80;
|
||||
if (ch & 0x80) { // image has local color table
|
||||
// printf("Local Color Table at offset %ld\n", rdr.tell());
|
||||
BitsPerPixel = (ch & 7) + 1;
|
||||
ColorMapSize = 2 << (ch & 7);
|
||||
memset(LocalColorTable, 0, sizeof(LocalColorTable));
|
||||
for (i=0; i < ColorMapSize; i++) {
|
||||
CMap.Red[i] = rdr.read_byte();
|
||||
CMap.Green[i] = rdr.read_byte();
|
||||
CMap.Blue[i] = rdr.read_byte();
|
||||
// store away for reading of further images in file (Fl_Anim_GIF_Image)
|
||||
// because the values are changed during processing.
|
||||
LocalColorTable[i].r = CMap.Red[i];
|
||||
LocalColorTable[i].g = CMap.Green[i];
|
||||
LocalColorTable[i].b = CMap.Blue[i];
|
||||
}
|
||||
}
|
||||
CHECK_ERROR
|
||||
|
||||
// read image data
|
||||
|
||||
// printf("Image Data at offset %ld\n", rdr.tell());
|
||||
|
||||
int CodeSize = rdr.read_byte(); // LZW initial Code Size (increases...)
|
||||
CHECK_ERROR
|
||||
if (CodeSize < 2 || CodeSize > 8) { // though invalid, other decoders accept an use it
|
||||
Fl::warning("Fl_GIF_Image: %s invalid LZW-initial code size %d.\n", rdr.name(), CodeSize);
|
||||
}
|
||||
CodeSize++;
|
||||
|
||||
// Fix images w/o color table. The standard allows this and lets the
|
||||
// decoder choose a default color table. The standard recommends the
|
||||
// first two color table entries should be black and white.
|
||||
|
||||
if (ColorMapSize == 0) { // no global and no local color table
|
||||
Fl::warning("%s does not have a color table, using default.\n", rdr.name());
|
||||
BitsPerPixel = CodeSize - 1;
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
CMap.Red[0] = CMap.Green[0] = CMap.Blue[0] = 0; // black
|
||||
CMap.Red[1] = CMap.Green[1] = CMap.Blue[1] = 255; // white
|
||||
for (int i = 2; i < ColorMapSize; i++) {
|
||||
CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = (uchar)(255 * i / (ColorMapSize - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for broken GIF files...
|
||||
BitsPerPixel = CodeSize - 1;
|
||||
if (1 << BitsPerPixel <= 256)
|
||||
ColorMapSize = 1 << BitsPerPixel;
|
||||
|
||||
// Fix transparent pixel index outside ColorMap (Issue #271)
|
||||
if (has_transparent && transparent_pixel >= ColorMapSize) {
|
||||
for (int k = ColorMapSize; k <= transparent_pixel; k++)
|
||||
CMap.Red[k] = CMap.Green[k] = CMap.Blue[k] = 0xff; // white (color is irrelevant)
|
||||
ColorMapSize = transparent_pixel + 1;
|
||||
}
|
||||
|
||||
#if (0) // TEST/DEBUG: fill color table to maximum size
|
||||
for (int i = ColorMapSize; i < 256; i++) {
|
||||
CMap.Red[i] = CMap.Green[i] = CMap.Blue[i] = 0; // black
|
||||
}
|
||||
#endif
|
||||
|
||||
CHECK_ERROR
|
||||
|
||||
// now read the LZW compressed image data
|
||||
|
||||
Image = new uchar[Width*Height];
|
||||
lzw_decode(rdr, Image, Width, Height, CodeSize, ColorMapSize, Interlace);
|
||||
if (ld()) return; // CHECK_ERROR aborted already
|
||||
|
||||
// Notify derived class on loaded image data
|
||||
|
||||
GIF_FRAME gf(frame, ScreenWidth, ScreenHeight, XPos, YPos, Width, Height, Image);
|
||||
gf.disposal(dispose, user_input ? -delay - 1 : delay);
|
||||
gf.colors(ColorMapSize, background_color_index, has_transparent ? transparent_pixel : -1);
|
||||
GIF_FRAME::CPAL cpal[256] = { { 0 } };
|
||||
if (HasLocalColorTable)
|
||||
gf.cpal = LocalColorTable;
|
||||
else if (HasGlobalColorTable)
|
||||
gf.cpal = GlobalColorTable;
|
||||
else {
|
||||
for (i=0; i < ColorMapSize; i++) {
|
||||
cpal[i].r = CMap.Red[i]; cpal[i].g = CMap.Green[i]; cpal[i].b = CMap.Blue[i];
|
||||
}
|
||||
gf.cpal = cpal;
|
||||
}
|
||||
#if (0) // TEST/DEBUG: output palette values
|
||||
printf("palette:\n");
|
||||
for (i=0; i<ColorMapSize; i++) {
|
||||
printf("%d: #%02X%02X%02X\n", i, gf.cpal[i].r, gf.cpal[i].g, gf.cpal[i].b);
|
||||
}
|
||||
#endif
|
||||
on_frame_data(gf);
|
||||
|
||||
// We are done reading the image, now convert to xpm (first image only)
|
||||
if (!frame) {
|
||||
if (anim && ( (Width != ScreenWidth) || (Height != ScreenHeight) )) {
|
||||
// if we are reading this for Fl_Anim_GIF_Image, we must apply offsets
|
||||
w(ScreenWidth);
|
||||
h(ScreenHeight);
|
||||
d(1);
|
||||
uchar *moved_image = new uchar[ScreenWidth*ScreenHeight];
|
||||
memset(moved_image, has_transparent ? transparent_pixel : 0, ScreenWidth*ScreenHeight);
|
||||
int xstart = XPos; if (xstart < 0) xstart = 0;
|
||||
int ystart = YPos; if (ystart < 0) ystart = 0;
|
||||
int xmax = XPos + Width; if (xmax > ScreenWidth) xmax = ScreenWidth;
|
||||
int ymax = YPos + Height; if (ymax > ScreenHeight) ymax = ScreenHeight;
|
||||
for (int y = ystart; y<ymax; y++) {
|
||||
uchar *src = Image + (y-YPos) * Width + (xstart-XPos);
|
||||
uchar *dst = moved_image + y*ScreenWidth + xstart;
|
||||
memcpy(dst, src, xmax-xstart);
|
||||
}
|
||||
char **new_data = convert_to_xpm(moved_image, ScreenWidth, ScreenHeight, CMap, ColorMapSize, has_transparent ? transparent_pixel : -1);
|
||||
data((const char **)new_data, Height + 2);
|
||||
alloc_data = 1;
|
||||
delete[] moved_image;
|
||||
} else {
|
||||
// Fl_GIF_Image does not apply offsets and just show the first frame at 0, 0
|
||||
w(Width);
|
||||
h(Height);
|
||||
d(1);
|
||||
char **new_data = convert_to_xpm(Image, Width, Height, CMap, ColorMapSize, has_transparent ? transparent_pixel : -1);
|
||||
data((const char **)new_data, Height + 2);
|
||||
alloc_data = 1;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] Image;
|
||||
Image = NULL;
|
||||
|
||||
if (!anim)
|
||||
break; // okay, it is only the first image we want
|
||||
frame++; // continue to read more images (of animated GIF)
|
||||
// end of Image Descriptor block processing
|
||||
} else if (i == 0x3b) { // Trailer (end of GIF data)
|
||||
// printf("Trailer found at offset %ld\n", rdr.tell());
|
||||
if (!frame) {
|
||||
Fl::error("%s: no image data found.", rdr.name());
|
||||
ld(ERR_NO_IMAGE); // this GIF file is "empty" (no image)
|
||||
}
|
||||
return; // terminate
|
||||
} else {
|
||||
Fl::error("%s: unknown GIF code 0x%02x at offset %ld", rdr.name(), i, rdr.tell()-1);
|
||||
ld(ERR_FORMAT); // broken file
|
||||
return; // terminate
|
||||
}
|
||||
CHECK_ERROR
|
||||
|
||||
// skip all data (sub)blocks:
|
||||
while (blocklen > 0) {
|
||||
rdr.skip(blocklen);
|
||||
blocklen = rdr.read_byte();
|
||||
}
|
||||
// printf("End of data (sub)blocks at offset %ld\n", rdr.tell());
|
||||
}
|
||||
|
||||
delete[] Image;
|
||||
|
||||
} // load_gif_()
|
||||
|
||||
|
||||
/**
|
||||
The protected load() methods are used by Fl_Anim_GIF_Image
|
||||
to request loading of animated GIF's.
|
||||
|
||||
*/
|
||||
void Fl_GIF_Image::load(const char* filename, bool anim)
|
||||
{
|
||||
Fl_Image_Reader rdr;
|
||||
if (rdr.open(filename) == -1) {
|
||||
Fl::error("Fl_GIF_Image: Unable to open %s!", filename);
|
||||
ld(ERR_FILE_ACCESS);
|
||||
} else {
|
||||
load_gif_(rdr, anim);
|
||||
}
|
||||
}
|
||||
|
||||
void Fl_GIF_Image::load(const char *imagename, const unsigned char *data, const size_t len, bool anim)
|
||||
{
|
||||
Fl_Image_Reader rdr;
|
||||
if (rdr.open(imagename, data, len) == -1) {
|
||||
ld(ERR_FILE_ACCESS);
|
||||
} else {
|
||||
load_gif_(rdr, anim);
|
||||
}
|
||||
}
|
||||
|
@ -230,6 +230,7 @@ IMGCPPFILES = \
|
||||
Fl_BMP_Image.cxx \
|
||||
Fl_File_Icon2.cxx \
|
||||
Fl_GIF_Image.cxx \
|
||||
Fl_Anim_GIF_Image.cxx \
|
||||
Fl_Help_Dialog.cxx \
|
||||
Fl_ICO_Image.cxx \
|
||||
Fl_JPEG_Image.cxx \
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_BMP_Image.H>
|
||||
#include <FL/Fl_GIF_Image.H>
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include <FL/Fl_JPEG_Image.H>
|
||||
#include <FL/Fl_PNG_Image.H>
|
||||
#include <FL/Fl_PNM_Image.H>
|
||||
@ -89,7 +90,8 @@ fl_check_images(const char *name, // I - Filename
|
||||
|
||||
if (memcmp(header, "GIF87a", 6) == 0 ||
|
||||
memcmp(header, "GIF89a", 6) == 0) // GIF file
|
||||
return new Fl_GIF_Image(name);
|
||||
return Fl_GIF_Image::animate ? new Fl_Anim_GIF_Image(name) :
|
||||
new Fl_GIF_Image(name);
|
||||
|
||||
// BMP
|
||||
|
||||
|
@ -1954,6 +1954,11 @@ Fl_get_system_colors.o: flstring.h
|
||||
Fl_get_system_colors.o: Fl_Screen_Driver.H
|
||||
Fl_get_system_colors.o: Fl_System_Driver.H
|
||||
Fl_get_system_colors.o: tile.xpm
|
||||
Fl_Anim_GIF_Image.o: ../config.h
|
||||
Fl_Anim_GIF_Image.o: ../FL/Fl_Anim_GIF_Image.H
|
||||
Fl_Anim_GIF_Image.o: ../FL/Fl_GIF_Image.H
|
||||
Fl_Anim_GIF_Image.o: ../FL/Fl_Image.H
|
||||
Fl_Anim_GIF_Image.o: ../FL/Fl_Pixmap.H
|
||||
Fl_GIF_Image.o: ../config.h
|
||||
Fl_GIF_Image.o: ../FL/Enumerations.H
|
||||
Fl_GIF_Image.o: ../FL/Fl.H
|
||||
|
@ -113,7 +113,7 @@ CREATE_EXAMPLE (navigation navigation.cxx fltk)
|
||||
CREATE_EXAMPLE (output output.cxx fltk)
|
||||
CREATE_EXAMPLE (overlay overlay.cxx fltk)
|
||||
CREATE_EXAMPLE (pack pack.cxx fltk)
|
||||
CREATE_EXAMPLE (pixmap pixmap.cxx fltk)
|
||||
CREATE_EXAMPLE (pixmap pixmap.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (pixmap_browser pixmap_browser.cxx "fltk_images;fltk")
|
||||
CREATE_EXAMPLE (preferences preferences.fl fltk)
|
||||
CREATE_EXAMPLE (offscreen offscreen.cxx fltk)
|
||||
|
@ -512,7 +512,10 @@ overlay$(EXEEXT): overlay.o
|
||||
|
||||
pack$(EXEEXT): pack.o
|
||||
|
||||
pixmap$(EXEEXT): pixmap.o
|
||||
pixmap$(EXEEXT): pixmap.o $(IMGLIBNAME)
|
||||
echo Linking $@...
|
||||
$(CXX) $(ARCHFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ pixmap.o $(LINKFLTKIMG) $(LDLIBS)
|
||||
$(OSX_ONLY) ../fltk-config --post $@
|
||||
|
||||
pixmap_browser$(EXEEXT): pixmap_browser.o $(IMGLIBNAME)
|
||||
echo Linking $@...
|
||||
|
@ -24,9 +24,18 @@
|
||||
//
|
||||
|
||||
#include <FL/Fl_Help_Dialog.H>
|
||||
#include <FL/Fl_GIF_Image.H>
|
||||
#include <FL/filename.H> /* FL_PATH_MAX */
|
||||
#include <FL/Fl.H> /* Fl::first_window(), etc */
|
||||
#include <string.h> /* strcpy(), etc */
|
||||
|
||||
static void cb_refresh(void *d) {
|
||||
// trigger a redraw of the window to see animated GIF's
|
||||
if (Fl::first_window())
|
||||
Fl::first_window()->redraw();
|
||||
Fl::repeat_timeout(1./10, cb_refresh, d);
|
||||
}
|
||||
|
||||
//
|
||||
// 'main()' - Display the help GUI...
|
||||
//
|
||||
@ -35,6 +44,7 @@ int // O - Exit status
|
||||
main(int argc, // I - Number of command-line arguments
|
||||
char *argv[]) // I - Command-line arguments
|
||||
{
|
||||
Fl_GIF_Image::animate = true; // create animated shared .GIF images
|
||||
Fl_Help_Dialog *help = new Fl_Help_Dialog;
|
||||
int i;
|
||||
if (!Fl::args(argc, argv, i)) Fl::fatal(Fl::help);
|
||||
@ -44,6 +54,7 @@ main(int argc, // I - Number of command-line arguments
|
||||
|
||||
help->show(1, argv);
|
||||
|
||||
Fl::add_timeout(1./10, cb_refresh, help); // to animate GIF's
|
||||
Fl::run();
|
||||
|
||||
delete help;
|
||||
|
@ -263,6 +263,9 @@ Nested OL/UL:
|
||||
</TR><TR>
|
||||
<TD><IMG SRC="images/tiny.png" alt="Tiny FLTK logo"></TD>
|
||||
<TD>Tiny FLTK logo.</TD>
|
||||
</TR><TR>
|
||||
<TD><IMG SRC="pixmaps/fltk_animated.gif" WIDTH="200" HEIGHT="50" alt="Animated FLTK logo"></TD>
|
||||
<TD>Animated FLTK logo.</TD>
|
||||
</TR><TR>
|
||||
<TD><IMG SRC="images/Fl_Value_Input.png" alt="Fl_Value_Input"></TD>
|
||||
<TD>This is an image of Fl_Value_Input</TD>
|
||||
|
@ -18,17 +18,20 @@
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Pixmap.H>
|
||||
#include <FL/Fl_Anim_GIF_Image.H>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pixmaps/porsche.xpm"
|
||||
#include "pixmaps/animated_fluid_gif.h"
|
||||
|
||||
#include <FL/Fl_Toggle_Button.H>
|
||||
|
||||
Fl_Toggle_Button *leftb,*rightb,*topb,*bottomb,*insideb,*overb,*inactb;
|
||||
Fl_Button *b;
|
||||
Fl_Double_Window *w;
|
||||
Fl_Anim_GIF_Image *pixmap;
|
||||
Fl_Anim_GIF_Image *depixmap;
|
||||
|
||||
void button_cb(Fl_Widget *,void *) {
|
||||
void button_cb(Fl_Widget *wgt,void *) {
|
||||
int i = 0;
|
||||
if (leftb->value()) i |= FL_ALIGN_LEFT;
|
||||
if (rightb->value()) i |= FL_ALIGN_RIGHT;
|
||||
@ -42,6 +45,21 @@ void button_cb(Fl_Widget *,void *) {
|
||||
w->redraw();
|
||||
}
|
||||
|
||||
void play_cb(Fl_Widget *wgt,void *) {
|
||||
pixmap->start();
|
||||
depixmap->start();
|
||||
}
|
||||
|
||||
void stop_cb(Fl_Widget *wgt,void *) {
|
||||
pixmap->stop();
|
||||
depixmap->stop();
|
||||
}
|
||||
|
||||
void step_cb(Fl_Widget *wgt,void *) {
|
||||
pixmap->next();
|
||||
depixmap->next();
|
||||
}
|
||||
|
||||
int dvisual = 0;
|
||||
int arg(int, char **argv, int &i) {
|
||||
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
|
||||
@ -53,18 +71,24 @@ int arg(int, char **argv, int &i) {
|
||||
int main(int argc, char **argv) {
|
||||
int i = 1;
|
||||
if (Fl::args(argc,argv,i,arg) < argc)
|
||||
Fl::fatal(" -8 # : use default visual\n%s\n",Fl::help);
|
||||
Fl::fatal(" -8 # : use default visual\n%s\n", Fl::help);
|
||||
if (!dvisual) Fl::visual(FL_RGB);
|
||||
|
||||
Fl_Double_Window window(400,400); ::w = &window;
|
||||
Fl_Button b(140,160,120,120,"Pixmap"); ::b = &b;
|
||||
Fl_Pixmap *pixmap = new Fl_Pixmap(porsche_xpm);
|
||||
Fl_Pixmap *depixmap;
|
||||
depixmap = (Fl_Pixmap *)pixmap->copy();
|
||||
Fl_Double_Window window(400,440); ::w = &window;
|
||||
Fl_Button b(130,170,140,140,"Pixmap"); ::b = &b;
|
||||
|
||||
Fl_Anim_GIF_Image::animate = true;
|
||||
pixmap = new Fl_Anim_GIF_Image("fluid", animated_fluid_gif, animated_fluid_gif_size,
|
||||
&b, Fl_Anim_GIF_Image::DONT_RESIZE_CANVAS);
|
||||
pixmap->speed(0.5);
|
||||
b.image(pixmap);
|
||||
|
||||
depixmap = (Fl_Anim_GIF_Image*)pixmap->copy();
|
||||
depixmap->inactive();
|
||||
b.deimage(depixmap);
|
||||
|
||||
// "bind" images to avoid memory leak reports (valgrind, asan)
|
||||
// note: these reports are benign because they appear at exit, but anyway
|
||||
|
||||
b.bind_image(pixmap);
|
||||
b.bind_deimage(depixmap);
|
||||
|
||||
@ -82,7 +106,17 @@ int main(int argc, char **argv) {
|
||||
overb->callback(button_cb);
|
||||
inactb = new Fl_Toggle_Button(125,75,100,25,"inactive");
|
||||
inactb->callback(button_cb);
|
||||
if (!dvisual) Fl::visual(FL_RGB);
|
||||
|
||||
Fl_Button* play = new Fl_Button(300, 50, 25, 25, "@>");
|
||||
play->labelcolor(FL_DARK2);
|
||||
play->callback(play_cb);
|
||||
Fl_Button* stop = new Fl_Button(325, 50, 25, 25, "@||");
|
||||
stop->labelcolor(FL_DARK2);
|
||||
stop->callback(stop_cb);
|
||||
Fl_Button* step = new Fl_Button(350, 50, 25, 25, "@|>");
|
||||
step->labelcolor(FL_DARK2);
|
||||
step->callback(step_cb);
|
||||
|
||||
window.resizable(window);
|
||||
window.end();
|
||||
window.show(argc,argv);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Shared_Image.H>
|
||||
#include <FL/Fl_GIF_Image.H>
|
||||
#include <FL/Fl_Printer.H>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
@ -36,6 +37,17 @@ Fl_Shared_Image *img;
|
||||
|
||||
static char name[1024];
|
||||
|
||||
void cb_forced_redraw(void *) {
|
||||
Fl_Window *win = Fl::first_window();
|
||||
while (win) {
|
||||
if (!win->menu_window())
|
||||
win->redraw();
|
||||
win = Fl::next_window(win);
|
||||
}
|
||||
if (Fl::first_window())
|
||||
Fl::repeat_timeout(1./10, cb_forced_redraw);
|
||||
}
|
||||
|
||||
void load_file(const char *n) {
|
||||
if (img) {
|
||||
((Fl_Shared_Image*)b->image())->release();
|
||||
@ -118,8 +130,10 @@ void svg_cb(Fl_Widget *widget, void *) {
|
||||
}
|
||||
|
||||
int dvisual = 0;
|
||||
int animate = 1;
|
||||
int arg(int, char **argv, int &i) {
|
||||
if (argv[i][1] == '8') {dvisual = 1; i++; return 1;}
|
||||
if (argv[i][1] == 'a') {animate = 1; i++; return 1;}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -131,6 +145,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
Fl::args(argc,argv,i,arg);
|
||||
|
||||
if (animate)
|
||||
Fl_GIF_Image::animate = true; // create animated shared .GIF images (e.g. file chooser)
|
||||
|
||||
Fl_Double_Window window(400,450); ::w = &window;
|
||||
Fl_Box b(10,45,380,380); ::b = &b;
|
||||
b.box(FL_THIN_DOWN_BOX);
|
||||
@ -146,5 +163,7 @@ int main(int argc, char **argv) {
|
||||
svg.callback(svg_cb);
|
||||
|
||||
window.show(argc,argv);
|
||||
if (animate)
|
||||
Fl::add_timeout(1./10, cb_forced_redraw); // force periodic redraw
|
||||
return Fl::run();
|
||||
}
|
||||
|
118
test/pixmaps/animated_fluid_gif.h
Normal file
118
test/pixmaps/animated_fluid_gif.h
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
static const size_t animated_fluid_gif_size = 2545;
|
||||
static const unsigned char animated_fluid_gif[] =
|
||||
{71,73,70,56,57,97,96,0,96,0,132,31,0,0,1,0,3,31,63,46,48,45,0,54,108,78,80,
|
||||
77,64,123,116,124,126,123,125,173,98,107,166,116,171,204,63,220,233,19,253,254,
|
||||
0,196,218,42,147,189,83,20,101,159,44,112,135,0,88,172,0,96,191,0,109,220,91,
|
||||
161,140,68,152,169,38,140,205,0,128,255,15,133,249,45,146,236,47,148,254,108,
|
||||
182,255,164,166,162,187,222,255,202,204,201,253,255,252,0,0,0,33,255,11,78,69,
|
||||
84,83,67,65,80,69,50,46,48,3,1,0,0,0,33,249,4,5,10,0,31,0,44,0,0,0,0,96,0,96,0,
|
||||
0,5,254,224,39,142,100,105,158,104,170,174,108,235,190,112,44,207,116,109,223,
|
||||
120,110,2,124,239,3,186,160,238,71,36,14,34,61,161,18,86,244,13,32,78,139,5,201,
|
||||
91,90,87,63,143,118,171,201,112,184,25,11,180,122,45,239,120,219,180,135,147,
|
||||
241,174,219,223,164,121,46,234,169,211,108,111,87,163,149,211,205,118,119,96,28,
|
||||
93,95,28,3,100,127,101,129,130,90,95,107,26,93,22,136,138,128,104,120,28,143,
|
||||
90,124,121,97,80,149,139,151,142,109,164,111,134,153,99,160,87,140,155,145,153,
|
||||
142,142,113,137,170,66,172,130,108,90,112,126,180,65,182,119,93,163,26,136,64,
|
||||
188,181,162,183,112,111,25,169,197,189,199,119,121,143,108,204,205,57,190,120,
|
||||
25,124,91,28,187,213,54,215,120,119,221,222,52,224,141,125,179,228,229,207,231,
|
||||
105,227,234,49,230,231,239,240,47,242,141,244,245,45,247,130,249,250,88,236,218,
|
||||
161,35,246,47,222,179,78,110,196,165,43,184,239,24,194,100,106,252,49,60,193,
|
||||
232,33,41,77,3,39,50,17,101,17,226,22,137,26,73,84,36,69,50,225,199,133,33,254,
|
||||
81,140,44,233,49,99,74,22,172,186,148,212,230,14,229,203,18,172,44,98,116,121,
|
||||
51,133,47,66,26,118,158,36,216,147,98,64,129,32,95,242,83,72,180,40,206,163,
|
||||
237,124,56,61,3,245,156,128,164,19,125,16,16,40,104,131,212,169,31,180,114,109,
|
||||
100,224,171,83,31,99,149,37,236,64,192,236,77,31,27,198,178,204,48,180,105,72,
|
||||
177,92,59,62,242,138,213,155,15,1,105,231,182,217,210,182,111,51,31,29,2,11,78,
|
||||
83,216,38,60,196,105,61,8,166,91,211,49,57,31,6,34,171,37,185,147,175,229,195,
|
||||
61,0,107,222,108,146,177,219,199,61,226,142,134,228,202,234,105,191,169,87,107,
|
||||
246,108,23,52,15,213,178,35,211,86,135,55,183,230,198,181,85,193,245,189,250,
|
||||
234,103,58,195,183,93,36,126,174,195,235,74,189,37,179,100,78,246,249,159,208,
|
||||
216,88,10,165,238,1,56,45,200,91,38,115,23,100,60,120,168,219,106,196,143,103,
|
||||
106,126,73,244,92,139,215,171,41,107,184,134,143,0,24,34,233,143,116,161,191,
|
||||
255,11,251,5,40,224,128,4,6,24,128,117,198,0,254,16,128,4,82,52,232,224,131,16,
|
||||
70,40,225,132,16,74,128,224,16,61,68,64,225,134,28,118,8,33,21,199,217,215,195,
|
||||
0,30,150,104,226,132,99,132,56,67,15,1,104,248,32,6,48,62,120,193,137,52,98,
|
||||
192,160,20,7,214,215,16,15,46,54,136,65,3,12,36,160,0,2,20,76,128,0,144,61,122,
|
||||
120,65,3,9,84,112,227,139,8,28,144,0,3,10,56,41,133,4,57,182,183,98,15,16,60,88,
|
||||
129,2,11,20,48,193,2,11,8,73,38,3,17,60,217,33,2,103,166,9,33,6,19,48,64,166,2,
|
||||
110,74,145,162,150,27,241,64,226,131,114,162,201,166,2,14,200,185,64,3,117,118,
|
||||
120,193,1,115,66,160,166,131,9,144,153,64,161,98,92,104,15,139,139,82,64,38,2,
|
||||
16,68,48,1,5,16,128,25,38,164,28,126,57,36,168,82,92,32,40,166,139,102,137,39,
|
||||
76,25,202,40,232,3,105,74,32,65,5,115,58,32,43,141,18,144,42,5,173,11,0,10,42,
|
||||
150,58,62,197,67,151,47,38,170,225,140,108,150,169,40,174,183,74,152,172,2,138,
|
||||
46,58,133,164,42,254,68,225,96,5,19,52,112,38,2,19,220,216,232,2,168,74,128,65,
|
||||
145,7,80,192,32,156,155,58,152,65,5,69,54,43,5,5,9,36,48,193,183,13,44,27,225,
|
||||
48,42,10,11,192,158,14,206,235,169,2,65,106,136,129,167,176,86,32,40,153,182,
|
||||
90,128,232,160,26,82,224,233,160,79,98,208,232,144,7,23,96,111,132,170,202,224,
|
||||
131,180,22,152,74,166,197,178,74,96,105,175,209,122,188,0,154,12,10,58,65,154,
|
||||
23,12,76,230,202,231,202,233,235,152,189,218,202,177,20,17,100,105,144,158,18,
|
||||
186,188,128,3,246,46,92,47,131,38,31,160,40,175,63,187,233,51,172,82,124,91,64,
|
||||
154,52,51,144,233,134,22,246,101,109,132,35,51,96,179,20,130,62,205,32,175,10,
|
||||
192,122,65,178,82,19,157,245,212,52,39,144,169,4,218,46,96,244,205,14,226,187,
|
||||
234,125,20,38,171,246,141,24,144,249,243,178,81,71,43,232,219,82,180,253,54,6,
|
||||
42,47,75,176,174,16,234,204,42,15,27,126,139,64,157,125,223,40,184,162,35,47,0,
|
||||
235,141,93,67,109,172,5,35,67,235,238,134,254,146,250,144,100,132,135,75,78,38,
|
||||
224,25,148,254,45,180,46,130,237,128,134,223,222,205,182,163,203,194,237,224,
|
||||
157,62,177,184,97,222,100,70,219,177,167,94,115,158,168,4,19,120,58,180,20,125,
|
||||
71,112,129,167,143,139,203,252,197,29,202,109,20,15,11,110,120,118,235,181,62,
|
||||
112,128,5,52,215,27,168,227,16,32,192,224,228,13,60,160,55,200,109,91,94,0,5,38,
|
||||
2,59,142,238,28,78,126,35,205,128,54,57,187,219,129,82,208,117,3,221,90,0,252,
|
||||
1,7,144,128,167,140,118,36,48,133,13,101,237,59,141,15,136,213,184,143,65,78,
|
||||
111,10,40,128,172,210,55,36,1,206,233,81,12,122,24,6,41,152,0,243,205,233,1,159,
|
||||
235,16,238,234,48,162,14,185,204,115,13,50,216,201,130,247,165,147,193,12,81,10,
|
||||
120,27,131,254,212,128,215,137,75,91,10,168,87,4,26,197,128,203,209,104,18,82,
|
||||
185,218,134,120,165,67,7,229,42,86,13,58,34,18,143,232,174,92,133,236,74,76,12,
|
||||
89,4,88,246,67,11,232,140,82,20,194,128,147,46,64,51,31,62,232,86,79,122,148,
|
||||
226,141,158,104,196,207,49,72,2,51,234,216,25,171,104,129,170,253,32,0,27,146,
|
||||
147,248,26,37,59,54,218,241,142,86,36,2,28,41,68,166,6,208,202,87,182,195,163,
|
||||
32,39,164,42,234,109,8,1,10,152,82,15,17,55,200,70,74,168,144,10,226,144,3,40,
|
||||
96,195,16,58,242,146,247,210,99,135,66,22,72,76,98,18,146,0,128,158,39,71,121,
|
||||
34,9,224,238,141,1,72,165,42,87,201,202,86,186,242,149,176,140,165,44,103,201,
|
||||
202,31,144,176,9,184,204,165,46,119,201,203,94,246,82,36,190,12,166,48,135,73,
|
||||
76,34,76,175,152,200,76,102,49,75,16,2,0,33,249,4,5,10,0,31,0,44,30,0,4,0,38,0,
|
||||
57,0,0,5,254,224,39,142,31,96,158,104,170,2,100,235,174,112,236,206,174,103,
|
||||
223,56,158,210,60,205,113,185,91,111,152,201,136,56,25,100,50,232,25,246,126,71,
|
||||
227,143,233,57,57,121,72,13,105,169,51,93,105,154,204,141,243,225,222,172,95,
|
||||
151,70,227,209,126,128,65,116,186,85,92,127,168,115,44,156,218,204,147,236,111,
|
||||
100,83,113,94,126,128,69,101,98,132,44,115,124,124,114,126,45,123,57,145,88,102,
|
||||
56,149,60,110,153,156,157,158,159,160,161,162,149,142,120,145,165,76,164,168,
|
||||
148,167,171,152,173,174,54,170,177,125,126,180,178,176,177,179,76,28,107,26,100,
|
||||
163,34,97,69,69,192,162,74,196,197,163,201,201,155,160,204,196,206,159,208,117,
|
||||
163,195,204,198,160,200,209,66,161,189,35,147,184,78,183,169,227,228,229,78,189,
|
||||
191,231,226,62,208,225,186,154,208,108,231,150,212,240,174,238,247,236,181,36,
|
||||
219,201,217,60,253,35,22,80,224,187,96,111,0,130,226,199,176,161,67,90,219,128,
|
||||
61,196,49,144,204,68,27,3,139,93,244,144,49,137,175,143,32,67,138,244,149,225,
|
||||
130,201,147,38,3,51,132,0,0,33,249,4,5,10,0,31,0,44,34,0,7,0,34,0,54,0,0,5,202,
|
||||
224,39,138,94,105,158,168,57,174,236,154,190,104,43,143,112,237,205,179,13,227,
|
||||
178,254,242,45,95,10,200,18,198,136,52,163,10,73,82,150,152,77,39,116,74,141,42,
|
||||
167,206,39,52,123,171,122,191,224,176,120,76,46,155,207,232,244,151,195,230,156,
|
||||
57,154,140,60,227,94,107,52,245,185,190,62,229,232,229,113,127,114,85,129,130,
|
||||
134,83,1,126,130,23,134,25,136,138,127,140,135,80,137,141,134,124,76,144,127,
|
||||
112,43,28,90,80,154,114,158,30,109,163,93,125,123,58,72,92,75,64,172,39,106,177,
|
||||
76,175,63,69,175,112,119,152,46,172,133,162,61,92,161,190,182,89,141,26,65,92,
|
||||
197,199,196,134,198,195,78,189,115,186,31,172,193,205,100,112,209,68,144,120,
|
||||
102,208,116,180,90,193,25,26,224,93,222,114,229,34,231,25,233,31,25,23,240,241,
|
||||
240,119,244,245,246,247,244,33,0,33,249,4,5,10,0,31,0,44,36,0,13,0,26,0,48,0,0,
|
||||
5,196,224,39,138,156,102,114,99,170,174,100,230,186,26,43,143,220,107,163,243,
|
||||
26,104,182,157,235,188,158,235,167,218,9,135,196,84,77,24,75,166,130,55,167,
|
||||
106,153,209,224,164,88,44,103,123,205,150,162,217,207,177,155,164,246,178,208,
|
||||
51,54,237,211,30,51,225,177,103,78,247,252,190,175,79,189,46,219,115,57,123,
|
||||
124,44,129,132,123,125,133,136,42,0,139,136,137,41,139,0,141,30,93,100,31,144,
|
||||
141,102,46,28,1,131,133,98,71,14,157,132,153,47,26,156,41,152,111,149,57,164,
|
||||
154,104,76,97,164,171,101,39,78,84,86,97,31,108,25,128,146,83,71,26,146,118,79,
|
||||
111,194,42,187,46,198,196,71,202,52,114,190,191,54,193,205,74,38,86,194,216,217,
|
||||
218,219,136,102,171,194,178,43,146,173,188,42,227,170,199,214,234,214,25,23,238,
|
||||
239,238,112,41,33,0,33,249,4,5,10,0,31,0,44,38,0,5,0,21,0,56,0,0,5,232,224,39,
|
||||
142,80,52,158,104,202,101,25,151,190,98,166,105,172,11,167,44,171,125,156,125,
|
||||
139,171,26,173,245,27,245,56,195,93,17,185,11,250,96,131,97,203,89,20,205,106,
|
||||
181,170,199,99,67,102,127,219,174,231,11,3,132,129,231,159,57,204,217,186,223,
|
||||
111,145,185,7,175,199,81,109,207,76,249,91,105,182,82,79,48,109,121,71,85,64,68,
|
||||
135,39,52,127,112,76,26,130,136,132,133,57,58,47,121,34,92,149,57,28,1,153,118,
|
||||
122,155,57,3,159,118,82,155,164,31,160,161,162,25,169,171,65,155,26,175,171,167,
|
||||
53,158,170,171,154,58,79,186,160,138,192,193,194,39,190,118,55,73,160,0,0,120,
|
||||
162,121,111,2,56,173,117,27,203,70,173,45,117,204,173,206,110,218,205,198,39,
|
||||
215,191,39,177,156,197,110,73,96,231,235,117,71,189,190,167,124,240,162,74,186,
|
||||
229,149,46,246,215,249,176,251,185,160,247,56,85,177,37,67,81,188,17,231,220,17,
|
||||
99,199,176,225,186,61,16,35,74,220,19,2,0,59};
|
||||
|
BIN
test/pixmaps/fltk_animated.gif
Normal file
BIN
test/pixmaps/fltk_animated.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 114 KiB |
BIN
test/pixmaps/fltk_animated2.gif
Normal file
BIN
test/pixmaps/fltk_animated2.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
test/pixmaps/fltk_animated3.gif
Normal file
BIN
test/pixmaps/fltk_animated3.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
@ -47,11 +47,10 @@ int arg(int argc, char **argv, int &i) {
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
#ifdef FLTK_USE_X11
|
||||
int i = 1;
|
||||
|
||||
Fl::args(argc,argv,i,arg);
|
||||
|
||||
|
||||
#ifdef FLTK_USE_X11
|
||||
if (visid >= 0) {
|
||||
fl_open_display();
|
||||
XVisualInfo templt; int num;
|
||||
|
@ -609,7 +609,7 @@ int main(int argc, char** argv)
|
||||
end_list /= 16;
|
||||
}
|
||||
argc = 1;
|
||||
for (long y = off; y < end_list; y++) {
|
||||
for (int y = off; y < end_list; y++) {
|
||||
int o = 0;
|
||||
char bu[25]; // index label
|
||||
char buf[16 * 6]; // utf8 text
|
||||
@ -622,7 +622,7 @@ int main(int argc, char** argv)
|
||||
i++;
|
||||
}
|
||||
buf[o] = '\0';
|
||||
snprintf(bu, sizeof(bu), "0x%06lX", y * 16);
|
||||
snprintf(bu, sizeof(bu), "0x%06X", y * 16);
|
||||
Fl_Input *b = new Fl_Input(200,(y-off)*25,80,25);
|
||||
b->textfont(FL_COURIER);
|
||||
b->value(fl_strdup(bu));
|
||||
|
Loading…
Reference in New Issue
Block a user