/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * filename: xcolmap.c * * * * UTIL C-source: Medical Image Conversion Utility * * * * purpose : colormap changing * * * * project : (X)MedCon by Erik Nolf * * * * Functions : XMdcRemovePreviousColorMap() - Hide previous colormap * * XMdcApplyNewColorMap() - Apply new selected map * * XMdcColorMapCallbackClicked() - Clicked colormap * * XMdcColorMapSelCallbackApply() - Apply callback * * XMdcColorMapSel() - Select map & colors * * XMdcColorMapCallbackExpose() - Expose callback * * XMdcApplyMapPlace() - Apply new placement * * XMdcMapPlaceSel() - Select map placement * * XMdcMapPlaceSelCallbackApply() - Apply place selection * * XMdcBuildColorMap() - Build the colormap * * XMdcLoadLUT() - Load the LUT file * * XMdcChangeLUT() - Load another LUT file * * XMdcMapNotAllowed() - Not allowed on colorfile* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: xcolmap.c,v 1.28 2007/05/21 20:16:16 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 #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #ifndef _WIN32 #include #endif #endif #include "xmedcon.h" /**************************************************************************** D E F I N E S ****************************************************************************/ static GtkWidget *wcolor=NULL; static GtkWidget *wplace=NULL; Uint8 XMDC_CMAP_PLACE = MDC_RIGHT; /**************************************************************************** F U N C T I O N S ****************************************************************************/ void XMdcRemovePreviousColorMap(void) { gdk_pixbuf_unref(my.imcmap); } void XMdcApplyNewColorMap(int map) { gtk_widget_set_sensitive(my.viewwindow,FALSE); XMdcRemovePreviousColorMap(); XMdcRemovePreviousImages(); XMdcColorMapReset(map); XMdcBuildColorMap(); XMdcBuildCurrentImages(); gtk_widget_set_sensitive(my.viewwindow,TRUE); } gboolean XMdcColorMapCallbackClicked(GtkWidget *widget, GdkEventButton *button, gpointer data) { if (button->button == 1) { /* select color map */ XMdcColorMapSel(); } if (button->button == 2) { /* select color map */ XMdcColorMapSel(); } if (button->button == 3) { /* placement color map */ XMdcMapPlaceSel(); } return(TRUE); } void XMdcColorMapSelCallbackApply (GtkWidget *widget, gpointer data) { gint map=MDC_MAP_GRAY; if (XMdcMapNotAllowed() == TRUE) return; MdcDebugPrint("colormap type: "); if (GTK_TOGGLE_BUTTON(sColormapSelection.Gray)->active) { MdcDebugPrint("\tgray normal"); map = MDC_MAP_GRAY; }else if (GTK_TOGGLE_BUTTON(sColormapSelection.Inverted)->active) { MdcDebugPrint("\tgray invers"); map = MDC_MAP_INVERTED; }else if (GTK_TOGGLE_BUTTON(sColormapSelection.Rainbow)->active) { MdcDebugPrint("\trainbow"); map = MDC_MAP_RAINBOW; }else if (GTK_TOGGLE_BUTTON(sColormapSelection.Combined)->active) { MdcDebugPrint("\tcombined"); map = MDC_MAP_COMBINED; }else if (GTK_TOGGLE_BUTTON(sColormapSelection.Hotmetal)->active) { MdcDebugPrint("\thotmetal"); map = MDC_MAP_HOTMETAL; }else if (GTK_TOGGLE_BUTTON(sColormapSelection.Loaded)->active) { MdcDebugPrint("\tloaded"); map = MDC_MAP_LOADED; } if (map == MDC_MAP_LOADED) { XMdcLutSelOpen(NULL,NULL); return; } if (map != sColormapSelection.CurMap) { sColormapSelection.CurMap = map; MDC_COLOR_MAP = map; if (XMDC_FILE_OPEN == MDC_YES) XMdcApplyNewColorMap(map); else XMdcColorMapReset(map); } } gboolean XMdcColorMapSel(void) { GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; GtkWidget *box4; GtkWidget *frame; GtkWidget *button; GtkWidget *separator; GSList *group; if (XMdcMapNotAllowed() == TRUE) return(TRUE); if (wcolor == NULL) { wcolor = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(wcolor),"destroy", GTK_SIGNAL_FUNC(XMdcMedconQuit),NULL); gtk_signal_connect(GTK_OBJECT(wcolor),"delete_event", GTK_SIGNAL_FUNC(XMdcHandlerToHide),NULL); gtk_window_set_title(GTK_WINDOW(wcolor),"Palette Selection"); gtk_container_set_border_width (GTK_CONTAINER (wcolor), 0); box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (wcolor), box1); gtk_widget_show(box1); /* create upper box - colormap */ box2 = gtk_vbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER(box2), 5); gtk_widget_show(box2); box3 = gtk_hbox_new (FALSE, 5); gtk_box_pack_start(GTK_BOX(box2), box3, TRUE, TRUE, 0); gtk_widget_show(box3); /* create colormap frame */ frame = gtk_frame_new("Color Map"); gtk_box_pack_start(GTK_BOX (box3), frame, TRUE, TRUE, 0); gtk_widget_show(frame); box4 = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(frame), box4); gtk_container_set_border_width(GTK_CONTAINER(box4), 5); gtk_widget_show(box4); /* create radiobuttons */ button = gtk_radio_button_new_with_label (NULL, "Gray Normal"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_GRAY) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Gray = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "Gray Invers"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_INVERTED) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Inverted = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "Rainbow"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_RAINBOW) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Rainbow = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "Combined"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_COMBINED) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Combined = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "Hotmetal"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_HOTMETAL) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Hotmetal = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "LUT loaded ..."); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (sColormapSelection.CurMap == MDC_MAP_LOADED) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sColormapSelection.Loaded = button; /* create horizontal separator */ separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, FALSE, 0); gtk_widget_show (separator); /* create bottom button box */ box2 = gtk_hbox_new (FALSE, 0); gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 2); gtk_widget_show(box2); button = gtk_button_new_with_label("Apply"); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),GTK_OBJECT(wcolor)); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcColorMapSelCallbackApply), NULL); gtk_widget_show(button); button = gtk_button_new_with_label ("Cancel"); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2); gtk_signal_connect_object(GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),GTK_OBJECT(wcolor)); gtk_widget_show(button); }else{ /* set buttons to appropriate state */ GtkWidget *b1, *b2, *b3, *b4, *b5, *b6; gtk_widget_hide(wcolor); b1 = sColormapSelection.Gray; b2 = sColormapSelection.Inverted; b3 = sColormapSelection.Rainbow; b4 = sColormapSelection.Combined; b5 = sColormapSelection.Hotmetal; b6 = sColormapSelection.Loaded; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b3),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b4),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b5),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b6),FALSE); switch (sColormapSelection.CurMap) { case MDC_MAP_GRAY : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1),TRUE); break; case MDC_MAP_INVERTED: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2),TRUE); break; case MDC_MAP_RAINBOW : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b3),TRUE); break; case MDC_MAP_COMBINED: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b4),TRUE); break; case MDC_MAP_HOTMETAL: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b5),TRUE); break; case MDC_MAP_LOADED: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b6),TRUE); } } XMdcShowWidget(wcolor); return(TRUE); } gboolean XMdcColorMapCallbackExpose(GtkWidget *widget,GdkEventExpose *event,gpointer data) { GdkGC *gc = widget->style->white_gc; gint w, h; gdk_window_set_back_pixmap(widget->window, NULL, FALSE); w = my.cmap_w; h = my.cmap_h; gdk_pixbuf_render_to_drawable(my.imcmap,widget->window,gc, 0,0,0,0,25,h, sRenderSelection.Dither,0,0); return(TRUE); } void XMdcApplyMapPlace(int place) { GtkWidget *parent=NULL; if (XMDC_FILE_OPEN == MDC_YES) { parent = my.cmapbox->parent; switch (place) { case MDC_LEFT : gtk_box_reorder_child(GTK_BOX(parent),my.cmapbox,0); gtk_box_reorder_child(GTK_BOX(parent),my.imgsbox,2); break; case MDC_RIGHT: gtk_box_reorder_child(GTK_BOX(parent),my.cmapbox,2); gtk_box_reorder_child(GTK_BOX(parent),my.imgsbox,0); break; } } } void XMdcMapPlaceSelCallbackApply (GtkWidget *widget, gpointer data) { MdcDebugPrint("colormap location: "); if (GTK_TOGGLE_BUTTON(sMapPlaceSelection.Left)->active) { MdcDebugPrint("\tleft"); XMDC_CMAP_PLACE = MDC_LEFT; }else if (GTK_TOGGLE_BUTTON(sMapPlaceSelection.Right)->active) { MdcDebugPrint("\tright"); XMDC_CMAP_PLACE = MDC_RIGHT; } XMdcApplyMapPlace(XMDC_CMAP_PLACE); } gboolean XMdcMapPlaceSel(void) { GtkWidget *box1; GtkWidget *box2; GtkWidget *box3; GtkWidget *box4; GtkWidget *frame; GtkWidget *button; GtkWidget *separator; GSList *group; if (wplace == NULL) { wplace = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_signal_connect(GTK_OBJECT(wplace),"destroy", GTK_SIGNAL_FUNC(XMdcMedconQuit),NULL); gtk_signal_connect(GTK_OBJECT(wplace),"delete_event", GTK_SIGNAL_FUNC(XMdcHandlerToHide),NULL); gtk_window_set_title(GTK_WINDOW(wplace),"Placement Selection"); gtk_container_set_border_width (GTK_CONTAINER (wplace), 0); box1 = gtk_vbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (wplace), box1); gtk_widget_show(box1); /* create upper box - placement */ box2 = gtk_vbox_new (FALSE, 5); gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0); gtk_container_set_border_width (GTK_CONTAINER(box2), 5); gtk_widget_show(box2); box3 = gtk_hbox_new (FALSE, 5); gtk_box_pack_start(GTK_BOX(box2), box3, TRUE, TRUE, 0); gtk_widget_show(box3); /* create placement frame */ frame = gtk_frame_new("Placement"); gtk_box_pack_start(GTK_BOX (box3), frame, TRUE, TRUE, 0); gtk_widget_show(frame); box4 = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(frame), box4); gtk_container_set_border_width(GTK_CONTAINER(box4), 5); gtk_widget_show(box4); /* create radiobuttons */ button = gtk_radio_button_new_with_label (NULL, "Left side"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (XMDC_CMAP_PLACE == MDC_LEFT) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sMapPlaceSelection.Left = button; group = gtk_radio_button_group (GTK_RADIO_BUTTON (button)); button = gtk_radio_button_new_with_label(group, "Right side"); gtk_box_pack_start (GTK_BOX (box4), button, TRUE, TRUE, 0); if (XMDC_CMAP_PLACE == MDC_RIGHT) gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); gtk_widget_show (button); sMapPlaceSelection.Right = button; /* create horizontal separator */ separator = gtk_hseparator_new (); gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, FALSE, 0); gtk_widget_show (separator); /* create bottom button box */ box2 = gtk_hbox_new (FALSE, 0); gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 2); gtk_widget_show(box2); button = gtk_button_new_with_label("Apply"); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),GTK_OBJECT(wplace)); gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(XMdcMapPlaceSelCallbackApply), NULL); gtk_widget_show(button); button = gtk_button_new_with_label ("Cancel"); gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 2); gtk_signal_connect_object(GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC(gtk_widget_hide),GTK_OBJECT(wplace)); gtk_widget_show(button); }else{ /* set buttons to appropriate state */ GtkWidget *b1, *b2; gtk_widget_hide(wplace); b1 = sMapPlaceSelection.Left; b2 = sMapPlaceSelection.Right; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1),FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2),FALSE); switch (XMDC_CMAP_PLACE) { case MDC_LEFT : gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b1),TRUE); break; case MDC_RIGHT: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b2),TRUE); break; } } XMdcShowWidget(wplace); return(TRUE); } void XMdcBuildColorMap(void) { Uint8 *imgRGB, rr, gg, bb; Uint32 pix, i, r, c; MdcDebugPrint("Building colormap ..."); imgRGB = (Uint8 *)malloc((unsigned)(my.cmap_w * my.cmap_h * 3)); if (imgRGB == NULL) XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't alloc colormap imgRGB"); pix=0; i=0; for (r=my.cmap_h ; r>0; r--) { i = (255 * r) / my.cmap_h; for (c=0; cpalette[i * 3 + 0]; gg = my.fi->palette[i * 3 + 1]; bb = my.fi->palette[i * 3 + 2]; imgRGB[pix * 3 + 0] = sGbc.mod.vgbc[rr]; imgRGB[pix * 3 + 1] = sGbc.mod.vgbc[gg]; imgRGB[pix * 3 + 2] = sGbc.mod.vgbc[bb]; } } my.imcmap=gdk_pixbuf_new_from_data(imgRGB,GDK_COLORSPACE_RGB,FALSE,8 ,my.cmap_w,my.cmap_h,3*my.cmap_w ,XMdcFreeRGB,NULL); /* add the colormap image to page layout */ if (my.cmap == NULL ) { my.cmap = gtk_drawing_area_new(); gtk_widget_set_events(my.cmap, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); gtk_container_add(GTK_CONTAINER(my.cmapbox), my.cmap); gtk_signal_connect(GTK_OBJECT(my.cmap),"button_press_event", GTK_SIGNAL_FUNC(XMdcColorMapCallbackClicked), NULL); gtk_signal_connect(GTK_OBJECT(my.cmap),"expose_event", GTK_SIGNAL_FUNC(XMdcColorMapCallbackExpose), NULL); } gtk_drawing_area_size(GTK_DRAWING_AREA(my.cmap), my.cmap_w, my.cmap_h); if (my.fi->type != COLRGB) gtk_widget_show(my.cmap); } int XMdcLoadLUT(gchar *lutname) { if (MdcLoadLUT(lutname) == MDC_YES) { sColormapSelection.CurMap = MDC_MAP_LOADED; MDC_COLOR_MAP = MDC_MAP_LOADED; if (XMDC_FILE_OPEN == MDC_YES) XMdcApplyNewColorMap(MDC_COLOR_MAP); }else{ /* XMdcDisplayWarn("Couldn't load specified LUT file");*/ return(MDC_NO); } return(MDC_YES); } gboolean XMdcChangeLUT(GtkWidget *spinner, gpointer data) { int nr; gchar lutname[10]; GtkSpinButton *spin = GTK_SPIN_BUTTON(spinner); if (XMdcMapNotAllowed() == MDC_YES) return(TRUE); nr = gtk_spin_button_get_value_as_int(spin); if (nr == sColormapSelection.Nr) return(TRUE); /* make appropriate path name */ sprintf(lutname,"ct%03d.lut",nr); if (XMEDCONLUT != NULL) { strncpy(xmdcstr,XMEDCONLUT,MDC_1KB_OFFSET); xmdcstr[strlen(xmdcstr)]='\0'; if (xmdcstr[strlen(xmdcstr)-1] != MDC_PATH_DELIM_CHR) strcat(xmdcstr,MDC_PATH_DELIM_STR); }else{ /* installation dir */ strncpy(xmdcstr,XMDCLUT,MDC_1KB_OFFSET); xmdcstr[strlen(xmdcstr)]='\0'; } sprintf(lutname,"ct%03d.lut",nr); strcat(xmdcstr,lutname); if (XMdcLoadLUT(xmdcstr) == MDC_YES) { /* set to new LUT number */ sColormapSelection.Nr = nr; } gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinner) ,(gfloat)sColormapSelection.Nr); return(TRUE); } /* prevent gray maps on colored images */ gboolean XMdcMapNotAllowed(void) { /* no file opened, can select grayscale colormap */ if (XMDC_FILE_OPEN == MDC_NO) return(FALSE); /* no grayscale colormap selection for colored files */ if ((MDC_MAKE_GRAY == MDC_NO) && (my.fi->map == MDC_MAP_PRESENT)) { XMdcDisplayWarn("Grayscale tables not available for colored images.\n"\ "Otherwise force remap to grayscale in\n"\ "Options || MedCon || Slices"); return(TRUE); } /* default allow grayscale colormap selection */ return(FALSE); }