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
00026
00027
00028
00029 #include "stat.h"
00030
00031
00032 static void stat_window_connect_signals(heraia_plugin_t *plugin);
00033
00034 static void statw_close_clicked(GtkWidget *widget, gpointer data);
00035 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data);
00036
00037 static void statw_save_as_clicked(GtkWidget *widget, gpointer data);
00038 static void statw_export_to_csv_clicked(GtkWidget *widget, gpointer data);
00039 static void statw_export_to_gnuplot_clicked(GtkWidget *widget, gpointer data);
00040 static void statw_export_to_pcv_clicked(GtkWidget *widget, gpointer data);
00041
00042 static gchar *stat_select_file_to_save(gchar *window_text, stat_t *extra);
00043 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data);
00044 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data );
00045 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00046 static void init_stats_histos(heraia_plugin_t *plugin);
00047 static void set_statw_button_state(GladeXML *xml, gboolean sensitive);
00048 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin);
00049 static void calc_infos_histo_1D(stat_t *extra);
00050 static void calc_infos_histo_2D(stat_t *extra);
00051 static void init_stats_pixbufs(stat_t *extra);
00052 static void make_pixbufs_from_histos(stat_t *extra);
00053 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha);
00054 static void do_pixbuf_1D_from_histo1D(stat_t *extra);
00055 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D);
00056
00057
00058
00059
00060
00061
00062
00063
00064 heraia_plugin_t *heraia_plugin_init(heraia_plugin_t *plugin)
00065 {
00066 stat_t *extra = NULL;
00067 window_prop_t *stat_prop = NULL;
00068
00069 plugin->state = PLUGIN_STATE_INITIALIZING;
00070 plugin->xml = NULL;
00071
00072 plugin->info->api_version = API_VERSION;
00073 plugin->info->type = PLUGIN_TYPE;
00074 plugin->info->priority = HERAIA_PRIORITY_DEFAULT;
00075 plugin->info->name = PLUGIN_NAME;
00076 plugin->info->version = PLUGIN_VERSION;
00077 plugin->info->summary = PLUGIN_SUMMARY;
00078 plugin->info->description = PLUGIN_DESCRIPTION;
00079 plugin->info->author = PLUGIN_AUTHOR;
00080 plugin->info->homepage = PLUGIN_HOMEPAGE;
00081
00082 plugin->init_proc = init;
00083 plugin->quit_proc = quit;
00084 plugin->run_proc = run;
00085 plugin->refresh_proc = refresh;
00086
00087 plugin->filter->extensions = NULL;
00088 plugin->filter->import = NULL;
00089 plugin->filter->export = NULL;
00090
00091
00092 extra = (stat_t *) g_malloc0 (sizeof(stat_t));
00093 extra->infos_1D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00094 extra->infos_2D = (histo_infos_t *) g_malloc0 (sizeof(histo_infos_t));
00095 extra->dirname = NULL;
00096
00097
00098 stat_prop = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00099 stat_prop->displayed = FALSE;
00100 stat_prop->x = 0;
00101 stat_prop->y = 0;
00102
00103 plugin->win_prop = stat_prop;
00104
00105 plugin->extra = extra;
00106
00107
00108 return plugin;
00109 }
00110
00111
00112
00113
00114
00115
00116 void init(heraia_window_t *main_struct)
00117 {
00118 heraia_plugin_t *plugin = NULL;
00119
00120 log_message(main_struct, G_LOG_LEVEL_INFO, "Initializing plugin %s", PLUGIN_NAME);
00121
00122 plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00123
00124 if (plugin != NULL)
00125 {
00126
00127 log_message(main_struct, G_LOG_LEVEL_INFO, "Plugin from %s found !", plugin->info->author);
00128 if (load_plugin_glade_xml(main_struct, plugin) == TRUE)
00129 {
00130 log_message(main_struct, G_LOG_LEVEL_INFO, "%s xml interface loaded.", plugin->info->name);
00131 }
00132 else
00133 {
00134 log_message(main_struct, G_LOG_LEVEL_WARNING, "Unable to load %s xml interface.", plugin->info->name);
00135 }
00136
00137
00138 set_statw_button_state(plugin->xml, FALSE);
00139
00140
00141 if (plugin->win_prop->displayed == FALSE)
00142 {
00143 gtk_widget_hide(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")));
00144 }
00145 else
00146 {
00147 gtk_check_menu_item_set_active(plugin->cmi_entry, TRUE);
00148 }
00149
00150
00151 stat_window_connect_signals(plugin);
00152
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161 void quit(void)
00162 {
00163 g_print("Quitting %s\n", PLUGIN_NAME);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 void run(GtkWidget *widget, gpointer data)
00174 {
00175 heraia_window_t *main_struct = (heraia_window_t *) data;
00176 heraia_plugin_t *plugin = NULL;
00177
00178
00179 plugin = find_plugin_by_name(main_struct->plugins_list, PLUGIN_NAME);
00180
00181 if (plugin != NULL)
00182 {
00183 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")),
00184 gtk_check_menu_item_get_active(plugin->cmi_entry), plugin->win_prop);
00185 if (gtk_check_menu_item_get_active(plugin->cmi_entry) == TRUE)
00186 {
00187 plugin->state = PLUGIN_STATE_RUNNING;
00188 realize_some_numerical_stat(main_struct, plugin);
00189 }
00190 else
00191 {
00192 plugin->state = PLUGIN_STATE_NONE;
00193 }
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 static void set_statw_button_state(GladeXML *xml, gboolean sensitive)
00204 {
00205 if (xml != NULL)
00206 {
00207 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_save_as"), sensitive);
00208 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_csv"), sensitive);
00209 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_gnuplot"), sensitive);
00210 gtk_widget_set_sensitive(glade_xml_get_widget(xml, "statw_export_to_pcv"), sensitive);
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void refresh(heraia_window_t *main_struct, void *data)
00223 {
00224 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00225
00226 if (main_struct != NULL && plugin != NULL)
00227 {
00228 if (main_struct->event == HERAIA_REFRESH_NEW_FILE || main_struct->event == HERAIA_REFRESH_TAB_CHANGED)
00229 {
00230 set_statw_button_state(plugin->xml, TRUE);
00231 plugin->run_proc(NULL, (gpointer) main_struct);
00232 }
00233 }
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 static gboolean delete_stat_window_event(GtkWidget *widget, GdkEvent *event, gpointer data)
00251 {
00252 statw_close_clicked(widget, data);
00253
00254 return TRUE;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 static void destroy_stat_window(GtkWidget *widget, GdkEvent *event, gpointer data)
00266 {
00267 statw_close_clicked(widget, data);
00268 }
00269
00270
00271
00272
00273
00274
00275
00276 static void statw_close_clicked(GtkWidget *widget, gpointer data)
00277 {
00278 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00279
00280 if (plugin != NULL)
00281 {
00282 show_hide_widget(GTK_WIDGET(glade_xml_get_widget(plugin->xml, "stat_window")), FALSE, plugin->win_prop);
00283 gtk_check_menu_item_set_active(plugin->cmi_entry, FALSE);
00284 }
00285 }
00286
00287
00288
00289
00290
00291
00292
00293 static void statw_save_as_clicked(GtkWidget *widget, gpointer data)
00294 {
00295 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00296 stat_t *extra = NULL;
00297 GtkImage *image = NULL;
00298 GdkPixbuf *pixbuf = NULL;
00299 gchar *filename = NULL;
00300 GError **error = NULL;
00301
00302 if (plugin != NULL)
00303 {
00304 extra = (stat_t *) plugin->extra;
00305
00306 image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00307 pixbuf = gtk_image_get_pixbuf(image);
00308
00309 filename = stat_select_file_to_save("Enter filename's to save the image to", extra);
00310 if (filename != NULL)
00311 {
00312 gdk_pixbuf_save(pixbuf, filename, "png", error, "compression", "9", NULL);
00313 g_free(filename);
00314 }
00315 }
00316 }
00317
00318
00319
00320
00321
00322
00323 static gchar *stat_select_file_to_save(gchar *window_text, stat_t *extra)
00324 {
00325 GtkFileChooser *file_chooser = NULL;
00326 gint response_id = 0;
00327 gchar *filename;
00328
00329 file_chooser = GTK_FILE_CHOOSER(gtk_file_chooser_dialog_new(window_text, NULL,
00330 GTK_FILE_CHOOSER_ACTION_SAVE,
00331 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
00332 GTK_STOCK_OPEN, GTK_RESPONSE_OK,
00333 NULL));
00334
00335
00336 gtk_window_set_modal(GTK_WINDOW(file_chooser), TRUE);
00337 gtk_file_chooser_set_select_multiple(file_chooser, FALSE);
00338 gtk_file_chooser_set_do_overwrite_confirmation(file_chooser, TRUE);
00339
00340
00341 if (extra != NULL && extra->dirname != NULL)
00342 {
00343 gtk_file_chooser_set_current_folder(file_chooser, extra->dirname);
00344 }
00345
00346 response_id = gtk_dialog_run(GTK_DIALOG(file_chooser));
00347
00348 switch (response_id)
00349 {
00350 case GTK_RESPONSE_OK:
00351 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
00352
00353
00354 if (filename != NULL)
00355 {
00356 if (extra->dirname != NULL)
00357 {
00358 g_free(extra->dirname);
00359 }
00360 extra->dirname = g_path_get_dirname(filename);
00361 }
00362
00363 break;
00364 case GTK_RESPONSE_CANCEL:
00365 default:
00366 filename = NULL;
00367 break;
00368 }
00369
00370 gtk_widget_destroy(GTK_WIDGET(file_chooser));
00371 return filename;
00372 }
00373
00374
00375
00376
00377
00378
00379 static void statw_export_to_csv_clicked(GtkWidget *widget, gpointer data)
00380 {
00381 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00382 stat_t *extra = NULL;
00383 gchar *filename = NULL;
00384 FILE *fp = NULL;
00385 guint i = 0;
00386 guint j = 0;
00387
00388 if (plugin != NULL)
00389 {
00390 extra = (stat_t *) plugin->extra;
00391
00392 filename = stat_select_file_to_save("Enter filename to export data as CSV to", extra);
00393
00394 if (filename != NULL)
00395 {
00396 fp = g_fopen(filename, "w+");
00397 }
00398
00399 if (fp != NULL && extra != NULL)
00400 {
00401 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00402 {
00403
00404 fprintf(fp, "\"Byte\";\"Count\"\n");
00405
00406 for (i=0; i<=255; i++)
00407 {
00408 fprintf(fp, "%d;%Ld\n", i, extra->histo1D[i]);
00409 }
00410
00411 }
00412 else
00413 {
00414
00415 fprintf(fp, "\"Byte/Byte\";");
00416 for (j=0; j<255; j++)
00417 {
00418 fprintf(fp, "\"%d\";", j);
00419 }
00420 fprintf(fp, "\"%d\"\n", 255);
00421
00422 for (i=0; i<=255; i++)
00423 {
00424 fprintf(fp, "\"%d\";", i);
00425 for (j=0 ; j<255; j++)
00426 {
00427 fprintf(fp, "\"%Ld\";", extra->histo2D[i][j]);
00428 }
00429 fprintf(fp, "\"%Ld\"\n", extra->histo2D[i][255]);
00430 }
00431 }
00432 fclose(fp);
00433 }
00434 if (filename != NULL)
00435 {
00436 g_free(filename);
00437 }
00438 }
00439 }
00440
00441
00442
00443
00444
00445
00446 static void statw_export_to_gnuplot_clicked(GtkWidget *widget, gpointer data)
00447 {
00448 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00449 stat_t *extra = NULL;
00450 gchar *filename = NULL;
00451 FILE *fp = NULL;
00452 guint i = 0;
00453 guint j = 0;
00454
00455 if (plugin != NULL)
00456 {
00457 extra = (stat_t *) plugin->extra;
00458
00459 filename = stat_select_file_to_save("Enter filename to export data as gnuplot to", extra);
00460
00461 if (filename != NULL)
00462 {
00463 fp = g_fopen(filename, "w+");
00464 }
00465
00466 if (fp != NULL && extra != NULL)
00467 {
00468
00469 fprintf(fp, "set terminal png transparent nocrop enhanced small size 1280,960\n");
00470 fprintf(fp, "set output '%s.png'\n", g_path_get_basename(filename));
00471 fprintf(fp, "set xrange [-10:265]\n");
00472 fprintf(fp, "set xlabel 'Bytes'\n");
00473
00474 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00475 {
00476
00477 fprintf(fp, "set title 'Classical histogram'\n");
00478 fprintf(fp, "set ylabel 'Count'\n");
00479 fprintf(fp, "plot '-' title 'Byte count' with impulses\n");
00480
00481 for (i=0; i<=255; i++)
00482 {
00483 fprintf(fp, "%Ld\n", extra->histo1D[i]);
00484 }
00485 fprintf(fp, "e\n");
00486 }
00487 else
00488 {
00489
00490 fprintf(fp, "set title 'Heatmap histogram'\n");
00491 fprintf(fp, "set bar 1.000000\n");
00492 fprintf(fp, "set style rectangle back fc lt -3 fillstyle solid 1.00 border -1\n");
00493 fprintf(fp, "unset key\n");
00494 fprintf(fp, "set view map\n");
00495 fprintf(fp, "set yrange [-10:265]\n");
00496 fprintf(fp, "set ylabel 'Bytes'\n");
00497 fprintf(fp, "set palette rgbformulae 36, 13, 15\n");
00498 fprintf(fp, "splot '-' matrix with image\n");
00499
00500 for (i=0; i<=255; i++)
00501 {
00502 for (j=0; j<=255; j++)
00503 {
00504 fprintf(fp, "%Ld ", extra->histo2D[i][j]);
00505 }
00506 fprintf(fp, "\n");
00507 }
00508
00509 fprintf(fp, "e\n");
00510 fprintf(fp, "e\n");
00511 }
00512 fclose(fp);
00513 }
00514 if (filename != NULL)
00515 {
00516 g_free(filename);
00517 }
00518 }
00519 }
00520
00521
00522
00523
00524
00525
00526 static void statw_export_to_pcv_clicked(GtkWidget *widget, gpointer data)
00527 {
00528 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00529 stat_t *extra = NULL;
00530 gchar *filename = NULL;
00531 FILE *fp = NULL;
00532 guint i = 0;
00533 guint j = 0;
00534
00535 if (plugin != NULL)
00536 {
00537 extra = (stat_t *) plugin->extra;
00538
00539 filename = stat_select_file_to_save("Enter filename to export data as PCV to", extra);
00540
00541 if (filename != NULL)
00542 {
00543 fp = g_fopen(filename, "w+");
00544 }
00545
00546 if (fp != NULL && extra != NULL)
00547 {
00548 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00549 {
00550
00551 fprintf(fp, "header {\n");
00552 fprintf(fp, "\theight = \"960\";\n");
00553 fprintf(fp, "\twidth = \"1280\";\n");
00554 fprintf(fp, "\ttitle = \"Classical histogram\";\n");
00555 fprintf(fp, "}\n");
00556 fprintf(fp, "axes {\n");
00557 fprintf(fp, "\tinteger b [label=\"Bytes\"];\n");
00558 fprintf(fp, "\tinteger c [label=\"Byte count\"];\n");
00559 fprintf(fp, "}\n");
00560 fprintf(fp, "data {\n");
00561
00562 for (i=0; i<=255; i++)
00563 {
00564 fprintf(fp, "\tb=\"%d\", c=\"%Ld\";\n", i, extra->histo1D[i]);
00565 }
00566 fprintf(fp, "}\n");
00567 }
00568 else
00569 {
00570
00571 fprintf(fp, "header {\n");
00572 fprintf(fp, "\theight = \"960\";\n");
00573 fprintf(fp, "\twidth = \"1280\";\n");
00574 fprintf(fp, "\ttitle = \"Classical histogram\";\n");
00575 fprintf(fp, "}\n");
00576 fprintf(fp, "axes {\n");
00577 fprintf(fp, "\tchar a [label=\"Bytes\"];\n");
00578 fprintf(fp, "\tport c [label=\"Byte count\"];\n");
00579 fprintf(fp, "\tchar b [label=\"Bytes\"];\n");
00580 fprintf(fp, "}\n");
00581 fprintf(fp, "data {\n");
00582
00583 for (i=0; i<=255; i++)
00584 {
00585 for (j=0; j<=255; j++)
00586 {
00587 if (extra->histo2D[i][j] == extra->infos_2D->max)
00588 {
00589 fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\" [color=\"red\"];\n", i, extra->histo2D[i][j], j);
00590 }
00591 else
00592 {
00593 if (extra->histo2D[i][j] == extra->infos_2D->min)
00594 {
00595 fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\" [color=\"green\"];\n", i, extra->histo2D[i][j], j);
00596 }
00597 else
00598 {
00599 fprintf(fp, "\ta=\"%d\", c=\"%Ld\", b=\"%d\";\n", i, extra->histo2D[i][j], j);
00600 }
00601 }
00602 }
00603 }
00604 fprintf(fp, "}\n");
00605 }
00606 fclose(fp);
00607 }
00608 if (filename != NULL)
00609 {
00610 g_free(filename);
00611 }
00612 }
00613 }
00614
00615
00616
00617
00618
00619
00620
00621
00622 static void histo_radiobutton_toggled(GtkWidget *widget, gpointer data)
00623 {
00624 heraia_plugin_t *plugin = (heraia_plugin_t *) data;
00625
00626 if (plugin != NULL)
00627 {
00628 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00629 stat_t *extra = (stat_t *) plugin->extra;
00630
00631 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"))) == TRUE)
00632 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00633 else
00634 {
00635 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"))) == TRUE)
00636 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00637 }
00638 }
00639 }
00640
00641
00642
00643
00644
00645
00646 static void stat_window_connect_signals(heraia_plugin_t *plugin)
00647 {
00648
00649 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "delete_event",
00650 G_CALLBACK(delete_stat_window_event), plugin);
00651
00652 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "stat_window")), "destroy",
00653 G_CALLBACK(destroy_stat_window), plugin);
00654
00655
00656 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_close_b")), "clicked",
00657 G_CALLBACK(statw_close_clicked), plugin);
00658
00659
00660 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_1D")), "toggled",
00661 G_CALLBACK(histo_radiobutton_toggled), plugin);
00662
00663 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "rb_2D")), "toggled",
00664 G_CALLBACK(histo_radiobutton_toggled), plugin);
00665
00666
00667 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_save_as")), "clicked",
00668 G_CALLBACK(statw_save_as_clicked), plugin);
00669
00670
00671 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_csv")), "clicked",
00672 G_CALLBACK(statw_export_to_csv_clicked), plugin);
00673
00674
00675 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_gnuplot")), "clicked",
00676 G_CALLBACK(statw_export_to_gnuplot_clicked), plugin);
00677
00678
00679 g_signal_connect(G_OBJECT(glade_xml_get_widget(plugin->xml, "statw_export_to_pcv")), "clicked",
00680 G_CALLBACK(statw_export_to_pcv_clicked), plugin);
00681
00682
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 static void realize_some_numerical_stat(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00692 {
00693 struct stat *stat_buf;
00694 gchar buf[42];
00695 gchar *filename = NULL;
00696 stat_t *extra = NULL;
00697 GtkTextView *textview = GTK_TEXT_VIEW(glade_xml_get_widget(plugin->xml, "statw_textview"));
00698
00699 if (main_struct != NULL && main_struct->current_doc != NULL)
00700 {
00701 filename = doc_t_document_get_filename(main_struct->current_doc);
00702 }
00703
00704 if (filename != NULL)
00705 {
00706 log_message(main_struct, G_LOG_LEVEL_INFO, "Calculating stats on %s", filename);
00707
00708 stat_buf = (struct stat *) g_malloc0 (sizeof(struct stat));
00709 g_lstat(filename, stat_buf);
00710 if (S_ISREG(stat_buf->st_mode))
00711 {
00712 kill_text_from_textview(textview);
00713 add_text_to_textview(textview, "File size : %Ld bytes\n\n", stat_buf->st_size);
00714 ctime_r(&(stat_buf->st_mtime), buf);
00715 add_text_to_textview(textview, "Last intern modification : %s", buf);
00716 ctime_r(&(stat_buf->st_atime), buf);
00717 add_text_to_textview(textview, "Last acces to the file : %s", buf);
00718 ctime_r(&(stat_buf->st_ctime), buf);
00719 add_text_to_textview(textview, "Last extern modification : %s", buf);
00720
00721 populate_stats_histos(main_struct, plugin);
00722
00723 extra = (stat_t *) plugin->extra;
00724
00725 add_text_to_textview(textview, "\n1D histogram statistics :\n");
00726 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_1D->min);
00727 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_1D->max);
00728 add_text_to_textview(textview, " . mean : %lld\n", extra->infos_1D->mean);
00729 add_text_to_textview(textview, " . number of values : %lld\n", extra->infos_1D->nb_val);
00730 add_text_to_textview(textview, "\n2D histogram statistics :\n");
00731 add_text_to_textview(textview, " . minimum : %lld\n", extra->infos_2D->min);
00732 add_text_to_textview(textview, " . maximum : %lld\n", extra->infos_2D->max);
00733 add_text_to_textview(textview, " . mean : %lld\n", extra->infos_2D->mean);
00734 add_text_to_textview(textview, " . number of values : %lld\n", extra->infos_2D->nb_val);
00735 log_message(main_struct, G_LOG_LEVEL_INFO, "Histos calculated !");
00736 }
00737 }
00738 }
00739
00740
00741
00742
00743
00744 static void init_stats_histos(heraia_plugin_t *plugin)
00745 {
00746 guint i = 0;
00747 guint j = 0;
00748 stat_t *extra = NULL;
00749
00750
00751 extra = (stat_t *) plugin->extra;
00752 for (i=0; i<=255; i++)
00753 {
00754 extra->histo1D[i] = 0 ;
00755 for (j=0; j<=255; j++)
00756 extra->histo2D[i][j] = 0 ;
00757 }
00758 }
00759
00760
00761
00762
00763
00764 static void populate_stats_histos(heraia_window_t *main_struct, heraia_plugin_t *plugin)
00765 {
00766 GtkHex *gh = GTK_HEX(main_struct->current_doc->hex_widget);
00767 guint64 i = 0;
00768 guint64 taille = ghex_file_size(gh);
00769 guchar c1, c2;
00770 stat_t *extra = (stat_t *) plugin->extra;
00771 GtkImage *image = GTK_IMAGE(glade_xml_get_widget(plugin->xml, "histo_image"));
00772 GtkToggleButton *rb_1D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_1D"));
00773 GtkToggleButton *rb_2D = GTK_TOGGLE_BUTTON(glade_xml_get_widget(plugin->xml, "rb_2D"));
00774
00775 init_stats_histos(plugin);
00776
00777 while (i < taille)
00778 {
00779 c1 = gtk_hex_get_byte(gh, i);
00780 extra->histo1D[c1]++;
00781 if (i+1 < taille)
00782 {
00783 i++;
00784 c2 = gtk_hex_get_byte(gh, i);
00785 extra->histo1D[c2]++;
00786 extra->histo2D[c1][c2]++;
00787 }
00788 i++;
00789 }
00790
00791 make_pixbufs_from_histos(extra);
00792
00793 if (gtk_toggle_button_get_active(rb_1D) == TRUE)
00794 gtk_image_set_from_pixbuf(image, extra->pixbuf_1D);
00795 else
00796 if (gtk_toggle_button_get_active(rb_2D) == TRUE)
00797 gtk_image_set_from_pixbuf(image, extra->pixbuf_2D);
00798 }
00799
00800
00801
00802
00803
00804 static void calc_infos_histo_1D(stat_t *extra)
00805 {
00806 guint i = 0;
00807 gint64 n = 1;
00808 guint64 max = 0;
00809 guint64 min = G_MAXUINT64;
00810 gint64 mean = extra->histo1D[0];
00811 gint64 diff = 0;
00812
00813 extra->infos_1D->nb_val = 0;
00814
00815 for (i=0; i<=255; i++)
00816 {
00817
00818 if (extra->histo1D[i] > max)
00819 max = extra->histo1D[i];
00820
00821
00822 if (extra->histo1D[i] < min)
00823 min = extra->histo1D[i];
00824
00825
00826 if (extra->histo1D[i] > 0)
00827 extra->infos_1D->nb_val++;
00828
00829
00830 diff = extra->histo1D[i] - mean;
00831 mean = mean + diff/n;
00832 n++;
00833 }
00834
00835 extra->infos_1D->min = min;
00836 extra->infos_1D->max = max;
00837 extra->infos_1D->mean = (guint64) mean;
00838 }
00839
00840
00841
00842
00843
00844 static void calc_infos_histo_2D(stat_t *extra)
00845 {
00846 guint i = 0;
00847 guint j = 0;
00848 gint64 n = 1;
00849 guint64 max = 0;
00850 guint64 min = G_MAXUINT;
00851 gint64 mean = extra->histo2D[0][0];
00852 gint64 diff = 0;
00853
00854 extra->infos_2D->nb_val = 0;
00855
00856 for (i=0; i<=255; i++)
00857 {
00858 for (j=0; j<=255; j++)
00859 {
00860
00861 if (extra->histo2D[i][j] > max)
00862 max = extra->histo2D[i][j];
00863
00864
00865 if (extra->histo2D[i][j] < min)
00866 min = extra->histo2D[i][j];
00867
00868
00869 if (extra->histo2D[i][j] > 0)
00870 extra->infos_2D->nb_val++;
00871
00872
00873 diff = extra->histo2D[i][j] - mean;
00874 mean = mean + diff/n;
00875 n++;
00876 }
00877 }
00878
00879 extra->infos_2D->min = min;
00880 extra->infos_2D->max = max;
00881 extra->infos_2D->mean = (guint64) mean;
00882 }
00883
00884
00885
00886
00887
00888 static void init_stats_pixbufs(stat_t *extra)
00889 {
00890
00891 extra->pixbuf_1D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00892 gdk_pixbuf_fill(extra->pixbuf_1D, 0xFFFFFF00);
00893 gdk_pixbuf_add_alpha(extra->pixbuf_1D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00894
00895 extra->pixbuf_2D = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 255, 255);
00896 gdk_pixbuf_fill(extra->pixbuf_2D, 0xFFFFFF00);
00897 gdk_pixbuf_add_alpha(extra->pixbuf_2D, TRUE, (guchar) 255, (guchar) 255, (guchar) 255);
00898
00899 }
00900
00901
00902
00903
00904
00905 static void make_pixbufs_from_histos(stat_t *extra)
00906 {
00907 init_stats_pixbufs(extra);
00908 calc_infos_histo_1D(extra);
00909 calc_infos_histo_2D(extra);
00910
00911 if (extra->infos_1D->max > 0)
00912 do_pixbuf_1D_from_histo1D(extra);
00913 if (extra->infos_2D->max > 0)
00914 do_pixbuf_2D_from_histo2D(extra, extra->infos_2D->max);
00915 }
00916
00917
00918
00919
00920
00921 static void plot_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y, guchar red, guchar green, guchar blue, guchar alpha)
00922 {
00923 guchar *pixels = NULL;
00924 guchar *p = NULL;
00925
00926 pixels = gdk_pixbuf_get_pixels(pixbuf);
00927
00928 p = pixels + y * gdk_pixbuf_get_rowstride(pixbuf) + x * gdk_pixbuf_get_n_channels(pixbuf);
00929
00930 p[0] = red;
00931 p[1] = green;
00932 p[2] = blue;
00933 p[3] = alpha;
00934
00935 }
00936
00937
00938
00939
00940
00941 static void line_in_pixbuf(GdkPixbuf *pixbuf, gint64 x, gint64 y)
00942 {
00943 guchar *pixels = NULL;
00944 guchar *p = NULL;
00945
00946 if (pixbuf != NULL)
00947 {
00948
00949 gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00950 gint n_channels = gdk_pixbuf_get_n_channels(pixbuf);
00951
00952 pixels = gdk_pixbuf_get_pixels(pixbuf);
00953
00954 while (y<255)
00955 {
00956 p = pixels + y * rowstride + x * n_channels;
00957 p[0] = (guchar) 255-(y/2);
00958 p[1] = (guchar) 16;
00959 p[2] = (guchar) y/2;
00960 p[3] = (guchar) 255;
00961 y++;
00962 }
00963 }
00964 }
00965
00966
00967
00968
00969
00970
00971 static void do_pixbuf_1D_from_histo1D(stat_t *extra)
00972 {
00973 guint i = 0;
00974 gint64 y = 0;
00975 gdouble inter = 0;
00976 gdouble y_norm = 0;
00977
00978 for (i=0; i<=255; i++)
00979 {
00980
00981 y_norm = (gdouble) extra->infos_1D->max - (gdouble) extra->histo1D[i];
00982 inter = (gdouble) (y_norm*255) / (gdouble)(extra->infos_1D->max);
00983 y = (gint64) inter;
00984 line_in_pixbuf(extra->pixbuf_1D, i, y);
00985 }
00986 }
00987
00988
00989
00990
00991
00992
00993
00994
00995 static void do_pixbuf_2D_from_histo2D(stat_t *extra, guint max_2D)
00996 {
00997
00998 guint i = 0;
00999 guint j = 0;
01000 guchar red;
01001 guchar green;
01002 guchar blue;
01003 gdouble height = 0;
01004 gdouble max = 0;
01005 gdouble min = 0;
01006 gdouble mean = 0;
01007 gdouble threshold1 = 0;
01008 gdouble threshold2 = 0;
01009 guchar ceill;
01010 guchar floor;
01011
01012 max = extra->infos_2D->max;
01013 min = extra->infos_2D->min;
01014 mean = extra->infos_2D->mean;
01015
01016 threshold1 = min + (mean - min) / 2;
01017 threshold2 = mean + (max - mean) / 2;
01018
01019 floor = (guchar) 50;
01020 ceill = (guchar) 200;
01021
01022 for (i=0; i<=255; i++)
01023 {
01024 for (j=0; j<=255; j++)
01025 {
01026 height = extra->histo2D[i][j];
01027
01028 if (height > 0)
01029 {
01030
01031 if (height >= min && height <= threshold1)
01032 {
01033 red = floor;
01034 green = floor;
01035 blue = (guchar) (height - min)*(ceill-floor) / threshold1;
01036
01037
01038
01039
01040
01041
01042 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01043 }
01044 else if (height > threshold1 && height <= threshold2)
01045 {
01046 red = (guchar) floor;
01047 green = (guchar) (height - threshold1)*(ceill-floor) / (threshold2 - threshold1);
01048 blue = (guchar) floor;
01049 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01050 }
01051 else if (height > threshold2 && height <= max)
01052 {
01053 red = (guchar) (height - threshold2)*(ceill-floor) / (max - threshold2);
01054 green = floor;
01055 blue = floor;
01056
01057
01058
01059
01060
01061
01062 plot_in_pixbuf(extra->pixbuf_2D, i, 255-j, red, green, blue, (guchar) 255);
01063 }
01064 }
01065 }
01066 }
01067 }
01068
01069