Example #1
0
static void animation_render_main (IterativeMap *map,
                                   Animation    *animation,
                                   const gchar  *filename,
                                   double        quality) {
    const double frame_rate = 24;
    AnimationIter iter;
    ParameterHolderPair frame;
    guint frame_count = 0;
    gboolean continuation;
    double current_quality;

    AviWriter *avi = avi_writer_new(fopen(filename, "wb"),
                                    HISTOGRAM_IMAGER(map)->width,
                                    HISTOGRAM_IMAGER(map)->height,
                                    frame_rate);

    animation_iter_get_first(animation, &iter);
    frame.a = PARAMETER_HOLDER(de_jong_new());
    frame.b = PARAMETER_HOLDER(de_jong_new());

    while (animation_iter_read_frame(animation, &iter, &frame, frame_rate)) {

        continuation = FALSE;
        do {
            /* Calculate 0.5 seconds between quality updates. This is lower than the
             * batch image rendering default of 2.0 seconds, to better handle
             * lower-quality animations where the individual frames go quicker.
             */
            iterative_map_calculate_motion_timed(map, 0.5, continuation,
                                                 PARAMETER_INTERPOLATOR(parameter_holder_interpolate_linear),
                                                 &frame);
            current_quality = histogram_imager_compute_quality(HISTOGRAM_IMAGER(map));

            printf("\rFrame %d, %e iterations, %.04f quality", frame_count,
                   map->iterations, current_quality);
            fflush(stdout);

            continuation = TRUE;
        } while (current_quality < quality);

        histogram_imager_update_image(HISTOGRAM_IMAGER(map));
        avi_writer_append_frame(avi, HISTOGRAM_IMAGER(map)->image);

        /* Move to the next line for each frame.
         * Updates within a frame overwrite that line.
         */
        printf("\n");

        frame_count++;
    }

    avi_writer_close(avi);
}
Example #2
0
static BifurcationDiagram* get_bifurcation_diagram  (CellRendererBifurcation  *self) {
    /* Using the current iterator and animation, find the corresponding
     * bifurcation diagram object, creating and/or updating it if necessary.
     */
    GObject *obj;
    BifurcationDiagram *bd;
    GtkTreeIter keyframe, next_keyframe;
    DeJong *a, *b;

    /* Look up the first keyframe from a row ID */
    if (!animation_keyframe_find_by_id(self->animation, self->row_id, &keyframe))
	return NULL;

    /* Iterate to the next keyframe */
    next_keyframe = keyframe;
    if (!gtk_tree_model_iter_next(GTK_TREE_MODEL(self->animation->model), &next_keyframe)) {
	/* We're at the last keyframe, no bifurcation diagram for us */
	return NULL;
    }

    /* Try to extract an existing bifurcation diagram */
    gtk_tree_model_get(GTK_TREE_MODEL(self->animation->model), &keyframe,
		       ANIMATION_MODEL_BIFURCATION, &obj,
		       -1);
    if (obj) {
	/* We have an existing object, yay */
	bd = BIFURCATION_DIAGRAM(obj);
    }
    else {
	/* Nope, create a new object and store it in the model */
	bd = bifurcation_diagram_new();
	gtk_list_store_set(self->animation->model, &keyframe,
			   ANIMATION_MODEL_BIFURCATION, bd,
			   -1);
    }

    /* Load parameters from both keyframes */
    a = de_jong_new();
    b = de_jong_new();
    animation_keyframe_load(self->animation, &keyframe, PARAMETER_HOLDER(a));
    animation_keyframe_load(self->animation, &next_keyframe,  PARAMETER_HOLDER(b));

    /* Set up this bifurcation diagram for linear interpolation between the two */
    bifurcation_diagram_set_linear_endpoints(bd, a, b);

    g_object_unref(a);
    g_object_unref(b);
    return bd;
}
Example #3
0
static void       cmd_set_param        (RemoteServerConn*  self,
					const char*        command,
					const char*        parameters)
{
    parameter_holder_set_from_line(PARAMETER_HOLDER(self->map), parameters);
    remote_server_send_response(self, FYRE_RESPONSE_OK, "ok");
}
void
histogram_imager_load_image_file (HistogramImager *self, const gchar *filename, GError **error)
{
    /* Try to open the given PNG file and load parameters from it */
    const gchar *params;
    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, error);
    if (!pixbuf)
	return;

    params = gdk_pixbuf_get_option (pixbuf, "tEXt::fyre_params");

    /* For backward compatibility with de Jong Explorer and early versions of Fyre */
    if (!params)
	params = gdk_pixbuf_get_option (pixbuf, "tEXt::de_jong_params");

    if (params) {
	parameter_holder_load_string (PARAMETER_HOLDER (self), params);
    } else {
	if (error != NULL) {
	    GError *nerror = g_error_new (fyre_histogram_imager_error_quark(),
			                  FYRE_HISTOGRAM_IMAGER_ERROR_NO_METADATA,
				          "The image does not contain Fyre metadata");
	    *error = nerror;
	}
    }
    gdk_pixbuf_unref (pixbuf);
}
Example #5
0
static void animation_render_ui_init(AnimationRenderUi *self) {
    if (g_file_test (FYRE_DATADIR "/animation-render.glade", G_FILE_TEST_EXISTS))
        self->xml = glade_xml_new(FYRE_DATADIR "/animation-render.glade", NULL, NULL);
    if (!self->xml)
	self->xml = glade_xml_new(BR_DATADIR("/fyre/animation-render.glade"), NULL, NULL);

    fyre_set_icon_later(glade_xml_get_widget(self->xml, "window"));

    glade_xml_signal_connect_data(self->xml, "on_ok_clicked",                 G_CALLBACK(on_ok_clicked),                 self);
    glade_xml_signal_connect_data(self->xml, "on_cancel_clicked",             G_CALLBACK(on_cancel_clicked),             self);
    glade_xml_signal_connect_data(self->xml, "on_select_output_file_clicked", G_CALLBACK(on_select_output_file_clicked), self);
    glade_xml_signal_connect_data(self->xml, "on_delete_event",               G_CALLBACK(on_delete_event),               self);

    self->map = ITERATIVE_MAP(de_jong_new());
    self->frame.a = PARAMETER_HOLDER(de_jong_new());
    self->frame.b = PARAMETER_HOLDER(de_jong_new());
}
Example #6
0
Explorer* explorer_new(IterativeMap *map, Animation *animation) {
    Explorer *self = EXPLORER(g_object_new(explorer_get_type(), NULL));
    GtkWidget *editor, *window, *scroll;
    GtkRequisition win_req;

    self->animation = ANIMATION(g_object_ref(animation));
    self->map = ITERATIVE_MAP(g_object_ref(map));

    /* Create the parameter editor */
    editor = parameter_editor_new(PARAMETER_HOLDER(map));
    gtk_box_pack_start(GTK_BOX(glade_xml_get_widget(self->xml, "parameter_editor_box")),
		       editor, FALSE, FALSE, 0);
    gtk_widget_show_all(editor);

    /* Create the view */
    self->view = histogram_view_new(HISTOGRAM_IMAGER(map));
    gtk_container_add(GTK_CONTAINER(glade_xml_get_widget(self->xml, "drawing_area_viewport")), self->view);
    gtk_widget_show_all(self->view);

    /* Set the initial render time */
    on_render_time_changed(glade_xml_get_widget(self->xml, "render_time"), self);

    explorer_init_history(self);
    explorer_init_animation(self);
    explorer_init_tools(self);
    explorer_init_cluster(self);
    explorer_init_about(self);

    /* Start the iterative map rendering in the background, and get a callback every time a block
     * of calculations finish so we can update the GUI.
     */
    iterative_map_start_calculation(self->map);
    g_signal_connect(G_OBJECT(self->map), "calculation-finished",
		     G_CALLBACK(on_calculation_finished), self);

    /* Set the window's default size to include our default image size.
     * The cleanest way I know of to do this is to set the scrolled window's scrollbar policies
     * to 'never' and get the window's size requests, set them back to automatic, then set the
     * default size to that size request.
     */
    window = glade_xml_get_widget(self->xml, "explorer_window");
    scroll = glade_xml_get_widget(self->xml, "main_scrolledwindow");
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_NEVER);
    gtk_widget_size_request(window, &win_req);
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
    gtk_window_set_default_size(GTK_WINDOW(window), win_req.width, win_req.height);
    gtk_widget_show(window);

    return self;
}
Example #7
0
ScreenSaver* screensaver_new(IterativeMap *map, Animation *animation) {
    ScreenSaver *self = SCREENSAVER(g_object_new(screensaver_get_type(), NULL));
    int i;
    AnimationIter iter;
    gchar* common_parameters;

    self->animation = ANIMATION(g_object_ref(animation));
    self->map = ITERATIVE_MAP(g_object_ref(map));
    self->view = g_object_ref(histogram_view_new(HISTOGRAM_IMAGER(self->map)));

    /* Allocate and interpolate all frames */
    self->framerate = 10;
    self->num_frames = animation_get_length(self->animation) * self->framerate;
    self->frame_renders = g_new0(IterativeMap*, self->num_frames);
    self->frame_parameters = g_new0(ParameterHolderPair, self->num_frames);
    self->current_frame = 0;
    common_parameters = parameter_holder_save_string(PARAMETER_HOLDER(map));

    animation_iter_seek(animation, &iter, 0);
    for (i=0; i<self->num_frames; i++) {
	self->frame_renders[i] = ITERATIVE_MAP(de_jong_new());
	parameter_holder_load_string(PARAMETER_HOLDER(self->frame_renders[i]), common_parameters);

	self->frame_parameters[i].a = PARAMETER_HOLDER(de_jong_new());
	animation_iter_load(animation, &iter, self->frame_parameters[i].a);
	animation_iter_seek_relative(animation, &iter, 1/self->framerate);
    }
    for (i=0; i<self->num_frames-1; i++)
	self->frame_parameters[i].b = self->frame_parameters[i+1].a;
    self->frame_parameters[self->num_frames-1].b = self->frame_parameters[self->num_frames-1].a;

    g_free(common_parameters);
    self->direction = 1;

    screensaver_start(self);
    return self;
}
void
histogram_imager_save_image_file (HistogramImager *self, const gchar *filename, GError **error)
{
    /* Save our current image to a .PNG file */
    gchar *params;

    histogram_imager_update_image (self);

    /* Save our current parameters in a tEXt chunk, using a format that
     * is both human-readable and easy to load parameters from automatically.
     */
    params = parameter_holder_save_string (PARAMETER_HOLDER(self));
    gdk_pixbuf_save (self->image, filename, "png", error, "tEXt::fyre_params", params, NULL);
    g_free (params);
}
Example #9
0
static HistoryNode* history_node_new   (HistogramImager* map)
{
    HistoryNode* self = g_new0(HistoryNode, 1);
    gint width, height;

    g_get_current_time(&self->timestamp);
    self->params = parameter_holder_save_string(PARAMETER_HOLDER(map));

    /* Use the normal icon size plus a little extra */
    gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
    width *= 1.75;
    height *= 1.75;
    self->thumbnail = histogram_imager_make_thumbnail(map, width, height);

    return self;
}
Example #10
0
static void on_load_defaults(GtkWidget *widget, Explorer* self) {
    parameter_holder_reset_to_defaults(PARAMETER_HOLDER(self->map));
}
Example #11
0
int main(int argc, char ** argv) {
    IterativeMap* map;
    Animation* animation;
    gboolean animate = FALSE;
    gboolean have_gtk;
    gboolean verbose = FALSE;
    gboolean hidden = FALSE;
    enum {INTERACTIVE, RENDER, SCREENSAVER, REMOTE} mode = INTERACTIVE;
    const gchar *outputFile = NULL;
    const gchar *pidfile = NULL;
    int c, option_index=0;
    double quality = 1.0;
#ifdef HAVE_GNET
    int port_number = FYRE_DEFAULT_PORT;
#endif
    GError *error = NULL;

    math_init();
    g_type_init();
    have_gtk = gtk_init_check(&argc, &argv);

#ifdef HAVE_GNET
    gnet_init();
#  ifdef WIN32
    gnet_ipv6_set_policy(GIPV6_POLICY_IPV4_ONLY);
#  endif
#endif

    map = ITERATIVE_MAP(de_jong_new());
    animation = animation_new();

    while (1) {
        static struct option long_options[] = {
            {"help",         0, NULL, 'h'},
            {"read",         1, NULL, 'i'},
            {"animate",      1, NULL, 'n'},
            {"output",       1, NULL, 'o'},
            {"param",        1, NULL, 'p'},
            {"size",         1, NULL, 's'},
            {"oversample",   1, NULL, 'S'},
            {"quality",      1, NULL, 'q'},
            {"remote",       0, NULL, 'r'},
            {"verbose",      0, NULL, 'v'},
            {"port",         1, NULL, 'P'},
            {"cluster",      1, NULL, 'c'},
            {"auto-cluster", 0, NULL, 'C'},
            {"screensaver",  0, NULL, 1000},   /* Undocumented, still experimental */
            {"hidden",       0, NULL, 1001},
            {"chdir",        1, NULL, 1002},   /* Undocumented, used by win32 file associations */
            {"pidfile",      1, NULL, 1003},
            {"version",      0, NULL, 1004},
            {NULL},
        };
        c = getopt_long(argc, argv, "hi:n:o:p:s:S:q:rvP:c:C",
                        long_options, &option_index);
        if (c == -1)
            break;

        switch (c) {

        case 'i':
        {
            histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), optarg, &error);
            break;
        }

        case 'n':
        {
            GtkTreeIter iter;

            animation_load_file(animation, optarg);
            animate = TRUE;
            gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter);
            animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map));
            break;
        }

        case 'o':
            mode = RENDER;
            outputFile = optarg;
            break;

        case 'p':
            parameter_holder_load_string(PARAMETER_HOLDER(map), optarg);
            break;

        case 's':
            parameter_holder_set(PARAMETER_HOLDER(map), "size" , optarg);
            break;

        case 'S':
            parameter_holder_set(PARAMETER_HOLDER(map), "oversample", optarg);
            break;

        case 'q':
            quality = atof(optarg);
            break;

        case 'v':
            verbose = TRUE;
            break;

