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