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; }
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); }
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; }
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", >K_WIDGET(widget)->style->fg[state], "bgcolor-gdk", >K_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); }