1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6 // drg - added this coxplot.h inclusion for macos10.15
7 // implicit declaration of find_color_name not allowed
8 #include "coxplot.h"
9
10 #include "display.h"
11 #include "mrilib.h"
12
13 static char *x11_vcl[] = { "StaticGray" , "GrayScale" , "StaticColor" ,
14 "PseudoColor" , "TrueColor" , "DirectColor" } ;
15
16 MCW_DC *first_dc = NULL ; /* 26 Jun 2003 */
17
18 int npane_big = 256 ; /* 06 May 2016 */
19
20 extern int find_color_name( char *cnam, float *rr, float *gg, float *bb ) ; ;
21
22 /*--------------------------------------------------------------------------*/
23 #undef USE_TURBO /* 22 Aug 2019 - made obsolete below */
24 #define USE_PBARDEFS /* 24 Oct 2019 */
25
26 #ifdef USE_PBARDEFS
27
28 # undef USE_TURBO
29 # include "pbardefs_float.h"
30
31 # define NPBARF 4
32 static char *pbarfname[NPBARF] = { magma_name, plasma_name, viridis_name, googleturbo_name } ;
33 static float *pbarfar[NPBARF] = { magma_data, plasma_data, viridis_data, googleturbo_data } ;
34
35 #endif
36
37 /* use 256 colors for the colorbar? */
38
39 #if defined(USE_TURBO) || defined(USE_PBARDEFS)
40 # define USE_256
41 #else
42 # undef USE_256
43 #endif
44 /*------------------------------------------------------------------------*/
45
46 /*------------------------------------------------------------------------
47 Returns position of highest set bit in 'ul' as an integer (0-31),
48 or returns -1 if no bit is set.
49 --------------------------------------------------------------------------*/
50
highbit(unsigned long ul)51 static int highbit(unsigned long ul)
52 {
53 int i; unsigned long hb;
54
55 hb = 0x80; hb = hb << 24; /* hb = 0x80000000UL */
56 for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1);
57 return i;
58 }
59
60 /*-------------------------------------------------------------------------
61 Setup the number of bytes per pixel. For depth 24, this might
62 be 3 or 4, depending on the server. RWCox -- 23 Aug 1998.
63 ---------------------------------------------------------------------------*/
64
setup_byper(MCW_DC * dc)65 static void setup_byper( MCW_DC *dc )
66 {
67 XPixmapFormatValues * xpv ;
68 int nxpv = 0 , ii ;
69
70 xpv = XListPixmapFormats( dc->display , &nxpv ) ;
71
72 if( xpv == NULL || nxpv == 0 ){
73 dc->byper = dc->depth / 8 ; dc->bypad = 1 ; /* defaults */
74 return ;
75 }
76
77 /* scan for this depth in the array of pixmap formats */
78
79 for( ii=0 ; ii < nxpv ; ii++ ){
80 if( xpv[ii].depth == dc->depth ){
81 dc->byper = xpv[ii].bits_per_pixel / 8 ; /* bytes, not bits */
82 dc->bypad = xpv[ii].scanline_pad / 8 ;
83 XFree(xpv) ; return ;
84 }
85 }
86
87 dc->byper = dc->depth / 8 ; dc->bypad = 1 ; /* defaults */
88 XFree(xpv) ; return ;
89 }
90
91 /*------------------------------------------------------------------------
92 Create and initialize a new MCW_DC structure.
93
94 wid = widget used to get info about Display, etc.
95 ncol = number of colors to use for images
96 novr = number of overlay colors
97 covr = array of strings of overlay color names [used for XAlloc...]
98 lovr = array of strings of overlay color labels [used for display]
99 gam = gamma value to use
100
101 22 Aug 1998: Modified to support TrueColor visuals,
102 as well as the original PseudoColor -- RWCox.
103
104 14 Sep 1998: Modified to add argument
105 newcmap = if nonzero, create a new Colormap;
106 if zero, use the default Colormap for the display
107 this option is only for PseudoColor
108 [does anyone use PseudoColor any more?]
109 ------------------------------------------------------------------------*/
110
111 static MCW_DCOV * only_ovc = NULL ; /* Dec 1997 */
112
MCW_new_DC(Widget wid,int ncol,int novr,char * covr[],char * lovr[],double gam,int newcmap)113 MCW_DC * MCW_new_DC( Widget wid , int ncol ,
114 int novr , char * covr[] , char * lovr[] ,
115 double gam , int newcmap )
116 {
117 MCW_DC *dc ;
118 int ok , ii , new_ovc ;
119 unsigned int nplmsk = 0 ; /* dummy arguments for XAllocColorCells */
120 unsigned long plane_masks[1] ;
121
122 ENTRY("MCW_new_DC") ;
123
124 if( ncol < 4 || novr < 0 || ncol > MAX_COLORS || novr > MAX_COLORS ){
125 fprintf(stderr,"\n*** MCW_new_DC: ILLEGAL number of colors: %d %d\n",ncol,novr) ;
126 ncol = 4 ; novr = 0 ;
127 }
128
129 if(PRINT_TRACING){
130 char str[256]; sprintf(str,"ncol=%d novr=%d gam=%g",ncol,novr,gam); STATUS(str);
131 }
132
133 dc = myXtNew(MCW_DC) ;
134
135 dc->appcontext = XtWidgetToApplicationContext( wid ) ;
136 dc->display = XtDisplay( wid ) ;
137 dc->screen = XtScreen( wid ) ;
138 dc->screen_num = XScreenNumberOfScreen( dc->screen ) ;
139 dc->visual = DefaultVisualOfScreen( dc->screen ) ;
140 dc->origGC = DefaultGCOfScreen( dc->screen ) ;
141 dc->planes = PlanesOfScreen( dc->screen ) ;
142 dc->depth = DefaultDepthOfScreen( dc->screen ) ;
143
144 dc->cdef = NULL ; /* 11 Feb 1999: will be loaded later */
145
146 setup_byper(dc) ; /* 23 Aug 1998 */
147
148 dc->default_colormap = DefaultColormapOfScreen( dc->screen ) ; /* 01 Sep 1998 */
149
150 dc->colormap = DefaultColormapOfScreen( dc->screen ) ; /* may be changed later */
151
152 dc->parent_widget = wid ; /* 06 Oct 1996 */
153
154 dc->does_backingstore = DoesBackingStore(dc->screen) ; /* 27 Feb 2001 */
155 dc->does_saveunders = DoesSaveUnders(dc->screen) ;
156
157 /** 07 Aug 1998: get more information about the visual **/
158
159 { XVisualInfo vinfo , *vinfo_list ;
160 int count ;
161
162 dc->visual_id = XVisualIDFromVisual( dc->visual ) ;
163 vinfo.visualid = dc->visual_id ;
164 vinfo_list = XGetVisualInfo(dc->display,VisualIDMask,&vinfo,&count) ;
165 if( count > 0 && vinfo_list != NULL ){
166 dc->visual_info = vinfo_list ;
167 dc->visual_redmask = dc->visual_info->red_mask ;
168 dc->visual_greenmask = dc->visual_info->green_mask ;
169 dc->visual_bluemask = dc->visual_info->blue_mask ;
170 dc->visual_redshift = 7 - highbit(dc->visual_redmask) ;
171 dc->visual_greenshift = 7 - highbit(dc->visual_greenmask) ;
172 dc->visual_blueshift = 7 - highbit(dc->visual_bluemask) ;
173 #if defined(__cplusplus) || defined(c_plusplus)
174 dc->visual_class = dc->visual_info->c_class ;
175 #else
176 dc->visual_class = dc->visual_info->class ;
177 #endif
178 if( dc->visual_class != PseudoColor &&
179 dc->visual_class != TrueColor ){
180
181 fprintf(stderr,"\n\n"
182 " ** The default X11 visual type on your computer is set to %s.\n"
183 " ** AFNI programs only work with PseudoColor or TrueColor visuals.\n"
184 " ** You must have your superuser modify your system's setup.\a\n" ,
185 x11_vcl[dc->visual_class] ) ;
186
187 dc->visual_class = PseudoColor ; /* let the program fail later */
188 }
189
190 #if 0
191 if( dc->visual_class == TrueColor ){ /* removed 28 Oct 1999 */
192 static int done = 0 ;
193 if( !done )
194 fprintf(stderr,
195 "\n"
196 " ** The default X11 visual type on your computer is %d bit TrueColor.\n"
197 " ** Support for this is experimental. AFNI was developed to use 4..12\n"
198 " ** bit PseudoColor visuals for image display -- RW Cox, 22 Aug 1998.\n" ,
199 dc->depth ) ;
200 done = 1 ;
201 }
202 #endif
203
204 #if 0
205 fprintf(stderr,"\n"
206 "DC: redmask=%lx greenmask=%lx bluemask=%lx\n"
207 " redshift=%d greenshift=%d blueshift=%d\n"
208 " class=%d=%s depth=%d\n",
209 dc->visual_redmask , dc->visual_greenmask , dc->visual_bluemask ,
210 dc->visual_redshift , dc->visual_greenshift , dc->visual_blueshift ,
211 dc->visual_class , x11_vcl[dc->visual_class] , dc->depth ) ;
212 #endif
213
214 } else { /* should never occur! */
215 dc->visual_info = NULL ;
216 dc->visual_class = PseudoColor ; /* we hope this still works [probably not] */
217 }
218 }
219
220 #if 0
221 { long reqmax ;
222 reqmax = XMaxRequestSize(dc->display) ;
223 printf("max X11 request size = %d\n",reqmax) ;
224 }
225 #endif
226
227 #define DEPTH_BOT 4
228 #define DEPTH_TOP 32
229
230 if( dc->depth < DEPTH_BOT || dc->depth > DEPTH_TOP ){
231 fprintf(stderr,"\n\n"
232 " ** Your X11 display is set to %d bitplanes for image display.\n"
233 " ** AFNI programs can only deal with between %d and %d bitplanes.\n"
234 " ** You must have your superuser modify your system's setup.\a\n" ,
235 dc->depth , DEPTH_BOT , DEPTH_TOP ) ;
236 exit(1) ;
237 }
238
239 dc->width = WidthOfScreen( dc->screen ) ;
240 dc->height = HeightOfScreen( dc->screen ) ;
241
242 if( dc->visual_class == TrueColor ){ /* 23 Feb 2011 */
243 #ifndef USE_256
244 if( ncol < 160 ) ncol = 160 ;
245 #else
246 if( ncol < 256 ) ncol = 256 ;
247 #endif
248 }
249
250 dc->ncol_im = ncol ;
251 dc->gamma = dc->gamma_init = gam ;
252
253 if( dc->visual_class == PseudoColor ){ /* 22 Aug 1998 */
254
255 if( newcmap ){ /* 14 Sep 1998 */
256 int ncold , cc ;
257 XColor xcold ;
258
259 /* make a new colormap */
260
261 dc->colormap = XCreateColormap( dc->display , RootWindowOfScreen(dc->screen) ,
262 dc->visual , AllocNone ) ;
263
264 /* allocate some colors from the old one (to reduce flashing) */
265
266 #define NREUSE 9
267 ncold = dc->visual_info->colormap_size ;
268 if( ncold > NREUSE ) ncold = NREUSE ;
269 for( cc=0 ; cc < ncold ; cc++ ){
270 xcold.pixel = cc ;
271 XQueryColors( dc->display , dc->default_colormap , &xcold , 1 ) ;
272 XAllocColor( dc->display , dc->colormap , &xcold ) ;
273 }
274 }
275
276 ok = XAllocColorCells( dc->display , dc->colormap ,
277 True , plane_masks , nplmsk ,
278 dc->pix_im , dc->ncol_im ) ;
279
280 if( ! ok ){
281 fprintf(stderr,
282 "\a\n** XAllocColorCells fails for %d colors\n",dc->ncol_im) ;
283 fprintf(stderr,
284 "\n** try the -ncolor option to reduce # of colors\n");
285 exit(1) ;
286 }
287
288 dc->pix_im_ready = 1 ;
289 } else if( dc->visual_class == TrueColor ){
290 dc->pix_im_ready = 0 ;
291 }
292
293 DC_init_im_col( dc ) ;
294 DC_init_im_gry( dc ) ;
295
296 dc->use_xcol_im = False ;
297 DC_set_image_colors( dc ) ; /* 22 Aug 1998: replaces XStoreColors */
298
299 /* set up overlay colors from list of names
300 (since the XImage routines use negative indices
301 to indicate overlays, the 0th overlay color is not used) */
302
303 /* Dec 1997: put all overlay stuff into a single place */
304
305 new_ovc = 0 ;
306 if( only_ovc == NULL ){ only_ovc = myXtNew(MCW_DCOV) ; new_ovc = 1 ; }
307 dc->ovc = only_ovc ;
308
309 if( new_ovc ){
310 only_ovc->xcol_ov[0] = dc->xgry_im[0] ;
311 only_ovc->pix_ov[0] = dc->pix_im[0] ;
312 only_ovc->name_ov[0] = XtNewString("none") ;
313 only_ovc->label_ov[0] = only_ovc->name_ov[0] ;
314 only_ovc->ncol_ov = 1 ;
315
316 only_ovc->bright_ov[0] = 0.0 ; /* 20 Dec 1999 */
317
318 dc->ovc->r_ov[0] = 0 ; /* 04 Mar 2002 */
319 dc->ovc->g_ov[0] = 0 ;
320 dc->ovc->b_ov[0] = 0 ;
321 }
322
323 for( ii=0 ; ii < novr ; ii++ ){
324
325 ok = DC_add_overlay_color( dc , covr[ii] , lovr[ii] ) ;
326
327 if( ok < 0 )
328 fprintf(stderr,
329 "\n*** can't get X11 colormap entry for overlay color %s" , lovr[ii] ) ;
330 #ifdef DISPLAY_DEBUG
331 else {
332 printf("\n*** overlay color %s has pixel %d at index %d" ,
333 dc->ovc->name_ov[ok] , (int)dc->ovc->pix_ov[ok] , ok ) ;
334 fflush(stdout) ;
335 }
336 #endif
337 }
338 OVC_mostest( dc->ovc ) ;
339
340 /*-- May 1996: create new GC for use with text and graphics. --*/
341 /*-- Note that myGC is used only for text in afni_graph.c, --*/
342 /*-- but is used for drawing graphics in some other places. --*/
343
344 { XGCValues gcv;
345 int ifont ;
346 XFontStruct *mfinfo = NULL ;
347 char *xdef , dashlist[2] = {6,4} ;
348
349 /* create the GC */
350
351 gcv.function = GXcopy ;
352 dc->myGC = XCreateGC( dc->display,
353 RootWindowOfScreen(dc->screen) ,
354 GCFunction , &gcv ) ;
355
356 /** XSetFillRule( dc->display, dc->myGC, WindingRule ) ; **/
357
358 /**** find some font to load into myGC ****/
359
360 /* first try */
361
362 xdef = XGetDefault(dc->display,"AFNI","gfont") ; /* from ~/.Xdefaults */
363 if( xdef != NULL ){
364 mfinfo = XLoadQueryFont(dc->display,xdef) ;
365 /** if( mfinfo != NULL ) INFO_message("gfontX = %s",xdef) ; **/
366 }
367
368 /* second try */
369
370 if( mfinfo == NULL ){
371 xdef = getenv("AFNI_GRAPH_FONT") ; /* from ~/.afnirc */
372 if( xdef != NULL ){
373 mfinfo = XLoadQueryFont(dc->display,xdef) ;
374 /** if( mfinfo != NULL ) INFO_message("gfontA = %s",xdef) ; **/
375 }
376 }
377
378 /* third try: a list of fonts in display.h */
379
380 if( mfinfo == NULL ){
381 for( ifont=0 ; tfont_hopefuls[ifont] != NULL ; ifont++ ){
382 mfinfo = XLoadQueryFont(dc->display, tfont_hopefuls[ifont]) ;
383 if( mfinfo != NULL ) break ; /* found one! */
384 }
385 /** if( mfinfo != NULL ) INFO_message("gfont[%d] = %s",ifont,tfont_hopefuls[ifont]) ; **/
386 }
387
388 /* store font that we found above */
389
390 if( mfinfo == NULL ){ /* This has never happened, to my knowledge */
391 ERROR_message("Cannot load any text fonts in display.c :(") ;
392 } else {
393 XSetFont( dc->display, dc->myGC, mfinfo->fid ); /* put font into myGC */
394 }
395 dc->myFontStruct = mfinfo ; /* save font info into AFNI display context (dc) */
396
397 /*** set initial colors in myGC ***/
398
399 XSetForeground(dc->display , dc->myGC , dc->ovc->pixov_darkest ) ;
400 XSetBackground(dc->display , dc->myGC , dc->ovc->pixov_brightest ) ;
401 XSetDashes( dc->display , dc->myGC , 0 , dashlist , 2 ) ;
402 }
403
404 dc->parent = dc->aux = NULL ;
405
406 #ifdef DISPLAY_DEBUG
407 printf("\n") ;
408 #endif
409
410 #if 0
411 reload_DC_colordef( dc ) ; /* 11 Feb 1999 */
412 #else
413 dc->cdef = NULL ;
414 #endif
415
416 if( first_dc == NULL ) first_dc = dc ; /* 26 Jun 2003 */
417
418 RETURN(dc) ;
419 }
420
421 /*-----------------------------------------------------------------------
422 Set the image display to grayscale
423 -------------------------------------------------------------------------*/
424
DC_palette_setgray(MCW_DC * dc)425 void DC_palette_setgray( MCW_DC *dc )
426 {
427 dc->use_xcol_im = False ;
428 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
429 return ;
430 }
431
432 /*-----------------------------------------------------------------------
433 Set the image display to colorscale
434 -------------------------------------------------------------------------*/
435
DC_palette_setcolor(MCW_DC * dc)436 void DC_palette_setcolor( MCW_DC *dc )
437 {
438 dc->use_xcol_im = True ;
439 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
440 return ;
441 }
442
443 /*-----------------------------------------------------------------------
444 Restore the color and grayscale palettes to their defaults
445 -------------------------------------------------------------------------*/
446
DC_palette_restore(MCW_DC * dc,double new_gamma)447 void DC_palette_restore( MCW_DC *dc , double new_gamma )
448 {
449 dc->gamma = (new_gamma > 0 ) ? new_gamma : dc->gamma_init ;
450 DC_init_im_col( dc ) ;
451 DC_init_im_gry( dc ) ;
452 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
453 }
454
455 /*-----------------------------------------------------------------------
456 Initialize the grayscale image palette.
457 Modified 22 Aug 1998 for TrueColor support.
458 -------------------------------------------------------------------------*/
459
mypow(double x,double y)460 static double mypow( double x , double y ) /* replaces the math library pow */
461 {
462 double b ;
463 if( x <= 0.0 ) return 0.0 ;
464 if( y == 1.0 ) return x ;
465 b = log(x) ; b = exp( y*b ) ;
466 return b ;
467 }
468
DC_init_im_gry(MCW_DC * dc)469 void DC_init_im_gry( MCW_DC *dc )
470 {
471 int i, k, m, nc ;
472 float a , gamm , b ;
473
474 char *env ; /* 11 Apr 2000 */
475 float atop=255.0 , abot=33.0 ;
476
477 #if 0
478 env = getenv("AFNI_GRAYSCALE_TOP") ;
479 if( env != NULL ){
480 float val = strtod(env,NULL) ;
481 if( val <= 255.0 && val >= 100.0 ) atop = val ;
482 }
483 #endif
484
485 env = getenv("AFNI_GRAYSCALE_BOT") ;
486 if( env != NULL ){
487 float val = strtod(env,NULL) ;
488 if( val < atop && val >= 0.0 ) abot = val ;
489 }
490
491 nc = dc->ncol_im ;
492 gamm = dc->gamma ;
493 a = (atop-abot) / nc ;
494
495 for (i=0; i < nc ; i++) {
496 b = log( (a*i+abot)/255.0 ) ; /* The code that used to be here */
497 b = exp( gamm * b ) ; /* (using pow) was replaced due */
498 k = (int)( 255.0 * b + 0.5 ) ; /* to some bug in gcc on Linux. */
499
500 m = BYTE_TO_INTEN(k) ;
501
502 dc->xint_im[i] = m ;
503 dc->xgry_im[i].red = m ;
504 dc->xgry_im[i].green = m ;
505 dc->xgry_im[i].blue = m ;
506 dc->xgry_im[i].flags = DoRed|DoGreen|DoBlue;
507
508 if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */
509 dc->xgry_im[i].pixel = dc->pix_im[i];
510 }
511
512 return ;
513 }
514
515 /*----------------------------------------------------------------------*/
516 /*! Return a color from the spectrum. Input "an" is between 0 and 360.
517 Adapted from Ziad Saad. -- 01 Feb 2003 - RWCox.
518 ------------------------------------------------------------------------*/
519
DC_spectrum_ZSS(double an,double gamm)520 rgbyte DC_spectrum_ZSS( double an , double gamm )
521 {
522 int r,g,b , m ;
523 rgbyte color ;
524
525 if( gamm <= 0.0 ) gamm = 1.0 ;
526
527 while( an < 0.0 ) an += 360.0 ;
528 while( an > 360.0 ) an -= 360.0 ;
529
530 an = an / 90.0 ;
531
532 if( an <= 1.0 ){
533 r = 255.*mypow(1.0-an,gamm)+0.5 ;
534 g = 255.*mypow(0.5*an,gamm)+0.5 ;
535 b = 255.*mypow(an ,gamm)+0.5 ;
536 } else if( an <= 2.0 ){
537 r = 0 ;
538 g = 255.*mypow(0.5*an,gamm)+0.5 ;
539 b = 255.*mypow(2.0-an,gamm)+0.5 ;
540 } else if( an <= 3.0 ){
541 r = 255.*mypow(an-2.0,gamm)+0.5 ;
542 g = 255 ;
543 b = 0 ;
544 } else {
545 r = 255 ;
546 g = 255.*mypow(4.0-an,gamm)+0.5 ;
547 b = 0 ;
548 }
549
550 #if 0
551 m = MAX(r,g) ; m = MAX(m,b) ;
552 if( m < 255 ){ float s=255.0/m; r *= s; g *= s; b *= s; }
553 #endif
554
555 color.r = r ; color.g = g ; color.b = b ; return color ;
556 }
557
558 /*----------------------------------------------------------------------*/
559 /*! Return a color from the spectrum. Input "an" is between 0 and 360.
560 Adapted from Andrzej Jesmanowicz. -- 30 Jan 2003 - RWCox.
561 ------------------------------------------------------------------------*/
562
DC_spectrum_AJJ(double an,double gamm)563 rgbyte DC_spectrum_AJJ( double an , double gamm )
564 {
565 int r,g,b , m ;
566 double ak,ab,s,c,sb,cb ;
567 rgbyte color ;
568
569 if( gamm <= 0.0 ) gamm = 1.0 ;
570
571 #if 0
572 ak = 105.; s = 255.0-ak; c = s /60.; /* AJ's choices */
573 ab = 65.; sb = 255.0-ab; cb = sb/60.;
574 #else
575 ak = 5.; s = 255.0-ak; c = s /60.; /* RWC's choices */
576 ab = 5.; sb = 255.0-ab; cb = sb/60.;
577 #endif
578
579 while( an < 0.0 ) an += 360.0 ;
580 while( an > 360.0 ) an -= 360.0 ;
581
582 if( an < 120. ){
583 r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
584 g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
585 m = MAX(r,g) ;
586 b = 0;
587 } else if( an < 240. ){
588 r = 0;
589 g = 255.*mypow((ak + MIN(s ,(240. - an)*c ))/255., gamm) +.5;
590 b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
591 m = MAX(g,b) ;
592 } else {
593 r = 255.*mypow((ak + MIN(s,(an - 240.)*c ))/255., gamm) +.5;
594 g = 0;
595 b = 255.*mypow((ab + MIN(s,(360. - an)*cb))/255., gamm) +.5;
596 m = MAX(r,b) ;
597 }
598
599 #if 0
600 if( m < 255 ){ s = 255.0/m ; r *= s ; g *= s ; b *= s ; }
601 #endif
602
603 color.r = r ; color.g = g ; color.b = b ; return color ;
604 }
605
606 /*----------------------------------------------------------------------------*/
607 #ifdef USE_TURBO /* https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html */
608 static byte const turbo_srgb_bytes[256][3] = {
609 {48,18,59},{50,21,67},{51,24,74},{52,27,81},{53,30,88},{54,33,95},{55,36,102},{56,39,109},{57,42,115},
610 {58,45,121},{59,47,128},{60,50,134},{61,53,139},{62,56,145},{63,59,151},{63,62,156},{64,64,162},{65,67,167},
611 {65,70,172},{66,73,177},{66,75,181},{67,78,186},{68,81,191},{68,84,195},{68,86,199},{69,89,203},{69,92,207},
612 {69,94,211},{70,97,214},{70,100,218},{70,102,221},{70,105,224},{70,107,227},{71,110,230},{71,113,233},{71,115,235},
613 {71,118,238},{71,120,240},{71,123,242},{70,125,244},{70,128,246},{70,130,248},{70,133,250},{70,135,251},{69,138,252},
614 {69,140,253},{68,143,254},{67,145,254},{66,148,255},{65,150,255},{64,153,255},{62,155,254},{61,158,254},{59,160,253},
615 {58,163,252},{56,165,251},{55,168,250},{53,171,248},{51,173,247},{49,175,245},{47,178,244},{46,180,242},{44,183,240},
616 {42,185,238},{40,188,235},{39,190,233},{37,192,231},{35,195,228},{34,197,226},{32,199,223},{31,201,221},{30,203,218},
617 {28,205,216},{27,208,213},{26,210,210},{26,212,208},{25,213,205},{24,215,202},{24,217,200},{24,219,197},{24,221,194},
618 {24,222,192},{24,224,189},{25,226,187},{25,227,185},{26,228,182},{28,230,180},{29,231,178},{31,233,175},{32,234,172},
619 {34,235,170},{37,236,167},{39,238,164},{42,239,161},{44,240,158},{47,241,155},{50,242,152},{53,243,148},{56,244,145},
620 {60,245,142},{63,246,138},{67,247,135},{70,248,132},{74,248,128},{78,249,125},{82,250,122},{85,250,118},{89,251,115},
621 {93,252,111},{97,252,108},{101,253,105},{105,253,102},{109,254,98},{113,254,95},{117,254,92},{121,254,89},{125,255,86},
622 {128,255,83},{132,255,81},{136,255,78},{139,255,75},{143,255,73},{146,255,71},{150,254,68},{153,254,66},{156,254,64},
623 {159,253,63},{161,253,61},{164,252,60},{167,252,58},{169,251,57},{172,251,56},{175,250,55},{177,249,54},{180,248,54},
624 {183,247,53},{185,246,53},{188,245,52},{190,244,52},{193,243,52},{195,241,52},{198,240,52},{200,239,52},{203,237,52},
625 {205,236,52},{208,234,52},{210,233,53},{212,231,53},{215,229,53},{217,228,54},{219,226,54},{221,224,55},{223,223,55},
626 {225,221,55},{227,219,56},{229,217,56},{231,215,57},{233,213,57},{235,211,57},{236,209,58},{238,207,58},{239,205,58},
627 {241,203,58},{242,201,58},{244,199,58},{245,197,58},{246,195,58},{247,193,58},{248,190,57},{249,188,57},{250,186,57},
628 {251,184,56},{251,182,55},{252,179,54},{252,177,54},{253,174,53},{253,172,52},{254,169,51},{254,167,50},{254,164,49},
629 {254,161,48},{254,158,47},{254,155,45},{254,153,44},{254,150,43},{254,147,42},{254,144,41},{253,141,39},{253,138,38},
630 {252,135,37},{252,132,35},{251,129,34},{251,126,33},{250,123,31},{249,120,30},{249,117,29},{248,114,28},{247,111,26},
631 {246,108,25},{245,105,24},{244,102,23},{243,99,21},{242,96,20},{241,93,19},{240,91,18},{239,88,17},{237,85,16},
632 {236,83,15},{235,80,14},{234,78,13},{232,75,12},{231,73,12},{229,71,11},{228,69,10},{226,67,10},{225,65,9},
633 {223,63,8},{221,61,8},{220,59,7},{218,57,7},{216,55,6},{214,53,6},{212,51,5},{210,49,5},{208,47,5},
634 {206,45,4},{204,43,4},{202,42,4},{200,40,3},{197,38,3},{195,37,3},{193,35,2},{190,33,2},{188,32,2},
635 {185,30,2},{183,29,2},{180,27,1},{178,26,1},{175,24,1},{172,23,1},{169,22,1},{167,20,1},{164,19,1},
636 {161,18,1},{158,16,1},{155,15,1},{152,14,1},{149,13,1},{146,11,1},{142,10,1},{139,9,2},{136,8,2},
637 {133,7,2},{129,6,2},{126,5,2},{122,4,3}
638 };
639 #endif
640 /*----------------------------------------------------------------------------*/
641
642 /*-----------------------------------------------------------------------
643 Initialize the color image palette.
644 Modified 22 Aug 1998 for TrueColor support.
645 -------------------------------------------------------------------------*/
646
DC_init_im_col(MCW_DC * dc)647 void DC_init_im_col( MCW_DC *dc )
648 {
649 int i, r=0, g=0, b=0, nc ;
650 double gamm ;
651
652 #ifdef USE_256
653 int kt ; float tfac ;
654 #else
655 double da, an, c, s, sb, cb, ak, ab , a1,a2 ;
656 #endif
657
658 #ifdef USE_PBARDEFS /* 24 Oct 2019 */
659 static int mypbar = -1 ;
660 static float *mypbarf = NULL ;
661 #endif
662
663 #ifdef USE_PBARDEFS
664 mypbar = -1 ; mypbarf = NULL ; /* reset the color pbar to use */
665 #endif
666 if( dc == NULL ) return ;
667
668 nc = dc->ncol_im ;
669 gamm = dc->gamma ;
670
671 #ifdef USE_256 /* setup for getting colors directly from a table */
672 tfac = 255.4f / (float)(nc-1) ;
673 #else /* setup for calculating AJJ's old color circle (from FD) */
674 a1 = 0.0 ;
675 a2 = AFNI_numenv("AFNI_IMAGE_COLORANGLE") ; /* 08 Nov 2011 */
676 if( a2 < 90.0 || a2 > 360.0 ) a2 = 240.0 ; /* set range */
677
678 ak = 105.; s = 150.; c = s/60.;
679 ab = 65.; sb = 190.; cb = s/60.;
680
681 an = a1; da = (a2 - a1)/nc ; an = an-da+360.;
682 #endif
683
684 for( i=0 ; i < nc ; i++ ){
685
686 #ifdef USE_TURBO /* directly use Google Turbo */
687 kt = (int)rint(tfac*i) ; if( kt < 0 ) kt=0; else if( kt > 255 ) kt=255 ;
688 r = turbo_srgb_bytes[kt][0] ;
689 g = turbo_srgb_bytes[kt][1] ;
690 b = turbo_srgb_bytes[kt][2] ;
691 #elif defined(USE_PBARDEFS) /* 24 Oct 2019 */
692 if( mypbar < 0 ){
693 char *eee = getenv("AFNI_IMAGE_COLORSCALE") ; /* figure out which */
694 if( eee == NULL || *eee == '\0' ){ /* colorscale to use */
695 mypbar = NPBARF-1 ;
696 } else {
697 int qq ;
698 for( qq=0 ; qq < NPBARF ; qq++ ){
699 if( strcasecmp(eee,pbarfname[qq]) == 0 ) break ;
700 }
701 if( qq == NPBARF ) qq-- ;
702 mypbar = qq ;
703 }
704 mypbarf = pbarfar[mypbar] ;
705 }
706 kt = (int)rint(tfac*i) ; if( kt < 0 ) kt=0; else if( kt > 255 ) kt=255 ;
707 r = (int)(255.4f*mypow(mypbarf[3*kt+0],gamm/1.555)) ;
708 g = (int)(255.4f*mypow(mypbarf[3*kt+1],gamm/1.555)) ;
709 b = (int)(255.4f*mypow(mypbarf[3*kt+2],gamm/1.555)) ;
710 #else /* the olden AJJ way, from program FD */
711 an += da; an = fmod(an,360.);
712
713 if((an >= 0) && (an < 120.)) {
714 r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
715 g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
716 b = 0;
717 } else if((an >= 120.) && (an < 240.)) {
718 r = 0;
719 g = 255.*mypow((ak + MIN(s ,(240. - an)*c))/255., gamm) +.5;
720 b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
721 } else if(an >= 240.) {
722 r = 255.*mypow((ak + MIN(s,(an - 240.)*c))/255., gamm) +.5;
723 g = 0;
724 b = 255.*mypow((ak + MIN(s,(360. - an)*c))/255., gamm) +.5;
725 }
726 #endif
727
728 dc->xcol_im[i].red = BYTE_TO_INTEN(r) ;
729 dc->xcol_im[i].green = BYTE_TO_INTEN(g) ;
730 dc->xcol_im[i].blue = BYTE_TO_INTEN(b) ;
731 dc->xcol_im[i].flags = DoRed|DoGreen|DoBlue;
732
733 if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */
734 dc->xcol_im[i].pixel = dc->pix_im[i];
735 }
736 return ;
737 }
738
739 #if 0 /*******************************************************************/
740 /* --------------------------------------------------------------------------
741 Given an triple of bytes (0..255), make a color and return its pixel value
742 -----------------------------------------------------------------------------*/
743
744 Pixel RGB_byte_to_color( MCW_DC *dc , int r , int g , int b )
745 {
746 XColor any_col;
747
748 any_col.red = BYTE_TO_INTEN(r);
749 any_col.green = BYTE_TO_INTEN(g);
750 any_col.blue = BYTE_TO_INTEN(b);
751 any_col.flags = DoRed | DoGreen | DoBlue;
752 XAllocColor( dc->display , dc->colormap , &any_col );
753 return any_col.pixel ;
754 }
755
756 /*--------------------------------------------------------------------------
757 Given a color named by a string, allocate it and return its pixel value
758 ----------------------------------------------------------------------------*/
759
760 Pixel Name_to_color( MCW_DC *dc , char * name )
761 {
762 XColor cell , exact ;
763 int ok ;
764
765 ok = XAllocNamedColor( dc->display , dc->colormap , name , &cell , &exact ) ;
766
767 if( ok ) return cell.pixel ;
768 else return BlackPixelOfScreen( dc->screen ) ;
769 }
770 #endif /********************************************************************/
771
772 /*--------------------------------------------------------------------------
773 Given a color name, allocate it, put it into the DC overlay table,
774 and return its index (negative if an error occurred)
775 Dec 1997: modified to use read-write color cells,
776 and recycle them if the same label is passed in.
777 22 Aug 1998: modified for TrueColor support
778 ----------------------------------------------------------------------------*/
779
DC_add_overlay_color(MCW_DC * dc,char * name,char * label)780 int DC_add_overlay_color( MCW_DC *dc , char *name , char *label )
781 {
782 int ii , ok , newcol ;
783 Pixel newpix ;
784 XColor cell ;
785
786 ENTRY("DC_add_overlay_color") ;
787
788 if( name == NULL || strlen(name) == 0 ) RETURN(-1) ; /* error */
789 if( label == NULL ) label = name ;
790
791 if(PRINT_TRACING){
792 char str[256]; sprintf(str,"color=%s label=%s",name,label); STATUS(str);
793 }
794
795 /** see if label is already in the table **/
796
797 for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ )
798 if( strcmp(label,dc->ovc->label_ov[ii]) == 0 ) break ;
799
800 newcol = (ii == dc->ovc->ncol_ov) ; /** need a new color cell? **/
801 if( ii == dc->ovc->ncol_ov ){ /** Yes **/
802 unsigned int nplmsk = 0 ;
803 unsigned long plane_masks[1] ;
804
805 STATUS("creating new color table entry") ;
806
807 if( ii >= MAX_COLORS ) RETURN(-1) ; /* too many overlay colors! */
808
809 if( dc->visual_class == PseudoColor ){ /* 22 Aug 1998 */
810 ok = XAllocColorCells( dc->display , dc->colormap ,
811 True , plane_masks , nplmsk , &newpix , 1 ) ;
812 if( !ok ) RETURN(-1) ; /* couldn't get a new cell */
813 cell.pixel = newpix ;
814 }
815
816 } else { /** Reusing an old cell **/
817
818 if( strcmp(name,dc->ovc->name_ov[ii]) == 0 ) RETURN(ii) ; /* no change! */
819
820 STATUS("re-defining old color table entry") ;
821
822 if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */
823 cell.pixel = dc->ovc->pix_ov[ii] ;
824 else if( dc->visual_class == TrueColor )
825 XFreeColors( dc->display, dc->colormap, dc->ovc->pix_ov+ii, 1, 0 ) ;
826 }
827
828 ok = XParseColor( dc->display , dc->colormap , name, &cell ) ;
829 if( !ok ) RETURN(-1) ;
830
831 if( newcol ){ /** made a new cell **/
832 dc->ovc->ncol_ov++ ;
833 } else { /** free old cell stuff **/
834 myXtFree( dc->ovc->name_ov[ii] ) ;
835 myXtFree( dc->ovc->label_ov[ii] ) ;
836 }
837
838 if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */
839 XStoreColor( dc->display , dc->colormap , &cell ) ;
840 else if( dc->visual_class == TrueColor )
841 XAllocColor( dc->display , dc->colormap , &cell ) ;
842
843 if(PRINT_TRACING){
844 char str[256]; sprintf(str,"overlay color index=%d",ii); STATUS(str);
845 }
846
847 dc->ovc->xcol_ov[ii] = cell ; /* save cell info */
848 dc->ovc->pix_ov[ii] = cell.pixel ;
849 dc->ovc->name_ov[ii] = XtNewString(name) ;
850 dc->ovc->label_ov[ii] = XtNewString(label) ;
851
852 dc->ovc->r_ov[ii] = INTEN_TO_BYTE(cell.red) ; /* 06 Mar 2001 */
853 dc->ovc->g_ov[ii] = INTEN_TO_BYTE(cell.green) ;
854 dc->ovc->b_ov[ii] = INTEN_TO_BYTE(cell.blue) ;
855
856 if( dc->visual_class == PseudoColor ) /* 11 Feb 1999: */
857 FREE_DC_colordef(dc->cdef) ; /* will need to be recomputed */
858
859 dc->ovc->bright_ov[ii] = BRIGHTNESS( DCOV_REDBYTE(dc,ii) , /* 20 Dec 1999 */
860 DCOV_GREENBYTE(dc,ii) ,
861 DCOV_BLUEBYTE(dc,ii) ) ;
862 RETURN(ii) ;
863 }
864
865 /*-------------------------------------------------------------------------*/
866
DC_find_overlay_color(MCW_DC * dc,char * label)867 int DC_find_overlay_color( MCW_DC *dc , char *label )
868 {
869 int ii ;
870 if( dc == NULL || label == NULL ) return -1 ;
871 for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
872 if( strcasecmp(label,dc->ovc->label_ov[ii]) == 0 ) return ii ;
873 return -1 ;
874 }
875
876 /*-------------------------------------------------------------------------*/
877
DC_find_closest_overlay_color(MCW_DC * dc,char * cname)878 int DC_find_closest_overlay_color( MCW_DC *dc , char *cname )
879 {
880 float rr,gg,bb ; int b_rr,b_gg,b_bb ;
881 int ii , jj;
882
883 if( dc == NULL || cname == NULL || *cname == '\0' ) return -1 ;
884
885 #if 0
886 if( strcmp(cname,"none") == 0 ) return -1 ;
887 #endif
888
889 ii = DC_find_overlay_color( dc , cname ) ;
890 if( ii >= 0 ) return ii ;
891
892 ii = DC_parse_color( dc, cname, &rr,&gg,&bb ) ;
893 if( ii ) return -1 ;
894
895 b_rr = (int)(255.9*rr) ;
896 b_gg = (int)(255.9*gg) ;
897 b_bb = (int)(255.9*bb) ;
898
899 jj = 0 ; rr = 9999999.9 ;
900 for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ){
901 gg = abs(b_rr-(int)dc->ovc->r_ov[ii])
902 +abs(b_gg-(int)dc->ovc->g_ov[ii])
903 +abs(b_bb-(int)dc->ovc->b_ov[ii]) ;
904 if( gg < rr ){ jj = ii ; rr = gg ; }
905 }
906
907 return jj ;
908 }
909
910 /*-------------------------------------------------------------------------
911 load the tmp? arrays (alas, GLOBAL data, a sin against God and Man)
912 from an array of colors
913 --------------------------------------------------------------------------*/
914
915 static unsigned short tmp1[MAX_COLORS] , tmp2[MAX_COLORS] , tmp3[MAX_COLORS] ;
916 static int tmpi[MAX_COLORS] ;
917
load_tmp_colors(int nc,XColor * ccc)918 void load_tmp_colors( int nc , XColor *ccc )
919 {
920 register int i ;
921
922 for( i=0 ; i < nc ; i++ ){
923 tmp1[i] = ccc[i].red ;
924 tmp2[i] = ccc[i].green ;
925 tmp3[i] = ccc[i].blue ;
926 }
927 return ;
928 }
929
930 /*-------------------------------------------------------------------------
931 rotate active palette k steps
932 -------------------------------------------------------------------------*/
933
DC_palette_rotate(MCW_DC * dc,int kk)934 void DC_palette_rotate( MCW_DC *dc , int kk )
935 {
936 register int i , j , nc , k ;
937 XColor * xc ;
938
939 nc = dc->ncol_im ;
940
941 if( dc->use_xcol_im ){
942 xc = & ( dc->xcol_im[0] ) ; /* choose active palette */
943 k = -kk ; /* direction of rotation */
944 } else {
945 xc = & ( dc->xgry_im[0] ) ;
946 k = -kk ;
947 }
948
949 load_tmp_colors( nc , xc ) ; /* store RGB values in tmp? */
950
951 for( i=0 ; i < nc ; i++ ){
952 j = (i+nc+k) % nc ;
953
954 xc[i].red = tmp1[j] ;
955 xc[i].green = tmp2[j] ;
956 xc[i].blue = tmp3[j] ;
957 }
958
959 if( ! dc->use_xcol_im ){ /* rotate xint_im as well for graymap */
960 for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
961 for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[(i+nc+k)%nc] ;
962 }
963
964 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
965 return ;
966 }
967
968 /*------------------------------------------------------------------------*/
969
DC_palette_swap(MCW_DC * dc)970 void DC_palette_swap( MCW_DC *dc )
971 {
972 register int i, k , nc ;
973 XColor * xc ;
974
975 nc = dc->ncol_im ;
976 k = nc - 1 ;
977
978 if( dc->use_xcol_im ){
979 xc = & ( dc->xcol_im[0] ) ;
980 } else {
981 xc = & ( dc->xgry_im[0] ) ;
982 }
983
984 load_tmp_colors( nc , xc ) ;
985
986 for(i=0; i < nc ; i++) {
987 xc[i].red = tmp1[k-i];
988 xc[i].green = tmp2[k-i];
989 xc[i].blue = tmp3[k-i];
990 }
991
992 if( ! dc->use_xcol_im ){ /* swap xint_im as well for graymap */
993 for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
994 for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[k-i] ;
995 }
996
997 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
998 return ;
999 }
1000
1001 /*-----------------------------------------------------------------------*/
1002
DC_palette_bright(MCW_DC * dc,int dd)1003 void DC_palette_bright( MCW_DC *dc , int dd )
1004 {
1005 if( dc->use_xcol_im ) DC_color_bright( dc , dd ) ;
1006 else DC_gray_change( dc , -2*dd ) ;
1007 return;
1008 }
1009
1010 /*-----------------------------------------------------------------------*/
1011
DC_color_bright(MCW_DC * dc,int dlev)1012 void DC_color_bright( MCW_DC *dc , int dlev )
1013 {
1014 register int i ;
1015 double c ;
1016 int nc = dc->ncol_im ;
1017 XColor * xc = dc->xcol_im ;
1018
1019 c = 1.0 - 0.005 * (double) dlev ;
1020
1021 for( i=0 ; i < nc ; i++ ){
1022 xc[i].red = CLIP_INTEN( c * xc[i].red ) ;
1023 xc[i].green = CLIP_INTEN( c * xc[i].green ) ;
1024 xc[i].blue = CLIP_INTEN( c * xc[i].blue ) ;
1025 }
1026 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
1027 return ;
1028 }
1029
1030 /*------------------------------------------------------------------------*/
1031
DC_gray_change(MCW_DC * dc,int dlev)1032 void DC_gray_change( MCW_DC *dc , int dlev )
1033 {
1034 register int i, k, delta ;
1035 int nc = dc->ncol_im ;
1036 XColor * xc = dc->xgry_im ;
1037 int * in = dc->xint_im ;
1038
1039 if( dc->use_xcol_im ) return ;
1040
1041 delta = dlev * abs( (in[nc-1] - in[0]) / nc ) ;
1042
1043 for( i=0 ; i < nc ; i++ ){
1044 k = in[i] += delta ;
1045 xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1046 }
1047 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
1048 return ;
1049 }
1050
1051 /*------------------------------------------------------------------------*/
1052
DC_palette_squeeze(MCW_DC * dc,int dd)1053 void DC_palette_squeeze( MCW_DC *dc , int dd )
1054 {
1055 if( dc->use_xcol_im ) DC_color_squeeze( dc , dd ) ;
1056 else DC_gray_contrast( dc , -2*dd ) ;
1057 return;
1058 }
1059
1060 /*------------------------------------------------------------------------*/
1061
DC_color_squeeze(MCW_DC * dc,int dlev)1062 void DC_color_squeeze( MCW_DC *dc , int dlev )
1063 {
1064 return ; /* not implemented */
1065 }
1066
1067 /*------------------------------------------------------------------------*/
1068
DC_gray_contrast(MCW_DC * dc,int dlev)1069 void DC_gray_contrast( MCW_DC *dc , int dlev )
1070 {
1071 register int i, k, delta ;
1072 int nc = dc->ncol_im ;
1073 XColor * xc = dc->xgry_im ;
1074 int * in = dc->xint_im ;
1075
1076 if( dc->use_xcol_im ) return ;
1077
1078 delta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
1079 if( delta == 0 ) delta = dlev ;
1080
1081 for( i=0 ; i < nc ; i++ ){
1082 k = in[i] += i * delta ;
1083 xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1084 }
1085 DC_set_image_colors( dc ) ; /* 22 Aug 1998 */
1086 return ;
1087 }
1088
1089 /*------------------------------------------------------------------------*/
1090
DC_gray_conbrio(MCW_DC * dc,int dlev)1091 void DC_gray_conbrio( MCW_DC *dc , int dlev ) /* 23 Oct 2003 */
1092 {
1093 register int i, k, bdelta,cdelta ;
1094 int nc = dc->ncol_im ;
1095 XColor * xc = dc->xgry_im ;
1096 int * in = dc->xint_im ;
1097
1098 if( dc->use_xcol_im ) return ;
1099
1100 bdelta = dlev * abs(in[nc-1] - in[0]) / nc ;
1101 cdelta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
1102 if( cdelta == 0 ) cdelta = dlev ;
1103
1104 for( i=0 ; i < nc ; i++ ){
1105 k = in[i] += i * cdelta - bdelta ;
1106 xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
1107 }
1108 DC_set_image_colors( dc ) ;
1109 return ;
1110 }
1111
1112 /*---------------------------------------------------------------------------*/
1113
DC_char_height(MCW_DC * dc,char ccc)1114 int DC_char_height( MCW_DC *dc , char ccc ) /* 18 Apr 2011 */
1115 {
1116 int dret , fasc , fdes ; XCharStruct cst ; char str[2] ;
1117
1118 if( dc == NULL || ccc == '\0' ) return 0 ;
1119 str[0] = ccc ; str[1] = '\0' ;
1120
1121 cst.ascent = cst.descent = 0 ;
1122 XTextExtents( dc->myFontStruct , str , 1 ,
1123 &dret , &fasc , &fdes , &cst ) ;
1124
1125 return (int)(cst.ascent + cst.descent) ;
1126 }
1127
1128 /*---------------------------------------------------------------------------*/
1129
DC_char_adscent(MCW_DC * dc,char ccc)1130 int_pair DC_char_adscent( MCW_DC *dc , char ccc ) /* 18 Apr 2011 */
1131 {
1132 int dret , fasc , fdes ; XCharStruct cst ; char str[2] ; int_pair ad={0,0} ;
1133
1134 if( dc == NULL || ccc == '\0' ) return ad ;
1135 str[0] = ccc ; str[1] = '\0' ;
1136
1137 cst.ascent = cst.descent = 0 ;
1138 XTextExtents( dc->myFontStruct , str , 1 ,
1139 &dret , &fasc , &fdes , &cst ) ;
1140
1141 ad.i = (int)cst.ascent ; ad.j = (int)cst.descent ; return ad ;
1142 }
1143
1144 /*---------------------------------------------------------------------------*/
1145
DC_char_width(MCW_DC * dc,char ccc)1146 int DC_char_width( MCW_DC *dc , char ccc ) /* 18 Apr 2011 */
1147 {
1148 int dret , fasc , fdes ; XCharStruct cst ; char str[2] ;
1149
1150 if( dc == NULL || ccc == '\0' ) return 0 ;
1151 str[0] = ccc ; str[1] = '\0' ;
1152
1153 cst.width = 0 ;
1154 XTextExtents( dc->myFontStruct , str , 1 ,
1155 &dret , &fasc , &fdes , &cst ) ;
1156
1157 return (int)(cst.width) ;
1158 }
1159
1160 /*-------------------------------------------------------------------*/
1161
MCW_check_iconsize(int width,int height,MCW_DC * dc)1162 RwcBoolean MCW_check_iconsize( int width , int height , MCW_DC *dc )
1163 {
1164 int ii ;
1165 RwcBoolean good ;
1166 int nsl = 0 ;
1167 XIconSize * xsl = NULL ;
1168
1169 /** elementary checks **/
1170
1171 if( width < 1 || height < 1 ) return False ;
1172
1173 XGetIconSizes( dc->display , RootWindowOfScreen(dc->screen) , &xsl , &nsl ) ;
1174
1175 if( xsl == NULL || nsl < 1 ) return True ;
1176
1177 good = False ;
1178
1179 for( ii=0 ; ii < nsl ; ii++ ){
1180
1181 if( width >= xsl[ii].min_width && width <= xsl[ii].max_width &&
1182 height >= xsl[ii].min_height && height <= xsl[ii].max_height &&
1183
1184 (width - xsl[ii].min_width ) % xsl[ii].width_inc == 0 &&
1185 (height - xsl[ii].min_height) % xsl[ii].height_inc == 0 ) { good = True ; break ; }
1186 }
1187
1188 XFree(xsl) ;
1189 return good ;
1190 }
1191
1192 /*---------------------------------------------------------------------------
1193 Given a pixel index, return a pointer to its color (not very efficiently).
1194 11 Feb 1999: if use_cmap != 0, use the colormap instead of
1195 the internal dc color arrays
1196 -----------------------------------------------------------------------------*/
1197
DCpix_to_XColor(MCW_DC * dc,Pixel pp,int use_cmap)1198 XColor * DCpix_to_XColor( MCW_DC *dc , Pixel pp , int use_cmap )
1199 {
1200 XColor * ulc , * ovc ;
1201 int ii ;
1202
1203 if( use_cmap ){ /* 11 Feb 1999 */
1204 static XColor xc ;
1205 byte rr,gg,bb ;
1206
1207 DC_pixel_to_rgb( dc , pp , &rr,&gg,&bb ) ;
1208 xc.red = BYTE_TO_INTEN(rr) ;
1209 xc.green = BYTE_TO_INTEN(gg) ;
1210 xc.blue = BYTE_TO_INTEN(bb) ;
1211 return &xc ;
1212 }
1213
1214 ulc = (dc->use_xcol_im) ? dc->xcol_im : dc->xgry_im ;
1215 ovc = dc->ovc->xcol_ov ;
1216
1217 for( ii=0 ; ii < dc->ncol_im ; ii++ )
1218 if( pp == dc->pix_im[ii] ) return (ulc+ii) ;
1219
1220 for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
1221 if( pp == dc->ovc->pix_ov[ii] ) return (ovc+ii) ;
1222
1223 return ulc ; /* not found, but must return something */
1224 }
1225
1226 /*-------------------------------------------------------------------------*/
1227
DC_fg_color(MCW_DC * dc,int nov)1228 void DC_fg_color( MCW_DC *dc , int nov )
1229 {
1230 XSetForeground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
1231 return ;
1232 }
1233
DC_bg_color(MCW_DC * dc,int nov)1234 void DC_bg_color( MCW_DC *dc , int nov )
1235 {
1236 XSetBackground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
1237 return ;
1238 }
1239
DC_fg_colorpix(MCW_DC * dc,Pixel pix)1240 void DC_fg_colorpix( MCW_DC *dc , Pixel pix )
1241 {
1242 XSetForeground( dc->display , dc->myGC , pix ) ;
1243 return ;
1244 }
1245
DC_fg_colortext(MCW_DC * dc,char * cname)1246 void DC_fg_colortext( MCW_DC *dc , char * cname )
1247 {
1248 XColor any_col , rgb_col ;
1249
1250 if( ! XAllocNamedColor( dc->display , dc->colormap ,
1251 cname , &any_col, &rgb_col ) ){
1252
1253 fprintf(stderr,"\n** XAllocNamedColor problem: %s **\n",cname ) ;
1254 } else {
1255 XSetForeground( dc->display , dc->myGC , any_col.pixel ) ;
1256 }
1257 return ;
1258 }
1259
DC_linewidth(MCW_DC * dc,int lw)1260 void DC_linewidth( MCW_DC *dc , int lw )
1261 {
1262 XGCValues gcv ;
1263
1264 if( lw >= 0 ){
1265 gcv.line_width = lw ;
1266 gcv.join_style = JoinBevel ;
1267 XChangeGC( dc->display , dc->myGC , GCLineWidth | GCJoinStyle , &gcv ) ;
1268 }
1269 return ;
1270 }
1271
DC_linestyle(MCW_DC * dc,int lw)1272 void DC_linestyle( MCW_DC *dc , int lw )
1273 {
1274 XGCValues gcv ;
1275 gcv.line_style = lw ;
1276 XChangeGC( dc->display , dc->myGC , GCLineStyle , &gcv ) ;
1277 return ;
1278 }
1279
1280 /*-------------------------------------------------------------------------
1281 May 1996: save the indices of the darkest and brightest overlays
1282 Dec 1997: moved into a separate routine
1283 ---------------------------------------------------------------------------*/
1284
OVC_mostest(MCW_DCOV * ovc)1285 void OVC_mostest( MCW_DCOV * ovc )
1286 {
1287 float bright_inten , dark_inten , red_inten , green_inten , blue_inten , inten ;
1288 int bright_ii , dark_ii , red_ii , green_ii , blue_ii ;
1289 float yellow_inten ;
1290 int yellow_ii ;
1291 int ii ;
1292
1293 if( ovc == NULL || ovc->ncol_ov < 2 ) return ;
1294
1295 bright_inten = dark_inten = XCOL_BRIGHTNESS( ovc->xcol_ov[1] ) ;
1296 bright_ii = dark_ii = 1 ;
1297
1298 red_inten = XCOL_REDNESS ( ovc->xcol_ov[1] ) ; /* June 1997 */
1299 green_inten = XCOL_GREENNESS( ovc->xcol_ov[1] ) ;
1300 blue_inten = XCOL_BLUENESS ( ovc->xcol_ov[1] ) ;
1301 red_ii = green_ii = blue_ii = 1 ;
1302
1303 yellow_ii = 1 ;
1304 yellow_inten = XCOL_YELLOWNESS( ovc->xcol_ov[1] ) ; /* 28 Jan 2004 */
1305
1306 for( ii=2 ; ii < ovc->ncol_ov ; ii++ ){
1307 inten = XCOL_BRIGHTNESS( ovc->xcol_ov[ii] ) ;
1308 if( inten > bright_inten ){
1309 bright_inten = inten ; bright_ii = ii ;
1310 } else if( inten < dark_inten ){
1311 dark_inten = inten ; dark_ii = ii ;
1312 }
1313
1314 inten = XCOL_REDNESS( ovc->xcol_ov[ii] ) ;
1315 if( inten > red_inten ){
1316 red_inten = inten ; red_ii = ii ;
1317 }
1318
1319 inten = XCOL_GREENNESS( ovc->xcol_ov[ii] ) ;
1320 if( inten > green_inten ){
1321 green_inten = inten ; green_ii = ii ;
1322 }
1323
1324 inten = XCOL_BLUENESS( ovc->xcol_ov[ii] ) ;
1325 if( inten > blue_inten ){
1326 blue_inten = inten ; blue_ii = ii ;
1327 }
1328
1329 inten = XCOL_YELLOWNESS( ovc->xcol_ov[ii] ) ;
1330 if( inten > yellow_inten ){
1331 yellow_inten = inten ; yellow_ii = ii ;
1332 }
1333 }
1334 ovc->ov_brightest = bright_ii ; ovc->pixov_brightest = ovc->pix_ov[bright_ii] ;
1335 ovc->ov_darkest = dark_ii ; ovc->pixov_darkest = ovc->pix_ov[dark_ii] ;
1336 ovc->ov_reddest = red_ii ; ovc->pixov_reddest = ovc->pix_ov[red_ii] ;
1337 ovc->ov_greenest = green_ii ; ovc->pixov_greenest = ovc->pix_ov[green_ii] ;
1338 ovc->ov_bluest = blue_ii ; ovc->pixov_bluest = ovc->pix_ov[blue_ii] ;
1339 ovc->ov_yellowest = yellow_ii ; ovc->pixov_yellowest = ovc->pix_ov[yellow_ii] ;
1340 }
1341
1342 /*-------------------------------------------------------------------------------
1343 Store the colors needed for image display,
1344 based on the value of dc->use_xcol_im (colors for image, or grayscale?).
1345 This replaces the use of XStoreColors directly in the code above.
1346 22 Aug 1998 -- RWCox.
1347 ---------------------------------------------------------------------------------*/
1348
DC_set_image_colors(MCW_DC * dc)1349 void DC_set_image_colors( MCW_DC *dc )
1350 {
1351 int ii , nc ;
1352 XColor * xc ;
1353
1354 nc = dc->ncol_im ;
1355 xc = (dc->use_xcol_im) ? (dc->xcol_im) : (dc->xgry_im) ;
1356
1357 if( dc->visual_class == PseudoColor ){ /* actually change colormap */
1358
1359 XStoreColors( dc->display , dc->colormap , xc , nc ) ;
1360
1361 #if 0
1362 if( dc->cdef != NULL ) reload_DC_colordef( dc ) ; /* 11 Feb 1999 */
1363 #else
1364 /* FREE_DC_colordef(dc->cdef) ; */
1365 #endif
1366
1367 } else if( dc->visual_class == TrueColor ){ /* change internal pixel array */
1368
1369 for( ii=0 ; ii < nc ; ii++ ){
1370 if( dc->pix_im_ready )
1371 XFreeColors( dc->display, dc->colormap, dc->pix_im+ii, 1, 0 ) ;
1372
1373 XAllocColor( dc->display , dc->colormap , xc+ii ) ;
1374 dc->pix_im[ii] = xc[ii].pixel ;
1375 }
1376 dc->pix_im_ready = 1 ;
1377
1378 }
1379
1380 /* 06 Mar 2001: save RGB of colors into arrays for quick use later */
1381
1382 for( ii=0 ; ii < nc ; ii++ ){
1383 dc->r_im[ii] = INTEN_TO_BYTE( xc[ii].red ) ;
1384 dc->g_im[ii] = INTEN_TO_BYTE( xc[ii].green ) ;
1385 dc->b_im[ii] = INTEN_TO_BYTE( xc[ii].blue ) ;
1386 #if 0
1387 dc->gray_im[ii] = BRIGHTNESS( dc->r_im[ii] , dc->g_im[ii] , dc->b_im[ii] ) ;
1388 #endif
1389 }
1390
1391 return ;
1392 }
1393
1394 /*--------------------------------------------------------------
1395 Yoke the widget to the DC -- 14 Sep 1998
1396 ----------------------------------------------------------------*/
1397
DC_yokify(Widget w,MCW_DC * dc)1398 void DC_yokify( Widget w , MCW_DC *dc )
1399 {
1400 if( w == NULL || dc == NULL || !XtIsWidget(w) ) return ;
1401
1402 XtVaSetValues( w ,
1403 XmNvisual , dc->visual ,
1404 XmNcolormap , dc->colormap ,
1405 XmNdepth , dc->depth ,
1406 XmNscreen , dc->screen ,
1407 XmNbackground , 0 ,
1408 XmNborderColor , 0 ,
1409 NULL ) ;
1410 return ;
1411 }
1412
1413 /*---------------------------------------------------------------------
1414 Load the colordef structure in the DC -- 11 Feb 1999
1415 -----------------------------------------------------------------------*/
1416
reload_DC_colordef(MCW_DC * dc)1417 void reload_DC_colordef( MCW_DC *dc )
1418 {
1419 XVisualInfo * vin ;
1420 DC_colordef * cd ; /* will be the output */
1421
1422 ENTRY("reload_DC_colordef") ;
1423
1424 /*--- sanity check ---*/
1425
1426 if( dc == NULL || dc->visual_info == NULL ){
1427 fprintf(stderr,"reload_DC_colordef: entry values are NULL\n") ;
1428 EXRETURN ;
1429 }
1430
1431 vin = dc->visual_info ;
1432
1433 /*--- PseudoColor case ---*/
1434
1435 #if defined(__cplusplus) || defined(c_plusplus)
1436 if( vin->c_class == PseudoColor ){
1437 #else
1438 if( vin->class == PseudoColor ){
1439 #endif
1440
1441 int iz , count , ii ;
1442 XColor * xcol ;
1443
1444 /* create output */
1445
1446 cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
1447 cd->classKRH = PseudoColor ;
1448 cd->depth = vin->depth ;
1449
1450 /* get all the colors in the colormap */
1451
1452 count = vin->colormap_size ;
1453 xcol = (XColor *) malloc( sizeof(XColor) * count ) ;
1454 for( ii=0 ; ii < count ; ii++ ) xcol[ii].pixel = ii ;
1455
1456 XQueryColors( dc->display , dc->colormap , xcol , count ) ;
1457
1458 /* store them in the output, truncated to 8 bit resolution */
1459
1460 cd->ncolors = count ;
1461 cd->rr = (byte *) malloc( count ) ;
1462 cd->gg = (byte *) malloc( count ) ;
1463 cd->bb = (byte *) malloc( count ) ;
1464
1465 for( ii=0 ; ii < count ; ii++ ){
1466 cd->rr[ii] = xcol[ii].red >> 8 ;
1467 cd->gg[ii] = xcol[ii].green >> 8 ;
1468 cd->bb[ii] = xcol[ii].blue >> 8 ;
1469 }
1470
1471 /* find a pure white color, if any */
1472
1473 for( iz=0 ; iz < count ; iz++ )
1474 if( cd->rr[iz] == 255 && cd->gg[iz] == 255 && cd->bb[iz] == 255 ) break ;
1475
1476 cd->nwhite = (iz < count) ? iz : -1 ;
1477
1478 /* find first all zero color; discard others at end of colormap */
1479
1480 for( iz=0 ; iz < count ; iz++ )
1481 if( cd->rr[iz] == 0 && cd->gg[iz] == 0 && cd->bb[iz] == 0 ) break ;
1482
1483 cd->nblack = (iz < count) ? iz : -1 ;
1484
1485 if( iz < count-1 ){ /* if found one before the end */
1486
1487 for( ii=count-1 ; ii > iz ; ii-- ) /* scan backwards */
1488 if( cd->rr[ii] != 0 || cd->gg[ii] != 0 || cd->bb[ii] != 0 ) break ;
1489
1490 count = ii+1 ; /* number of colors left */
1491
1492 if( count == 1 ){ /* colormap is all black?! */
1493 free(xcol) ; FREE_DC_colordef(cd) ;
1494 fprintf(stderr,"reload_DC_colordef: colormap is all black?\n") ;
1495 EXRETURN ;
1496 }
1497
1498 cd->ncolors = count ;
1499 }
1500
1501 FREE_DC_colordef(dc->cdef) ; /* if already present, kill it */
1502
1503 free(xcol) ; dc->cdef = cd ; EXRETURN ;
1504 }
1505
1506 /*--- TrueColor case ---*/
1507
1508 #if defined(__cplusplus) || defined(c_plusplus)
1509 if( vin->c_class == TrueColor ){
1510 #else
1511 if( vin->class == TrueColor ){
1512 #endif
1513
1514 unsigned long r , g , b ;
1515 byte rr, gg, bb ;
1516
1517 /* create output */
1518
1519 cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
1520 cd->classKRH = TrueColor ;
1521 cd->depth = vin->depth ;
1522
1523 cd->rrmask = vin->red_mask ; /* bit masks for color */
1524 cd->ggmask = vin->green_mask ; /* storage inside pixel */
1525 cd->bbmask = vin->blue_mask ;
1526 cd->rrshift = 7 - highbit(cd->rrmask) ; /* shift puts high bit of */
1527 cd->ggshift = 7 - highbit(cd->ggmask) ; /* a color byte into place */
1528 cd->bbshift = 7 - highbit(cd->bbmask) ; /* +shift == >> ; - == << */
1529
1530 /* compute the all white pixel as a common case */
1531
1532 rr = gg = bb = 255 ;
1533
1534 r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
1535 : (rr>>cd->rrshift) ; r = r & cd->rrmask ;
1536
1537 g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
1538 : (gg>>cd->ggshift) ; g = g & cd->ggmask ;
1539
1540 b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
1541 : (bb>>cd->bbshift) ; b = b & cd->bbmask ;
1542
1543 cd->whpix = r | g | b ;
1544
1545 cd->rr = cd->gg = cd->bb = NULL ; /* not used */
1546
1547 FREE_DC_colordef(dc->cdef) ; /* if already present, kill it */
1548
1549 dc->cdef = cd ; EXRETURN ;
1550 }
1551
1552 /*--- Illegal Visual class! [do nothing]---*/
1553
1554 #if defined(__cplusplus) || defined(c_plusplus)
1555 fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
1556 x11_vcl[vin->c_class] ) ;
1557 #else
1558 fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
1559 x11_vcl[vin->class] ) ;
1560 #endif
1561 EXRETURN ;
1562 }
1563
1564 /*---------------------------------------------------------------------
1565 Compute the Pixel that is closest to the given (r,g,b) color
1566 -----------------------------------------------------------------------*/
1567
1568 Pixel DC_rgb_to_pixel( MCW_DC *dc, byte rr, byte gg, byte bb )
1569 {
1570 static MCW_DC *dcold = NULL ;
1571 DC_colordef *cd = dc->cdef ;
1572
1573 if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
1574
1575 switch( cd->classKRH ){
1576
1577 /*--- TrueColor case: make color by appropriate bit twiddling ---*/
1578 /*--- The code below is duplicated in xim.c for efficiency :) ---*/
1579
1580 case TrueColor:{
1581 static unsigned long pold=0 ;
1582 static byte rold=0 , gold=0 , bold=0 ;
1583 unsigned long r , g , b ;
1584
1585 if( rr == 0 && gg == 0 && bb == 0 ) return 0 ; /* common */
1586 if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ; /* cases */
1587
1588 if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
1589 return (Pixel) pold ;
1590
1591 rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* OK, remember for next time */
1592
1593 r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
1594 : (rr>>cd->rrshift) ; r = r & cd->rrmask ;
1595
1596 g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
1597 : (gg>>cd->ggshift) ; g = g & cd->ggmask ;
1598
1599 b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
1600 : (bb>>cd->bbshift) ; b = b & cd->bbmask ;
1601
1602 pold = r | g | b ; /* assemble color from components */
1603 return (Pixel) pold ;
1604 }
1605
1606 /*--- PseudoColor case: find closest match in colormap.
1607 Red, green, and blue are weighted according
1608 to their importance to the human visual system.
1609 This code is slower than the TrueColor case above,
1610 which is due to the search through the PseudoColor palette. */
1611
1612 case PseudoColor:{
1613
1614 #define RW 2 /* the weights alluded to above */
1615 #define GW 4
1616 #define BW 1
1617 #define RGBSUM 4 /* max allowed difference */
1618
1619 static int iold=0 , rold=0,gold=0,bold=0 ;
1620 int ii , rdif,gdif,bdif,dif , ibest,dbest ;
1621
1622 if( cd->nblack >= 0 && rr == 0 && gg == 0 && bb == 0 ) /* deal with */
1623 return (Pixel) cd->nblack ; /* 2 special */
1624 /* and common */
1625 if( cd->nwhite >= 0 && rr == 255 && gg == 255 && bb == 255 ) /* cases */
1626 return (Pixel) cd->nwhite ;
1627
1628 if( dc == dcold ){ /* check in with the last call - maybe it's good */
1629 rdif = rold - rr ;
1630 gdif = gold - gg ;
1631 bdif = bold - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1632 if( dif <= RGBSUM ) return (Pixel) iold ; /* Remembrance of Things Past? */
1633 }
1634
1635 rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* No? Remember for next time. */
1636
1637 /* check first color in palette; if it is "close enough" (RGBSUM), use it */
1638
1639 rdif = cd->rr[0] - rr ;
1640 gdif = cd->gg[0] - gg ;
1641 bdif = cd->bb[0] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1642 if( dif <= RGBSUM ){ iold = 0 ; return 0 ; }
1643
1644 /* scan thru the rest of the colors in palette,
1645 either finding one close enough, or finding the closest one */
1646
1647 ibest = 0 ; dbest = dif ;
1648 for( ii=1 ; ii < cd->ncolors ; ii++ ){
1649 rdif = cd->rr[ii] - rr ;
1650 gdif = cd->gg[ii] - gg ;
1651 bdif = cd->bb[ii] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1652 if( dif <= RGBSUM ){ iold = ii ; return (Pixel) ii ; }
1653 if( dif < dbest ){ ibest = ii ; dbest = dif ; }
1654 }
1655 iold = ibest ; return (Pixel) ibest ;
1656 }
1657 }
1658
1659 /*--- Illegal case! ---*/
1660
1661 return 0 ; /* Black is always valid (but not very colorful) */
1662 }
1663
1664 /*---------------------------------------------------------------------
1665 Compute the Pixel that is closest to the given (r,g,b) color,
1666 but if the pixel isn't gray (r=g=b), the color must be from
1667 the specified set of overlay colors. [20 Dec 1999 - RW Cox]
1668 -----------------------------------------------------------------------*/
1669
1670 Pixel DC_rgb_to_ovpix( MCW_DC *dc, byte rr, byte gg, byte bb )
1671 {
1672 static MCW_DC *dcold=NULL ;
1673 static Pixel pold=0 ;
1674 static int rold=0,gold=0,bold=0 ;
1675 int ii , rdif,gdif,bdif,dif , ibest,dbest ;
1676
1677 if( rr == gg && rr == bb ) return DC_rgb_to_pixel(dc,rr,gg,bb) ;
1678
1679 if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return 0 ;
1680
1681 if( dc == dcold ){ /* check if we just saw this */
1682 rdif = rold - rr ;
1683 gdif = gold - gg ;
1684 bdif = bold - bb ;
1685 dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1686 if( dif <= RGBSUM ) return pold ;
1687 }
1688
1689 rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* remember for next time */
1690
1691 rdif = DCOV_REDBYTE(dc,0) - rr ;
1692 gdif = DCOV_GREENBYTE(dc,0) - gg ;
1693 bdif = DCOV_BLUEBYTE(dc,0) - bb ;
1694 dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1695 if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[0] ; return pold ; }
1696
1697 ibest = 0 ; dbest = dif ;
1698 for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ ){
1699 rdif = DCOV_REDBYTE(dc,ii) - rr ;
1700 gdif = DCOV_GREENBYTE(dc,ii) - gg ;
1701 bdif = DCOV_BLUEBYTE(dc,ii) - bb ;
1702 dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
1703 if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[ii] ; return pold ; }
1704 if( dif < dbest ){ ibest = ii ; dbest = dif ; }
1705 }
1706 pold = dc->ovc->pix_ov[ibest] ; return pold ;
1707 }
1708
1709 /*---------------------------------------------------------------------
1710 Convert color to triple in overlay color list that is closest.
1711 -----------------------------------------------------------------------*/
1712
1713 void DC_rgb_to_ovrgb( MCW_DC *dc , int nlist , int * list , int shade ,
1714 byte *rrin , byte *ggin, byte *bbin )
1715 {
1716 int jj,jtop,ii , rdif,gdif,bdif,dif , ibest,dbest ;
1717 byte rr=*rrin , gg=*ggin , bb=*bbin , mm , rt,gt,bt , rtbest,gtbest,btbest;
1718 float brig , fac ;
1719
1720 if( rr == gg && rr == bb ) return ; /* if grayscale, is OK */
1721
1722 if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return ;
1723
1724 /* start with the gray color with the same brightness */
1725
1726 brig = BRIGHTNESS(rr,gg,bb) ; mm = (byte)(brig + 0.499) ;
1727 dbest = RW*abs(mm-rr)+GW*abs(mm-gg)+BW*abs(mm-bb) ; /* diff from gray */
1728 if( dbest <= RGBSUM ){
1729 *rrin = *ggin = *bbin = mm ; return ;
1730 }
1731 ibest = 0 ; rtbest = gtbest = btbest = mm ;
1732
1733 /* now check the colors in the list given, or the entire set if no list */
1734
1735 jtop = (nlist > 0) ? nlist : dc->ovc->ncol_ov ;
1736 for( jj=0 ; jj < jtop ; jj++ ){
1737 ii = (nlist > 0) ? list[jj] : jj ;
1738 if( ii <= 0 || ii >= dc->ovc->ncol_ov || dc->ovc->bright_ov[ii] <= 0.0 ) continue ;
1739
1740 rt = DCOV_REDBYTE(dc,ii) ; gt = DCOV_GREENBYTE(dc,ii) ; bt = DCOV_BLUEBYTE(dc,ii) ;
1741 if( shade ){
1742 fac = brig / dc->ovc->bright_ov[ii] ;
1743 rt = (byte)( fac*rt + 0.499 ) ;
1744 gt = (byte)( fac*gt + 0.499 ) ;
1745 bt = (byte)( fac*bt + 0.499 ) ;
1746 }
1747 dif = RW*abs(rt-rr)+GW*abs(gt-gg)+BW*abs(bt-bb) ;
1748 if( dif <= RGBSUM ){
1749 *rrin = rt ; *ggin = gt ; *bbin = bt ; return ;
1750 }
1751 if( dif < dbest ){
1752 ibest = ii ; dbest = dif ; rtbest = rt ; gtbest = gt ; btbest = bt ;
1753 }
1754 }
1755
1756 *rrin = rtbest ; *ggin = gtbest ; *bbin = btbest ; return ;
1757 }
1758
1759 /*---------------------------------------------------------------------
1760 Compute the (r,g,b) color corresponding to a given Pixel
1761 -----------------------------------------------------------------------*/
1762
1763 void DC_pixel_to_rgb( MCW_DC *dc , Pixel ppp ,
1764 byte * rr , byte * gg , byte * bb )
1765 {
1766 DC_colordef * cd = dc->cdef ;
1767
1768 if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
1769
1770 switch( cd->classKRH ){
1771
1772 /*--- TrueColor case: unmake color by appropriate bit twiddling ---*/
1773
1774 case TrueColor:{
1775 unsigned long r , g , b ;
1776
1777 if( ppp == 0 ){ *rr = *bb = *gg = 0 ; return ; } /* common cases */
1778 if( ppp == cd->whpix ){ *rr = *bb = *gg = 255 ; return ; }
1779
1780 r = ppp & cd->rrmask ;
1781 *rr = (cd->rrshift<0) ? (r>>(-cd->rrshift)) : (r<<cd->rrshift) ;
1782
1783 g = ppp & cd->ggmask ;
1784 *gg = (cd->ggshift<0) ? (g>>(-cd->ggshift)) : (g<<cd->ggshift) ;
1785
1786 b = ppp & cd->bbmask ;
1787 *bb = (cd->bbshift<0) ? (b>>(-cd->bbshift)) : (b<<cd->bbshift) ;
1788
1789 return ;
1790 }
1791
1792 /*--- PseudoColor case: extract from colormap ---*/
1793
1794 case PseudoColor:{
1795 int ii = (int) ppp ;
1796 *rr = cd->rr[ii] ; *gg = cd->gg[ii] ; *bb = cd->bb[ii] ; return ;
1797 }
1798 }
1799
1800 return ;
1801 }
1802
1803 /*-------------------------------------------------------------------------
1804 21 Sep 2001: compute an (r,g,b) triple (floating point, 0..1)
1805 for the given color string;
1806 return value is 0 for good, 1 for bad
1807 (if bad, *rr, *gg, *bb aren't touched)
1808 ---------------------------------------------------------------------------*/
1809
1810 int DC_parse_color( MCW_DC *dc, char *str, float *rr, float *gg, float *bb )
1811 {
1812 XColor cell ; int ok ;
1813
1814 if( str == NULL || *str == '\0' ) return 1 ;
1815
1816 if( strncmp(str,"AJJ:",4) == 0 ){ /* 07 Feb 2003 */
1817 float ang=-6666.0 ;
1818 sscanf(str+4,"%f",&ang) ;
1819 if( ang != -6666.0 ){
1820 rgbyte col = DC_spectrum_AJJ( ang , 0.8 ) ;
1821 *rr = col.r / 255.0f ; *gg = col.g / 255.0f ; *bb = col.b / 255.0f ;
1822 return 0 ;
1823 }
1824 return 1 ;
1825 }
1826
1827 if( strncmp(str,"RGB:",4) == 0 ){ /* 18 Sep 2007 */
1828 float ir=-1.0f,ig=-1.0f,ib=-1.0f ; char s1,s2 ;
1829 sscanf( str+4 ,"%f%c%f%c%f" , &ir,&s1,&ig,&s2,&ib ) ;
1830 if( ir >= 0.0f && ig >= 0.0f && ib >= 0.0f ){
1831 ir = MIN(ir,255.0f); ig = MIN(ig,255.0f); ib = MIN(ib,255.0f);
1832 *rr = ir / 255.0f ; *gg = ig / 255.0f ; *bb = ib / 255.0f ;
1833 return 0 ;
1834 }
1835 }
1836
1837 ok = find_color_name(str,rr,gg,bb) ; if( ok >= 0 ) return 0 ; /* 02 Dec 2015 */
1838
1839 /* let X11 try to understand the input string */
1840
1841 ok = XParseColor( dc->display , dc->colormap , str , &cell ) ;
1842 if( ok ){
1843 *rr = cell.red / 65535.0f ;
1844 *gg = cell.green / 65535.0f ;
1845 *bb = cell.blue / 65535.0f ;
1846 return 0 ;
1847 }
1848
1849 return 1 ;
1850 }
1851
1852 /* Create those AJJ maps */
1853 int NJ_bigmaps_init(int bigmap_num, char ***bigmap_namep, rgbyte ***bigmapp)
1854 {
1855 char **bigmap_name=NULL;
1856 rgbyte **bigmap = NULL;
1857 int ii=0 ,mm=0, NPB_2=NPANE_BIG/2;
1858
1859 if ( !bigmap_namep || !bigmapp ||
1860 bigmap_num != NBIGMAP_INIT) return 1;
1861
1862 {
1863 bigmap_name = (char **) malloc(sizeof(char *)*bigmap_num) ;
1864 /* copy all names */
1865 for(mm = 0; mm < bigmap_num; mm++ )
1866 bigmap_name[mm] = strdup(BIGMAP_NAMES[mm]) ;
1867
1868 bigmap = (rgbyte **)malloc(sizeof(rgbyte *)*bigmap_num) ;
1869
1870 /* ZSS: The +1 is to stop a a MCW_malloc post-corruption which happens
1871 under certain compiler/OS combinations. The likely cause is the uneven
1872 byte size of rgbyte which might be causing misalignment problems at the
1873 very end March 27 2012 */
1874
1875 /* allocate all RGB arrays */
1876 for(mm = 0; mm < bigmap_num; mm++ )
1877 bigmap[mm] = (rgbyte *) malloc(sizeof(rgbyte)*(NPANE_BIG+1)) ;
1878
1879 /* fill RGB arrays */
1880 for( ii=0 ; ii < NPANE_BIG ; ii++ ){
1881 bigmap[0][ii] = DC_spectrum_AJJ( ii*((AJJ_BLU+8.0)/(NPANE_BIG-1.0))-4.0,0.8);
1882 bigmap[4][ii] = DC_spectrum_AJJ( 60.0-ii*(AJJ_YEL/(NPANE_BIG-1.0)) ,0.7);
1883 bigmap[5][ii] = DC_spectrum_AJJ( ii*(360.0 /(NPANE_BIG-1.0)) ,0.8);
1884 bigmap[6][ii] = DC_spectrum_ZSS(360.0-ii*(360.0 /(NPANE_BIG-1.0)) ,1.0);
1885 if( ii < NBIG_MBOT ){
1886 bigmap[1][ii] = DC_spectrum_AJJ( ii*(AJJ_YEL/(NBIG_MBOT-1.0)) , 0.8 );
1887 bigmap[2][ii] = DC_spectrum_AJJ( AJJ_YEL-ii*(AJJ_YEL/(NBIG_MBOT-1.0)) , 0.8 );
1888 bigmap[3][ii] = bigmap[2][ii] ;
1889 } else if( ii > NBIG_MTOP ){
1890 bigmap[1][ii] = DC_spectrum_AJJ( AJJ_CYN+(ii-NBIG_MTOP-1)*(60.0/(NPANE_BIG-NBIG_MTOP-2.0)),0.8);
1891 bigmap[2][ii] = DC_spectrum_AJJ( AJJ_BLU-(ii-NBIG_MTOP-1)*(60.0/(NPANE_BIG-NBIG_MTOP-2.0)),0.8);
1892 bigmap[3][ii] = bigmap[2][ii] ;
1893 } else {
1894 bigmap[1][ii].r = bigmap[1][ii].g = bigmap[1][ii].b = 0 ;
1895 bigmap[2][ii] = DC_spectrum_AJJ( 360.0-(ii-NBIG_MBOT+1)*(120.0/(NBIG_MTOP-NBIG_MBOT+2.0)),0.8) ;
1896 bigmap[3][ii].r = bigmap[3][ii].g = bigmap[3][ii].b = 0 ;
1897 }
1898 }
1899
1900 /* map[7] = "Reds_and_Blues" 10 Nov, 2014 [rickr] */
1901 for( ii=0 ; ii < NPB_2 ; ii++ ) {
1902 bigmap[7][ii] = DC_spectrum_AJJ(AJJ_YEL-ii*(AJJ_YEL/(NPB_2-1.0)), 0.8);
1903 bigmap[8][ii] = DC_spectrum_AJJ(AJJ_YEL-ii*(AJJ_YEL/(NPB_2-1.0)), 0.8);
1904 }
1905 for( ii=NPB_2 ; ii < NPANE_BIG ; ii++ ) {
1906 bigmap[7][ii] = DC_spectrum_AJJ(AJJ_BLU-(ii-NBIG_MTOP-1)*
1907 (60.0/(NPANE_BIG-NPB_2-2.0)),0.8);
1908 bigmap[8][ii] = DC_spectrum_AJJ(AJJ_BLU-(ii-NBIG_MTOP-1)*
1909 (60.0/(NPANE_BIG-NPB_2-2.0)),0.8);
1910 }
1911
1912 /* add greens to map[8] for "Reds_and_Blues_w_Green" */
1913 bigmap[8][NPB_2-1] = bigmap[8][NPB_2] =
1914 DC_spectrum_AJJ( (NPB_2)*((AJJ_BLU+8.0)/(NPANE_BIG-1.0))-4.0,0.8);
1915 }
1916 *bigmapp = bigmap;
1917 *bigmap_namep = bigmap_name;
1918 return 0;
1919 }
1920
1921 /* want to check this from the command line 4 Mar 2009 [rickr] */
1922 void show_motif_version_string(void)
1923 {
1924 char * verstr = "** VERSION STRING NOT DEFINED**";
1925 char * typestr = source_is_lesstif() ? "LessTif" : "Motif";
1926
1927 #ifdef XmVERSION_STRING
1928 verstr = XmVERSION_STRING;
1929 #endif
1930
1931 #ifdef AFNI_MOTIF_TYPE
1932 typestr = AFNI_MOTIF_TYPE;
1933 #endif
1934
1935 fprintf(stderr, "-- Motif source = %s, USING_LESSTIF = %d\n",
1936 typestr, using_lesstif_is_defined());
1937 fprintf(stderr, " %s\n", verstr);
1938 }
1939
1940 int source_is_lesstif(void)
1941 {
1942 #ifdef LESSTIF_VERSION
1943 return 1;
1944 #endif
1945 return 0;
1946 }
1947
1948 int using_lesstif_is_defined(void)
1949 {
1950 #ifdef USING_LESSTIF
1951 return 1;
1952 #endif
1953 return 0;
1954 }
1955