1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * filename: xutils.c                                                      *
3  *                                                                         *
4  * UTIL C-source: Medical Image Conversion Utility                         *
5  *                                                                         *
6  * purpose      : utility routines                                         *
7  *                                                                         *
8  * project      : (X)MedCon by Erik Nolf                                   *
9  *                                                                         *
10  * Functions    : XMdcMedconQuit()            - Quit XMedCon main program  *
11  *                XMdcMainWidgetsInsensitive()- Make them insensitive      *
12  *                XMdcMainWidgetsResensitive()- Make them   sensitive      *
13  *                XMdcWidgetCallbackDestroy() - General Destroy callback   *
14  *                XMdcConfigureXMedcon()      - Parse configuration file   *
15  *                XMdcAskYesNo()              - Ask a Yes/No question      *
16  *                XMdcRunDialog()             - Run modal dialog           *
17  *                XMdcShowWidget()            - Our show the widget routine*
18  *                XMdcWidgetDestroy()         - Destroy widget = NULL      *
19  *                XMdcSetGbcCorrection()      - Set GBC corrected values   *
20  *                XMdcBuildRgbImage()         - Build an RGB image         *
21  *                XMdcBuildGdkPixbuf()        - Build GdkPixbuf out img8   *
22  *                XMdcBuildGdkPixbufFI()      - Build GdkPixbuf out FI img *
23  *                XMdcPreventDelete()         - Prevent delete event       *
24  *                XMdcHandlerToHide()         - Hide widget (no delete)    *
25  *                XMdcFreeRGB()               - Free RGB image             *
26  *                XMdcToggleVisibility()      - Toggle widget visibility   *
27  *                XMdcSetImageScales()        - Set width & height scale   *
28  *                XMdcScaleW()                - Scale image width          *
29  *                XMdcScaleH()                - Scale image height         *
30  *                                                                         *
31  * Note         : Algoritme for gamma/brightness/contrast correction in    *
32  *                function XMdcSetGbcCorrection() copied from library      *
33  *                Imlib by Rasterman                                       *
34  *                                                                         *
35  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
36 /*
37  */
38 
39 /*
40    Copyright (C) 1997-2021 by Erik Nolf
41 
42    This program is free software; you can redistribute it and/or modify it
43    under the terms of the GNU General Public License as published by the
44    Free Software Foundation; either version 2, or (at your option) any later
45    version.
46 
47    This program is distributed in the hope that it will be useful, but
48    WITHOUT ANY WARRANTY; without even the implied warranty of
49    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
50    Public License for more details.
51 
52    You should have received a copy of the GNU General Public License along
53    with this program; if not, write to the Free Software Foundation, Inc.,
54    59 Place - Suite 330, Boston, MA 02111-1307, USA.  */
55 
56 /****************************************************************************
57                               H E A D E R S
58 ****************************************************************************/
59 
60 #include "m-depend.h"
61 
62 #include <stdio.h>
63 #include <math.h>
64 #ifdef HAVE_STDLIB_H
65 #include <stdlib.h>
66 #endif
67 
68 #include "xmedcon.h"
69 
70 /****************************************************************************
71                             F U N C T I O N S
72 ****************************************************************************/
73 
XMdcMedconQuit(GtkWidget * widget,gpointer data)74 void XMdcMedconQuit(GtkWidget *widget, gpointer data)
75 {
76   XMdcFileReset();
77   XMdcFreeMyStuff();
78 
79   exit(MDC_OK);
80 
81 }
82 
XMdcMainWidgetsInsensitive(void)83 void XMdcMainWidgetsInsensitive(void)
84 {
85 
86   if (my.viewwindow != NULL)
87     gtk_widget_set_sensitive(my.viewwindow,FALSE);
88   if (my.mainwindow != NULL)
89     gtk_widget_set_sensitive(my.mainwindow,FALSE);
90 
91 }
92 
XMdcMainWidgetsResensitive(void)93 void XMdcMainWidgetsResensitive(void)
94 {
95 
96   if (my.viewwindow != NULL)
97     gtk_widget_set_sensitive(my.viewwindow,TRUE);
98   if (my.mainwindow != NULL)
99     gtk_widget_set_sensitive(my.mainwindow,TRUE);
100 
101 }
102 
XMdcWidgetCallbackDestroy(GtkWidget * window)103 void XMdcWidgetCallbackDestroy(GtkWidget *window)
104 {
105   gtk_widget_destroy(window); window = NULL;
106   XMdcMainWidgetsResensitive();
107 }
108 
XMdcConfigureXMedcon(void)109 void XMdcConfigureXMedcon(void)
110 {
111   char *h;
112 
113   MdcDebugPrint("XMDCRC   = %s",XMDCRC);
114   MdcDebugPrint("XMDCHELP = %s",XMDCHELP);
115 
116   XMEDCONLUT = getenv("XMEDCONLUT");
117   XMEDCONRPI = getenv("XMEDCONRPI");
118 
119 #ifdef _WIN32
120   /* try windows Program Files path */
121   sprintf(xmdcstr,"c:\\program files\\xmedcon\\etc\\xmedconrc");
122   if (MdcFileExists(xmdcstr)) {
123     MdcDebugPrint("rc file found in \"Program Files\"");
124     gtk_rc_parse(xmdcstr); return;
125   }
126 #else
127   /* try unixes HOME environment variable */
128   h = getenv("HOME");
129   if (h != NULL) {
130     sprintf(xmdcstr,"%s/.xmedconrc",h);
131     if (MdcFileExists(xmdcstr)) {
132       MdcDebugPrint("rc file found in HOME = %s",xmdcstr);
133       gtk_rc_parse(xmdcstr); return;
134     }
135   }
136 #endif
137 
138   /* try XMEDCONRC environment variable */
139   h = getenv("XMEDCONRC");
140   if (h != NULL) {
141     if (MdcFileExists(h)) {
142       MdcDebugPrint("rc file found in XMEDCONRC = %s",h);
143       gtk_rc_parse(h); return;
144     }
145   }
146 
147   /* try hardcoded install path */
148   if (MdcFileExists(XMDCRC)) {
149     MdcDebugPrint("rc file found in XMDCRC = %s",XMDCRC);
150     gtk_rc_parse(XMDCRC);
151   }
152 
153 }
154 
XMdcAskYesNo(GCallback YesFunc,GCallback NoFunc,char * question)155 void XMdcAskYesNo(GCallback YesFunc, GCallback NoFunc, char *question)
156 {
157   GtkWidget *dialog;
158   GtkWidget *label;
159   GtkWidget *button;
160   GtkWidget *action_area;
161   GtkWidget *content_area;
162 
163   if (YesFunc == (GCallback)NULL ) return;
164 
165   dialog = gtk_dialog_new();
166 
167   action_area  = gtk_dialog_get_action_area(GTK_DIALOG(dialog));
168   content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
169 
170   gtk_container_set_border_width(GTK_CONTAINER(action_area),0);
171 
172   g_signal_connect(GTK_OBJECT(dialog),"destroy",
173                      G_CALLBACK(gtk_widget_destroy),NULL);
174   gtk_window_set_title(GTK_WINDOW(dialog), "Question");
175   gtk_container_set_border_width(GTK_CONTAINER(dialog),0);
176 
177   label = gtk_label_new(question);
178   gtk_misc_set_padding(GTK_MISC(label),30,5);
179   gtk_box_pack_start(GTK_BOX(content_area), label, TRUE, TRUE, 0);
180   gtk_widget_show(label);
181 
182   button=gtk_button_new_with_label("Yes");
183   gtk_box_pack_start(GTK_BOX(action_area), button,TRUE,TRUE,0);
184   g_signal_connect_swapped(GTK_OBJECT(button),"clicked",
185                      G_CALLBACK(gtk_widget_hide), GTK_OBJECT(dialog));
186   g_signal_connect(GTK_OBJECT(button),"clicked",
187                      G_CALLBACK(YesFunc),NULL);
188   g_signal_connect_swapped(GTK_OBJECT(button),"clicked",
189                      G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog));
190   gtk_widget_show(button);
191 
192   button=gtk_button_new_with_label("No");
193   gtk_box_pack_start(GTK_BOX(action_area), button,TRUE,TRUE,0);
194   if (NoFunc == (GCallback)NULL) {
195     g_signal_connect_swapped(GTK_OBJECT(button),"clicked",
196                        G_CALLBACK(gtk_widget_destroy),
197                        GTK_OBJECT(dialog));
198   }else{
199     g_signal_connect_swapped(GTK_OBJECT(button),"clicked",
200                        G_CALLBACK(gtk_widget_hide), GTK_OBJECT(dialog));
201     g_signal_connect(GTK_OBJECT(button),"clicked",
202                        G_CALLBACK(NoFunc),NULL);
203     g_signal_connect_swapped(GTK_OBJECT(button),"clicked",
204                        G_CALLBACK(gtk_widget_destroy), GTK_OBJECT(dialog));
205   }
206   gtk_widget_show(button);
207 
208   XMdcRunDialog(dialog);
209 
210 }
211 
XMdcRunDialog(GtkWidget * dialog)212 void XMdcRunDialog(GtkWidget *dialog)
213 {
214   gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
215   gtk_dialog_run(GTK_DIALOG(dialog));
216 }
217 
XMdcShowWidget(GtkWidget * widget)218 void XMdcShowWidget(GtkWidget *widget)
219 {
220   gtk_window_set_position(GTK_WINDOW(widget), GTK_WIN_POS_MOUSE);
221   gtk_widget_show(widget);
222 }
223 
XMdcWidgetDestroy(GtkWidget * widget,gpointer data)224 void XMdcWidgetDestroy(GtkWidget *widget, gpointer data)
225 {
226   MdcDebugPrint("XMdcDestroyWidget()");
227   if (data != NULL) {
228     gtk_widget_destroy(GTK_WIDGET(data)); data = NULL;
229   }
230 }
231 
XMdcSetGbcCorrection(ColorModifier * mod)232 void XMdcSetGbcCorrection(ColorModifier *mod)
233 {
234    double g, b, c, ii, v;
235    Uint32 i;
236 
237    g = ((double)mod->gamma)      / 256.;
238    b = ((double)mod->brightness) / 256.;
239    c = ((double)mod->contrast)   / 256.;
240 
241    if (g < 0.01) g = 0.01;
242 
243    for (i = 0; i < 256; i++) {
244       ii = ((double)i) / 256.;
245       v = ((ii - 0.5) * c) + 0.5 + (b - 1.);
246       if (v > 0) {
247         v = pow(((ii - 0.5) * c) + 0.5 + (b - 1.), 1. / g) * 256.;
248       }else{
249         v = 0.;
250       }
251       if (v > 255.) {
252         v = 255.;
253       }else if (v < 0.) {
254         v = 0.;
255       }
256       mod->vgbc[i] = (guchar)v;
257    }
258 
259 }
260 
XMdcBuildRgbImage(Uint8 * img8,Int16 type,Uint32 pixels,Uint8 * vgbc)261 Uint8 *XMdcBuildRgbImage(Uint8 *img8, Int16 type, Uint32 pixels, Uint8 *vgbc)
262 {
263   Uint8 *imgRGB, rr, gg, bb;
264   Uint32 pix;
265 
266   imgRGB = (Uint8 *)malloc(pixels * 3);
267   if (imgRGB == NULL) return(NULL);
268 
269   for (pix=0; pix < pixels; pix++) {
270      if (type == COLRGB) {
271        rr = img8[pix * 3 + 0];
272        gg = img8[pix * 3 + 1];
273        bb = img8[pix * 3 + 2];
274      }else{
275        rr = my.fi->palette[img8[pix] * 3 + 0];
276        gg = my.fi->palette[img8[pix] * 3 + 1];
277        bb = my.fi->palette[img8[pix] * 3 + 2];
278      }
279      imgRGB[pix * 3 + 0] = vgbc[rr];
280      imgRGB[pix * 3 + 1] = vgbc[gg];
281      imgRGB[pix * 3 + 2] = vgbc[bb];
282   }
283 
284   return(imgRGB);
285 }
286 
XMdcBuildGdkPixbuf(Uint8 * img8,Uint32 w,Uint32 h,Int16 type,Uint8 * vgbc)287 GdkPixbuf *XMdcBuildGdkPixbuf(Uint8 *img8, Uint32 w, Uint32 h, Int16 type, Uint8 *vgbc)
288 {
289   GdkPixbuf *imtmp, *im;
290   Uint8 *imgRGB;
291   Uint32 pixels = w * h;
292   gint rw, rh;
293 
294   imgRGB = XMdcBuildRgbImage(img8, type, pixels, vgbc);
295   if (imgRGB == NULL) return(NULL);
296 
297   rw = (gint)w; rh = (gint)h;
298 
299   imtmp = gdk_pixbuf_new_from_data(imgRGB,GDK_COLORSPACE_RGB,FALSE,8,rw,rh
300                                          ,(int)(3*w),XMdcFreeRGB,NULL);
301   if (imtmp == NULL) { MdcFree(imgRGB); return(NULL); }
302 
303   rw = (gint)XMdcScaleW(w); rh = (gint)XMdcScaleH(h);
304 
305   if ((rw != w) || (rh != h)) {
306     im = gdk_pixbuf_scale_simple(imtmp,rw,rh,sRenderSelection.Interp);
307     g_object_unref(imtmp);
308   }else{
309     im = imtmp;
310   }
311 
312   return(im);
313 }
314 
XMdcBuildGdkPixbufFI(FILEINFO * fi,Uint32 i,Uint8 * vgbc)315 GdkPixbuf *XMdcBuildGdkPixbufFI(FILEINFO *fi,Uint32 i,Uint8 *vgbc)
316 {
317    GdkPixbuf *im;
318    Uint8 *img8;
319    Uint32 w, h;
320    Int16 t;
321 
322    w = fi->image[i].width;
323    h = fi->image[i].height;
324    t = fi->image[i].type;
325 
326    img8 = MdcGetDisplayImage(fi,i);
327    if (img8 == NULL)
328      XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't create byte image");
329 
330    im = XMdcBuildGdkPixbuf(img8, w, h, t, vgbc);
331 
332    MdcFree(img8);
333 
334    if (im == NULL) {
335      XMdcDisplayFatalErr(MDC_BAD_ALLOC,"Couldn't create GdkPixbuf");
336    }
337 
338    return(im);
339 
340 }
341 
XMdcPreventDelete(GtkWidget * widget,GdkEvent * event,gpointer data)342 gboolean XMdcPreventDelete(GtkWidget *widget, GdkEvent *event, gpointer data)
343 {
344   return(TRUE);
345 }
346 
XMdcHandlerToHide(GtkWidget * widget,GdkEvent * event,gpointer data)347 gboolean XMdcHandlerToHide(GtkWidget *widget, GdkEvent *event, gpointer data)
348 {
349   gtk_widget_hide(widget);
350   return(TRUE);
351 }
352 
XMdcFreeRGB(guchar * pixdata,gpointer data)353 void XMdcFreeRGB(guchar *pixdata, gpointer data)
354 {
355   MdcFree(pixdata);
356 }
357 
XMdcToggleVisibility(GtkWidget * widget)358 void XMdcToggleVisibility(GtkWidget *widget)
359 {
360   if (gtk_widget_get_visible(widget)) {
361     gtk_widget_hide(widget);
362   }else{
363     gtk_widget_show(widget);
364   }
365 }
366 
XMdcSetImageScales(void)367 void XMdcSetImageScales(void)
368 {
369   float ratio_width, ratio_height;
370 
371   my.scale_width = 1.; my.scale_height = 1.;
372 
373   /* scale to real world sizes */
374 
375   if (my.fi->pixdim[1] > my.fi->pixdim[2]) {
376 
377     /* width > height -> height is unit */
378     my.scale_width  = my.fi->pixdim[1] / my.fi->pixdim[2];
379 
380   }else if (my.fi->pixdim[2] > my.fi->pixdim[1]) {
381 
382     /* height > width -> width  is unit */
383     my.scale_height = my.fi->pixdim[2] / my.fi->pixdim[1];
384 
385   }
386 
387   /* fit to screen sizes */
388 
389   ratio_width = ((float)my.fi->mwidth * my.scale_width)
390            / ((float)gdk_screen_width()  - (1.2 * (float)XMDC_FREE_BORDER));
391 
392   ratio_height = ((float)my.fi->mheight * my.scale_height)
393            / ((float)gdk_screen_height() - (1.2 * (float)XMDC_FREE_BORDER));
394 
395   if ((ratio_width <= 1.) && (ratio_height <= 1.)) return; /* both fit */
396 
397   /* needs resizing */
398   if (ratio_width > ratio_height) {
399     /* fit via width */
400     my.scale_width  /= ratio_width;
401     my.scale_height /= ratio_width;
402   }else{
403     /* fit via height */
404     my.scale_width  /= ratio_height;
405     my.scale_height /= ratio_height;
406   }
407 
408 }
409 
XMdcScaleW(Uint32 width)410 Uint32 XMdcScaleW(Uint32 width)
411 {
412   Uint32 new_width = width;
413 
414   if (my.scale_width != 1.) {
415 
416     new_width = (Uint32)((float)width * my.scale_width);
417 
418   }
419 
420   return(XMdcResize(new_width));
421 }
422 
XMdcScaleH(Uint32 height)423 Uint32 XMdcScaleH(Uint32 height)
424 {
425   Uint32 new_height = height;
426 
427   if (my.scale_height != 1.) {
428 
429     new_height = (Uint32)((float)height * my.scale_height);
430 
431   }
432 
433   return(XMdcResize(new_height));
434 }
435