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 "heraia_types.h"
00026 #include "stat.h"
00027
00028
00029 static void stat_window_connect_signals(heraia_plugin_t *plugin);
00030 static void statw_close_clicked(GtkWidget *widget, gpointer data);
00031 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data);
00032 static void statw_save_as_clicked(GtkWidget *widget, gpointer data);
00033 static gchar *stat_select_file_to_save(void);
00034 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data);
00035 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data );
00036 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00037 static void init_stats_histos(heraia_plugin_t *plugin);
00038 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00039 static void calc_infos_histo_1D(stat_t *extra);
00040 static void calc_infos_histo_2D(stat_t *extra);
00041 static void init_stats_pixbufs(stat_t *extra);
00042 static void make_pixbufs_from_histos(stat_t *extra);
00043 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha);
00044 static void do_pixbuf_1D_from_histo1D(stat_t *extra);
00045 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D);
00046
00047
00051 heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00052 {
00053 stat_t *extra = NULL;
00054 window_prop_t *stat_prop = NULL;
00055
00056 plugin->state = PLUGIN_STATE_INITIALIZING;
00057 plugin->xml = NULL;
00058
00059 plugin->info->api_version = API_VERSION;
00060 plugin->info->type = PLUGIN_TYPE;
00061 plugin->info->priority = HERAIA_PRIORITY_DEFAULT;
00062 plugin->info->name = PLUGIN_NAME;
00063 plugin->info->version = PLUGIN_VERSION;
00064 plugin->info->summary = PLUGIN_SUMMARY;
00065 plugin->info->description = PLUGIN_DESCRIPTION;
00066 plugin->info->author = PLUGIN_AUTHOR;
00067 plugin->info->homepage = PLUGIN_HOMEPAGE;
00068
00069 plugin->init_proc = init;
00070 plugin->quit_proc = quit;
00071 plugin->run_proc = run;
00072 plugin->refresh_proc = refresh;
00073
00074 plugin->filter->extensions = NULL;
00075 plugin->filter->import = NULL;
00076 plugin->filter->export = NULL;
00077
00078
00079 extra = (stat_t *) g_malloc0 (sizeof(stat_t));
00080 extra->infos_1D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00081 extra->infos_2D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00082
00083
00084 stat_prop = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00085 stat_prop->displayed = FALSE;
00086 stat_prop->x = 0;
00087 stat_prop->y = 0;
00088
00089 plugin->win_prop = stat_prop;
00090
00091 plugin->extra = extra;
00092
00093
00094 return plugin;
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
00143 void quit(void)
00144 {
00145 g_print("Quitting %s\n", PLUGIN_NAME);
00146 }
00147
00151 void run(GtkWidget *widget, gpointer data)
00152 {
00153 heraia_window_t *main_struct = (heraia_window_t *) data;
00154 heraia_plugin_t *plugin = NULL;
00155
00156
00157 plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00158
00159 if (plugin != NULL)
00160 {
00161 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00162 gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00163 if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00164 {
00165 plugin->state = PLUGIN_STATE_RUNNING;
00166 realize_some_numerical_stat(main_struct, plugin);
00167 }
00168 else
00169 plugin->state = PLUGIN_STATE_NONE;
00170 }
00171
00172 }
00173
00179 void refresh(heraia_window_t *main_struct, void *data)
00180 {
00181 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00182
00183 if (main_struct != NULL && plugin != NULL)
00184 {
00185 if (main_struct->event == HERAIA_REFRESH_NEW_FILE && plugin->state == PLUGIN_STATE_RUNNING)
00186 {
00187 plugin->run_proc(NULL, (gpointer) main_struct);
00188 }
00189 }
00190 }
00191
00192
00193
00202 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data )
00203 {
00204 statw_close_clicked(widget, data);
00205
00206 return TRUE;
00207 }
00208
00209 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data)
00210 {
00211 statw_close_clicked(widget, data);
00212 }
00213
00214
00215 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00216 {
00217 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00218
00219 if (plugin != NULL)
00220 {
00221 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00222 gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00223 }
00224 }
00225
00226
00227 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00228 {
00229 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00230
00231 if (plugin != NULL)
00232 {
00233 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00234 GdkPixbuf *pixbuf = gtk_image_get_pixbuf(image);
00235 gchar *filename = NULL;
00236 GError **error = NULL;
00237
00238 filename = stat_select_file_to_save();
00239 gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00240
00241 if (filename != NULL)
00242 g_free(filename);
00243 }
00244 }
00245
00246 static gchar *stat_select_file_to_save(void)
00247 {
00248 GtkFileSelection *file_selector = NULL;
00249 gint response_id = 0;
00250 gchar *filename;
00251
00252 file_selector = GTK_FILE_SELECTION (gtk_file_selection_new ("Entrez le nom du fichier image"));
00253
00254
00255 gtk_file_selection_set_select_multiple(file_selector, FALSE);
00256
00257 response_id = gtk_dialog_run(GTK_DIALOG (file_selector));
00258
00259 switch (response_id)
00260 {
00261 case GTK_RESPONSE_OK:
00262 filename = g_strdup(gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_selector)));
00263 break;
00264 case GTK_RESPONSE_CANCEL:
00265 default:
00266 filename = NULL;
00267 break;
00268 }
00269
00270 gtk_widget_destroy (GTK_WIDGET(file_selector));
00271
00272 return filename;
00273 }
00274
00275
00276 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00277 {
00278 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00279
00280 if (plugin != NULL)
00281 {
00282 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00283 stat_t *extra = (stat_t *) plugin->extra;
00284
00285 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00286 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00287 else
00288 {
00289 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00290 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00291 }
00292 }
00293 }
00294
00295
00299 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00300 {
00301
00302 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event",
00303 G_CALLBACK(delete_stat_window_event), plugin);
00304
00305 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy",
00306 G_CALLBACK(destroy_stat_window), plugin);
00307
00308
00309 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked",
00310 G_CALLBACK(statw_close_clicked), plugin);
00311
00312
00313 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled",
00314 G_CALLBACK(histo_radiobutton_toggled), plugin);
00315
00316 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled",
00317 G_CALLBACK(histo_radiobutton_toggled), plugin);
00318
00319
00320 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked",
00321 G_CALLBACK(statw_save_as_clicked), plugin);
00322
00323
00324
00325 }
00326
00327
00331 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00332 {
00333 struct stat *stat_buf;
00334 gchar buf[42];
00335 stat_t *extra = NULL;
00336 GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00337
00338 if (main_struct->filename != NULL)
00339 {
00340 log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s", main_struct->filename);
00341
00342 stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00343 lstat(main_struct->filename, stat_buf);
00344 if (S_ISREG(stat_buf->st_mode))
00345 {
00346 kill_text_from_textview(textview);
00347 add_text_to_textview(textview, "Taille du Fichier : %Ld octets\n\n", stat_buf->st_size);
00348 ctime_r(&(stat_buf->st_mtime), buf);
00349 add_text_to_textview(textview, "Dernière modification interne : %s", buf);
00350 ctime_r(&(stat_buf->st_atime), buf);
00351 add_text_to_textview(textview, "Dernier accès au fichier : %s", buf);
00352 ctime_r(&(stat_buf->st_ctime), buf);
00353 add_text_to_textview(textview, "Dernier changement externe : %s", buf);
00354
00355 populate_stats_histos(main_struct, plugin);
00356
00357 extra = (stat_t *) plugin->extra;
00358
00359 add_text_to_textview(textview, "\nNombre d'octets différents : %d\n", extra->infos_1D->nb_val);
00360 add_text_to_textview(textview, "Nombre de paires d'octets différentes : %d\n", extra->infos_2D->nb_val);
00361 add_text_to_textview(textview, "\nStatistiques pour l'histogramme 1D :\n");
00362 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_1D->min);
00363 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_1D->max);
00364 add_text_to_textview(textview, " . moyenne : %lld\n", extra->infos_1D->mean);
00365 add_text_to_textview(textview, "\nStatistiques pour l'histogramme 2D :\n");
00366 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_2D->min);
00367 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_2D->max);
00368 add_text_to_textview(textview, " . moyenne : %lld\n", extra->infos_2D->mean);
00369
00370 log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00371 }
00372 }
00373 }
00374
00375
00379 static void init_stats_histos(heraia_plugin_t *plugin)
00380 {
00381 guint i = 0;
00382 guint j = 0;
00383 stat_t *extra = NULL;
00384
00385
00386 extra = (stat_t *) plugin->extra;
00387 for (i=0; i<=255; i++)
00388 {
00389 extra->histo1D[i] = 0 ;
00390 for (j=0; j<=255; j++)
00391 extra->histo2D[i][j] = 0 ;
00392 }
00393 }
00394
00395
00396
00397
00401 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00402 {
00403 GtkHex *gh = GTK_HEX(main_struct->current_DW->current_hexwidget);
00404 guint64 i = 0;
00405 guint64 taille = ghex_file_size(gh);
00406 guchar c1, c2;
00407 stat_t *extra = (stat_t *) plugin->extra;
00408 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00409 GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00410 GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00411
00412 init_stats_histos(plugin);
00413
00414 while (i < taille)
00415 {
00416 c1 = gtk_hex_get_byte(gh, i);
00417 extra->histo1D[c1]++;
00418 if (i+1 < taille)
00419 {
00420 i++;
00421 c2 = gtk_hex_get_byte(gh, i);
00422 extra->histo1D[c2]++;
00423 extra->histo2D[c1][c2]++;
00424 }
00425 i++;
00426 }
00427
00428 make_pixbufs_from_histos(extra);
00429
00430 if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00431 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00432 else
00433 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00434 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00435 }
00436
00437
00441 static void calc_infos_histo_1D(stat_t *extra)
00442 {
00443 guint i = 0;
00444 gint64 n = 1;
00445 guint64 max = 0;
00446 guint64 min = G_MAXUINT64;
00447 gint64 mean = extra->histo1D[0];
00448 gint64 diff = 0;
00449
00450 extra->infos_1D->nb_val = 0;
00451
00452 for (i=0; i<=255; i++)
00453 {
00454
00455 if (extra->histo1D[i] > max)
00456 max = extra->histo1D[i];
00457
00458
00459 if (extra->histo1D[i] < min)
00460 min = extra->histo1D[i];
00461
00462
00463 if (extra->histo1D[i] > 0)
00464 extra->infos_1D->nb_val++;
00465
00466
00467 diff = extra->histo1D[i] - mean;
00468 mean = mean + diff/n;
00469 n++;
00470 }
00471
00472 extra->infos_1D->min = min;
00473 extra->infos_1D->max = max;
00474 extra->infos_1D->mean = (guint64) mean;
00475 }
00476
00477
00481 static void calc_infos_histo_2D(stat_t *extra)
00482 {
00483 guint i = 0;
00484 guint j = 0;
00485 gint64 n = 1;
00486 guint64 max = 0;
00487 guint64 min = G_MAXUINT;
00488 gint64 mean = extra->histo2D[0][0];
00489 gint64 diff = 0;
00490
00491 extra->infos_2D->nb_val = 0;
00492
00493 for (i=0; i<=255; i++)
00494 {
00495 for (j=0; j<=255; j++)
00496 {
00497
00498 if (extra->histo2D[i][j] > max)
00499 max = extra->histo2D[i][j];
00500
00501
00502 if (extra->histo2D[i][j] < min)
00503 min = extra->histo2D[i][j];
00504
00505
00506 if (extra->histo2D[i][j] > 0)
00507 extra->infos_2D->nb_val++;
00508
00509
00510 diff = extra->histo1D[i] - mean;
00511 mean = mean + diff/n;
00512 n++;
00513 }
00514 }
00515 extra->infos_2D->min = min;
00516 extra->infos_2D->max = max;
00517 extra->infos_2D->mean = (guint64) mean;
00518 }
00519
00520
00524 static void init_stats_pixbufs(stat_t *extra)
00525 {
00526
00527 extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00528 gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00529 gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00530
00531 extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00532 gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00533 gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00534
00535 }
00536
00537
00541 static void make_pixbufs_from_histos(stat_t *extra)
00542 {
00543 init_stats_pixbufs(extra);
00544 calc_infos_histo_1D(extra);
00545 calc_infos_histo_2D(extra);
00546
00547 if (extra->infos_1D->max > 0)
00548 do_pixbuf_1D_from_histo1D(extra);
00549 if (extra->infos_2D->max > 0)
00550 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00551 }
00552
00553
00557 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00558 {
00559 guchar *pixels = NULL;
00560 guchar *p = NULL;
00561
00562 pixels = gdk_pixbuf_get_pixels(pixbuf);
00563
00564 p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00565
00566 p[0] = red;
00567 p[1] = green;
00568 p[2] = blue;
00569 p[3] = alpha;
00570
00571 }
00572
00573
00577 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00578 {
00579 guchar *pixels = NULL;
00580 guchar *p = NULL;
00581
00582 if (pixbuf != NULL)
00583 {
00584
00585 gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00586 gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00587
00588 pixels = gdk_pixbuf_get_pixels(pixbuf);
00589
00590 while (y<255)
00591 {
00592 p = pixels + y * rowstride + x * n_channels;
00593 p[0] = (guchar) 255-(y/2);
00594 p[1] = (guchar) 16;
00595 p[2] = (guchar) y/2;
00596 p[3] = (guchar) 255;
00597 y++;
00598 }
00599 }
00600 }
00601
00602
00607 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00608 {
00609 guint i = 0;
00610 gint64 y = 0;
00611 gdouble inter = 0;
00612 gdouble y_norm = 0;
00613
00614 for (i=0; i<=255; i++)
00615 {
00616
00617 y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00618 inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00619 y = (gint64) inter;
00620 line_in_pixbuf(extra->pixbuf_1D, i, y);
00621 }
00622 }
00623
00624
00631 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00632 {
00633 guint i = 0;
00634 guint j = 0;
00635 guchar red;
00636 guchar green;
00637 guchar blue;
00638 gdouble height = 0;
00639
00640
00641
00642 for (i=0; i<=255; i++)
00643 {
00644 for (j=0; j<=255; j++)
00645 {
00646 height = extra->histo2D[i][j];
00647 if (height>0 && height<extra->infos_2D->mean/2)
00648 {
00649 height = (gdouble) (height*255) / (gdouble) extra->infos_2D->max;
00650 red = (guchar) height;
00651 green = (guchar) 255 - (height);
00652 blue = (guchar) height/2;
00653 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00654 }
00655 else if (height>extra->infos_2D->mean/2)
00656 {
00657 height = (gdouble) height*255 / (gdouble) extra->infos_2D->max;
00658 red = (guchar) 255 - (height);
00659 green = (guchar) height/2;
00660 blue = (guchar) height;
00661 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
00662 }
00663 }
00664 }
00665 }
00666
00667