/*~~~~~~~~~~~~~WRITTEN BY, ~~Abhijit Singh~~ ,TRAINEE,SISL~~~~~~~~~~~~~~~*/ /*~~~~~~~~~ Imp. Note This program plots a graph of some dummy values in the upper section of the drawing area. X-axis corresponds to number of frames( or simply natural numbers 1 to 40).And Y-axis corresponds to PSNR values ( or some floating values) A "zoom window" moves over the graph and whatever area falls within the window is scaled and drawn in the lower section of the drawing area. The graph has as its origin :-(x,y) where y is the minimum value falling in the "zoom window" and x is the corresponding frame number. The zoomed graph stretches to X,Y where Y-> maximum floating value in the "zoom window" and X = x + Number of points in the "zoom window".(though i 've drawn it exceeding mark X). A button named "Data" shows how switching between two windows should be done. Clicking it shows another window with some components. See their usage. They might prove helpful. */ #include #include #include #include #include #include #ifdef WIN32 #include #define Delay(x) Sleep(x) #else #include #define Delay(x) sleep(x) #endif #define Unit_Size 10 // Graph Unit const int WX_EXTENT = 1024; // Parent Window dimensions const int WY_EXTENT = 768; const double X_EXTENT = 2048.0; // The maximum X of the Drawing_Area const double Y_EXTENT = 1000.0; // The maximum Y of the Drawing_Area const int GX_EXTENT = 2048; // These extents define the size of the graph. const int GY_EXTENT = 200; // Keep the entity --> (Y_EXTENT - GY_EXTENT)/2 + GY_EXTENT // an even number to get a symetric division of the drawing area #define X_SHIFT 10 //Transformation of X-axis #define Y_SHIFT (GY_EXTENT/2) //Transformation of Y-axis #define Transp_Window_Width 100 //While changing this value, remember to update 2D 'buf' in //'Mov_Transp_Window' accordingly #define Scale_Factor 5 #define PrintingOFF struct Point { double x; double y; } Coords[50]; static GdkPixmap *Pixmap = NULL,*ImgPixMap = NULL; static GdkPixbuf *ImgBuf; const int count = 20; /*~~~~~~~~~Number of pixel points~~~~~~~~~~~*/ static GError *error; static GtkObject *adj; static GdkPoint Pix_Array[50]; int width,height; /* Create a new Pixmap of the appropriate size to store the graph */ static gboolean configure_graph_event (GtkWidget *widget, GdkEventConfigure *event) { if (Pixmap) g_object_unref (Pixmap); Pixmap = gdk_pixmap_new (widget->window,(int) X_EXTENT, (int) Y_EXTENT,-1); gdk_pixbuf_render_to_drawable_alpha(ImgBuf, Pixmap, 20, 20, //Source co-ordinates i.e Start from here (int) X_EXTENT-width, (int) Y_EXTENT-height/2, //Destination co-ordinates i.e the drawing area width-40, height-40, //Copy this much area from the Source GDK_PIXBUF_ALPHA_BILEVEL, 32, GDK_RGB_DITHER_NORMAL, 0, 0); return TRUE; } /* Redraw the screen from the Pixmap */ static gboolean expose_graph ( GtkWidget *widget, GdkEventExpose *event) { gdk_draw_drawable (widget->window, widget->style->fg_gc[GTK_STATE_NORMAL], Pixmap, /* Only copy the area that was exposed. */ 0,0, 0,0,(int) X_EXTENT,(int) Y_EXTENT); return TRUE; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~GRAPH MODIFCATION~~~~~~~~~~~~~~~~~~~~~~~*/ /* Draw the graph here */ static void Modify_Graph (GtkWidget *widget, GtkAdjustment *adj) { int x,y,i = 0,No_Of_Marks; char buf[20]; GdkGC *p; GdkColor c; PangoLayout *Layout; PangoFontDescription *fontdesc; gdouble Y_Min,Y_Max,Step_Size,Mark,Y_Disp; /*~~~~~~~~Creating a new GdkGC with a different foreground~~~~~*/ p = gdk_gc_new(widget->window); c.red = 55000; c.blue = 60000 ; c.green = 55000; gdk_gc_set_rgb_fg_color(p,&c); //gdk_gc_set_line_attributes (p, 1, GDK_LINE_SOLID, 0, 0); gdk_draw_rectangle (Pixmap,p,FALSE,X_SHIFT,0,GX_EXTENT,GY_EXTENT); /* Frame No. PSNR Value */ Coords[0].x = 10.0; Coords[0].y = 10.5; Coords[1].x = 11.0; Coords[1].y = 8.0; ; Coords[2].x = 12.0; Coords[2].y = 2.5; Coords[3].x = 13.0; Coords[3].y = 7.0; Coords[4].x = 14.0; Coords[4].y = -11.5; Coords[5].x = 16.0; Coords[5].y = 8.0; Coords[6].x = 17.0; Coords[6].y = 6.5; Coords[7].x = 18.0; Coords[7].y = 9.0; Coords[8].x = 19.0; Coords[8].y = 7.5; Coords[9].x = 20.0; Coords[9].y = 21.0; Coords[10].x = 24.0; Coords[10].y = 8.0; ; Coords[11].x = 22.0; Coords[11].y = 8.0; ; Coords[12].x = 25.0; Coords[12].y = 2.5; Coords[13].x = 26.0; Coords[13].y = 7.0; Coords[14].x = 27.0; Coords[14].y = 6.5; Coords[15].x = 28.0; Coords[15].y = -8.0; Coords[16].x = 29.0; Coords[16].y = 6.5; Coords[17].x = 30.0; Coords[17].y = 9.0; Coords[18].x = 39.0; Coords[18].y = 7.5; Coords[19].x = 40.0; Coords[19].y = 4.0; /*~~~~~Find the Y_Min and Y_Max from the array 'Coords'~~~~~~*/ Y_Min = GY_EXTENT; Y_Max = -65535.0; for ( i = 0; i < count; i++) { if ( Y_Min > fabs(Coords[i].y) ) Y_Min = fabs(Coords[i].y); if ( Y_Max < fabs(Coords[i].y) ) Y_Max = fabs(Coords[i].y); } sprintf(buf,"Origin - (%d,%.2f)",0,Y_Min); Layout = gtk_widget_create_pango_layout (widget, buf); fontdesc = pango_font_description_from_string ("Times New Roman 10"); pango_layout_set_font_description (Layout, fontdesc); gdk_draw_layout (Pixmap,p,800,GY_EXTENT-20, Layout); /* strcpy(buf,"Abhijit Singh"); Layout = gtk_widget_create_pango_layout (widget, buf); fontdesc = pango_font_description_from_string ("Times New Roman 16"); pango_layout_set_font_description (Layout, fontdesc); gdk_draw_layout (Pixmap,p,400,40,Layout); */ /*~~~~~~~Draw the calliberations along Y-axis~~~~~~~~*/ No_Of_Marks = (int) ( (GY_EXTENT)/2 / Unit_Size ); /*~~~~WE FIND IT ONLY FOR THE UPPER HALF~~~~*/ Step_Size = (Y_Max - Y_Min) / No_Of_Marks; Mark = Y_Max; for ( y = 0; y < 2*No_Of_Marks; y++) /*~~~~~SINCE THE GRAPH IS SYMETRIC, WE MULT. BY 2~~~~*/ { gdk_draw_line (Pixmap,p, X_SHIFT - 5, y*Unit_Size, X_SHIFT + 5, y*Unit_Size); ( y*Unit_Size < Y_SHIFT ) ? sprintf(buf,"%.2f",Mark) : sprintf(buf,"-%.2f",Mark); Layout = gtk_widget_create_pango_layout (widget, buf); fontdesc = pango_font_description_from_string ("Times New Roman 6"); pango_layout_set_font_description (Layout, fontdesc); if ( !(y % 2) && y*Unit_Size != Y_SHIFT ) //i.e don't draw the Mark at the origin gdk_draw_layout(Pixmap,p, X_SHIFT+10, y*Unit_Size-Unit_Size/2, //More like a hit n trial formula Layout); if ( y*Unit_Size < Y_SHIFT) //If above the origin Mark -= Step_Size; else { if ( y*Unit_Size == Y_SHIFT ) //If at origin then Mark = Y_Min + Step_Size; //initialize with next Mark else Mark += Step_Size; //If below the origin } //End of IF }//End of FOR /*~~~~~~~~~~~~~~~~~~~~~~~Draw then Custom X-Axis~~~~~~~~~~~~~~~~~~~~~~~~~~*/ gdk_draw_line (Pixmap,p,X_SHIFT,Y_SHIFT,GX_EXTENT,Y_SHIFT); /*~~~~~~~~~~~~~~Draw the calliberations along X-axis~~~~~~~~~~~~~~*/ for ( x = 0; x < GX_EXTENT/Unit_Size; x++) { gdk_draw_line (Pixmap,p, x*Unit_Size+X_SHIFT, Y_SHIFT-5, x*Unit_Size+X_SHIFT, Y_SHIFT+5); sprintf(buf,"%d",x); Layout = gtk_widget_create_pango_layout (widget, buf); fontdesc = pango_font_description_from_string ("Times New Roman 6"); pango_layout_set_font_description (Layout, fontdesc); if ( !(x % 2) && x ) //Every even position except 0 gdk_draw_layout(Pixmap,p, x*Unit_Size+X_SHIFT, Y_SHIFT+5, Layout ); } /*~~~~~~~~~~~~~~~Create pixel mappings i.e the pixel values equivalent to the floating values~~~~~~~~~~~~~~*/ for ( i = 0; i < count ; i++) { Pix_Array[i].x = (int) Coords[i].x * Unit_Size + X_SHIFT; Y_Disp = fabs(Coords[i].y) - Y_Min; //Actual displacement in floating points //from the origin which is Y_Min /*~~~~~Restore the sign but value stored is the displacement~~~~~~*/ Coords[i].y = ( Coords[i].y < 0.0 ) ? Y_Disp*-1.0 : Y_Disp; Pix_Array[i].y = Y_SHIFT - (int)( (Coords[i].y/Step_Size) * Unit_Size ); //The subtracted part is the displacement //from the origin in pixels } /* for (i = 0; i < count; i++) printf("\n\nPix_array[%d].x \t %d Pix_Array[%d].y \t %d \t\t Coords[%d].x \t %f Coords[%d].y %f", i, Pix_Array[i].x, i, Pix_Array[i].y, i, Coords[i].x, i, Coords[i].y); */ /*~~~~~~~~Print the co-ordinates as (x,y) at each Pix_Array point~~~~~~~~~*/ for (i = 0; i < count; i++) { /*~~~~~~Restore to original values in floating point~~~~~~*/ Coords[i].y = ( Coords[i].y < 0.0 ) ? Coords[i].y - Y_Min : Coords[i].y + Y_Min; c.red = 0; c.blue = 0 ; c.green = 0; gdk_gc_set_rgb_fg_color(p,&c); sprintf(buf,"(%.2f,%.2f)",Coords[i].x,Coords[i].y); Layout = gtk_widget_create_pango_layout (widget, buf); fontdesc = pango_font_description_from_string ("Times New Roman 8"); pango_layout_set_font_description (Layout, fontdesc); #ifdef PrintingON if ( i % 2 ) gdk_draw_layout(Pixmap,p,Pix_Array[i].x,Pix_Array[i].y+5,Layout); else gdk_draw_layout(Pixmap,p,Pix_Array[i].x,Pix_Array[i].y-5,Layout); #endif /* if ( Coords[i].y != Y_Min) //Horizontal ; Not to draw over the X-axis { c.red = 10000; c.blue = 15000 ; c.green = 10000; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_line(Pixmap, p,X_SHIFT,Pix_Array[i].y,Pix_Array[i].x,Pix_Array[i].y); } if ( X_SHIFT != Pix_Array[i].x ) //Vertical ; Not to draw over the Y-axis { c.red = 15000; //Brightness for the vertically drawn lines c.blue = 20000 ; //appears to be quite less than the ones drawn c.green = 15000; //horizontally gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_line(Pixmap, p,Pix_Array[i].x,Y_SHIFT,Pix_Array[i].x,Pix_Array[i].y); } */ } c.red = 45000; c.blue =65535 ; c.green = 55000; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_lines(Pixmap, p, Pix_Array, (gint)count); gtk_widget_queue_draw_area (widget,0,0, (int) X_EXTENT,(int) Y_EXTENT); gdk_window_process_updates(widget->window,TRUE); //Expedites the refreshing process pango_font_description_free (fontdesc); g_object_unref (Layout); gdk_gc_unref(p); } /*~~~~~~~~~~~~~~~~~MOV_TRANSP_WINDOW~~~~~~~~~~~~~~~~~~~~*/ static void Mov_Transp_Window (GtkWidget *widget, GtkAdjustment *adj) { static GdkPoint Pix_ZoomArray[50]; GdkGC *p; GdkColor c; PangoLayout *Layout; PangoFontDescription *fontdesc; gint x,y,Graph_Cell_Width,Graph_Cell_Height; int i,j,k,r,MinX,No_Of_Marks,Zoom_Pts; char buf[50][25]; //'25' is a trial value, must be changed if density of points // in the transparent window increases. char Buf_Mark[20]; double Step_Size,Mark,Y_Max,Y_Min,Y_Disp; struct Win_Point { double x; double y; }Win_Coords[50]; int New_Y_SHIFT; /*~~~~~~~~Creating a new GdkGC with a different foreground~~~~~*/ p = gdk_gc_new(widget->window); c.red = 30000; c.blue = 35000 ; c.green = 30000; gdk_gc_set_rgb_fg_color(p,&c); /*~~~~~Clear the drawing area to re-draw the transparent window at a position decided by the slider value~~~~~~~~*/ configure_graph_event(widget,NULL); /*~~~~~~~~~~~~~~Draw the transparent window~~~~~~~~~~~~~~*/ gdk_draw_rectangle (Pixmap,p,TRUE, (gint) adj->value * Unit_Size + X_SHIFT, 0, Transp_Window_Width,Y_SHIFT); /*~~~~~~~~~~~~~Draw a Mesh below the actual graph~~~~~~~~~~~~~~*/ Graph_Cell_Width = 10; Graph_Cell_Height = 10; x = X_SHIFT ; for ( y = GY_EXTENT+1; y <= Y_EXTENT; y += Graph_Cell_Height ) { c.red = 15000; c.blue = 20000 ; c.green = 15000; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_line(Pixmap, p,x,y,GX_EXTENT,y); } y = GY_EXTENT+1; for ( x = X_SHIFT; x <= GX_EXTENT; x += Graph_Cell_Width ) { c.red = 20000; //Brightness for the vertically drawn lines c.blue = 25000 ; //appears to be quite less than the ones drawn c.green = 20000; //horizontally. So increased magnitude gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_line(Pixmap, p,x,y,x,(int) Y_EXTENT); } /*~~~~~~~~~~~~Identify the points that fall within the transparent window~~~~~~~~~~~~*/ Y_Min = Y_EXTENT; Y_Max = -65535.0; k = (gint) adj->value * Unit_Size + X_SHIFT; Zoom_Pts = 0; // printf("\n\n"); for ( i = 0, Zoom_Pts = 0; i < count; i++) if ( Pix_Array[i].x >= k && Pix_Array[i].x <= Transp_Window_Width + k) { Win_Coords[Zoom_Pts].x = Coords[i].x; Win_Coords[Zoom_Pts].y = Coords[i].y; sprintf(buf[Zoom_Pts],"(%d,%.2f)", (int) Win_Coords[Zoom_Pts].x, Win_Coords[Zoom_Pts].y); /*~~~~~Find the Y_Min and Y_Max from the array 'Coords'~~~~~~*/ if ( Y_Min > fabs(Win_Coords[Zoom_Pts].y) ) Y_Min = fabs(Win_Coords[Zoom_Pts].y); if ( Y_Max < fabs(Win_Coords[Zoom_Pts].y) ) Y_Max = fabs(Win_Coords[Zoom_Pts].y); Zoom_Pts++; } /* THE "New_Y_SHIFT" IS THE MAGNITUDINAL HALF OF THE SECOND DRAWING AREA, THE AREA USED FOR DRAWING THE ZOOMED GRAPH. SO WE ADD ( GY_EXTENT ) TO ACTUALLY TRANSFORM THE POINTS RELATIVE TO THE POSITIONAL HALF WHICH LIES AT [ New_Y_SHIFT + GY_EXTENT ] */ New_Y_SHIFT = (int ) (Y_EXTENT - GY_EXTENT) / 2; /*~~~~~~~~~~~~~~~Create pixel mappings i.e the pixel values equivalent to the floating values~~~~~~~~~~~~~~*/ k = 0; j = Unit_Size * Scale_Factor; r = New_Y_SHIFT ; MinX = 65535; No_Of_Marks = New_Y_SHIFT / j ; Step_Size = (Y_Max - Y_Min) / No_Of_Marks; for ( i = 0; i < Zoom_Pts ; i++) { Pix_ZoomArray[i].x = (int) Win_Coords[i].x * j + X_SHIFT; Y_Disp = fabs(Win_Coords[i].y) - Y_Min; //Actual displacement in floating points //from the origin which is Y_Min /*~~~~~Restore the sign but value restored is the displacement~~~~~~*/ Win_Coords[i].y = ( Win_Coords[i].y < 0.0 ) ? Y_Disp*-1.0 : Y_Disp; Pix_ZoomArray[i].y = (New_Y_SHIFT - (int)( (Win_Coords[i].y/Step_Size) * j )) + GY_EXTENT; //The subtracted part is the displacement from the origin in pixels if ( Pix_ZoomArray[i].x < MinX ) { MinX = Pix_ZoomArray[i].x; k = i; } } /*~~~~~~~~~~Translating towards Y-axis by MinX and then away from Y-axis by Unit_Size~~~~~~~~~~~~*/ for ( i = 0 ; i < Zoom_Pts; i++) Pix_ZoomArray[i].x -= MinX - X_SHIFT; /*~~Subtracting 'Unit_Size' ultimately adds to the x value~~*/ /* -(-) = + */ /*~~~~~~~~~~~~~~~~~~~~~~~Draw then Custom X-Axis~~~~~~~~~~~~~~~~~~~~~~~~~~*/ c.red = 60000; c.blue = 65000 ; c.green = 55000; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_line (Pixmap,p,X_SHIFT, New_Y_SHIFT + GY_EXTENT, GX_EXTENT, New_Y_SHIFT + GY_EXTENT); /*~~~~~~~~~~~~~~Draw the calliberations along X-axis~~~~~~~~~~~~~~*/ i = Scale_Factor*Unit_Size; j = New_Y_SHIFT + GY_EXTENT; for ( x = 0; x < GX_EXTENT/i ; x++) { gdk_draw_line (Pixmap,p, x*i+X_SHIFT, j + 5, x*i+X_SHIFT, j - 5); sprintf(Buf_Mark,"%d",x + (int) Win_Coords[k].x ); Layout = gtk_widget_create_pango_layout (widget, Buf_Mark); fontdesc = pango_font_description_from_string ("Times New Roman 8"); pango_layout_set_font_description (Layout, fontdesc); if ( x ) gdk_draw_layout(Pixmap,p,x*i+X_SHIFT,j + 5,Layout); } /*~~~~~~~~~~~~~~~~~~~~~~~Draw then Custom Y-Axis~~~~~~~~~~~~~~~~~~~~~~~~~~*/ gdk_draw_line (Pixmap,p,X_SHIFT, GY_EXTENT, X_SHIFT, (int) Y_EXTENT); /*~~~~~~~Draw the calliberations along Y-axis~~~~~~~~*/ j = Unit_Size * Scale_Factor; No_Of_Marks = New_Y_SHIFT / j ; Y_Max = (int) Y_Max == -65535 ? 0.0 : Y_Max; Y_Min = (int) Y_Min == Y_EXTENT ? 0.0 : Y_Min; Step_Size = (Y_Max - Y_Min) / No_Of_Marks; Mark = Y_Max != -65535 ? Y_Max : 0.0; for ( y = 0 ; y <= 2*No_Of_Marks ; y++) { i = y*j+GY_EXTENT ; gdk_draw_line (Pixmap,p, X_SHIFT-5, i, X_SHIFT+5, i); ( i < New_Y_SHIFT + GY_EXTENT ) ? sprintf(Buf_Mark,"%.2f",Mark) : sprintf(Buf_Mark,"-%.2f",Mark); Layout = gtk_widget_create_pango_layout (widget, Buf_Mark); fontdesc = pango_font_description_from_string ("Times New Roman 8"); pango_layout_set_font_description (Layout, fontdesc); if ( i != New_Y_SHIFT + GY_EXTENT ) //i.e don't draw the Mark at the origin gdk_draw_layout(Pixmap,p, X_SHIFT+10, i, Layout); if ( i < New_Y_SHIFT + GY_EXTENT ) //If above the origin Mark -= Step_Size; else { if ( i == New_Y_SHIFT + GY_EXTENT ) //If at origin then Mark += Step_Size; //initialize with next Mark else Mark += Step_Size; //If below the origin } //End of IF }//End of FOR sprintf(Buf_Mark,"Origin - (%d,%.2f)",(int) Win_Coords[k].x ,Y_Min); Layout = gtk_widget_create_pango_layout (widget, Buf_Mark); fontdesc = pango_font_description_from_string ("Times New Roman 14"); pango_layout_set_font_description (Layout, fontdesc); gdk_draw_layout (Pixmap,p,800,GY_EXTENT+20, Layout); /*~~~~~~~~~~~~~~Plot the ZOOMED graph on the mesh~~~~~~~~~~~~~~~~*/ c.red = 65535; c.blue = 65535 ; c.green = 65535; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_lines(Pixmap, p, Pix_ZoomArray, Zoom_Pts); /*~~~~~~~~Print the co-ordinates as (x,y) at each Pix_Array point~~~~~~~~~*/ for (i = 0; i < Zoom_Pts; i++) { // printf("\n---- %s %d \t%.2f", buf[i], (int) Win_Coords[i].x, Win_Coords[i].y ); Layout = gtk_widget_create_pango_layout (widget, buf[i]); fontdesc = pango_font_description_from_string ("Times New Roman 10"); pango_layout_set_font_description (Layout, fontdesc); c.red = 10535; c.blue = 10535; c.green = 65535; gdk_gc_set_rgb_fg_color(p,&c); /*~~~~~~~Prevent the overlapping of the dislayed co-ordinate values~~~~~~~~~*/ /* 15 is SUBTARCTED in first case and 5 is ADDED in the second */ /* because fonts grow downward from the starting point. Therefore */ /* compensation provided for the font size ( = 10, above ) */ if ( i < Zoom_Pts && Pix_ZoomArray[i].y < Pix_ZoomArray[i+1].y ) gdk_draw_layout(Pixmap,p,Pix_ZoomArray[i].x+20,Pix_ZoomArray[i].y - 15,Layout); else gdk_draw_layout(Pixmap,p,Pix_ZoomArray[i].x+20,Pix_ZoomArray[i].y + 5,Layout); c.red = 55535; c.blue = 65535 ; c.green = 50535; gdk_gc_set_rgb_fg_color(p,&c); gdk_draw_arc (Pixmap, p, TRUE, Pix_ZoomArray[i].x - 5 , Pix_ZoomArray[i].y - 5, 10,10, 0, 360*64); // gdk_draw_rectangle (Pixmap,p, TRUE, Pix_ZoomArray[i].x - 3, Pix_ZoomArray[i].y - 3, 6,6); } /* for (i = 0; i < Zoom_Pts; i++) printf("\n\nPix_Zoomarray[%d].x \t %d Pix_ZoomArray[%d].y \t %d ", i, Pix_ZoomArray[i].x, i, Pix_ZoomArray[i].y ); */ /*~~~~~~~~~~~~~~~~~~~~IMP. NOTE~~~~~~~~~~~~~~~~~~~~*/ /* CALLING FOLLOWING FUNCTION IMMEDIATELY AFTER CALLING 'configure_event' * ,OR SOMEWHERE BEFORE DRAWING THE TRANSPARENT WINDOW AND PLOTTING THE * ZOOMED GRAPH, CAUSES HORRIBLE FLICKER. I DON'T KNOW THE REASON. * CALLING IT HERE MAKES THE DRAWING PREOCESS SMOOTH AS EXPECTED */ /*~~~~~~~~~~~~~Redraw the ORIGINAL graph~~~~~~~~~~~~~~*/ Modify_Graph(widget, (gpointer) adj); /*~~~~~~~~~~~~~Request fo the refreshing/redrawing of the area~~~~~~~~~~*/ /*~~~~~COMMENTING FOLLOWING CALLS DOESN'T CAUSE ANY VISIBLE SPEEDUP OR SLOWDOWN~~~~~~~~*/ /* * SO WE COMMENT THEM FOR THE TIME BEING * SINCE A SET OF SIMILAR CALLS IS BEING MADE IN 'Modify_Graph(.......)' gtk_widget_queue_draw_area (widget,0,0,(int) X_EXTENT, (int) Y_EXTENT); gdk_window_process_updates(widget->window,TRUE); //Expedites the refreshing process */ } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~BUTTON PRESS~~~~~~~~~~~~~~~~~~~~~~~~*/ static gboolean Graph_button_press_event (GtkWidget *widget, GdkEventButton *event) { if (Pixmap == NULL) return FALSE; /* paranoia check, in case we haven't gotten a configure event */ //if (event->button == 1) // Mov_Transp_Window (widget, (gpointer) adj); /* We've handled the event, stop processing */ return TRUE; } /*~~~~~~~~~~~~~~~~~~~~FILE SELECTION WINDOW~~~~~~~~~~~~~~~~*/ static gboolean Swap_Windows ( GtkButton *Button , gpointer Win_Array[2]) { GtkWidget *Parent_Window = GTK_WIDGET (Win_Array[0]); GtkWidget *File_Select = GTK_WIDGET (Win_Array[1]); if ( GTK_WIDGET_VISIBLE (Parent_Window) ) { gtk_widget_hide( Parent_Window ); gtk_widget_show_all( File_Select ); } else { gtk_widget_hide( File_Select ); gtk_widget_show_all( Parent_Window ); } return TRUE; } /*~~~~~~~~~~~~~~~~~~~~~MESS WITH THIS CODE TO GET/DISPLAY THE CHOSEN FILE~~~~~~~~~~~~~~*/ static void Get_File_Name(GtkWidget *W, gpointer File_Entry) { GtkWidget *Dialog; char *File_Name; gint Response; Dialog = gtk_file_chooser_dialog_new ("Open File", NULL , GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, NULL); gtk_widget_show( Dialog ); Response = gtk_dialog_run (GTK_DIALOG (Dialog) ); switch( Response ) { case GTK_RESPONSE_ACCEPT: File_Name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (Dialog)); gtk_entry_set_text ( GTK_ENTRY (File_Entry) , File_Name); g_free (File_Name); gtk_widget_destroy (Dialog); break; case GTK_RESPONSE_CANCEL: gtk_widget_destroy (Dialog); } } /*~~~~~~~~~~~~~~~~~~~~~SCRIBBLE HERE TO CHECK AND DISPLAY THE TEXT ACTIVE IN COMBO BOX ENTRY ~~~~~~~~~~~~~~*/ static void Get_Active_Combo_Entry(GtkComboBox *Combo_Box) { GtkMessageDialog *MsgDialog; char *Unit = gtk_combo_box_get_active_text ( Combo_Box); if ( stricmp(Unit,"MSE") && stricmp(Unit,"PSNR") ) { MsgDialog = GTK_MESSAGE_DIALOG ( gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Invalid Unit of Measure") ); gtk_dialog_run (GTK_DIALOG (MsgDialog)); gtk_widget_destroy ( GTK_WIDGET (MsgDialog) ); } } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~MAIN~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~MAIN~~~~~~~~~~~~~~~~~~~~~~~*/ int main(int argc,char *argv[]) { GtkWidget *Window, *Scrolled_Window, *File_Select, *Win_Array[2]; GtkWidget *HBox, *VBox, *FS_VBox, *FS_Ref_HBox, *FS_Proc_HBox, *FS_Measure_VBox; GtkWidget *FS_Color_HBox, *FS_Button_Panel_HBox ; GtkWidget *Drawing_Area; //FS ---> File Selection GtkWidget *VScale; GtkWidget *Quit_Button, *Data_Button, *FS_Ref_Browse_Button, *FS_Proc_Browse_Button; GtkWidget *FS_Process_Button, *FS_Quit_Button; GtkWidget *Y_Radio_Button, *U_Radio_Button, *V_Radio_Button; GtkWidget *FS_Frame, *FS_Measure_Frame, *FS_Color_Frame, *FS_Button_Panel_Frame; GtkWidget *FS_Ref_Label, *FS_Proc_Label, *Y_Radio_Button_Label; GtkWidget *FS_Ref_File_Entry, *FS_Proc_File_Entry; GtkWidget *FS_Measure_Combo; gdk_rgb_init (); gtk_init(&argc,&argv); { /*~~~~~~~~~~~PARENT WINDOW~~~~~~~~~~*/ Window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (Window), "Graph Zoomer"); g_signal_connect (Window, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request(Window,(gint) WX_EXTENT/2, (gint) WY_EXTENT/2); gtk_container_set_border_width (GTK_CONTAINER (Window), 0); Win_Array[0] = Window; HBox = gtk_hbox_new (FALSE, 0); gtk_container_add ( GTK_CONTAINER (Window) , HBox); gtk_widget_show(HBox); Scrolled_Window = gtk_scrolled_window_new (NULL,NULL); gtk_container_set_border_width (GTK_CONTAINER (Scrolled_Window), 0); /* the policy is one of GTK_POLICY AUTOMATIC, or GTK_POLICY_ALWAYS. * GTK_POLICY_AUTOMATIC will automatically decide whether you need * scrollbars, whereas GTK_POLICY_ALWAYS will always leave the scrollbars * there. The first one is the horizontal scrollbar, the second, * the vertical. */ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (Scrolled_Window), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_box_pack_start (GTK_BOX (HBox) , Scrolled_Window, TRUE, TRUE, 0); gtk_widget_show (Scrolled_Window); Drawing_Area = gtk_drawing_area_new (); //The graph will be drawn on this area gtk_widget_set_size_request (Drawing_Area, (gint) X_EXTENT, (gint) Y_EXTENT); // set a minimum size gtk_scrolled_window_add_with_viewport ( GTK_SCROLLED_WINDOW (Scrolled_Window), Drawing_Area); /*~~~~~~~~~~~~~Create a vbox to contain a side panel for slider and buttons~~~~~~~~~~~~~~~*/ VBox = gtk_vbox_new (FALSE, 0); // FALSE ->unequal space allotments to the widgets // 0-> No spacing b/w the widgets gtk_container_set_border_width (GTK_CONTAINER (VBox), 0); gtk_box_pack_start ( GTK_BOX (HBox), VBox, FALSE, FALSE, 0); /* Initial value, Minimum, Maximum, step_increment, page_increment, page_size * Note that the page_size value only makes a difference for * scrollbar widgets, and the highest value you'll get is actually * (upper - page_size). */ /*~~~~We divide here by Unit_Size so that the 'adj->value' tells the actual frame number~~~*/ /* * i.e the 'adj->value' should match the point on the x-axis where the left most edge of * transparent window falls */ adj = gtk_adjustment_new (41.0, 0.0, (GX_EXTENT-Transp_Window_Width)/Unit_Size, 1.0, 1.0, 1.0); //the graph parameters can be placed in this array VScale = gtk_vscale_new (GTK_ADJUSTMENT (adj)); //If the size request in a given direction is -1 (unset), //then the "natural" size request of the widget will be used instead gtk_widget_set_size_request (GTK_WIDGET (VScale), 10,400); //The value displayed will be continuously updated as the slider is moved gtk_range_set_update_policy (GTK_RANGE (VScale),GTK_UPDATE_CONTINUOUS); //Set the number of decimal places that are displayed in the 'value' ; 0 for integer display gtk_scale_set_digits (GTK_SCALE (VScale), 0); //The position of the 'value', TOP , BOTTOM, LEFT, RIGHT gtk_scale_set_value_pos (GTK_SCALE (VScale), GTK_POS_TOP); //Specifies whether the current value is displayed as a string next to the slider. gtk_scale_set_draw_value (GTK_SCALE (VScale), TRUE); /* 'TRUE' in the 3rd arg. causes the total space in 'VBox' to be evenly distributed between all children of 'VBox' 'FALSE' in the 4rth argument causes extra padding to be done so that one element doesn't overlap the other,( Has effect only if 3rd arg is set to TRUE ) */ gtk_box_pack_start (GTK_BOX (VBox), VScale,FALSE,FALSE, 0); /*~~~~~Create a Quit/Exit button attached to/contained in the 'VScale' ~~~~~*/ Quit_Button = gtk_button_new_with_mnemonic ("_Quit"); gtk_box_pack_start (GTK_BOX (VBox), Quit_Button, FALSE, FALSE, 0); GTK_WIDGET_SET_FLAGS (Quit_Button, GTK_CAN_DEFAULT); /*~~~~~Create a button which opens window for selecting data files and sets other options~~~~~*/ Data_Button = gtk_button_new_with_mnemonic ("_Data"); gtk_box_pack_start (GTK_BOX (VBox), Data_Button, FALSE, TRUE, 10); /*******************************************************************/ /*~~~~~~~~~~~~~~~~~CREATING THE FILE SELECTION WINDOW~~~~~~~~~~~~~~*/ /*******************************************************************/ File_Select = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title (GTK_WINDOW (File_Select), "File Selection"); g_signal_connect (File_Select, "delete_event", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_set_size_request (File_Select , (gint) WX_EXTENT * 2/3, (gint) WY_EXTENT * 2/3); gtk_container_set_border_width (GTK_CONTAINER (File_Select), 10); Win_Array[1] = File_Select; FS_Frame = gtk_frame_new ("File Selection and Settings"); gtk_container_add (GTK_CONTAINER (File_Select), FS_Frame); /*~~~~~~~Create a PARENT vbox in File Selection Window which will contain several hboxes~~~~~~~~*/ FS_VBox = gtk_vbox_new (FALSE, 8); gtk_container_set_border_width (GTK_CONTAINER (FS_VBox), 8); gtk_container_add (GTK_CONTAINER (FS_Frame), FS_VBox); /*~~~~~~Create an hbox for REFERENCE FILE and pack it in FS_VBox~~~~~*/ FS_Ref_HBox = gtk_hbox_new (FALSE, 8); gtk_box_pack_start (GTK_BOX (FS_VBox), FS_Ref_HBox, FALSE, TRUE, 5); FS_Ref_Label = gtk_label_new_with_mnemonic ("Reference File"); gtk_box_pack_start (GTK_BOX (FS_Ref_HBox), FS_Ref_Label, FALSE, FALSE, 0); /*~~~~~~Create a Text box for the chosen/given REFERNCE file to be displayed~~~~~~~*/ FS_Ref_File_Entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (FS_Ref_Label), FS_Ref_File_Entry ); //Pressing Ctrl + 'mnemonic' will transfer the control to the text box gtk_box_pack_start (GTK_BOX (FS_Ref_HBox), FS_Ref_File_Entry, TRUE, TRUE, 5); //Though I 'vnt set any but still for reference purposes. /*~~~~~Create a 'Browse' button which lets user to browse and select REFERENCE file~~~~~*/ /* For the time being dropping its use. It dislays "OPEN" button which is a misnomer for our application, since the selected file is to be opened and processed internally. And So we want "OK" button to be there instead. FS_Ref_Browse_Button = gtk_file_chooser_button_new ("Reference File Selection", GTK_FILE_CHOOSER_ACTION_OPEN); gtk_file_chooser_button_set_width_chars ( (GtkFileChooserButton *) FS_Ref_Browse_Button, 35); gtk_label_set_mnemonic_widget ( GTK_LABEL (FS_Ref_Label), FS_Ref_Browse_Button ); //Pressing Ctrl + 'mnemonic' will transfer the control to the text box gtk_box_pack_start (GTK_BOX (FS_Ref_HBox), FS_Ref_Browse_Button, FALSE, TRUE, 5); gtk_file_chooser_set_filename ( (GtkFileChooser *) FS_Ref_Browse_Button, "D:\\Abhijit\\wallpaperSINGH.jpg" ); */ FS_Ref_Browse_Button = gtk_button_new_with_mnemonic ("Browse _Reference File"); gtk_box_pack_start (GTK_BOX (FS_Ref_HBox), FS_Ref_Browse_Button, FALSE, TRUE, 5); /*~~~~~~~~~~~~~~~~~~~~~~~~~~SEPARATOR~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ gtk_box_pack_start (GTK_BOX (FS_VBox), gtk_hseparator_new (), FALSE, FALSE, 20); /*~~~~~~~~~~~~~~~~~~~~~~~~~~SEPARATOR~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~Create an hbox for PROCESSED FILE and pack it in FS_VBox~~~~~*/ FS_Proc_HBox = gtk_hbox_new (FALSE, 8); gtk_box_pack_start (GTK_BOX (FS_VBox), FS_Proc_HBox , FALSE, TRUE, 5); FS_Proc_Label = gtk_label_new_with_mnemonic ("Processed File"); gtk_box_pack_start (GTK_BOX (FS_Proc_HBox ), FS_Proc_Label, FALSE, FALSE, 0); /*~~~~~~Create a Text box for the chosen/given PROCESSED file to be displayed~~~~~~~*/ FS_Proc_File_Entry = gtk_entry_new (); gtk_label_set_mnemonic_widget (GTK_LABEL (FS_Proc_Label), FS_Proc_File_Entry ); //Pressing Ctrl + 'mnemonic' will transfer the control to the text box gtk_box_pack_start (GTK_BOX (FS_Proc_HBox ), FS_Proc_File_Entry, TRUE, TRUE, 5); //Though I 'vnt set any but still for reference purposes. /*~~~~~Create a 'Browse' button which lets user to browse and select PROCESSED file~~~~~*/ /* For the time being dropping its use. It dislays "OPEN" button which is a misnomer for our application, since the selected file is to be opened and processed internally. FS_Proc_Browse_Button = gtk_file_chooser_button_new ("Processed File Selection", GTK_FILE_CHOOSER_ACTION_OPEN); gtk_file_chooser_button_set_width_chars ((GtkFileChooserButton *) FS_Proc_Browse_Button, 35); gtk_label_set_mnemonic_widget (GTK_LABEL (FS_Proc_Label), FS_Proc_Browse_Button ); //Pressing Ctrl + 'mnemonic' will transfer the control to the text box gtk_box_pack_start (GTK_BOX (FS_Proc_HBox ), FS_Proc_Browse_Button, FALSE, FALSE, 0); */ FS_Proc_Browse_Button = gtk_button_new_with_mnemonic ("Browse _Processed File"); gtk_box_pack_start (GTK_BOX (FS_Proc_HBox), FS_Proc_Browse_Button, FALSE, TRUE, 5); /*~~~~~~~~~~~~~~~~~~~~~~~~~~SEPARATOR~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ gtk_box_pack_start (GTK_BOX (FS_VBox), gtk_hseparator_new (), FALSE, FALSE, 20); /*~~~~~~~~~~~~~~~~~~~~~~~~~~SEPARATOR~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /*~~~~~~~~~~~~~~~~~~Create a Frame and put in it a Combo box~~~~~~~~~~~~~~~~~~~~~~~*/ FS_Measure_Frame = gtk_frame_new ("Unit of Measure"); gtk_box_pack_start (GTK_BOX (FS_VBox), FS_Measure_Frame , FALSE, FALSE, 0); FS_Measure_VBox = gtk_vbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (FS_Measure_VBox), 5); gtk_container_add (GTK_CONTAINER (FS_Measure_Frame), FS_Measure_VBox); FS_Measure_Combo = gtk_combo_box_entry_new_text (); gtk_combo_box_append_text (GTK_COMBO_BOX (FS_Measure_Combo), "MSE"); gtk_combo_box_append_text (GTK_COMBO_BOX (FS_Measure_Combo), "PSNR"); gtk_combo_box_set_active (GTK_COMBO_BOX (FS_Measure_Combo), 1); //Index --> 0,1,... gtk_box_pack_start (GTK_BOX (FS_Measure_VBox), FS_Measure_Combo , FALSE, FALSE, 0); /*~~~~~~~~~~ Create a Frame and put in it a Radio Buttons for Y , U and V ~~~~~~~~~*/ FS_Color_Frame = gtk_frame_new ("Color Component"); gtk_box_pack_start (GTK_BOX (FS_VBox), FS_Color_Frame , FALSE, FALSE, 25); FS_Color_HBox = gtk_hbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (FS_Color_HBox), 25); gtk_container_add (GTK_CONTAINER (FS_Color_Frame), FS_Color_HBox); Y_Radio_Button = gtk_radio_button_new (NULL); Y_Radio_Button_Label = gtk_label_new_with_mnemonic ("_Y-Component"); gtk_container_add (GTK_CONTAINER (Y_Radio_Button), Y_Radio_Button_Label); gtk_box_pack_start (GTK_BOX (FS_Color_HBox), Y_Radio_Button , FALSE, FALSE, 30); U_Radio_Button = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (Y_Radio_Button), "_U-Component"); gtk_box_pack_start (GTK_BOX (FS_Color_HBox), U_Radio_Button , FALSE, FALSE, 30); V_Radio_Button = gtk_radio_button_new_with_mnemonic_from_widget (GTK_RADIO_BUTTON (Y_Radio_Button), "_V-Component"); gtk_box_pack_start (GTK_BOX (FS_Color_HBox), V_Radio_Button , FALSE, FALSE, 30); /*~~~~~~~~~~~ Create a Frame and put in it two buttons PROCESS and QUIT ~~~~~~~~~~~*/ FS_Button_Panel_Frame = gtk_frame_new ("Operations"); gtk_box_pack_start (GTK_BOX (FS_VBox), FS_Button_Panel_Frame , FALSE, FALSE, 0); FS_Button_Panel_HBox = gtk_hbox_new (FALSE, 0); gtk_container_set_border_width (GTK_CONTAINER (FS_Button_Panel_HBox), 10); gtk_container_add (GTK_CONTAINER (FS_Button_Panel_Frame), FS_Button_Panel_HBox); FS_Process_Button = gtk_button_new_with_mnemonic ("Process _File"); gtk_box_pack_start (GTK_BOX (FS_Button_Panel_HBox), FS_Process_Button, TRUE, TRUE, 10); FS_Quit_Button = gtk_button_new_with_mnemonic ("_Quit"); gtk_box_pack_start (GTK_BOX (FS_Button_Panel_HBox), FS_Quit_Button, TRUE, TRUE, 10); GTK_WIDGET_SET_FLAGS (FS_Process_Button, GTK_CAN_DEFAULT); //The func. 'expose_graph' will be called automatically whenever there are changes in the // 'Pixmap' which is a drawing area in the memory. g_signal_connect (Drawing_Area, "expose_event", //All the changes made to Pixmap will G_CALLBACK (expose_graph), NULL); // eventually be visible on the window g_signal_connect (Drawing_Area,"configure_event", G_CALLBACK (configure_graph_event), NULL); g_signal_connect (Drawing_Area, "button_press_event", G_CALLBACK (Graph_button_press_event), NULL); g_signal_connect (VScale, "value_changed", G_CALLBACK (Mov_Transp_Window), (gpointer) adj ); g_signal_connect_swapped (G_OBJECT (Quit_Button), "clicked", G_CALLBACK (gtk_main_quit), NULL); g_signal_connect (G_OBJECT (Data_Button), "clicked", G_CALLBACK (Swap_Windows), Win_Array ); g_signal_connect (G_OBJECT (FS_Process_Button), "clicked", G_CALLBACK (Swap_Windows), Win_Array ); g_signal_connect (G_OBJECT (FS_Ref_Browse_Button), "clicked", G_CALLBACK (Get_File_Name), FS_Ref_File_Entry ); g_signal_connect (G_OBJECT (FS_Proc_Browse_Button), "clicked", G_CALLBACK (Get_File_Name), FS_Proc_File_Entry ); g_signal_connect (G_OBJECT (FS_Measure_Combo), "changed", G_CALLBACK (Get_Active_Combo_Entry), NULL); g_signal_connect (G_OBJECT (FS_Quit_Button), "clicked", G_CALLBACK (gtk_main_quit), NULL); /* Ask to receive events the drawing area doesn't normally subscribe to */ gtk_widget_set_events (Drawing_Area, gtk_widget_get_events (Drawing_Area) | GDK_EXPOSE | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); } ImgBuf = gdk_pixbuf_new_from_file("DarkNDirty.png",&error); width = gdk_pixbuf_get_width(ImgBuf); height = gdk_pixbuf_get_height(ImgBuf); gtk_widget_grab_default (Quit_Button); gtk_widget_show (Scrolled_Window); gtk_widget_show_all(Window); Modify_Graph (Drawing_Area, (gpointer) adj); Mov_Transp_Window( Drawing_Area, (gpointer) adj); gtk_window_fullscreen( GTK_WINDOW (Window)); // gtk_window_set_decorated( GTK_WINDOW ( Window), FALSE ); gtk_main(); printf("\n\n"); return 0; }