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