GdkPixbuf*
histogram_imager_make_thumbnail (HistogramImager *self, guint max_width, guint max_height)
{
    float aspect = ((float)self->width) / ((float)self->height);
    guint width, height;
    GdkPixbuf *thumb;

    /* Make sure the histogram is up to date */
    histogram_imager_update_image (self);

    /* Scale it down aspect-correctly */
    if (aspect > 1) {
	width = max_width;
	height = width / aspect;
    }
    else {
	height = max_height;
	width = height * aspect;
    }
    width = MAX(width, 5);
    height = MAX(height, 5);
    thumb = gdk_pixbuf_scale_simple (self->image, width, height, GDK_INTERP_BILINEAR);

    /* Do an in-place composite of a checkerboard behind this image, to make alpha visible */
    image_add_checkerboard(thumb);

    /* If the image is particularly small, enhance its visibility */
    if (width < 128 || height < 128)
	image_adjust_levels(thumb);

    /* Put a standard frame around it */
    image_add_thumbnail_frame(thumb);

    return thumb;
}
示例#2
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);
}
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);
}
示例#4
0
static int animation_render_ui_idle_handler(gpointer user_data) {
    AnimationRenderUi *self = (AnimationRenderUi*) user_data;
    gdouble frame_completion, anim_completion;

    animation_render_ui_run_timed_calculation(self);

    /* Figure out how complete this frame is */
    frame_completion = histogram_imager_compute_quality(HISTOGRAM_IMAGER(self->map)) / self->quality;
    if (frame_completion >= 1) {
	frame_completion = 1;

	/* Write out this frame */
	histogram_imager_update_image(HISTOGRAM_IMAGER(self->map));
	avi_writer_append_frame(self->avi, HISTOGRAM_IMAGER(self->map)->image);

	/* Show the completed frame in our GUI's preview area */
	gtk_image_set_from_pixbuf(GTK_IMAGE(glade_xml_get_widget(self->xml, "preview")),
				  HISTOGRAM_IMAGER(self->map)->image);
	gtk_widget_show(glade_xml_get_widget(self->xml, "preview_frame"));

	/* Move to the next frame */
	if (animation_iter_read_frame(self->animation, &self->iter, &self->frame, self->frame_rate)) {

	    /* We still have more to render, calculate how much we've done so far */
	    self->continuation = FALSE;
	    self->elapsed_anim_time += 1/self->frame_rate;
	    anim_completion = self->elapsed_anim_time / self->anim_length;
	}
	else {
	    /* We're done, yay. Clean up. */
	    anim_completion = 1;
	    animation_render_ui_stop(self);
	}

	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(glade_xml_get_widget(self->xml, "animation_progress")), anim_completion);
    }
    else {
	/* Continue this frame later */
	self->continuation = TRUE;
    }

    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(glade_xml_get_widget(self->xml, "frame_progress")), frame_completion);
    return 1;
}
示例#5
0
static void cell_renderer_bifurcation_render(GtkCellRenderer      *cell,
					     GdkWindow            *window,
					     GtkWidget            *widget,
					     GdkRectangle         *background_area,
					     GdkRectangle         *cell_area,
					     GdkRectangle         *expose_area,
					     GtkCellRendererState  flags) {
    CellRendererBifurcation *self = CELL_RENDERER_BIFURCATION(cell);
    BifurcationDiagram *bd = get_bifurcation_diagram(self);
    GtkStateType state;
    RedrawInfo *nr;

    if (!bd)
	return;

    /* Determine the correct state to render our text in, based on
     * the cell's selectedness and the widget's current state.
     * This was copied from GtkCellRendererText.
     */
    if ((flags & GTK_CELL_RENDERER_SELECTED) == GTK_CELL_RENDERER_SELECTED) {
	if (GTK_WIDGET_HAS_FOCUS (widget))
	    state = GTK_STATE_SELECTED;
	else
	    state = GTK_STATE_ACTIVE;
    }
    else {
	if (GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE)
	    state = GTK_STATE_INSENSITIVE;
	else
	    state = GTK_STATE_NORMAL;
    }

    /* Set the bifurcation diagram renderer's parameters appropriately for this
     * cell renderer. It will automatically figure out what if anything it has
     * to change internally. We size it to fit this cell exactly, and set
     * the colors appropriately for our state and theme.
     */
    g_object_set(bd,
		 "width",  cell_area->width,
		 "height", cell_area->height,
		 "fgcolor-gdk", &GTK_WIDGET(widget)->style->fg[state],
		 "bgcolor-gdk", &GTK_WIDGET(widget)->style->base[state],
		 NULL);

    /* Assume that 5*(cell area) is good enough) */
    if(HISTOGRAM_IMAGER(bd)->total_points_plotted > 5 * cell_area->width * cell_area->height) {
        gdk_draw_pixbuf(window, GTK_WIDGET(widget)->style->fg_gc[state],
		        HISTOGRAM_IMAGER(bd)->image,
		        0, 0, cell_area->x, cell_area->y, cell_area->width, cell_area->height,
		        GDK_RGB_DITHER_NONE, 0, 0);

        return;
    }

    /* Render it a bit and update the image */
    bifurcation_diagram_calculate(bd, 10000, 100);
    histogram_imager_update_image(HISTOGRAM_IMAGER(bd));

    gdk_draw_pixbuf(window, GTK_WIDGET(widget)->style->fg_gc[state],
		    HISTOGRAM_IMAGER(bd)->image,
		    0, 0, cell_area->x, cell_area->y, cell_area->width, cell_area->height,
		    GDK_RGB_DITHER_NONE, 0, 0);

    nr = g_new (RedrawInfo, 1);
    nr->view = self->tree;
    nr->rect.x = cell_area->x;
    nr->rect.y = cell_area->y;
    nr->rect.width = cell_area->width;
    nr->rect.height = cell_area->height;

    g_timeout_add (20, (GSourceFunc) cell_queue_redraw, nr);
}