/* info.c Copyright (C) 2005-2006 Mark Tyler This file is part of mtPaint. mtPaint is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. mtPaint is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with mtPaint in the file COPYING. */ #include #include #include #include "global.h" #include "memory.h" #include "png.h" #include "mainwindow.h" #include "canvas.h" #include "mygtk.h" #include "inifile.h" #include "layer.h" // Maximum median cuts to make #define MAX_CUTS 128 int hs_rgb[256][3], // Raw frequencies hs_rgb_sorted[256][3], // Sorted frequencies hs_rgb_norm[256][3] // Normalized frequencies ; #define HS_GRAPH_W 256 #define HS_GRAPH_H 64 unsigned char *hs_rgb_mem = NULL; // RGB chunk holding graphs GtkWidget *hs_drawingarea; gboolean hs_norm; static void hs_plot_graph() // Plot RGB graphs { unsigned char *im, col1[3] = { mem_pal_def[0].red, mem_pal_def[0].green, mem_pal_def[0].blue}, col2[3]; int i, j, k, t, min[3], max[3], med[3], bars[256][3]; float f; for ( i=0; i<3; i++ ) col2[i] = 255 - col1[i]; im = hs_rgb_mem; if ( im != NULL ) { // Flush background to palette 0 colour j = HS_GRAPH_W * HS_GRAPH_H * mem_img_bpp; for ( i=0; i0; j=j-HS_GRAPH_H/2 ) { im = hs_rgb_mem + j*HS_GRAPH_W*3; for ( i=0; i0; j=j-HS_GRAPH_W/4 ) { im = hs_rgb_mem + j*3; for ( i=0; i 0 ) { t = j; break; } } min[k] = hs_rgb_sorted[t][k]; med[k] = hs_rgb_sorted[(t+255)/2][k]; max[k] = hs_rgb_sorted[255][k]; } // Calculate bar values - either linear or normalized if ( hs_norm ) { for ( k=0; k63 ) t=63; im = hs_rgb_mem + i*3 + (k+1)*HS_GRAPH_H*HS_GRAPH_W*3; im = im - HS_GRAPH_W*3; for ( j=0; j0; j-- ) // The venerable bubble sort { for ( i=0; i hs_rgb_sorted[i+1][k] ) { t = hs_rgb_sorted[i][k]; hs_rgb_sorted[i][k] = hs_rgb_sorted[i+1][k]; hs_rgb_sorted[i+1][k] = t; } } } } } static gint hs_expose_graph( GtkWidget *widget, GdkEventExpose *event ) { int x = event->area.x, y = event->area.y; int w = event->area.width, h = event->area.height; if ( hs_rgb_mem == NULL ) return FALSE; if ( x >= HS_GRAPH_W || y >= HS_GRAPH_H*mem_img_bpp ) return FALSE; mtMIN( w, w, HS_GRAPH_W-x ) mtMIN( h, h, HS_GRAPH_H*3-y ) gdk_draw_rgb_image (hs_drawingarea->window, hs_drawingarea->style->black_gc, x, y, w, h, GDK_RGB_DITHER_NONE, hs_rgb_mem + 3*(x + y*HS_GRAPH_W), HS_GRAPH_W*3 ); return FALSE; } //// INFORMATION WINDOW GtkWidget *info_window; gint delete_info( GtkWidget *widget, GdkEvent *event, gpointer data ) { gtk_widget_destroy(info_window); if ( hs_rgb_mem != NULL ) { free( hs_rgb_mem ); hs_rgb_mem = NULL; } return FALSE; } void pressed_information( GtkMenuItem *menu_item, gpointer user_data ) { char txt[256]; int i, j, orphans = 0, maxi; GtkWidget *vbox4, *vbox5, *table4, *hs_normalize_check; GtkWidget *scrolledwindow1, *viewport1, *table5, *button3; GtkAccelGroup* ag = gtk_accel_group_new(); info_window = add_a_window( GTK_WINDOW_TOPLEVEL, _("Information"), GTK_WIN_POS_CENTER, TRUE ); if ( mem_img_bpp == 1 ) gtk_widget_set_usize (GTK_WIDGET (info_window), -2, 400); vbox4 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox4); gtk_container_add (GTK_CONTAINER (info_window), vbox4); table4 = gtk_table_new (3, 2, FALSE); gtk_widget_show (table4); add_with_frame(vbox4, _("Memory"), table4, 5); gtk_container_set_border_width (GTK_CONTAINER (table4), 5); add_to_table( _("Total memory for main + undo images"), table4, 0, 0, 5 ); snprintf(txt, 60, "%1.1f MB", ( (float) mem_used() )/1024/1024 ); add_to_table( txt, table4, 0, 1, 5 ); mtMIN( maxi, mt_round( ((double) mem_undo_limit*1024*1024) / ( mem_width * mem_height * mem_img_bpp * (layers_total+1) ) - 1.25), MAX_UNDO-1 ) mtMAX( maxi, maxi, 0 ) snprintf(txt, 60, "%i / %i / %i", mem_undo_done, mem_undo_redo, maxi ); add_to_table( txt, table4, 1, 1, 5 ); add_to_table( _("Undo / Redo / Max levels used"), table4, 1, 0, 5 ); if ( mem_clipboard == NULL ) { add_to_table( _("Clipboard"), table4, 2, 0, 5 ); add_to_table( _("Unused"), table4, 2, 1, 5 ); } else { if ( mem_clip_bpp == 1 ) snprintf(txt, 250, _("Clipboard = %i x %i"), mem_clip_w, mem_clip_h ); if ( mem_clip_bpp == 3 ) snprintf(txt, 250, _("Clipboard = %i x %i x RGB"), mem_clip_w, mem_clip_h ); add_to_table( txt, table4, 2, 0, 5 ); snprintf(txt, 250, "%1.1f MB", ( (float) mem_clip_w * mem_clip_h * mem_clip_bpp )/1024/1024 ); add_to_table( txt, table4, 2, 1, 5 ); } if ( mem_img_bpp == 3) // RGB image so count different colours { add_to_table( _("Unique RGB pixels"), table4, 3, 0, 5 ); i = mem_count_all_cols(); if ( i<0 ) { maxi = mem_cols_used(1024); if ( maxi < 1024 ) snprintf(txt, 250, "%i", maxi); else sprintf( txt, ">1023" ); } else snprintf(txt, 250, "%i", i); add_to_table( txt, table4, 3, 1, 5 ); } if ( layers_total>0 ) { add_to_table( _("Layers"), table4, 4, 0, 5 ); snprintf(txt, 60, "%i", layers_total ); add_to_table( txt, table4, 4, 1, 5 ); add_to_table( _("Total layer memory usage"), table4, 5, 0, 5 ); snprintf(txt, 60, "%1.1f MB", ( (float) mem_used_layers() )/1024/1024 ); add_to_table( txt, table4, 5, 1, 5 ); } vbox5 = gtk_vbox_new (FALSE, 0); gtk_widget_show (vbox5); add_with_frame(vbox4, _("Colour Histogram"), vbox5, 4); hs_norm = FALSE; hs_rgb_mem = malloc( HS_GRAPH_W * HS_GRAPH_H * 3 * mem_img_bpp ); hs_populate_rgb(); hs_plot_graph(); hs_drawingarea = gtk_drawing_area_new (); gtk_widget_show (hs_drawingarea); gtk_box_pack_start (GTK_BOX (vbox5), hs_drawingarea, FALSE, FALSE, 0); gtk_widget_set_usize (hs_drawingarea, HS_GRAPH_W, HS_GRAPH_H*mem_img_bpp); gtk_signal_connect_object( GTK_OBJECT(hs_drawingarea), "expose_event", GTK_SIGNAL_FUNC (hs_expose_graph), NULL ); hs_normalize_check = sig_toggle(_("Normalize"), FALSE, NULL, GTK_SIGNAL_FUNC(hs_click_normalize)); gtk_box_pack_start(GTK_BOX (vbox5), hs_normalize_check, FALSE, FALSE, 0); if ( mem_img_bpp == 1 ) { mem_get_histogram(CHN_IMAGE); j = 0; for ( i=0; i 0 ) j++; snprintf( txt, 250, _("Colour index totals - %i of %i used"), j, mem_cols ); scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); gtk_widget_show (scrolledwindow1); add_with_frame_x(vbox4, txt, scrolledwindow1, 4, TRUE); gtk_container_set_border_width (GTK_CONTAINER (scrolledwindow1), 4); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); viewport1 = gtk_viewport_new (NULL, NULL); gtk_widget_show (viewport1); gtk_container_add (GTK_CONTAINER (scrolledwindow1), viewport1); /// Big index table table5 = gtk_table_new (mem_cols+2+1, 3, FALSE); gtk_widget_show (table5); gtk_container_add (GTK_CONTAINER (viewport1), table5); add_to_table( _("Index"), table5, 0, 0, 5 ); add_to_table( _("Canvas pixels"), table5, 0, 1, 5 ); add_to_table( "%", table5, 0, 2, 5 ); for ( i=0; i