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                         /* greyed save as button */
00134                         gtk_widget_set_sensitive(glade_xml_get_widget(plugin->xml, "statw_save_as"), FALSE);
00135                         
00136                         
00137                         /* shows or hide the interface (hides it at first as all windows shows up) */
00138                         if (plugin->win_prop->displayed == FALSE)
00139                         {
00140                                 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")));
00141                         }
00142                         else
00143                         {
00144                                 gtk_check_menu_item_set_active(plugin->cmi_entry, TRUE);
00145                         }
00146 
00147                         /* connect some signals handlers */
00148                         stat_window_connect_signals(plugin);
00149 
00150                 }
00151 }
00152 
00153 
00154 /**  
00155  * @fn void quit(void)
00156  *  Normaly this is called when the plugin is unloaded
00157  *  One may wait it's entire life for this to be called !! ;)
00158  */ 
00159 void quit(void)
00160 {
00161         g_print("Quitting %s\n", PLUGIN_NAME);
00162 }
00163 
00164 
00165 /**
00166  * @fn run(GtkWidget *widget, gpointer data)
00167  *  This function is called via a signal handler when the menu entry is toggled
00168  * @param widget : widget which called the function (unused)
00169  * @param data : user data for the plugin, here MUST be heraia_window_t * main 
00170  *        structure
00171  */
00172 void run(GtkWidget *widget, gpointer data)
00173 {
00174         heraia_window_t *main_struct = (heraia_window_t *) data; /* the signal send the pointer to this structure */
00175         heraia_plugin_t *plugin = NULL;
00176 
00177         /* first, know who we are ! */
00178         plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00179         
00180         if (plugin != NULL)
00181                 {
00182                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00183                                                          gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00184                         if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00185                                 {
00186                                         plugin->state = PLUGIN_STATE_RUNNING;
00187                                         realize_some_numerical_stat(main_struct, plugin);
00188                                 }
00189                         else
00190                                 plugin->state = PLUGIN_STATE_NONE;
00191                 }
00192 
00193 }
00194 
00195 
00196 /**
00197  * @fn void refresh(heraia_window_t *main_struct, void *data)
00198  *  The refresh function is called when a new file is loaded or when the cursor is moved
00199  *  Here we want to refresh the plugin only if a new file is loaded AND if the plugin
00200  *  is already displayed (running)
00201  * @param main_struct : main structure
00202  * @param data : user data (the plugin itself) MUST be heraia_plugin_t *plugin
00203  *        structure
00204  */
00205 void refresh(heraia_window_t *main_struct, void *data)
00206 {
00207         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00208 
00209         if (main_struct != NULL && plugin != NULL)
00210                 {
00211                         if (main_struct->event == HERAIA_REFRESH_NEW_FILE && plugin->state == PLUGIN_STATE_RUNNING)
00212                                 {
00213                                         gtk_widget_set_sensitive(glade_xml_get_widget(plugin->xml, "statw_save_as"), TRUE);
00214                                         plugin->run_proc(NULL, (gpointer) main_struct);
00215                                 }
00216                 }
00217 }
00218 
00219 /* end of the plugin interface functions */
00220 
00221 /**
00222  *  Usefull functions for the stat plugin
00223  *  those may be included in an another .c source file ?!
00224  */
00225 
00226 /**
00227  * @fn gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00228  *  Closes stat window
00229  * @param widget : the widget which called this function
00230  * @param event : the event that issued the signal (unused here)
00231  * @param data : user data, MUST be heraia_plugin_t *plugin
00232  * @return resturns always FALSE (does not propagate the signal)
00233  */
00234 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent  *event, gpointer data)
00235 {
00236         statw_close_clicked(widget, data);
00237 
00238         return TRUE;
00239 }
00240 
00241 
00242 /**
00243  * @fn void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00244  *  Closes stat window
00245  * @param widget : the widget which called this function
00246  * @param event : the event that issued the signal (unused here)
00247  * @param data : user data, MUST be heraia_plugin_t *plugin
00248  */
00249 static void destroy_stat_window(GtkWidget *widget, GdkEvent  *event, gpointer data)
00250 {
00251         statw_close_clicked(widget, data);
00252 }
00253 
00254 
00255 /**
00256  * @fn void statw_close_clicked(GtkWidget *widget, gpointer data)
00257  *  What to do when the window is closed
00258  * @param widget : the widget which called this function (unused here)
00259  * @param data : user data, MUST be heraia_plugin_t *plugin
00260  */
00261 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00262 {
00263         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00264 
00265         if (plugin != NULL)
00266                 {
00267                         show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00268                         gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00269                 }
00270 }
00271 
00272 
00273 /**
00274  * @fn void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00275  *  What to do when the save as button is clicked
00276  * @param widget : the widget which called this function (unused here)
00277  * @param data : user data, MUST be heraia_plugin_t *plugin
00278  */
00279 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00280 {
00281         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00282 
00283         if (plugin != NULL)
00284                 {
00285                         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00286                         GdkPixbuf *pixbuf = gtk_image_get_pixbuf(image);
00287                         gchar *filename = NULL;
00288                         GError **error = NULL;
00289 
00290                         filename = stat_select_file_to_save();
00291                         gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00292                         
00293                         if (filename != NULL)
00294                                 g_free(filename);
00295                 }
00296 }
00297 
00298 /**
00299  * @fn gchar *stat_select_file_to_save(void)
00300  *  Selecting the file filename where to save the file
00301  * @return returns the new filename where to save a file
00302  */
00303 static gchar *stat_select_file_to_save(void)
00304 {
00305         GtkFileSelection *file_selector = NULL;
00306         gint response_id = 0;
00307         gchar *filename;
00308 
00309         file_selector = GTK_FILE_SELECTION (gtk_file_selection_new ("Entrez le nom du fichier image"));
00310 
00311         /* for the moment we do not want to retrieve multiples selections */
00312         gtk_file_selection_set_select_multiple(file_selector, FALSE);
00313 
00314         response_id = gtk_dialog_run(GTK_DIALOG (file_selector));
00315 
00316         switch (response_id) 
00317                 {
00318                 case GTK_RESPONSE_OK:
00319                         filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
00320                         break;
00321                 case GTK_RESPONSE_CANCEL:
00322                 default:
00323                         filename = NULL;
00324                         break;
00325                 }
00326 
00327         gtk_widget_destroy (GTK_WIDGET(file_selector));
00328 
00329         return filename;
00330 }
00331 
00332 
00333 /**
00334  * @fn void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00335  *  What to do when the user chooses a 1D or 2D histo 
00336  * @param widget : the widget which called this function (unused here)
00337  * @param data : user data, MUST be heraia_plugin_t *plugin
00338  */
00339 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00340 {
00341         heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00342         
00343         if (plugin != NULL)
00344                 {
00345                         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00346                         stat_t *extra = (stat_t *) plugin->extra;
00347 
00348                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00349                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00350                         else
00351                                 {
00352                                         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00353                                                 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00354                                 }
00355                 }
00356 }
00357 
00358 
00359 /**
00360  * @fn void stat_window_connect_signals(heraia_plugin_t *plugin)
00361  *  Connects all the signals to the correct functions
00362  * @param plugin : main plugin structure
00363  */
00364 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00365 {
00366 
00367         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event", 
00368                                          G_CALLBACK(delete_stat_window_event), plugin);
00369 
00370         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy", 
00371                                          G_CALLBACK(destroy_stat_window), plugin);
00372         
00373         /* Close Button */
00374         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked", 
00375                                          G_CALLBACK(statw_close_clicked), plugin);
00376         
00377         /* RadioButton */
00378         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled", 
00379                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00380 
00381         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled", 
00382                                          G_CALLBACK(histo_radiobutton_toggled), plugin);
00383 
00384         /* Save As Button */
00385         g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked", 
00386                                          G_CALLBACK(statw_save_as_clicked), plugin);
00387 
00388 
00389         /* the toogle button is already connected to the run_proc function ! */
00390 }
00391 
00392 
00393 /**
00394  * @fn void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00395  *  Do some stats on the selected file (entire file is used)
00396  * @param main_struct : main structure from heraia
00397  * @param plugin : main plugin structure (the plugin itself in fact)
00398  */
00399 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00400 {
00401         struct stat *stat_buf;
00402         gchar buf[42];
00403         stat_t *extra = NULL;
00404         GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00405 
00406         if (main_struct->filename != NULL)
00407                 {
00408                         log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s", main_struct->filename);
00409 
00410                         stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00411                         lstat(main_struct->filename, stat_buf);
00412                         if (S_ISREG(stat_buf->st_mode))
00413                                 {
00414                                         kill_text_from_textview(textview);
00415                                         add_text_to_textview(textview, "File size : %Ld bytes\n\n", stat_buf->st_size);
00416                                         ctime_r(&(stat_buf->st_mtime), buf);
00417                                         add_text_to_textview(textview, "Last intern modification : %s", buf);
00418                                         ctime_r(&(stat_buf->st_atime), buf);
00419                                         add_text_to_textview(textview, "Last acces to the file   : %s", buf);
00420                                         ctime_r(&(stat_buf->st_ctime), buf);
00421                                         add_text_to_textview(textview, "Last extern modification : %s", buf);
00422                                         
00423                                         populate_stats_histos(main_struct, plugin);
00424 
00425                                         extra = (stat_t *) plugin->extra;
00426                                         
00427                                         add_text_to_textview(textview, "\n1D histogram statistics :\n");
00428                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_1D->min);
00429                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_1D->max);
00430                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_1D->mean);
00431                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_1D->nb_val);
00432                                         add_text_to_textview(textview, "\n2D histogram statistics :\n");
00433                                         add_text_to_textview(textview, "     . minimum          : %lld\n", extra->infos_2D->min);
00434                                         add_text_to_textview(textview, "     . maximum          : %lld\n", extra->infos_2D->max);
00435                                         add_text_to_textview(textview, "     . mean             : %lld\n", extra->infos_2D->mean);
00436                                         add_text_to_textview(textview, "     . number of values : %lld\n", extra->infos_2D->nb_val);
00437                                         log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00438                                 }               
00439                 }
00440 }
00441 
00442 
00443 /**
00444  *  Inits the histograms
00445  */
00446 static void init_stats_histos(heraia_plugin_t *plugin)
00447 {
00448         guint i = 0;
00449         guint j = 0;
00450         stat_t *extra = NULL;
00451 
00452         /* inits the structures */
00453         extra = (stat_t *) plugin->extra;
00454         for (i=0; i<=255; i++)
00455                 {
00456                         extra->histo1D[i] = 0 ;
00457                         for (j=0; j<=255; j++)
00458                                 extra->histo2D[i][j] = 0 ;
00459                 }
00460 }
00461 
00462 
00463 /**
00464  *  Populates the histograms
00465  */
00466 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00467 {
00468         GtkHex *gh = GTK_HEX(main_struct->current_DW->current_hexwidget);
00469         guint64 i = 0;
00470         guint64 taille = ghex_file_size(gh);
00471         guchar c1, c2;
00472         stat_t *extra = (stat_t *) plugin->extra;
00473         GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00474         GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00475         GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00476 
00477         init_stats_histos(plugin);
00478 
00479         while (i < taille)
00480                 {
00481                         c1 = gtk_hex_get_byte(gh, i);
00482                         extra->histo1D[c1]++;
00483                         if (i+1 < taille)
00484                                 {
00485                                         i++;
00486                                         c2 = gtk_hex_get_byte(gh, i);
00487                                         extra->histo1D[c2]++;
00488                                         extra->histo2D[c1][c2]++;
00489                                 }
00490                         i++;
00491                 }
00492 
00493         make_pixbufs_from_histos(extra);
00494 
00495         if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00496                 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00497         else
00498                 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00499                         gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00500 }
00501 
00502 
00503 /**
00504  *  Seeks the histo1D struct to find the maximum value 
00505  */
00506 static void calc_infos_histo_1D(stat_t *extra)
00507 {
00508         guint i = 0;
00509         gint64 n = 1;
00510         guint64 max = 0;
00511         guint64 min = G_MAXUINT64;
00512         gint64 mean = extra->histo1D[0];
00513         gint64 diff = 0;
00514 
00515         extra->infos_1D->nb_val = 0;
00516 
00517         for (i=0; i<=255; i++)
00518                 {
00519                         /* maximum value */
00520                         if (extra->histo1D[i] > max)
00521                                 max = extra->histo1D[i];
00522 
00523                         /* minimum value */
00524                         if (extra->histo1D[i] < min)
00525                                 min = extra->histo1D[i];
00526                         
00527                         /* number of different values */
00528                         if (extra->histo1D[i] > 0)
00529                                 extra->infos_1D->nb_val++;
00530 
00531                         /* mean calculation */
00532                         diff = extra->histo1D[i] - mean;
00533                         mean = mean + diff/n;
00534                         n++;
00535                 }
00536 
00537         extra->infos_1D->min = min;
00538         extra->infos_1D->max = max;
00539         extra->infos_1D->mean = (guint64) mean;
00540 }
00541 
00542 
00543 /**
00544  *  Seeks the histo2D struct to find the maximum value
00545  */
00546 static void calc_infos_histo_2D(stat_t *extra)
00547 {
00548         guint i = 0;
00549         guint j = 0;
00550         gint64 n = 1;
00551         guint64 max = 0;
00552         guint64 min = G_MAXUINT;
00553         gint64 mean = extra->histo2D[0][0];
00554         gint64 diff = 0;
00555 
00556         extra->infos_2D->nb_val = 0;
00557 
00558         for (i=0; i<=255; i++)
00559                 {
00560                         for (j=0; j<=255; j++)
00561                                 {
00562                                         /* maximum value */
00563                                         if (extra->histo2D[i][j] > max)
00564                                                 max = extra->histo2D[i][j];
00565 
00566                                         /* minimum value */
00567                                         if (extra->histo2D[i][j] < min)
00568                                                 min = extra->histo2D[i][j];
00569 
00570                                         /* number of different values */
00571                                         if (extra->histo2D[i][j] > 0)
00572                                                 extra->infos_2D->nb_val++;
00573 
00574                                         /* mean calculation */
00575                                         diff = extra->histo2D[i][j] - mean;
00576                                         mean = mean + diff/n;
00577                                         n++;
00578                                 }
00579                 }
00580         
00581         extra->infos_2D->min = min;
00582         extra->infos_2D->max = max;
00583         extra->infos_2D->mean = (guint64) mean;
00584 }
00585 
00586 
00587 /**
00588  *  Inits the image buffers
00589  */
00590 static void init_stats_pixbufs(stat_t *extra)
00591 {
00592  
00593         extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00594         gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00595         gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00596 
00597         extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00598         gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00599         gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00600 
00601 }
00602 
00603 
00604 /**
00605  *  Makes the pixbufs from the histograms values
00606  */
00607 static void make_pixbufs_from_histos(stat_t *extra)
00608 {
00609         init_stats_pixbufs(extra);
00610         calc_infos_histo_1D(extra);
00611         calc_infos_histo_2D(extra);
00612 
00613         if (extra->infos_1D->max > 0)
00614                 do_pixbuf_1D_from_histo1D(extra);
00615         if (extra->infos_2D->max > 0)
00616                 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00617 }
00618 
00619 
00620 /**
00621  *  Prints a pixel in the corresponding pixbuf
00622  */
00623 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00624 {
00625   guchar *pixels = NULL;
00626   guchar *p = NULL;
00627 
00628   pixels = gdk_pixbuf_get_pixels(pixbuf);
00629 
00630   p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00631 
00632   p[0] = red;
00633   p[1] = green;
00634   p[2] = blue;
00635   p[3] = alpha;
00636 
00637 }
00638 
00639 
00640 /**
00641  *  Prints a line of pixels in the corresponding pixbuf (1D histo)
00642  */
00643 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00644 {
00645         guchar *pixels = NULL;
00646         guchar *p = NULL;
00647 
00648         if (pixbuf != NULL)
00649                 {
00650 
00651                         gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00652                         gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00653                         
00654                         pixels = gdk_pixbuf_get_pixels(pixbuf);
00655         
00656                         while (y<255)
00657                                 {
00658                                         p = pixels + y * rowstride + x * n_channels;
00659                                         p[0] = (guchar) 255-(y/2);
00660                                         p[1] = (guchar) 16;
00661                                         p[2] = (guchar) y/2;
00662                                         p[3] = (guchar) 255;
00663                                         y++;
00664                                 }
00665                 }
00666 }
00667 
00668 
00669 /**
00670  *  Fills the pixbuf with the corresponding data from the
00671  *  histo1D struct
00672  */
00673 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00674 {
00675         guint i = 0;
00676         gint64 y = 0;
00677         gdouble inter = 0;
00678         gdouble y_norm = 0;
00679 
00680         for (i=0; i<=255; i++)
00681                 {       
00682                         /* normalisation (here we know that max != 0 (cf make_pixbufs_from_histos) */
00683                         y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00684                         inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00685                         y = (gint64) inter;     
00686                         line_in_pixbuf(extra->pixbuf_1D, i, y);
00687                 }
00688 }
00689 
00690 
00691 /**
00692  *  Fills the pixbuf with the corresponding data from the
00693  *  histo2D struct
00694  *  It is really hard to make something very visible (to make colors
00695  *  look really different between to height values)
00696  */
00697 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00698 {
00699         /* A sort of color 'normalization' */
00700         guint i = 0;
00701         guint j = 0;
00702         guchar red;
00703         guchar green;
00704         guchar blue;
00705         gdouble height = 0;
00706         gdouble max = 0;
00707         gdouble min = 0;
00708         gdouble mean = 0;
00709         gdouble threshold1 = 0;
00710         gdouble threshold2 = 0;
00711         guchar ceill;
00712         guchar floor;
00713 
00714         max = extra->infos_2D->max;
00715         min = extra->infos_2D->min;
00716         mean = extra->infos_2D->mean;
00717         
00718         threshold1 = min + (mean - min) / 2;
00719         threshold2 = mean + (max - mean) / 2;
00720         
00721         floor = (guchar) 50;
00722         ceill = (guchar) 200;
00723         
00724         for (i=0; i<=255; i++)
00725         {
00726                         for (j=0; j<=255; j++)
00727                         {
00728                                         height = extra->histo2D[i][j];  /* min .. max */
00729                                         
00730                                 if (height > 0)
00731                                 {
00732                                         
00733                                         if (height >= min && height <= threshold1)
00734                                         {
00735                                                 red = floor;
00736                                                 green = floor;
00737                                                 blue = (guchar) (height - min)*(ceill-floor) / threshold1;
00738                                                 /*
00739                                                  * height = (gdouble) (height*255) / (gdouble) extra->infos_2D->max;
00740                                                  * red = (guchar)  height;
00741                                                  * green = (guchar) 255 - (height);
00742                                                  * blue = (guchar) height/2;
00743                                                  */
00744                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00745                                         }
00746                                         else if (height > threshold1 && height <= threshold2)
00747                                         {
00748                                                 red = (guchar) floor;
00749                                                 green = (guchar) (height - threshold1)*(ceill-floor) / (threshold2 - threshold1);
00750                                                 blue = (guchar) floor; /* ceill - green;*/
00751                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00752                                         }
00753                                         else if (height > threshold2 && height <= max)
00754                                         {
00755                                                 red = (guchar) (height - threshold2)*(ceill-floor) / (max - threshold2);
00756                                                 green = floor; /* ceill - red; */
00757                                                 blue = floor;
00758                                                 /*
00759                                                  * height = (gdouble) height*255 / (gdouble) extra->infos_2D->max;
00760                                                  * red = (guchar)  255 - (height);
00761                                                  * green = (guchar) height/2;
00762                                                  * blue = (guchar) height;
00763                                                  */
00764                                                 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00765                                         }
00766                                 }
00767                         }
00768         }
00769 }
00770 
00771 

Generated on Sat Mar 14 13:44:29 2009 for Heraia by  doxygen 1.5.6