/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filename: xviewer.c * * * * UTIL C-source: Medical Image Conversion Utility * * * * purpose : image viewer routines * * * * project : (X)MedCon by Erik Nolf * * * * Functions : XMdcGetBoardDimensions() - Get checker board display * * XMdcHandleBoardDimensions() - Create image number arrays* * XMdcBuildViewerWindow() - Build viewer window * * XMdcViewerHide() - Hide the viewer * * XMdcViewerShow() - Show the viewer * * XMdcViewerEnableAutoShrink() - Enable auto shrinking * * XMdcViewerDisableAutoShrink()- Disable auto shrinking * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: xviewer.c,v 1.25 2007/05/21 20:16:20 enlf Exp $ */ /* Copyright (C) 1997-2007 by Erik Nolf This program 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, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Place - Suite 330, Boston, MA 02111-1307, USA. */ /**************************************************************************** H E A D E R S ****************************************************************************/ #include "m-depend.h" #include #include #ifdef HAVE_STDLIB_H #include #endif #include "xmedcon.h" /**************************************************************************** F U N C T I O N S ****************************************************************************/ int XMdcGetBoardDimensions(void) { Uint32 i, total_images, real_images, mwidth, mheight; Uint32 arbitrary_row, arbitrary_col; Uint32 arbitrary_images_per_page, arbitrary_pages; Uint32 trial_images_vertical = 0, trial_images_horizontal = 0; int FOUND = MDC_NO; real_images = XMdcPagesGetNrImages(); if (real_images == 0) XMdcDisplayFatalErr(MDC_BAD_CODE,"Number of images is zero !?"); mwidth = XMdcScaleW(my.fi->mwidth); mheight = XMdcScaleH(my.fi->mheight); /* TRIAL#1: original number of images is a neat square ? */ total_images = real_images; if ((total_images % (Uint32)sqrt((double)total_images)) == 0 ) { FOUND = MDC_YES; trial_images_vertical = (Uint32)sqrt((double)total_images); trial_images_horizontal = total_images / trial_images_vertical; /* inside the screen boundaries ? */ if ((trial_images_vertical * mheight) > (gdk_screen_height() - XMDC_FREE_BORDER)) FOUND = MDC_NO; if ((trial_images_horizontal * mwidth) > (gdk_screen_width() - XMDC_FREE_BORDER)) FOUND = MDC_NO; } if (FOUND == MDC_NO) { /* TRIAL#2: based on divisors of closest even number */ total_images = real_images; if (total_images % 2) total_images += 1; for (i=(Uint32)sqrt((double)total_images); i>=1; i--) { if (!(total_images % i)) { FOUND = MDC_YES; /* found a possible dimension */ trial_images_vertical = i; trial_images_horizontal = total_images / trial_images_vertical; /* inside the screen boundaries ? */ if ((trial_images_vertical * mheight) > (gdk_screen_height() - XMDC_FREE_BORDER)) FOUND = MDC_NO; if ((trial_images_horizontal * mwidth) > (gdk_screen_width() - XMDC_FREE_BORDER)) FOUND = MDC_NO; } if (FOUND == MDC_YES) break; } } if (FOUND == MDC_NO) { /* TRIAL#3: based on closest square number */ /* always ok, except for screen boundaries */ FOUND = MDC_YES; total_images = real_images; while ( total_images % (Uint32)sqrt((double)total_images) ) { total_images += 1; } trial_images_vertical = (Uint32)sqrt((double)total_images); trial_images_horizontal = total_images / trial_images_vertical; /* inside the screen boundaries ? */ if ((trial_images_vertical * mheight) > (gdk_screen_height() - XMDC_FREE_BORDER)) FOUND = MDC_NO; if ((trial_images_horizontal * mwidth) > (gdk_screen_width() - XMDC_FREE_BORDER)) FOUND = MDC_NO; } if (FOUND == MDC_YES) { my.images_vertical = trial_images_vertical; my.images_horizontal = trial_images_horizontal; /* now get pages & images per page */ my.images_per_page = my.images_vertical * my.images_horizontal; if (real_images < my.images_per_page) { my.number_of_pages = (my.fi->number + real_images - 1) / real_images; }else{ my.number_of_pages = (my.fi->number + my.images_per_page - 1) / my.images_per_page; } if ((real_images < my.images_per_page) && (my.images_vertical == 1)) { /* Ola, all images fit on one row ! (ex.: 1 image) -> No board */ my.images_horizontal = real_images; my.images_per_page = my.images_vertical * my.images_horizontal; my.number_of_pages = (my.fi->number + my.images_per_page - 1) / my.images_per_page; } return(MDC_OK); } /* final fallback based on screen dimensions */ arbitrary_row = (gdk_screen_height() - XMDC_FREE_BORDER) / XMdcScaleH(my.fi->mheight); arbitrary_col = (gdk_screen_width() - XMDC_FREE_BORDER) / XMdcScaleW(my.fi->mwidth); if (arbitrary_row == 0 || arbitrary_col == 0) { arbitrary_row = 1; arbitrary_col = 1; } arbitrary_images_per_page = arbitrary_row * arbitrary_col; arbitrary_pages = (my.fi->number+(arbitrary_images_per_page - 1)) / arbitrary_images_per_page; my.images_vertical = arbitrary_row; my.images_horizontal = arbitrary_col; my.images_per_page = arbitrary_images_per_page; my.number_of_pages = arbitrary_pages; /* we still have to take care of less images per page */ if (XMdcPagesGetNrImages() < my.images_per_page ) { my.images_per_page = XMdcPagesGetNrImages(); my.number_of_pages = (my.fi->number+(my.images_per_page - 1)) / my.images_per_page; my.images_vertical = (my.images_per_page + (my.images_horizontal - 1)) / my.images_horizontal; } if ((my.fi->number < my.images_per_page) && (my.images_vertical == 1)) { /* Ola, all images fit on one row ! (ex.: 1 image) -> No chessboard */ my.images_horizontal = my.fi->number; my.images_per_page = my.images_vertical * my.images_horizontal; my.number_of_pages = 1; }else if (my.fi->number < my.images_per_page) { /* Ola, there could have been to much rows provided */ for (i=1; i<=my.images_vertical; i++) { if (i*my.images_horizontal >= my.fi->number) { my.images_vertical = i; my.images_per_page = my.images_vertical * my.images_horizontal; my.number_of_pages = 1; } } } return(MDC_OK); } void XMdcHandleBoardDimensions(void) { Uint32 vertical, i; Uint32 h=my.fi->mheight; /* derive colormap dimensions */ vertical = my.images_vertical; if (vertical*(XMdcScaleH(h)+(XMDC_IMAGE_BORDER<<1)) < XMDC_COLORMAP_HEIGHT) { my.cmap_h = XMDC_COLORMAP_HEIGHT; }else{ my.cmap_h = vertical * (XMdcScaleH(h) + XMDC_IMAGE_BORDER); } my.cmap_w = XMDC_COLORMAP_WIDTH; my.im=(GdkPixbuf **)malloc(sizeof(GdkPixbuf *) * my.images_per_page); if (my.im == NULL) { MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc GdkPixbuf array"); } my.imagenumber=(Uint32 *)malloc(sizeof(Uint32)*my.images_per_page); if (my.imagenumber == NULL) { MdcFree(my.im); MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc ImageNumbers array"); } my.realnumber =(Uint32 *)malloc(sizeof(Uint32)*my.images_per_page); if (my.realnumber == NULL) { MdcFree(my.im); MdcFree(my.imagenumber); MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc RealNumbers array"); } my.pagenumber=(Uint32 *)malloc(sizeof(Uint32)*my.number_of_pages); if (my.pagenumber == NULL) { MdcFree(my.im); MdcFree(my.imagenumber); MdcFree(my.realnumber); MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc PageNumbers array"); } my.image=(GtkWidget **)malloc(sizeof(GtkWidget *)*my.images_per_page); if (my.image == NULL) { MdcFree(my.im); MdcFree(my.imagenumber); MdcFree(my.realnumber); MdcFree(my.pagenumber); MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc Images array"); } #ifdef MDC_USE_SIGNAL_BLOCKER my.sblkr=(SignalBlocker *)malloc(sizeof(SignalBlocker)*my.images_per_page); if (my.sblkr == NULL) { MdcFree(my.im); MdcFree(my.imagenumber); MdcFree(my.realnumber); MdcFree(my.pagenumber); MdcFree(my.image); MdcCleanUpFI(my.fi); XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't malloc SignalBlockers"); } #else my.sblkr = NULL; #endif for (i = 0; imwidth); MdcDebugPrint("mheight = %u",my.fi->mheight); MdcDebugPrint("resize = %d",sResizeSelection.CurType); MdcDebugPrint("fi.number = %u",my.fi->number); MdcDebugPrint("fi.dim[3] = %u",my.fi->dim[3]); MdcDebugPrint("curpage = %u",my.curpage); MdcDebugPrint("images_horizontal = %u",my.images_horizontal); MdcDebugPrint("images_vertical = %u",my.images_vertical); MdcDebugPrint("images_per_page = %u",my.images_per_page); MdcDebugPrint("number_of_pages = %u",my.number_of_pages); MdcDebugPrint("cmap_w = %u",my.cmap_w); MdcDebugPrint("cmap_h = %u",my.cmap_h); } void XMdcBuildViewerWindow(void) { GtkWidget *box1; GtkWidget *box2; GtkWidget *vbox; GtkWidget *label; GtkWidget *frame; GtkWidget *winbox; GtkWidget *button; GtkWidget *spinner; GtkWidget *entrybox; GtkWidget *separator; GtkAdjustment *adj; if (my.viewwindow == NULL) { my.viewwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_policy(GTK_WINDOW(my.viewwindow),FALSE,FALSE,FALSE); gtk_signal_connect(GTK_OBJECT(my.viewwindow), "delete-event", GTK_SIGNAL_FUNC(XMdcViewerHide), NULL); gtk_signal_connect(GTK_OBJECT(my.viewwindow), "destroy", GTK_SIGNAL_FUNC(XMdcMedconQuit), NULL); gtk_container_set_border_width(GTK_CONTAINER (my.viewwindow), 0); } gtk_window_set_title(GTK_WINDOW(my.viewwindow), my.fi->ifname); gtk_widget_realize(my.viewwindow); box1 = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER (my.viewwindow), box1); gtk_widget_show(box1); my.viewbox = box1; box2 = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(box1),box2,FALSE,FALSE,0); gtk_widget_show(box2); my.pagemenu = gtk_option_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(my.pagemenu),XMdcPagesCreateMenu()); gtk_box_pack_start(GTK_BOX(box2),my.pagemenu,TRUE,TRUE,0); gtk_widget_show(my.pagemenu); button = gtk_button_new_with_label("Next"); gtk_signal_connect(GTK_OBJECT(button),"clicked", GTK_SIGNAL_FUNC(XMdcPagesNext),NULL); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); button = gtk_button_new_with_label("Prev"); gtk_signal_connect(GTK_OBJECT(button),"clicked", GTK_SIGNAL_FUNC(XMdcPagesPrev),NULL); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); /* layout for images and colormap */ frame = gtk_frame_new(NULL); gtk_container_set_border_width(GTK_CONTAINER(frame),4); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_OUT); gtk_box_pack_start(GTK_BOX(box1),frame,TRUE,TRUE,0); gtk_widget_show(frame); winbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(frame),winbox); gtk_widget_show(winbox); my.imgsbox = gtk_hbox_new(TRUE,0); gtk_container_set_border_width(GTK_CONTAINER(my.imgsbox),0); gtk_box_pack_start(GTK_BOX(winbox),my.imgsbox,TRUE,TRUE,0); gtk_widget_show(my.imgsbox); my.imgstable=gtk_table_new(my.images_vertical,my.images_horizontal,TRUE); gtk_box_pack_start(GTK_BOX(my.imgsbox), my.imgstable, TRUE, TRUE, 0); gtk_widget_show(my.imgstable); separator = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(winbox), separator, FALSE, FALSE, 0); gtk_widget_show(separator); my.cmapbox = gtk_event_box_new(); gtk_box_pack_start(GTK_BOX(winbox),my.cmapbox,FALSE,FALSE,0); gtk_widget_show(my.cmapbox); XMdcApplyMapPlace(XMDC_CMAP_PLACE); /* seperator */ separator = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, TRUE, 0); /* layout for buttons */ vbox = gtk_vbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(box2), 0); gtk_box_pack_start(GTK_BOX(box1), vbox, FALSE, TRUE, 0); gtk_widget_show(vbox); box2 = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(box2), 0); gtk_box_pack_start(GTK_BOX(vbox), box2, FALSE, FALSE, 0); gtk_widget_show(box2); button = gtk_button_new_with_label("Toggle Entries"); gtk_box_pack_start(GTK_BOX(box2),button,TRUE,TRUE,0); gtk_widget_show(button); entrybox = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(box2), 0); gtk_box_pack_start(GTK_BOX(box2), entrybox, FALSE, FALSE, 0); gtk_widget_show(entrybox); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcToggleVisibility), GTK_OBJECT(entrybox)); label = gtk_label_new("Page: "); gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT); gtk_widget_set_name(label,"FixedLabel"); gtk_box_pack_start(GTK_BOX(entrybox),label,FALSE,TRUE,5); gtk_widget_show(label); adj=(GtkAdjustment *)gtk_adjustment_new(1., 1., (float)my.number_of_pages, 1., 5., 0.); spinner = gtk_spin_button_new(adj, 0.0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE); gtk_spin_button_set_shadow_type(GTK_SPIN_BUTTON(spinner), GTK_SHADOW_ETCHED_IN); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner), TRUE); gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON(spinner), TRUE); gtk_box_pack_start(GTK_BOX(entrybox),spinner,FALSE,FALSE,5); gtk_signal_connect_after(GTK_OBJECT(spinner),"key_press_event", GTK_SIGNAL_FUNC(XMdcPagesGoTo),NULL); gtk_signal_connect_after(GTK_OBJECT(spinner), "button_release_event", GTK_SIGNAL_FUNC(XMdcPagesGoTo),NULL); gtk_widget_show(spinner); label = gtk_label_new("Table: "); gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT); gtk_widget_set_name(label,"FixedLabel"); gtk_box_pack_start(GTK_BOX(entrybox),label,FALSE,TRUE,5); gtk_widget_show(label); adj=(GtkAdjustment *)gtk_adjustment_new(1., 1., (float)XMDC_MAX_LOADABLE_LUTS, 1., 5., 0.); spinner = gtk_spin_button_new(adj, 0.0, 0); gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE); gtk_spin_button_set_shadow_type(GTK_SPIN_BUTTON(spinner), GTK_SHADOW_ETCHED_IN); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinner), TRUE); gtk_spin_button_set_snap_to_ticks (GTK_SPIN_BUTTON(spinner), TRUE); gtk_box_pack_start(GTK_BOX(entrybox),spinner,FALSE,FALSE,5); gtk_signal_connect_after(GTK_OBJECT(spinner),"key_press_event", GTK_SIGNAL_FUNC(XMdcChangeLUT),NULL); gtk_signal_connect_after(GTK_OBJECT(spinner), "button_release_event", GTK_SIGNAL_FUNC(XMdcChangeLUT),NULL); gtk_widget_show(spinner); box2 = gtk_hbox_new(FALSE, 2); gtk_container_set_border_width(GTK_CONTAINER(box2), 0); gtk_box_pack_start(GTK_BOX(vbox), box2, FALSE, TRUE, 0); gtk_widget_show(box2); button = gtk_button_new_with_label(" Hide "); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcViewerHide), NULL); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0); gtk_widget_show(button); button = gtk_button_new_with_label("Labels"); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcLabelSel), NULL); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0); gtk_widget_show(button); button = gtk_button_new_with_label("Render"); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcRenderingSel), NULL); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0); gtk_widget_show(button); } void XMdcViewerHide(void) { if (my.viewwindow != NULL) { gtk_widget_hide(my.viewwindow); } } void XMdcViewerShow(void) { if (XMDC_FILE_OPEN == MDC_NO) return; if (my.viewwindow != NULL) { MdcDebugPrint("Show viewer window ..."); gtk_widget_show(my.viewwindow); } XMdcViewerDisableAutoShrink(); } void XMdcViewerEnableAutoShrink(void) { if (my.viewwindow != NULL) { MdcDebugPrint("enable auto shrink"); gtk_window_set_policy(GTK_WINDOW(my.viewwindow),TRUE,TRUE,TRUE); } } void XMdcViewerDisableAutoShrink(void) { if (my.viewwindow != NULL) { MdcDebugPrint("disable auto shrink"); gtk_window_set_policy(GTK_WINDOW(my.viewwindow),FALSE,FALSE,FALSE); } }