stat.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003   stat.c
00004   an heraia plugin to calculate some stats on the opened file
00005  
00006   (C) Copyright 2007 - 2009 Olivier Delhomme
00007   e-mail : heraia@delhomme.org
00008   URL    : http://heraia.tuxfamily.org
00009  
00010   This program is free software; you can redistribute it and/or modify
00011   it under the terms of the GNU General Public License as published by
00012   the Free Software Foundation; either version 2, or  (at your option) 
00013   any later version.
00014  
00015   This program is distributed in the hope that it will be useful,
00016   but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017   MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018   GNU General Public License for more details.
00019  
00020   You should have received a copy of the GNU General Public License
00021   along with this program; if not, write to the Free Software
00022   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
00023 */
00024 /**
00025  * @file stat.c
00026  * does some basic statistics on the file and displays them
00027  * in a numerical or graphical way (histograms : 1D and 2D)
00028  */
00029 #include "stat.h"
00030 
00031 /* The functions for the plugin's usage */
00032 static void stat_window_connect_signals(heraia_plugin_t *plugin);
00033 static void statw_close_clicked(GtkWidget *widget, gpointer data);
00034 static void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data);
00035 static void statw_save_as_clicked(GtkWidget *widget, gpointer data);
00036 static gchar *stat_select_file_to_save(void);
00037 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data);
00038 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data );
00039 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00040 static void init_stats_histos(heraia_plugin_t *plugin);
00041 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00042 static void calc_infos_histo_1D(stat_t *extra);
00043 static void calc_infos_histo_2D(stat_t *extra);
00044 static void init_stats_pixbufs(stat_t *extra);
00045 static void make_pixbufs_from_histos(stat_t *extra);
00046 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha);
00047 static void do_pixbuf_1D_from_histo1D(stat_t *extra);
00048 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D);
00049 
00050 
00051 /**
00052  *  @fn heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00053  *  Initialisation plugin function called when the plugin is loaded
00054  *  (some sort of pre-init)
00055  *  @param[in,out] plugin : plugin's structure
00056  *  @return returns the plugin structure
00057  */
00058 heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00059 {
00060         stat_t *extra = NULL;  /**< extra structure specific to this plugin */
00061         window_prop_t *stat_prop = NULL; /**< window properties */
00062 
00063         plugin->state             = PLUGIN_STATE_INITIALIZING;
00064         plugin->xml = NULL;
00065 
00066         plugin->info->api_version = API_VERSION;
00067         plugin->info->type        = PLUGIN_TYPE;
00068         plugin->info->priority    = HERAIA_PRIORITY_DEFAULT;
00069         plugin->info->name        = PLUGIN_NAME;
00070         plugin->info->version     = PLUGIN_VERSION;
00071         plugin->info->summary     = PLUGIN_SUMMARY;
00072         plugin->info->description = PLUGIN_DESCRIPTION;
00073         plugin->info->author      = PLUGIN_AUTHOR;
00074         plugin->info->homepage    = PLUGIN_HOMEPAGE;
00075 
00076         plugin->init_proc    = init;
00077         plugin->quit_proc    = quit;
00078         plugin->run_proc     = run;
00079         plugin->refresh_proc = refresh;
00080 
00081         plugin->filter->extensions = NULL;
00082         plugin->filter->import     = NULL;
00083         plugin->filter->export     = NULL;
00084 
00085         /* add the extra struct to the plugin one */
00086         extra = (stat_t *) g_malloc0 (sizeof(stat_t));
00087         extra->infos_1D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00088         extra->infos_2D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00089 
00090         /* window properties */
00091         stat_prop = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00092         stat_prop->displayed = FALSE; /* by default, it might be anything else */
00093         stat_prop->x = 0;
00094         stat_prop->y = 0;
00095         
00096         plugin->win_prop = stat_prop;
00097         
00098         plugin->extra = extra;
00099         
00100 
00101         return plugin;
00102 }
00103 
00104 /* the plugin interface functions */
00105 
00106 
00107 /**
00108  * @fn init(heraia_window_t *main_struct)
00109  *  The real init function of the plugin (called at init time)
00110  * @param main_struct : main structure
00111  */
00112 void init(heraia_window_t *main_struct)
00113 {
00114         heraia_plugin_t *plugin = NULL;
00115 
00116         log_message(main_struct, G_LOG_LEVEL_INFO, "Initializing plugin %s", PLUGIN_NAME);
00117         /* first, know who we are ! */
00118         plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00119         
00120         if (plugin != NULL)
00121                 {
00122                         /* load the xml interface */
00123                         log_message(main_struct, G_LOG_LEVEL_INFO, "Plugin from %s found !", plugin->info->author);
00124                         if (load_plugin_glade_xml(main_struct, plugin) == TRUE)
00125                         {
00126                                 log_message(main_struct, G_LOG_LEVEL_INFO, "%s xml interface loaded.", plugin->info->name);
00127                         }
00128                         else
00129                         {
00130                                 log_message(main_struct, G_LOG_LEVEL_WARNING, "Unable to load %s xml interface.", plugin->info->name);
00131                         }
00132                         
00133                         /* shows or hide the interface (hides it at first as all windows shows up) */
00134                         if (plugin->win_prop->displayed == FALSE)
00135                         {
00136                                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")));
00137                         }
00138                         else
00139                         {
00140                                 gtk_check_menu_item_set_active(plugin->cmi_entry, TRUE);
00141                         }
00142 
00143                         /* connect some signals handlers */
00144                         stat_window_connect_signals(plugin);
00145 
00146                 }
00147 }
00148 
00149 
00150 /**  
00151  * @fn void quit(void)
00152  *  Normaly this is called when the plugin is unloaded
00153  *  One may wait it's entire life for this to be called !! ;)
00154  */ 
00155 void quit(void)
00156 {
00157         g_print("Quitting %s\n", PLUGIN_NAME);
00158 }
00159 
00160 
00161 /**
00162  * @fn run(GtkWidget *widget, gpointer data)
00163  *  This function is called via a signal handler when the menu entry is toggled
00164  * @param widget : widget which called the function (unused)
00165  * @param data : user data for the plugin, here MUST be heraia_window_t * main 
00166  *        structure
00167  */
00168 void run(GtkWidget *widget, gpointer data)
00169 {
00170         heraia_window_t *main_struct = (heraia_window_t *) data; /* the signal send the pointer to this structure */
00171         heraia_plugin_t *plugin = NULL;
00172 
00173         /* first, know who we are ! */
00174         plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00175         
00176         if (plugin != NULL)
00177                 {
00178                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00179                                                          gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00180                         if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00181                                 {
00182                                         plugin->state = PLUGIN_STATE_RUNNING;
00183                                         realize_some_numerical_stat(main_struct, plugin);
00184                                 }
00185                         else
00186                                 plugin->state = PLUGIN_STATE_NONE;
00187                 }
00188 
00189 }
00190 
00191 
00192 /**
00193  * @fn void refresh(heraia_window_t *main_struct, void *data)
00194  *  The refresh function Called when a new file is loaded or when the cursor is moved
00195  *  Here we want to refresh the plugin only if a new file is loaded AND if the plugin
00196  *  is already displayed (running)
00197  * @param main_struct : main structure
00198  * @param data : user data (the plugin itself) MUST be heraia_plugin_t *plugin
00199  *        structure
00200  */
00201 void refresh(heraia_window_t *main_struct, void *data)
00202 {
00203         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00204 
00205         if (main_struct != NULL && plugin != NULL)
00206                 {
00207                         if (main_struct->event == HERAIA_REFRESH_NEW_FILE && plugin->state == PLUGIN_STATE_RUNNING)
00208                                 {
00209                                         plugin->run_proc(NULL, (gpointer) main_struct);
00210                                 }
00211                 }
00212 }
00213 
00214 /* end of the plugin interface functions */
00215 
00216 /**
00217  *  Usefull functions for the stat plugin
00218  *  those may be included in an another .c source file ?!
00219  */
00220 
00221 /**
00222  * @fn gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00223  *  Closes stat window
00224  * @param widget : the widget which called this function
00225  * @param event : the event that issued the signal (unused here)
00226  * @param data : user data, MUST be heraia_plugin_t *plugin
00227  * @return resturns always FALSE (does not propagate the signal)
00228  */
00229 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00230 {
00231         statw_close_clicked(widget, data);
00232 
00233         return TRUE;
00234 }
00235 
00236 
00237 /**
00238  * @fn void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00239  *  Closes stat window
00240  * @param widget : the widget which called this function
00241  * @param event : the event that issued the signal (unused here)
00242  * @param data : user data, MUST be heraia_plugin_t *plugin
00243  */
00244 static void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00245 {
00246         statw_close_clicked(widget, data);
00247 }
00248 
00249 
00250 /**
00251  * @fn void statw_close_clicked(GtkWidget *widget, gpointer data)
00252  *  What to do when the window is closed
00253  * @param widget : the widget which called this function (unused here)
00254  * @param data : user data, MUST be heraia_plugin_t *plugin
00255  */
00256 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00257 {
00258         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00259 
00260         if (plugin != NULL)
00261                 {
00262                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00263                         gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00264                 }
00265 }
00266 
00267 
00268 /**
00269  * @fn void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00270  *  What to do when the save as button is clicked
00271  * @param widget : the widget which called this function (unused here)
00272  * @param data : user data, MUST be heraia_plugin_t *plugin
00273  */
00274 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00275 {
00276         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00277 
00278         if (plugin != NULL)
00279                 {
00280                         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00281                         GdkPixbuf *pixbuf = gtk_image_get_pixbuf(image);
00282                         gchar *filename = NULL;
00283                         GError **error = NULL;
00284 
00285                         filename = stat_select_file_to_save();
00286                         gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00287                         
00288                         if (filename != NULL)
00289                                 g_free(filename);
00290                 }
00291 }
00292 
00293 /**
00294  * @fn gchar *stat_select_file_to_save(void)
00295  *  Selecting the file filename where to save the file
00296  * @return returns the new filename where to save a file
00297  */
00298 static gchar *stat_select_file_to_save(void)
00299 {
00300         GtkFileSelection *file_selector = NULL;
00301         gint response_id = 0;
00302         gchar *filename;
00303 
00304         file_selector = GTK_FILE_SELECTION (gtk_file_selection_new ("Entrez le nom du fichier image"));
00305 
00306         /* for the moment we do not want to retrieve multiples selections */
00307         gtk_file_selection_set_select_multiple(file_selector, FALSE);
00308 
00309         response_id = gtk_dialog_run(GTK_DIALOG (file_selector));
00310 
00311         switch (response_id) 
00312                 {
00313                 case GTK_RESPONSE_OK:
00314                         filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
00315                         break;
00316                 case GTK_RESPONSE_CANCEL:
00317                 default:
00318                         filename = NULL;
00319                         break;
00320                 }
00321 
00322         gtk_widget_destroy (GTK_WIDGET(file_selector));
00323 
00324         return filename;
00325 }
00326 
00327 
00328 /**
00329  * @fn void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00330  *  What to do when the user chooses a 1D or 2D histo 
00331  * @param widget : the widget which called this function (unused here)
00332  * @param data : user data, MUST be heraia_plugin_t *plugin
00333  */
00334 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00335 {
00336         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00337         
00338         if (plugin != NULL)
00339                 {
00340                         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00341                         stat_t *extra = (stat_t *) plugin->extra;
00342 
00343                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00344                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00345                         else
00346                                 {
00347                                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00348                                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00349                                 }
00350                 }
00351 }
00352 
00353 
00354 /**
00355  * @fn void stat_window_connect_signals(heraia_plugin_t *plugin)
00356  *  Connects all the signals to the correct functions
00357  * @param plugin : main plugin structure
00358  */
00359 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00360 {
00361 
00362         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event", 
00363                                          G_CALLBACK(delete_stat_window_event), plugin);
00364 
00365         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy", 
00366                                          G_CALLBACK(destroy_stat_window), plugin);
00367         
00368         /* Close Button */
00369         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked", 
00370                                          G_CALLBACK(statw_close_clicked), plugin);
00371         
00372         /* RadioButton */
00373         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled", 
00374                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00375 
00376         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled", 
00377                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00378 
00379         /* Save As Button */
00380         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked", 
00381                                          G_CALLBACK(statw_save_as_clicked), plugin);
00382 
00383 
00384         /* the toogle button is already connected to the run_proc function ! */
00385 }
00386 
00387 
00388 /**
00389  * @fn void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00390  *  Do some stats on the selected file (entire file is used)
00391  * @param main_struct : main structure from heraia
00392  * @param plugin : main plugin structure (the plugin itself in fact)
00393  */
00394 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00395 {
00396         struct stat *stat_buf;
00397         gchar buf[42];
00398         stat_t *extra = NULL;
00399         GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00400 
00401         if (main_struct->filename != NULL)
00402                 {
00403                         log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s", main_struct->filename);
00404 
00405                         stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00406                         lstat(main_struct->filename, stat_buf);
00407                         if (S_ISREG(stat_buf->st_mode))
00408                                 {
00409                                         kill_text_from_textview(textview);
00410                                         add_text_to_textview(textview, "File size : %Ld bytes\n\n", stat_buf->st_size);
00411                                         ctime_r(&(stat_buf->st_mtime), buf);
00412                                         add_text_to_textview(textview, "Last intern modification : %s", buf);
00413                                         ctime_r(&(stat_buf->st_atime), buf);
00414                                         add_text_to_textview(textview, "Last acces to the file   : %s", buf);
00415                                         ctime_r(&(stat_buf->st_ctime), buf);
00416                                         add_text_to_textview(textview, "Last extern modification : %s", buf);
00417                                         
00418                                         populate_stats_histos(main_struct, plugin);
00419 
00420                                         extra = (stat_t *) plugin->extra;
00421                                         
00422                                         add_text_to_textview(textview, "\n1D histogram statistics :\n");
00423                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_1D->min);
00424                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_1D->max);
00425                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_1D->mean);
00426                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_1D->nb_val);
00427                                         add_text_to_textview(textview, "\n2D histogram statistics :\n");
00428                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_2D->min);
00429                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_2D->max);
00430                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_2D->mean);
00431                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_2D->nb_val);
00432                                         log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00433                                 }               
00434                 }
00435 }
00436 
00437 
00438 /**
00439  *  Inits the histograms
00440  */
00441 static void init_stats_histos(heraia_plugin_t *plugin)
00442 {
00443         guint i = 0;
00444         guint j = 0;
00445         stat_t *extra = NULL;
00446 
00447         /* inits the structures */
00448         extra = (stat_t *) plugin->extra;
00449         for (i=0; i<=255; i++)
00450                 {
00451                         extra->histo1D[i] = 0 ;
00452                         for (j=0; j<=255; j++)
00453                                 extra->histo2D[i][j] = 0 ;
00454                 }
00455 }
00456 
00457 
00458 /**
00459  *  Populates the histograms
00460  */
00461 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00462 {
00463         GtkHex *gh = GTK_HEX(main_struct->current_DW->current_hexwidget);
00464         guint64 i = 0;
00465         guint64 taille = ghex_file_size(gh);
00466         guchar c1, c2;
00467         stat_t *extra = (stat_t *) plugin->extra;
00468         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00469         GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00470         GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00471 
00472         init_stats_histos(plugin);
00473 
00474         while (i < taille)
00475                 {
00476                         c1 = gtk_hex_get_byte(gh, i);
00477                         extra->histo1D[c1]++;
00478                         if (i+1 < taille)
00479                                 {
00480                                         i++;
00481                                         c2 = gtk_hex_get_byte(gh, i);
00482                                         extra->histo1D[c2]++;
00483                                         extra->histo2D[c1][c2]++;
00484                                 }
00485                         i++;
00486                 }
00487 
00488         make_pixbufs_from_histos(extra);
00489 
00490         if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00491                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00492         else
00493                 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00494                         gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00495 }
00496 
00497 
00498 /**
00499  *  Seeks the histo1D struct to find the maximum value 
00500  */
00501 static void calc_infos_histo_1D(stat_t *extra)
00502 {
00503         guint i = 0;
00504         gint64 n = 1;
00505         guint64 max = 0;
00506         guint64 min = G_MAXUINT64;
00507         gint64 mean = extra->histo1D[0];
00508         gint64 diff = 0;
00509 
00510         extra->infos_1D->nb_val = 0;
00511 
00512         for (i=0; i<=255; i++)
00513                 {
00514                         /* maximum value */
00515                         if (extra->histo1D[i] > max)
00516                                 max = extra->histo1D[i];
00517 
00518                         /* minimum value */
00519                         if (extra->histo1D[i] < min)
00520                                 min = extra->histo1D[i];
00521                         
00522                         /* number of different values */
00523                         if (extra->histo1D[i] > 0)
00524                                 extra->infos_1D->nb_val++;
00525 
00526                         /* mean calculation */
00527                         diff = extra->histo1D[i] - mean;
00528                         mean = mean + diff/n;
00529                         n++;
00530                 }
00531 
00532         extra->infos_1D->min = min;
00533         extra->infos_1D->max = max;
00534         extra->infos_1D->mean = (guint64) mean;
00535 }
00536 
00537 
00538 /**
00539  *  Seeks the histo2D struct to find the maximum value
00540  */
00541 static void calc_infos_histo_2D(stat_t *extra)
00542 {
00543         guint i = 0;
00544         guint j = 0;
00545         gint64 n = 1;
00546         guint64 max = 0;
00547         guint64 min = G_MAXUINT;
00548         gint64 mean = extra->histo2D[0][0];
00549         gint64 diff = 0;
00550 
00551         extra->infos_2D->nb_val = 0;
00552 
00553         for (i=0; i<=255; i++)
00554                 {
00555                         for (j=0; j<=255; j++)
00556                                 {
00557                                         /* maximum value */
00558                                         if (extra->histo2D[i][j] > max)
00559                                                 max = extra->histo2D[i][j];
00560 
00561                                         /* minimum value */
00562                                         if (extra->histo2D[i][j] < min)
00563                                                 min = extra->histo2D[i][j];
00564 
00565                                         /* number of different values */
00566                                         if (extra->histo2D[i][j] > 0)
00567                                                 extra->infos_2D->nb_val++;
00568 
00569                                         /* mean calculation */
00570                                         diff = extra->histo2D[i][j] - mean;
00571                                         mean = mean + diff/n;
00572                                         n++;
00573                                 }
00574                 }
00575         
00576         extra->infos_2D->min = min;
00577         extra->infos_2D->max = max;
00578         extra->infos_2D->mean = (guint64) mean;
00579 }
00580 
00581 
00582 /**
00583  *  Inits the image buffers
00584  */
00585 static void init_stats_pixbufs(stat_t *extra)
00586 {
00587  
00588         extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00589         gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00590         gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00591 
00592         extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00593         gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00594         gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00595 
00596 }
00597 
00598 
00599 /**
00600  *  Makes the pixbufs from the histograms values
00601  */
00602 static void make_pixbufs_from_histos(stat_t *extra)
00603 {
00604         init_stats_pixbufs(extra);
00605         calc_infos_histo_1D(extra);
00606         calc_infos_histo_2D(extra);
00607 
00608         if (extra->infos_1D->max > 0)
00609                 do_pixbuf_1D_from_histo1D(extra);
00610         if (extra->infos_2D->max > 0)
00611                 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00612 }
00613 
00614 
00615 /**
00616  *  Prints a pixel in the corresponding pixbuf
00617  */
00618 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00619 {
00620   guchar *pixels = NULL;
00621   guchar *p = NULL;
00622 
00623   pixels = gdk_pixbuf_get_pixels(pixbuf);
00624 
00625   p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00626 
00627   p[0] = red;
00628   p[1] = green;
00629   p[2] = blue;
00630   p[3] = alpha;
00631 
00632 }
00633 
00634 
00635 /**
00636  *  Prints a line of pixels in the corresponding pixbuf (1D histo)
00637  */
00638 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00639 {
00640         guchar *pixels = NULL;
00641         guchar *p = NULL;
00642 
00643         if (pixbuf != NULL)
00644                 {
00645 
00646                         gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00647                         gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00648                         
00649                         pixels = gdk_pixbuf_get_pixels(pixbuf);
00650         
00651                         while (y<255)
00652                                 {
00653                                         p = pixels + y * rowstride + x * n_channels;
00654                                         p[0] = (guchar) 255-(y/2);
00655                                         p[1] = (guchar) 16;
00656                                         p[2] = (guchar) y/2;
00657                                         p[3] = (guchar) 255;
00658                                         y++;
00659                                 }
00660                 }
00661 }
00662 
00663 
00664 /**
00665  *  Fills the pixbuf with the corresponding data from the
00666  *  histo1D struct
00667  */
00668 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00669 {
00670         guint i = 0;
00671         gint64 y = 0;
00672         gdouble inter = 0;
00673         gdouble y_norm = 0;
00674 
00675         for (i=0; i<=255; i++)
00676                 {       
00677                         /* normalisation (here we know that max != 0 (cf make_pixbufs_from_histos) */
00678                         y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00679                         inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00680                         y = (gint64) inter;     
00681                         line_in_pixbuf(extra->pixbuf_1D, i, y);
00682                 }
00683 }
00684 
00685 
00686 /**
00687  *  Fills the pixbuf with the corresponding data from the
00688  *  histo2D struct
00689  *  It is really hard to make something very visible (to make colors
00690  *  look really different between to height values)
00691  */
00692 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00693 {
00694         /* A sort of color 'normalization' */
00695         guint i = 0;
00696         guint j = 0;
00697         guchar red;
00698         guchar green;
00699         guchar blue;
00700         gdouble height = 0;
00701         gdouble max = 0;
00702         gdouble min = 0;
00703         gdouble mean = 0;
00704         gdouble threshold1 = 0;
00705         gdouble threshold2 = 0;
00706         guchar ceill;
00707         guchar floor;
00708 
00709         max = extra->infos_2D->max;
00710         min = extra->infos_2D->min;
00711         mean = extra->infos_2D->mean;
00712         
00713         threshold1 = min + (mean - min) / 2;
00714         threshold2 = mean + (max - mean) / 2;
00715         
00716         floor = (guchar) 50;
00717         ceill = (guchar) 200;
00718         
00719         for (i=0; i<=255; i++)
00720         {
00721                         for (j=0; j<=255; j++)
00722                         {
00723                                         height = extra->histo2D[i][j];  /* min .. max */
00724                                         
00725                                 if (height > 0)
00726                                 {
00727                                         
00728                                         if (height >= min && height <= threshold1)
00729                                         {
00730                                                 red = floor;
00731                                                 green = floor;
00732                                                 blue = (guchar) (height - min)*(ceill-floor) / threshold1;
00733                                                 /*
00734                                                  * height = (gdouble) (height*255) / (gdouble) extra->infos_2D->max;
00735                                                  * red = (guchar)  height;
00736                                                  * green = (guchar) 255 - (height);
00737                                                  * blue = (guchar) height/2;
00738                                                  */
00739                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00740                                         }
00741                                         else if (height > threshold1 && height <= threshold2)
00742                                         {
00743                                                 red = (guchar) floor;
00744                                                 green = (guchar) (height - threshold1)*(ceill-floor) / (threshold2 - threshold1);
00745                                                 blue = (guchar) floor; /* ceill - green;*/
00746                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00747                                         }
00748                                         else if (height > threshold2 && height <= max)
00749                                         {
00750                                                 red = (guchar) (height - threshold2)*(ceill-floor) / (max - threshold2);
00751                                                 green = floor; /* ceill - red; */
00752                                                 blue = floor;
00753                                                 /*
00754                                                  * height = (gdouble) height*255 / (gdouble) extra->infos_2D->max;
00755                                                  * red = (guchar)  255 - (height);
00756                                                  * green = (guchar) height/2;
00757                                                  * blue = (guchar) height;
00758                                                  */
00759                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00760                                         }
00761                                 }
00762                         }
00763         }
00764 }
00765 
00766 

Generated on Sat Feb 14 11:44:16 2009 for Heraia by  doxygen 1.5.6