00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stat.h"
00026
00027
00028 static void stat_window_connect_signals(heraia_plugin_t *plugin);
00029 static void statw_close_clicked(GtkWidget *widget, gpointer data);
00030 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data);
00031 static void statw_save_as_clicked(GtkWidget *widget, gpointer data);
00032 static gchar *stat_select_file_to_save(void);
00033 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data);
00034 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data );
00035 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00036 static void init_stats_histos(heraia_plugin_t *plugin);
00037 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00038 static void calc_infos_histo_1D(stat_t *extra);
00039 static void calc_infos_histo_2D(stat_t *extra);
00040 static void init_stats_pixbufs(stat_t *extra);
00041 static void make_pixbufs_from_histos(stat_t *extra);
00042 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha);
00043 static void do_pixbuf_1D_from_histo1D(stat_t *extra);
00044 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D);
00045
00046
00050 heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00051 {
00052 stat_t *extra = NULL;
00053 window_prop_t *stat_prop = NULL;
00054
00055 plugin->state = PLUGIN_STATE_INITIALIZING;
00056 plugin->xml = NULL;
00057
00058 plugin->info->api_version = API_VERSION;
00059 plugin->info->type = PLUGIN_TYPE;
00060 plugin->info->priority = HERAIA_PRIORITY_DEFAULT;
00061 plugin->info->name = PLUGIN_NAME;
00062 plugin->info->version = PLUGIN_VERSION;
00063 plugin->info->summary = PLUGIN_SUMMARY;
00064 plugin->info->description = PLUGIN_DESCRIPTION;
00065 plugin->info->author = PLUGIN_AUTHOR;
00066 plugin->info->homepage = PLUGIN_HOMEPAGE;
00067
00068 plugin->init_proc = init;
00069 plugin->quit_proc = quit;
00070 plugin->run_proc = run;
00071 plugin->refresh_proc = refresh;
00072
00073 plugin->filter->extensions = NULL;
00074 plugin->filter->import = NULL;
00075 plugin->filter->export = NULL;
00076
00077
00078 extra = (stat_t *) g_malloc0 (sizeof(stat_t));
00079 extra->infos_1D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00080 extra->infos_2D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00081
00082
00083 stat_prop = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00084 stat_prop->displayed = FALSE;
00085 stat_prop->x = 0;
00086 stat_prop->y = 0;
00087
00088 plugin->win_prop = stat_prop;
00089
00090 plugin->extra = extra;
00091
00092
00093 return plugin;
00094 }
00095
00096
00097
00098
00102 void init(heraia_window_t *main_struct)
00103 {
00104 heraia_plugin_t *plugin = NULL;
00105
00106 log_message(main_struct, G_LOG_LEVEL_INFO, "Initializing plugin %s", PLUGIN_NAME);
00107
00108 plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00109
00110 if (plugin != NULL)
00111 {
00112
00113 log_message(main_struct, G_LOG_LEVEL_INFO, "Plugin from %s found !", plugin->info->author);
00114 if (load_plugin_glade_xml(main_struct, plugin) == TRUE)
00115 {
00116 log_message(main_struct, G_LOG_LEVEL_INFO, "%s xml interface loaded.", plugin->info->name);
00117 }
00118 else
00119 {
00120 log_message(main_struct, G_LOG_LEVEL_WARNING, "Unable to load %s xml interface.", plugin->info->name);
00121 }
00122
00123
00124 if (plugin->win_prop->displayed == FALSE)
00125 {
00126 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")));
00127 }
00128 else
00129 {
00130 gtk_check_menu_item_set_active(plugin->cmi_entry, TRUE);
00131 }
00132
00133
00134 stat_window_connect_signals(plugin);
00135
00136 }
00137 }
00138
00139
00144 void quit(void)
00145 {
00146 g_print("Quitting %s\n", PLUGIN_NAME);
00147 }
00148
00149
00153 void run(GtkWidget *widget, gpointer data)
00154 {
00155 heraia_window_t *main_struct = (heraia_window_t *) data;
00156 heraia_plugin_t *plugin = NULL;
00157
00158
00159 plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00160
00161 if (plugin != NULL)
00162 {
00163 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00164 gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00165 if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00166 {
00167 plugin->state = PLUGIN_STATE_RUNNING;
00168 realize_some_numerical_stat(main_struct, plugin);
00169 }
00170 else
00171 plugin->state = PLUGIN_STATE_NONE;
00172 }
00173
00174 }
00175
00176
00182 void refresh(heraia_window_t *main_struct, void *data)
00183 {
00184 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00185
00186 if (main_struct != NULL && plugin != NULL)
00187 {
00188 if (main_struct->event == HERAIA_REFRESH_NEW_FILE && plugin->state == PLUGIN_STATE_RUNNING)
00189 {
00190 plugin->run_proc(NULL, (gpointer) main_struct);
00191 }
00192 }
00193 }
00194
00195
00196
00205 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data )
00206 {
00207 statw_close_clicked(widget, data);
00208
00209 return TRUE;
00210 }
00211
00212
00213 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data)
00214 {
00215 statw_close_clicked(widget, data);
00216 }
00217
00218
00222 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00223 {
00224 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00225
00226 if (plugin != NULL)
00227 {
00228 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00229 gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00230 }
00231 }
00232
00233
00237 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00238 {
00239 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00240
00241 if (plugin != NULL)
00242 {
00243 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00244 GdkPixbuf *pixbuf = gtk_image_get_pixbuf(image);
00245 gchar *filename = NULL;
00246 GError **error = NULL;
00247
00248 filename = stat_select_file_to_save();
00249 gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00250
00251 if (filename != NULL)
00252 g_free(filename);
00253 }
00254 }
00255
00256
00257 static gchar *stat_select_file_to_save(void)
00258 {
00259 GtkFileSelection *file_selector = NULL;
00260 gint response_id = 0;
00261 gchar *filename;
00262
00263 file_selector = GTK_FILE_SELECTION (gtk_file_selection_new ("Entrez le nom du fichier image"));
00264
00265
00266 gtk_file_selection_set_select_multiple(file_selector, FALSE);
00267
00268 response_id = gtk_dialog_run(GTK_DIALOG (file_selector));
00269
00270 switch (response_id)
00271 {
00272 case GTK_RESPONSE_OK:
00273 filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
00274 break;
00275 case GTK_RESPONSE_CANCEL:
00276 default:
00277 filename = NULL;
00278 break;
00279 }
00280
00281 gtk_widget_destroy (GTK_WIDGET(file_selector));
00282
00283 return filename;
00284 }
00285
00286
00287
00288 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00289 {
00290 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00291
00292 if (plugin != NULL)
00293 {
00294 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00295 stat_t *extra = (stat_t *) plugin->extra;
00296
00297 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00298 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00299 else
00300 {
00301 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00302 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00303 }
00304 }
00305 }
00306
00307
00311 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00312 {
00313
00314 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event",
00315 G_CALLBACK(delete_stat_window_event), plugin);
00316
00317 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy",
00318 G_CALLBACK(destroy_stat_window), plugin);
00319
00320
00321 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked",
00322 G_CALLBACK(statw_close_clicked), plugin);
00323
00324
00325 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled",
00326 G_CALLBACK(histo_radiobutton_toggled), plugin);
00327
00328 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled",
00329 G_CALLBACK(histo_radiobutton_toggled), plugin);
00330
00331
00332 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked",
00333 G_CALLBACK(statw_save_as_clicked), plugin);
00334
00335
00336
00337 }
00338
00339
00343 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00344 {
00345 struct stat *stat_buf;
00346 gchar buf[42];
00347 stat_t *extra = NULL;
00348 GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00349
00350 if (main_struct->filename != NULL)
00351 {
00352 log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s", main_struct->filename);
00353
00354 stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00355 lstat(main_struct->filename, stat_buf);
00356 if (S_ISREG(stat_buf->st_mode))
00357 {
00358 kill_text_from_textview(textview);
00359 add_text_to_textview(textview, "Taille du Fichier : %Ld octets\n\n", stat_buf->st_size);
00360 ctime_r(&(stat_buf->st_mtime), buf);
00361 add_text_to_textview(textview, "Dernière modification interne : %s", buf);
00362 ctime_r(&(stat_buf->st_atime), buf);
00363 add_text_to_textview(textview, "Dernier accès au fichier : %s", buf);
00364 ctime_r(&(stat_buf->st_ctime), buf);
00365 add_text_to_textview(textview, "Dernier changement externe : %s", buf);
00366
00367 populate_stats_histos(main_struct, plugin);
00368
00369 extra = (stat_t *) plugin->extra;
00370
00371 add_text_to_textview(textview, "\nNombre d'octets différents : %d\n", extra->infos_1D->nb_val);
00372 add_text_to_textview(textview, "Nombre de paires d'octets différentes : %d\n", extra->infos_2D->nb_val);
00373 add_text_to_textview(textview, "\nStatistiques pour l'histogramme 1D :\n");
00374 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_1D->min);
00375 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_1D->max);
00376 add_text_to_textview(textview, " . moyenne : %lld\n", extra->infos_1D->mean);
00377 add_text_to_textview(textview, "\nStatistiques pour l'histogramme 2D :\n");
00378 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_2D->min);
00379 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_2D->max);
00380 add_text_to_textview(textview, " . moyenne : %lld\n", extra->infos_2D->mean);
00381
00382 log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00383 }
00384 }
00385 }
00386
00387
00391 static void init_stats_histos(heraia_plugin_t *plugin)
00392 {
00393 guint i = 0;
00394 guint j = 0;
00395 stat_t *extra = NULL;
00396
00397
00398 extra = (stat_t *) plugin->extra;
00399 for (i=0; i<=255; i++)
00400 {
00401 extra->histo1D[i] = 0 ;
00402 for (j=0; j<=255; j++)
00403 extra->histo2D[i][j] = 0 ;
00404 }
00405 }
00406
00407
00411 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00412 {
00413 GtkHex *gh = GTK_HEX(main_struct->current_DW->current_hexwidget);
00414 guint64 i = 0;
00415 guint64 taille = ghex_file_size(gh);
00416 guchar c1, c2;
00417 stat_t *extra = (stat_t *) plugin->extra;
00418 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00419 GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00420 GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00421
00422 init_stats_histos(plugin);
00423
00424 while (i < taille)
00425 {
00426 c1 = gtk_hex_get_byte(gh, i);
00427 extra->histo1D[c1]++;
00428 if (i+1 < taille)
00429 {
00430 i++;
00431 c2 = gtk_hex_get_byte(gh, i);
00432 extra->histo1D[c2]++;
00433 extra->histo2D[c1][c2]++;
00434 }
00435 i++;
00436 }
00437
00438 make_pixbufs_from_histos(extra);
00439
00440 if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00441 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00442 else
00443 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00444 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00445 }
00446
00447
00451 static void calc_infos_histo_1D(stat_t *extra)
00452 {
00453 guint i = 0;
00454 gint64 n = 1;
00455 guint64 max = 0;
00456 guint64 min = G_MAXUINT64;
00457 gint64 mean = extra->histo1D[0];
00458 gint64 diff = 0;
00459
00460 extra->infos_1D->nb_val = 0;
00461
00462 for (i=0; i<=255; i++)
00463 {
00464
00465 if (extra->histo1D[i] > max)
00466 max = extra->histo1D[i];
00467
00468
00469 if (extra->histo1D[i] < min)
00470 min = extra->histo1D[i];
00471
00472
00473 if (extra->histo1D[i] > 0)
00474 extra->infos_1D->nb_val++;
00475
00476
00477 diff = extra->histo1D[i] - mean;
00478 mean = mean + diff/n;
00479 n++;
00480 }
00481
00482 extra->infos_1D->min = min;
00483 extra->infos_1D->max = max;
00484 extra->infos_1D->mean = (guint64) mean;
00485 }
00486
00487
00491 static void calc_infos_histo_2D(stat_t *extra)
00492 {
00493 guint i = 0;
00494 guint j = 0;
00495 gint64 n = 1;
00496 guint64 max = 0;
00497 guint64 min = G_MAXUINT;
00498 gint64 mean = extra->histo2D[0][0];
00499 gint64 diff = 0;
00500
00501 extra->infos_2D->nb_val = 0;
00502
00503 for (i=0; i<=255; i++)
00504 {
00505 for (j=0; j<=255; j++)
00506 {
00507
00508 if (extra->histo2D[i][j] > max)
00509 max = extra->histo2D[i][j];
00510
00511
00512 if (extra->histo2D[i][j] < min)
00513 min = extra->histo2D[i][j];
00514
00515
00516 if (extra->histo2D[i][j] > 0)
00517 extra->infos_2D->nb_val++;
00518
00519
00520 diff = extra->histo1D[i] - mean;
00521 mean = mean + diff/n;
00522 n++;
00523 }
00524 }
00525 extra->infos_2D->min = min;
00526 extra->infos_2D->max = max;
00527 extra->infos_2D->mean = (guint64) mean;
00528 }
00529
00530
00534 static void init_stats_pixbufs(stat_t *extra)
00535 {
00536
00537 extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00538 gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00539 gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00540
00541 extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00542 gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00543 gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00544
00545 }
00546
00547
00551 static void make_pixbufs_from_histos(stat_t *extra)
00552 {
00553 init_stats_pixbufs(extra);
00554 calc_infos_histo_1D(extra);
00555 calc_infos_histo_2D(extra);
00556
00557 if (extra->infos_1D->max > 0)
00558 do_pixbuf_1D_from_histo1D(extra);
00559 if (extra->infos_2D->max > 0)
00560 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00561 }
00562
00563
00567 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00568 {
00569 guchar *pixels = NULL;
00570 guchar *p = NULL;
00571
00572 pixels = gdk_pixbuf_get_pixels(pixbuf);
00573
00574 p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00575
00576 p[0] = red;
00577 p[1] = green;
00578 p[2] = blue;
00579 p[3] = alpha;
00580
00581 }
00582
00583
00587 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00588 {
00589 guchar *pixels = NULL;
00590 guchar *p = NULL;
00591
00592 if (pixbuf != NULL)
00593 {
00594
00595 gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00596 gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00597
00598 pixels = gdk_pixbuf_get_pixels(pixbuf);
00599
00600 while (y<255)
00601 {
00602 p = pixels + y * rowstride + x * n_channels;
00603 p[0] = (guchar) 255-(y/2);
00604 p[1] = (guchar) 16;
00605 p[2] = (guchar) y/2;
00606 p[3] = (guchar) 255;
00607 y++;
00608 }
00609 }
00610 }
00611
00612
00617 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00618 {
00619 guint i = 0;
00620 gint64 y = 0;
00621 gdouble inter = 0;
00622 gdouble y_norm = 0;
00623
00624 for (i=0; i<=255; i++)
00625 {
00626
00627 y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00628 inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00629 y = (gint64) inter;
00630 line_in_pixbuf(extra->pixbuf_1D, i, y);
00631 }
00632 }
00633
00634
00641 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00642 {
00643 guint i = 0;
00644 guint j = 0;
00645 guchar red;
00646 guchar green;
00647 guchar blue;
00648 gdouble height = 0;
00649
00650
00651
00652 for (i=0; i<=255; i++)
00653 {
00654 for (j=0; j<=255; j++)
00655 {
00656 height = extra->histo2D[i][j];
00657 if (height>0 && height<extra->infos_2D->mean/2)
00658 {
00659 height = (gdouble) (height*255) / (gdouble) extra->infos_2D->max;
00660 red = (guchar) height;
00661 green = (guchar) 255 - (height);
00662 blue = (guchar) height/2;
00663 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00664 }
00665 else if (height>extra->infos_2D->mean/2)
00666 {
00667 height = (gdouble) height*255 / (gdouble) extra->infos_2D->max;
00668 red = (guchar) 255 - (height);
00669 green = (guchar) height/2;
00670 blue = (guchar) height;
00671 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00672 }
00673 }
00674 }
00675 }
00676
00677