#ifdef HAVE_GNET
        case 'c':
        {
            ClusterModel *cluster = cluster_model_get(map, TRUE);
            cluster_model_add_nodes(cluster, optarg);
        }
        break;
        case 'C':
        {
            ClusterModel *cluster = cluster_model_get(map, TRUE);
            cluster_model_enable_discovery(cluster);
        }
        break;
        case 'r':
            mode = REMOTE;
            break;
        case 'P':
            port_number = atol(optarg);
            break;
#else
        case 'c':
        case 'C':
        case 'P':
            fprintf(stderr,
                    "This Fyre binary was compiled without gnet support.\n"
                    "Cluster support is not available.\n");
            break;
        case 'r':
            fprintf(stderr,
                    "This Fyre binary was compiled without gnet support.\n"
                    "Cluster support is not available.\n");
            exit(1);
            break;
#endif

        case 1000: /* --screensaver */
            mode = SCREENSAVER;
            break;

        case 1001: /* --hidden */
            hidden = TRUE;
            break;

        case 1002: /* --chdir */
            chdir(optarg);
            break;

        case 1003: /* --pidfile */
            pidfile = optarg;
            break;

        case 1004: /* --version */
            printf("%s\n", VERSION);
            return 0;

        case 'h':
        default:
            usage(argv);
            return 1;
        }
    }

    if (optind + 1 < argc) {
        usage(argv);
        return 1;
    }

    if (optind != argc) {
        char *ext = strrchr (argv[optind], '.');
        if (ext) {
            if (g_strcasecmp(ext, ".png") == 0) {
                histogram_imager_load_image_file(HISTOGRAM_IMAGER(map), argv[optind], &error);
            } else if (g_strcasecmp(ext, ".fa") == 0) {
                GtkTreeIter iter;

                animation_load_file(animation, argv[optind]);
                animate = TRUE;
                gtk_tree_model_get_iter_first(GTK_TREE_MODEL(animation->model), &iter);
                animation_keyframe_load(animation, &iter, PARAMETER_HOLDER(map));
            } else {
                usage(argv);
                return 1;
            }
        } else {
            usage(argv);
            return 1;
        }
    }

    switch (mode) {

    case INTERACTIVE: {
        Explorer *explorer;

        if (!have_gtk) {
            fprintf(stderr, "GTK intiailization failed, can't start in interactive mode\n");
            return 1;
        }
        explorer = explorer_new (map, animation);
        if (error) {
            GtkWidget *dialog, *label;
            gchar *text;

            dialog = glade_xml_get_widget (explorer->xml, "error dialog");
            label = glade_xml_get_widget (explorer->xml, "error label");

            text = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">Error!</span>\n\n%s", error->message);
            gtk_label_set_markup (GTK_LABEL (label), text);
            g_free (text);
            g_error_free (error);

            gtk_dialog_run (GTK_DIALOG (dialog));
            gtk_widget_hide (dialog);
        }
        gtk_main();
        break;
    }

    case RENDER: {
        acquire_console();
        if (error) {
            g_print ("Error: %s\n", error->message);
            g_error_free (error);
        }
        if (animate)
            animation_render_main (map, animation, outputFile, quality);
        else
            batch_image_render (map, outputFile, quality);
        break;
    }

    case REMOTE: {
#ifdef HAVE_GNET
        if (verbose) {
            acquire_console();
        }
        else {
            daemonize_to_pidfile(pidfile);
        }
        if (!hidden)
            discovery_server_new(FYRE_DEFAULT_SERVICE, port_number);
        remote_server_main_loop(port_number, have_gtk, verbose);
#else
        fprintf(stderr,
                "This Fyre binary was compiled without gnet support.\n"
                "Remote control mode is not available.\n");
#endif
        break;
    }

    case SCREENSAVER: {
        ScreenSaver* screensaver;
        GtkWidget* window;

        if (!have_gtk) {
            fprintf(stderr, "GTK intiailization failed, can't start in screensaver mode\n");
            return 1;
        }

        screensaver = screensaver_new(map, animation);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        fyre_set_icon_later(window);
        gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
        gtk_window_set_title(GTK_WINDOW(window), "Fyre Screensaver");
        gtk_container_add(GTK_CONTAINER(window), screensaver->view);
        gtk_widget_show_all(window);

        gtk_main();
        break;
    }
    }

    return 0;
}
Example #12
0
static void         history_node_apply (HistoryNode* self, HistogramImager* map)
{
    parameter_holder_load_string(PARAMETER_HOLDER(map), self->params);
}