Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

display.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002    Major portions of this software are copyrighted by the Medical College
00003    of Wisconsin, 1994-2000, and are released under the Gnu General Public
00004    License, Version 2.  See the file README.Copyright for details.
00005 ******************************************************************************/
00006 
00007 #include "display.h"
00008 #include "mrilib.h"
00009 
00010 static char * x11_vcl[] =  { "StaticGray"  , "GrayScale" , "StaticColor" ,
00011                              "PseudoColor" , "TrueColor" , "DirectColor"  } ;
00012 
00013 MCW_DC *first_dc = NULL ;              /* 26 Jun 2003 */
00014 
00015 /*------------------------------------------------------------------------
00016   Returns position of highest set bit in 'ul' as an integer (0-31),
00017   or returns -1 if no bit is set.
00018 --------------------------------------------------------------------------*/
00019 
00020 static int highbit(unsigned long ul)
00021 {
00022   int i;  unsigned long hb;
00023 
00024   hb = 0x80;  hb = hb << 24;   /* hb = 0x80000000UL */
00025   for (i=31; ((ul & hb) == 0) && i>=0;  i--, ul<<=1);
00026   return i;
00027 }
00028 
00029 /*-------------------------------------------------------------------------
00030    Setup the number of bytes per pixel.  For depth 24, this might
00031    be 3 or 4, depending on the server.  RWCox -- 23 Aug 1998.
00032 ---------------------------------------------------------------------------*/
00033 
00034 static void setup_byper( MCW_DC * dc )
00035 {
00036    XPixmapFormatValues * xpv ;
00037    int                  nxpv = 0 , ii ;
00038 
00039    xpv = XListPixmapFormats( dc->display , &nxpv ) ;
00040 
00041    if( xpv == NULL || nxpv == 0 ){
00042       dc->byper = dc->depth / 8 ; dc->bypad = 1 ;  /* defaults */
00043       return ;
00044    }
00045 
00046    /* scan for this depth in the array of pixmap formats */
00047 
00048    for( ii=0 ; ii < nxpv ; ii++ ){
00049       if( xpv[ii].depth == dc->depth ){
00050          dc->byper = xpv[ii].bits_per_pixel / 8 ;  /* bytes, not bits */
00051          dc->bypad = xpv[ii].scanline_pad   / 8 ;
00052          XFree(xpv) ; return ;
00053       }
00054    }
00055 
00056    dc->byper = dc->depth / 8 ; dc->bypad = 1 ;  /* defaults */
00057    XFree(xpv) ; return ;
00058 }
00059 
00060 /*------------------------------------------------------------------------
00061   Create and initialize a new MCW_DC structure.
00062 
00063     wid  = widget used to get info about Display, etc.
00064     ncol = number of colors to use for images
00065     novr = number of overlay colors
00066     covr = array of strings of overlay color names  [used for XAlloc...]
00067     lovr = array of strings of overlay color labels [used for display]
00068     gam  = gamma value to use
00069 
00070   22 Aug 1998: Modified to support TrueColor visuals,
00071                as well as the original PseudoColor -- RWCox.
00072 
00073   14 Sep 1998: Modified to add argument
00074     newcmap = if nonzero, create a new Colormap;
00075               if zero, use the default Colormap for the display
00076 ------------------------------------------------------------------------*/
00077 
00078 static MCW_DCOV * only_ovc = NULL ;  /* Dec 1997 */
00079 
00080 MCW_DC * MCW_new_DC( Widget wid , int ncol ,
00081                      int novr , char * covr[] , char * lovr[] ,
00082                      double gam , int newcmap )
00083 {
00084    MCW_DC * dc ;
00085    int ok , ii , new_ovc ;
00086    unsigned int nplmsk = 0 ;  /* dummy arguments for XAllocColorCells */
00087    unsigned long plane_masks[1] ;
00088 
00089 ENTRY("MCW_new_DC") ;
00090 
00091    if( ncol < 4 || novr < 0 || ncol > MAX_COLORS || novr > MAX_COLORS ){
00092       fprintf(stderr,"\n*** MCW_new_DC: ILLEGAL number of colors: %d %d\n",ncol,novr) ;
00093       ncol = 4 ; novr = 0 ;
00094    }
00095 
00096    dc = myXtNew(MCW_DC) ;
00097 
00098    dc->appcontext = XtWidgetToApplicationContext( wid ) ;
00099    dc->display    = XtDisplay( wid ) ;
00100    dc->screen     = XtScreen( wid ) ;
00101    dc->screen_num = XScreenNumberOfScreen(   dc->screen ) ;
00102    dc->visual     = DefaultVisualOfScreen(   dc->screen ) ;
00103    dc->origGC     = DefaultGCOfScreen(       dc->screen ) ;
00104    dc->planes     = PlanesOfScreen(          dc->screen ) ;
00105    dc->depth      = DefaultDepthOfScreen(    dc->screen ) ;
00106 
00107    dc->cdef       = NULL ;  /* 11 Feb 1999: will be loaded later */
00108 
00109    setup_byper(dc) ;        /* 23 Aug 1998 */
00110 
00111    dc->default_colormap = DefaultColormapOfScreen( dc->screen ) ; /* 01 Sep 1998 */
00112 
00113    dc->colormap = DefaultColormapOfScreen( dc->screen ) ; /* may be changed later */
00114 
00115    dc->parent_widget = wid ;  /* 06 Oct 1996 */
00116 
00117    dc->does_backingstore = DoesBackingStore(dc->screen) ; /* 27 Feb 2001 */
00118    dc->does_saveunders   = DoesSaveUnders(dc->screen) ;
00119 
00120    /** 07 Aug 1998: get more information about the visual **/
00121 
00122    { XVisualInfo vinfo , * vinfo_list ;
00123      int count ;
00124 
00125      dc->visual_id  = XVisualIDFromVisual( dc->visual ) ;
00126      vinfo.visualid = dc->visual_id ;
00127      vinfo_list     = XGetVisualInfo(dc->display,VisualIDMask,&vinfo,&count) ;
00128      if( count > 0 && vinfo_list != NULL ){
00129         dc->visual_info       = vinfo_list ;
00130         dc->visual_redmask    = dc->visual_info->red_mask ;
00131         dc->visual_greenmask  = dc->visual_info->green_mask ;
00132         dc->visual_bluemask   = dc->visual_info->blue_mask ;
00133         dc->visual_redshift   = 7 - highbit(dc->visual_redmask) ;
00134         dc->visual_greenshift = 7 - highbit(dc->visual_greenmask) ;
00135         dc->visual_blueshift  = 7 - highbit(dc->visual_bluemask) ;
00136 #if defined(__cplusplus) || defined(c_plusplus)
00137         dc->visual_class      = dc->visual_info->c_class ;
00138 #else
00139         dc->visual_class      = dc->visual_info->class ;
00140 #endif
00141         if( dc->visual_class != PseudoColor &&
00142             dc->visual_class != TrueColor      ){
00143 
00144            fprintf(stderr,"\n\n"
00145                           " ** The default X11 visual type on your computer is set to %s.\n"
00146                           " ** AFNI programs only work with PseudoColor or TrueColor visuals.\n"
00147                           " ** You must have your superuser modify your system's setup.\a\n" ,
00148                    x11_vcl[dc->visual_class] ) ;
00149 
00150            dc->visual_class = PseudoColor ;  /* let the program fail later */
00151         }
00152 
00153 #if 0
00154         if( dc->visual_class == TrueColor ){  /* removed 28 Oct 1999 */
00155            static int done = 0 ;
00156            if( !done )
00157               fprintf(stderr,
00158                  "\n"
00159                  " ** The default X11 visual type on your computer is %d bit TrueColor.\n"
00160                  " ** Support for this is experimental.  AFNI was developed to use 4..12\n"
00161                  " ** bit PseudoColor visuals for image display -- RW Cox, 22 Aug 1998.\n" ,
00162                  dc->depth ) ;
00163            done = 1 ;
00164         }
00165 #endif
00166 
00167 #if 0
00168         fprintf(stderr,"\n"
00169                        "DC: redmask=%lx greenmask=%lx bluemask=%lx\n"
00170                        "    redshift=%d greenshift=%d blueshift=%d\n"
00171                        "    class=%d=%s depth=%d\n",
00172                 dc->visual_redmask , dc->visual_greenmask , dc->visual_bluemask ,
00173                 dc->visual_redshift , dc->visual_greenshift , dc->visual_blueshift ,
00174                 dc->visual_class , x11_vcl[dc->visual_class] , dc->depth ) ;
00175 #endif
00176 
00177      } else {                            /* should never occur! */
00178         dc->visual_info  = NULL ;
00179         dc->visual_class = PseudoColor ; /* we hope */
00180      }
00181    }
00182 
00183 #if 0
00184  {  long reqmax ;
00185     reqmax = XMaxRequestSize(dc->display) ;
00186     printf("max X11 request size = %d\n",reqmax) ;
00187  }
00188 #endif
00189 
00190 #define DEPTH_BOT  4
00191 #define DEPTH_TOP 32
00192 
00193    if( dc->depth < DEPTH_BOT || dc->depth > DEPTH_TOP ){
00194       fprintf(stderr,"\n\n"
00195                      " ** Your X11 display is set to %d bitplanes for image display.\n"
00196                      " ** AFNI programs can only deal with between %d and %d bitplanes.\n"
00197                      " ** You must have your superuser modify your system's setup.\a\n" ,
00198               dc->depth , DEPTH_BOT , DEPTH_TOP ) ;
00199       exit(1) ;
00200    }
00201 
00202    dc->width   = WidthOfScreen(  dc->screen ) ;
00203    dc->height  = HeightOfScreen( dc->screen ) ;
00204 
00205    dc->ncol_im = ncol ;
00206    dc->gamma   = dc->gamma_init = gam  ;
00207 
00208    if( dc->visual_class == PseudoColor ){                  /* 22 Aug 1998 */
00209 
00210       if( newcmap ){                                       /* 14 Sep 1998 */
00211          int ncold , cc ;
00212          XColor xcold ;
00213 
00214          /* make a new colormap */
00215 
00216          dc->colormap = XCreateColormap( dc->display , RootWindowOfScreen(dc->screen) ,
00217                                          dc->visual  , AllocNone ) ;
00218 
00219          /* allocate some colors from the old one (to reduce flashing) */
00220 
00221 #define NREUSE 9
00222          ncold = dc->visual_info->colormap_size ;
00223          if( ncold > NREUSE ) ncold = NREUSE ;
00224          for( cc=0 ; cc < ncold ; cc++ ){
00225             xcold.pixel = cc ;
00226             XQueryColors( dc->display , dc->default_colormap , &xcold , 1 ) ;
00227             XAllocColor( dc->display , dc->colormap , &xcold ) ;
00228          }
00229       }
00230 
00231       ok = XAllocColorCells( dc->display , dc->colormap ,
00232                              True , plane_masks , nplmsk ,
00233                              dc->pix_im , dc->ncol_im ) ;
00234 
00235       if( ! ok ){
00236          fprintf(stderr,
00237                  "\a\n** XAllocColorCells fails for %d colors\n",dc->ncol_im) ;
00238          fprintf(stderr,
00239                  "\n** try the -ncolor option to reduce # of colors\n");
00240          exit(1) ;
00241       }
00242 
00243       dc->pix_im_ready = 1 ;
00244    } else if( dc->visual_class == TrueColor ){
00245       dc->pix_im_ready = 0 ;
00246    }
00247 
00248    DC_init_im_col( dc ) ;
00249    DC_init_im_gry( dc ) ;
00250 
00251    dc->use_xcol_im = False ;
00252    DC_set_image_colors( dc ) ;  /* 22 Aug 1998: replaces XStoreColors */
00253 
00254    /* set up overlay colors from list of names
00255       (since the XImage routines use negative indices
00256        to indicate overlays, the 0th overlay color is not used) */
00257 
00258    /* Dec 1997: put all overlay stuff into a single place */
00259 
00260    new_ovc = 0 ;
00261    if( only_ovc == NULL ){ only_ovc = myXtNew(MCW_DCOV) ; new_ovc = 1 ; }
00262    dc->ovc = only_ovc ;
00263 
00264    if( new_ovc ){
00265       only_ovc->xcol_ov[0]  = dc->xgry_im[0] ;
00266       only_ovc->pix_ov[0]   = dc->pix_im[0] ;
00267       only_ovc->name_ov[0]  = XtNewString("none") ;
00268       only_ovc->label_ov[0] = only_ovc->name_ov[0] ;
00269       only_ovc->ncol_ov     = 1 ;
00270 
00271       only_ovc->bright_ov[0] = 0.0 ;  /* 20 Dec 1999 */
00272 
00273       dc->ovc->r_ov[0] = 0 ;          /* 04 Mar 2002 */
00274       dc->ovc->g_ov[0] = 0 ;
00275       dc->ovc->b_ov[0] = 0 ;
00276    }
00277 
00278    for( ii=0 ; ii < novr ; ii++ ){
00279 
00280      ok = DC_add_overlay_color( dc , covr[ii] , lovr[ii] ) ;
00281 
00282      if( ok < 0 )
00283         fprintf(stderr,
00284           "\n*** can't get X11 colormap entry for overlay color %s" , lovr[ii] ) ;
00285 #ifdef DISPLAY_DEBUG
00286      else {
00287         printf("\n*** overlay color %s has pixel %d at index %d" ,
00288                dc->ovc->name_ov[ok] , (int)dc->ovc->pix_ov[ok] , ok ) ;
00289         fflush(stdout) ;
00290      }
00291 #endif
00292    }
00293    OVC_mostest( dc->ovc ) ;
00294 
00295    /*-- May 1996: create new GC for use with text and graphics --*/
00296 
00297    { XGCValues  gcv;
00298      int ifont ;
00299      XFontStruct * mfinfo = NULL ;
00300      char * xdef ;
00301 
00302      gcv.function = GXcopy ;
00303      dc->myGC     = XCreateGC( dc->display,
00304                                RootWindowOfScreen(dc->screen) ,
00305                                GCFunction , &gcv ) ;
00306 
00307      xdef = XGetDefault(dc->display,"AFNI","gfont") ;
00308      if( xdef != NULL )
00309         mfinfo = XLoadQueryFont(dc->display,xdef) ;
00310 
00311      if( mfinfo == NULL ){
00312         for( ifont=0 ; tfont_hopefuls[ifont] != NULL ; ifont++ ){
00313            mfinfo = XLoadQueryFont(dc->display, tfont_hopefuls[ifont]) ;
00314            if( mfinfo != NULL ) break ;
00315         }
00316      }
00317      if( mfinfo == NULL ){
00318         fprintf(stderr,
00319                 "\n*** Cannot load any text fonts in display.c ***\n" ) ;
00320      } else {
00321         XSetFont( dc->display , dc->myGC , mfinfo->fid ) ;
00322      }
00323      XSetForeground(dc->display , dc->myGC , dc->ovc->pixov_darkest ) ;
00324      XSetBackground(dc->display , dc->myGC , dc->ovc->pixov_brightest ) ;
00325      dc->myFontStruct = mfinfo ;
00326    }
00327 
00328    dc->parent = dc->aux = NULL ;
00329 
00330 #ifdef DISPLAY_DEBUG
00331    printf("\n") ;
00332 #endif
00333 
00334 #if 0
00335    reload_DC_colordef( dc ) ;  /* 11 Feb 1999 */
00336 #else
00337    dc->cdef = NULL ;
00338 #endif
00339 
00340    if( first_dc == NULL ) first_dc = dc ;  /* 26 Jun 2003 */
00341 
00342    RETURN(dc) ;
00343 }
00344 
00345 /*-----------------------------------------------------------------------
00346    Set the image display to grayscale
00347 -------------------------------------------------------------------------*/
00348 
00349 void DC_palette_setgray( MCW_DC * dc )
00350 {
00351    dc->use_xcol_im = False ;
00352    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00353    return ;
00354 }
00355 
00356 /*-----------------------------------------------------------------------
00357    Set the image display to colorscale
00358 -------------------------------------------------------------------------*/
00359 
00360 void DC_palette_setcolor( MCW_DC * dc )
00361 {
00362    dc->use_xcol_im = True ;
00363    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00364    return ;
00365 }
00366 
00367 /*-----------------------------------------------------------------------
00368    Restore the color and grayscale palettes to their defaults
00369 -------------------------------------------------------------------------*/
00370 
00371 void DC_palette_restore( MCW_DC * dc , double new_gamma )
00372 {
00373    dc->gamma = (new_gamma > 0 ) ? new_gamma : dc->gamma_init ;
00374    DC_init_im_col( dc ) ;
00375    DC_init_im_gry( dc ) ;
00376    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00377 }
00378 
00379 /*-----------------------------------------------------------------------
00380    Initialize the grayscale image palette.
00381    Modified 22 Aug 1998 for TrueColor support.
00382 -------------------------------------------------------------------------*/
00383 
00384 static double mypow( double x , double y )  /* replaces the math library pow */
00385 {
00386    double b ;
00387    if( x <= 0.0 ) return 0.0 ;
00388    if( y == 1.0 ) return x ;
00389    b = log(x) ; b = exp( y*b ) ;
00390    return b ;
00391 }
00392 
00393 void DC_init_im_gry( MCW_DC * dc )
00394 {
00395    int i, k, m, nc ;
00396    float a , gamm , b ;
00397 
00398    char * env ;              /* 11 Apr 2000 */
00399    float atop=255.0 , abot=55.0 ;
00400 
00401 #if 0
00402    env = getenv("AFNI_GRAYSCALE_TOP") ;
00403    if( env != NULL ){
00404       float val = strtod(env,NULL) ;
00405       if( val <= 255.0 && val >= 100.0 ) atop = val ;
00406    }
00407 #endif
00408 
00409    env = getenv("AFNI_GRAYSCALE_BOT") ;
00410    if( env != NULL ){
00411       float val = strtod(env,NULL) ;
00412       if( val < atop && val >= 0.0 ) abot = val ;
00413    }
00414 
00415    nc   = dc->ncol_im ;
00416    gamm = dc->gamma ;
00417    a    = (atop-abot) / nc ;
00418 
00419    for (i=0; i < nc ; i++) {
00420       b = log( (a*i+abot)/255.0 ) ;   /* The code that used to be here */
00421       b = exp( gamm * b ) ;           /* (using pow) was replaced due  */
00422       k = (int)( 255.0 * b + 0.5 ) ;  /* to some bug in gcc on Linux.  */
00423 
00424       m = BYTE_TO_INTEN(k) ;
00425 
00426       dc->xint_im[i]       = m ;
00427       dc->xgry_im[i].red   = m ;
00428       dc->xgry_im[i].green = m ;
00429       dc->xgry_im[i].blue  = m ;
00430       dc->xgry_im[i].flags = DoRed|DoGreen|DoBlue;
00431 
00432       if( dc->visual_class == PseudoColor )        /* 22 Aug 1998 */
00433          dc->xgry_im[i].pixel = dc->pix_im[i];
00434    }
00435 
00436    return ;
00437 }
00438 
00439 /*----------------------------------------------------------------------*/
00440 /*! Return a color from the spectrum.  Input "an" is between 0 and 360.
00441     Adapted from Ziad Saad. -- 01 Feb 2003 - RWCox.
00442 ------------------------------------------------------------------------*/
00443 
00444 rgbyte DC_spectrum_ZSS( double an , double gamm )
00445 {
00446    int r,g,b , m ;
00447    rgbyte color ;
00448 
00449    if( gamm <= 0.0 ) gamm = 1.0 ;
00450 
00451    while( an <   0.0 ) an += 360.0 ;
00452    while( an > 360.0 ) an -= 360.0 ;
00453 
00454    an = an / 90.0 ;
00455 
00456    if( an <= 1.0 ){
00457      r = 255.*mypow(1.0-an,gamm)+0.5 ;
00458      g = 255.*mypow(0.5*an,gamm)+0.5 ;
00459      b = 255.*mypow(an    ,gamm)+0.5 ;
00460    } else if( an <= 2.0 ){
00461      r = 0 ;
00462      g = 255.*mypow(0.5*an,gamm)+0.5 ;
00463      b = 255.*mypow(2.0-an,gamm)+0.5 ;
00464    } else if( an <= 3.0 ){
00465      r = 255.*mypow(an-2.0,gamm)+0.5 ;
00466      g = 255 ;
00467      b = 0   ;
00468    } else {
00469      r = 255 ;
00470      g = 255.*mypow(4.0-an,gamm)+0.5 ;
00471      b = 0   ;
00472    }
00473 
00474 #if 0
00475    m = MAX(r,g) ; m = MAX(m,b) ;
00476    if( m < 255 ){ float s=255.0/m; r *= s; g *= s; b *= s; }
00477 #endif
00478 
00479    color.r = r ; color.g = g ; color.b = b ; return color ;
00480 }
00481 
00482 /*----------------------------------------------------------------------*/
00483 /*! Return a color from the spectrum.  Input "an" is between 0 and 360.
00484     Adapted from Andrzej Jesmanowicz. -- 30 Jan 2003 - RWCox.
00485 ------------------------------------------------------------------------*/
00486 
00487 rgbyte DC_spectrum_AJJ( double an , double gamm )
00488 {
00489    int r,g,b , m ;
00490    double ak,ab,s,c,sb,cb ;
00491    rgbyte color ;
00492 
00493    if( gamm <= 0.0 ) gamm = 1.0 ;
00494 
00495 #if 0
00496    ak = 105.; s  = 255.0-ak; c  = s /60.;     /* AJ's choices */
00497    ab =  65.; sb = 255.0-ab; cb = sb/60.;
00498 #else
00499    ak =   5.; s  = 255.0-ak; c  = s /60.;     /* RWC's choices */
00500    ab =   5.; sb = 255.0-ab; cb = sb/60.;
00501 #endif
00502 
00503    while( an <   0.0 ) an += 360.0 ;
00504    while( an > 360.0 ) an -= 360.0 ;
00505 
00506    if( an < 120. ){
00507      r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
00508      g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
00509      m = MAX(r,g) ;
00510      b = 0;
00511    } else if( an < 240. ){
00512      r = 0;
00513      g = 255.*mypow((ak + MIN(s ,(240. - an)*c ))/255., gamm) +.5;
00514      b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
00515      m = MAX(g,b) ;
00516    } else {
00517      r = 255.*mypow((ak + MIN(s,(an - 240.)*c ))/255., gamm) +.5;
00518      g = 0;
00519      b = 255.*mypow((ab + MIN(s,(360. - an)*cb))/255., gamm) +.5;
00520      m = MAX(r,b) ;
00521    }
00522 
00523 #if 0
00524    if( m < 255 ){ s = 255.0/m ; r *= s ; g *= s ; b *= s ; }
00525 #endif
00526 
00527    color.r = r ; color.g = g ; color.b = b ; return color ;
00528 }
00529 
00530 /*-----------------------------------------------------------------------
00531    Initialize the color image palette.
00532    Modified 22 Aug 1998 for TrueColor support.
00533 -------------------------------------------------------------------------*/
00534 
00535 void DC_init_im_col( MCW_DC * dc )
00536 {
00537    double da, an, c, s, sb, cb, ak, ab , a1,a2 , gamm ;
00538    int i, r, g, b , nc ;
00539 
00540    a1 = 0.0   ;  /* range of spectrum -- hardwired for now */
00541    a2 = 240.0 ;
00542 
00543    nc   = dc->ncol_im ;
00544    gamm = dc->gamma ;
00545 
00546    ak = 105.; s  = 150.; c  = s/60.;
00547    ab = 65.;  sb = 190.; cb = s/60.;
00548 
00549    an = a1;   da = (a2 - a1)/nc ; an = an-da+360.;
00550 
00551    for( i=0 ; i < nc ; i++ ){
00552 
00553      an += da; an = fmod(an,360.);
00554 
00555      if((an >= 0) && (an < 120.)) {
00556           r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5;
00557           g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5;
00558           b = 0;
00559      } else if((an >= 120.) && (an < 240.)) {
00560           r = 0;
00561           g = 255.*mypow((ak + MIN(s ,(240. - an)*c))/255., gamm) +.5;
00562           b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5;
00563      } else if(an >= 240.) {
00564           r =  255.*mypow((ak + MIN(s,(an - 240.)*c))/255., gamm) +.5;
00565           g = 0;
00566           b = 255.*mypow((ak + MIN(s,(360. - an)*c))/255., gamm) +.5;
00567      }
00568      dc->xcol_im[i].red   = BYTE_TO_INTEN(r) ;
00569      dc->xcol_im[i].green = BYTE_TO_INTEN(g) ;
00570      dc->xcol_im[i].blue  = BYTE_TO_INTEN(b) ;
00571      dc->xcol_im[i].flags = DoRed|DoGreen|DoBlue;
00572 
00573      if( dc->visual_class == PseudoColor )        /* 22 Aug 1998 */
00574         dc->xcol_im[i].pixel = dc->pix_im[i];
00575    }
00576    return ;
00577 }
00578 
00579 #if 0 /*******************************************************************/
00580 /* --------------------------------------------------------------------------
00581    Given an triple of bytes (0..255), make a color and return its pixel value
00582 -----------------------------------------------------------------------------*/
00583 
00584 Pixel RGB_byte_to_color( MCW_DC * dc , int r , int g , int b )
00585 {
00586    XColor  any_col;
00587 
00588    any_col.red   = BYTE_TO_INTEN(r);
00589    any_col.green = BYTE_TO_INTEN(g);
00590    any_col.blue  = BYTE_TO_INTEN(b);
00591    any_col.flags = DoRed | DoGreen | DoBlue;
00592    XAllocColor( dc->display , dc->colormap , &any_col );
00593    return any_col.pixel ;
00594 }
00595 
00596 /*--------------------------------------------------------------------------
00597   Given a color named by a string, allocate it and return its pixel value
00598 ----------------------------------------------------------------------------*/
00599 
00600 Pixel Name_to_color( MCW_DC * dc , char * name )
00601 {
00602    XColor cell , exact ;
00603    int ok ;
00604 
00605    ok = XAllocNamedColor( dc->display , dc->colormap , name , &cell , &exact ) ;
00606 
00607    if( ok ) return cell.pixel ;
00608    else     return BlackPixelOfScreen( dc->screen ) ;
00609 }
00610 #endif /********************************************************************/
00611 
00612 /*--------------------------------------------------------------------------
00613    Given a color name, allocate it, put it into the DC overlay table,
00614    and return its index (negative if an error occurred)
00615    Dec 1997: modified to use read-write color cells,
00616              and recycle them if the same label is passed in.
00617    22 Aug 1998: modified for TrueColor support
00618 ----------------------------------------------------------------------------*/
00619 
00620 int DC_add_overlay_color( MCW_DC * dc , char * name , char * label )
00621 {
00622    int ii , ok , newcol ;
00623    Pixel newpix ;
00624    XColor cell ;
00625 
00626 ENTRY("DC_add_overlay_color") ;
00627 
00628    if( name == NULL || strlen(name) == 0 ) RETURN(-1) ;  /* error */
00629    if( label == NULL ) label = name ;
00630 
00631    /** see if label is already in the table **/
00632 
00633    for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ )
00634       if( strcmp(label,dc->ovc->label_ov[ii]) == 0 ) break ;
00635 
00636    newcol = (ii == dc->ovc->ncol_ov) ;     /** need a new color cell? **/
00637    if( ii == dc->ovc->ncol_ov ){           /** Yes **/
00638       unsigned int nplmsk = 0 ;
00639       unsigned long plane_masks[1] ;
00640 
00641       if( ii >= MAX_COLORS ) RETURN(-1) ;   /* too many overlay colors! */
00642 
00643       if( dc->visual_class == PseudoColor ){  /* 22 Aug 1998 */
00644          ok = XAllocColorCells( dc->display , dc->colormap ,
00645                                 True , plane_masks , nplmsk , &newpix , 1 ) ;
00646          if( !ok ) RETURN(-1) ;                /* couldn't get a new cell */
00647          cell.pixel = newpix ;
00648       }
00649 
00650    } else {                                /** Reusing an old cell **/
00651 
00652       if( strcmp(name,dc->ovc->name_ov[ii]) == 0 ) RETURN(ii) ; /* no change! */
00653 
00654       if( dc->visual_class == PseudoColor )  /* 22 Aug 1998 */
00655          cell.pixel = dc->ovc->pix_ov[ii] ;
00656       else if( dc->visual_class == TrueColor )
00657          XFreeColors( dc->display, dc->colormap, dc->ovc->pix_ov+ii, 1, 0 ) ;
00658    }
00659 
00660    ok = XParseColor( dc->display , dc->colormap , name, &cell ) ;
00661    if( !ok ) RETURN(-1) ;
00662 
00663    if( newcol ){                      /** made a new cell **/
00664       dc->ovc->ncol_ov++ ;
00665    } else {                           /** free old cell stuff **/
00666       myXtFree( dc->ovc->name_ov[ii] ) ;
00667       myXtFree( dc->ovc->label_ov[ii] ) ;
00668    }
00669 
00670    if( dc->visual_class == PseudoColor )                  /* 22 Aug 1998 */
00671       XStoreColor( dc->display , dc->colormap , &cell ) ;
00672    else if( dc->visual_class == TrueColor )
00673       XAllocColor( dc->display , dc->colormap , &cell ) ;
00674 
00675    dc->ovc->xcol_ov[ii]  = cell ;                      /* save cell info */
00676    dc->ovc->pix_ov[ii]   = cell.pixel ;
00677    dc->ovc->name_ov[ii]  = XtNewString(name) ;
00678    dc->ovc->label_ov[ii] = XtNewString(label) ;
00679 
00680    dc->ovc->r_ov[ii] = INTEN_TO_BYTE(cell.red) ;       /* 06 Mar 2001 */
00681    dc->ovc->g_ov[ii] = INTEN_TO_BYTE(cell.green) ;
00682    dc->ovc->b_ov[ii] = INTEN_TO_BYTE(cell.blue) ;
00683 
00684    if( dc->visual_class == PseudoColor )  /* 11 Feb 1999: */
00685       FREE_DC_colordef(dc->cdef) ;        /* will need to be recomputed */
00686 
00687    dc->ovc->bright_ov[ii] = BRIGHTNESS( DCOV_REDBYTE(dc,ii) ,       /* 20 Dec 1999 */
00688                                         DCOV_GREENBYTE(dc,ii) ,
00689                                         DCOV_BLUEBYTE(dc,ii)   ) ;
00690    RETURN(ii) ;
00691 }
00692 
00693 /*-------------------------------------------------------------------------*/
00694 
00695 int DC_find_overlay_color( MCW_DC *dc , char *label )
00696 {
00697    int ii ;
00698    if( dc == NULL || label == NULL ) return -1 ;
00699    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
00700      if( strcasecmp(label,dc->ovc->label_ov[ii]) == 0 ) return ii ;
00701    return -1 ;
00702 }
00703 
00704 /*-------------------------------------------------------------------------*/
00705 
00706 int DC_find_closest_overlay_color( MCW_DC *dc , char *cname )
00707 {
00708    float rr,gg,bb ; int b_rr,b_gg,b_bb ;
00709    int ii , jj;
00710 
00711    if( dc == NULL || cname == NULL || *cname == '\0' ) return -1 ;
00712 
00713    ii = DC_find_overlay_color( dc , cname ) ;
00714    if( ii >= 0 ) return ii ;
00715 
00716    ii = DC_parse_color( dc, cname, &rr,&gg,&bb ) ;
00717    if( ii ) return -1 ;
00718 
00719    b_rr = (int)(255.9*rr) ;
00720    b_gg = (int)(255.9*gg) ;
00721    b_bb = (int)(255.9*bb) ;
00722 
00723    jj = 0 ; rr = 9999999.9 ;
00724    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ){
00725      gg = abs(b_rr-(int)dc->ovc->r_ov[ii])
00726          +abs(b_gg-(int)dc->ovc->g_ov[ii])
00727          +abs(b_bb-(int)dc->ovc->b_ov[ii]) ;
00728      if( gg < rr ){ jj = ii ; rr = gg ; }
00729    }
00730 
00731    return jj ;
00732 }
00733 
00734 /*-------------------------------------------------------------------------
00735   load the tmp? arrays (alas, GLOBAL data, a sin against God and Man)
00736   from an array of colors
00737 --------------------------------------------------------------------------*/
00738 
00739 static unsigned short tmp1[MAX_COLORS] , tmp2[MAX_COLORS] , tmp3[MAX_COLORS] ;
00740 static int            tmpi[MAX_COLORS] ;
00741 
00742 void load_tmp_colors( int nc , XColor *ccc )
00743 {
00744    register int i ;
00745 
00746    for( i=0 ; i < nc ; i++ ){
00747       tmp1[i] = ccc[i].red ;
00748       tmp2[i] = ccc[i].green ;
00749       tmp3[i] = ccc[i].blue ;
00750    }
00751    return ;
00752 }
00753 
00754 /*-------------------------------------------------------------------------
00755   rotate active palette k steps
00756 -------------------------------------------------------------------------*/
00757 
00758 void DC_palette_rotate( MCW_DC * dc , int kk )
00759 {
00760    register int i , j , nc , k ;
00761    XColor * xc ;
00762 
00763    nc = dc->ncol_im ;
00764 
00765    if( dc->use_xcol_im ){
00766       xc = & ( dc->xcol_im[0] ) ;  /* choose active palette */
00767       k  = -kk ;                   /* direction of rotation */
00768    } else {
00769       xc = & ( dc->xgry_im[0] ) ;
00770       k  = -kk ;
00771    }
00772 
00773    load_tmp_colors( nc , xc ) ;    /* store RGB values in tmp? */
00774 
00775    for( i=0 ; i < nc ; i++ ){
00776       j = (i+nc+k) % nc ;
00777 
00778       xc[i].red   = tmp1[j] ;
00779       xc[i].green = tmp2[j] ;
00780       xc[i].blue  = tmp3[j] ;
00781    }
00782 
00783    if( ! dc->use_xcol_im ){  /* rotate xint_im as well for graymap */
00784       for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
00785       for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[(i+nc+k)%nc] ;
00786    }
00787 
00788    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00789    return ;
00790 }
00791 
00792 /*------------------------------------------------------------------------*/
00793 
00794 void DC_palette_swap( MCW_DC * dc )
00795 {
00796    register int i, k , nc ;
00797    XColor * xc ;
00798 
00799    nc = dc->ncol_im ;
00800    k  = nc - 1 ;
00801 
00802    if( dc->use_xcol_im ){
00803       xc = & ( dc->xcol_im[0] ) ;
00804    } else {
00805       xc = & ( dc->xgry_im[0] ) ;
00806    }
00807 
00808    load_tmp_colors( nc , xc ) ;
00809 
00810    for(i=0; i < nc ; i++) {
00811      xc[i].red   = tmp1[k-i];
00812      xc[i].green = tmp2[k-i];
00813      xc[i].blue  = tmp3[k-i];
00814    }
00815 
00816    if( ! dc->use_xcol_im ){  /* swap xint_im as well for graymap */
00817       for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ;
00818       for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[k-i] ;
00819    }
00820 
00821    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00822    return ;
00823 }
00824 
00825 /*-----------------------------------------------------------------------*/
00826 
00827 void DC_palette_bright(  MCW_DC * dc , int dd )
00828 {
00829    if( dc->use_xcol_im ) DC_color_bright( dc ,    dd ) ;
00830    else                  DC_gray_change(  dc , -2*dd ) ;
00831    return;
00832 }
00833 
00834 /*-----------------------------------------------------------------------*/
00835 
00836 void DC_color_bright( MCW_DC * dc , int dlev )
00837 {
00838    register int i ;
00839    double c ;
00840    int      nc = dc->ncol_im ;
00841    XColor * xc = dc->xcol_im ;
00842 
00843    c = 1.0 - 0.005 * (double) dlev ;
00844 
00845    for( i=0 ; i < nc ; i++ ){
00846       xc[i].red   = CLIP_INTEN( c * xc[i].red   ) ;
00847       xc[i].green = CLIP_INTEN( c * xc[i].green ) ;
00848       xc[i].blue  = CLIP_INTEN( c * xc[i].blue  ) ;
00849    }
00850    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00851    return ;
00852 }
00853 
00854 /*------------------------------------------------------------------------*/
00855 
00856 void DC_gray_change( MCW_DC * dc , int dlev )
00857 {
00858    register int i, k, delta ;
00859    int      nc = dc->ncol_im ;
00860    XColor * xc = dc->xgry_im ;
00861    int    * in = dc->xint_im ;
00862 
00863    if( dc->use_xcol_im ) return ;
00864 
00865    delta = dlev * abs( (in[nc-1] - in[0]) / nc ) ;
00866 
00867    for( i=0 ; i < nc ; i++ ){
00868       k = in[i] += delta ;
00869       xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
00870    }
00871    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00872    return ;
00873 }
00874 
00875 /*------------------------------------------------------------------------*/
00876 
00877 void DC_palette_squeeze( MCW_DC * dc , int dd )
00878 {
00879    if( dc->use_xcol_im ) DC_color_squeeze( dc ,    dd ) ;
00880    else                  DC_gray_contrast( dc , -2*dd ) ;
00881    return;
00882 }
00883 
00884 /*------------------------------------------------------------------------*/
00885 
00886 void DC_color_squeeze( MCW_DC * dc , int dlev )
00887 {
00888    return ;  /* not implemented */
00889 }
00890 
00891 /*------------------------------------------------------------------------*/
00892 
00893 void DC_gray_contrast( MCW_DC * dc , int dlev )
00894 {
00895    register int i, k, delta ;
00896    int      nc = dc->ncol_im ;
00897    XColor * xc = dc->xgry_im ;
00898    int    * in = dc->xint_im ;
00899 
00900    if( dc->use_xcol_im ) return ;
00901 
00902    delta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
00903    if( delta == 0 ) delta = dlev ;
00904 
00905    for( i=0 ; i < nc ; i++ ){
00906       k = in[i] += i * delta ;
00907       xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
00908    }
00909    DC_set_image_colors( dc ) ;  /* 22 Aug 1998 */
00910    return ;
00911 }
00912 
00913 /*------------------------------------------------------------------------*/
00914 
00915 void DC_gray_conbrio( MCW_DC *dc , int dlev )  /* 23 Oct 2003 */
00916 {
00917    register int i, k, bdelta,cdelta ;
00918    int      nc = dc->ncol_im ;
00919    XColor * xc = dc->xgry_im ;
00920    int    * in = dc->xint_im ;
00921 
00922    if( dc->use_xcol_im ) return ;
00923 
00924    bdelta = dlev *  abs(in[nc-1] - in[0])       / nc ;
00925    cdelta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ;
00926    if( cdelta == 0 ) cdelta = dlev ;
00927 
00928    for( i=0 ; i < nc ; i++ ){
00929      k = in[i] += i * cdelta - bdelta ;
00930      xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ;
00931    }
00932    DC_set_image_colors( dc ) ;
00933    return ;
00934 }
00935 
00936 /*-------------------------------------------------------------------*/
00937 
00938 Boolean MCW_check_iconsize( int width , int height , MCW_DC * dc )
00939 {
00940    int ii ;
00941    Boolean good ;
00942    int nsl = 0 ;
00943    XIconSize * xsl = NULL ;
00944 
00945    /** elementary checks **/
00946 
00947    if( width < 1 || height < 1 ) return False ;
00948 
00949    XGetIconSizes( dc->display , RootWindowOfScreen(dc->screen) , &xsl , &nsl ) ;
00950 
00951    if( xsl == NULL || nsl < 1 )  return True ;
00952 
00953    good = False ;
00954 
00955    for( ii=0 ; ii < nsl ; ii++ ){
00956 
00957       if( width  >= xsl[ii].min_width  && width  <= xsl[ii].max_width  &&
00958           height >= xsl[ii].min_height && height <= xsl[ii].max_height &&
00959 
00960           (width  - xsl[ii].min_width ) % xsl[ii].width_inc  == 0 &&
00961           (height - xsl[ii].min_height) % xsl[ii].height_inc == 0   ) { good = True ; break ; }
00962    }
00963 
00964    XFree(xsl) ;
00965    return good ;
00966 }
00967 
00968 /*---------------------------------------------------------------------------
00969    Given a pixel index, return a pointer to its color (not very efficiently).
00970    11 Feb 1999: if use_cmap != 0, use the colormap instead of
00971                 the internal dc color arrays
00972 -----------------------------------------------------------------------------*/
00973 
00974 XColor * DCpix_to_XColor( MCW_DC * dc , Pixel pp , int use_cmap )
00975 {
00976    XColor * ulc , * ovc ;
00977    int ii ;
00978 
00979    if( use_cmap ){              /* 11 Feb 1999 */
00980       static XColor xc ;
00981       byte rr,gg,bb ;
00982 
00983       DC_pixel_to_rgb( dc , pp , &rr,&gg,&bb ) ;
00984       xc.red   = BYTE_TO_INTEN(rr) ;
00985       xc.green = BYTE_TO_INTEN(gg) ;
00986       xc.blue  = BYTE_TO_INTEN(bb) ;
00987       return &xc ;
00988    }
00989 
00990    ulc = (dc->use_xcol_im) ? dc->xcol_im : dc->xgry_im ;
00991    ovc = dc->ovc->xcol_ov ;
00992 
00993    for( ii=0 ; ii < dc->ncol_im ; ii++ )
00994       if( pp == dc->pix_im[ii] ) return (ulc+ii) ;
00995 
00996    for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ )
00997       if( pp == dc->ovc->pix_ov[ii] ) return (ovc+ii) ;
00998 
00999    return ulc ;  /* not found, but must return something */
01000 }
01001 
01002 /*-------------------------------------------------------------------------*/
01003 
01004 void DC_fg_color( MCW_DC * dc , int nov )
01005 {
01006    XSetForeground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
01007    return ;
01008 }
01009 
01010 void DC_bg_color( MCW_DC * dc , int nov )
01011 {
01012    XSetBackground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ;
01013    return ;
01014 }
01015 
01016 void DC_fg_colorpix( MCW_DC * dc , Pixel pix )
01017 {
01018    XSetForeground( dc->display , dc->myGC , pix ) ;
01019    return ;
01020 }
01021 
01022 void DC_fg_colortext( MCW_DC * dc , char * cname )
01023 {
01024    XColor any_col , rgb_col ;
01025 
01026    if( ! XAllocNamedColor( dc->display , dc->colormap ,
01027                            cname , &any_col, &rgb_col ) ){
01028 
01029       fprintf(stderr,"\n** XAllocNamedColor problem: %s **\n",cname ) ;
01030    } else {
01031       XSetForeground( dc->display , dc->myGC , any_col.pixel ) ;
01032    }
01033    return ;
01034 }
01035 
01036 void DC_linewidth( MCW_DC * dc , int lw )
01037 {
01038    XGCValues gcv ;
01039 
01040    if( lw >= 0 ){
01041       gcv.line_width = lw ;
01042       gcv.join_style = JoinBevel ;
01043       XChangeGC( dc->display , dc->myGC , GCLineWidth | GCJoinStyle , &gcv ) ;
01044    }
01045    return ;
01046 }
01047 
01048 void DC_linestyle( MCW_DC * dc , int lw )
01049 {
01050    XGCValues gcv ;
01051    gcv.line_style = lw ;
01052    XChangeGC( dc->display , dc->myGC , GCLineStyle , &gcv ) ;
01053    return ;
01054 }
01055 
01056 /*-------------------------------------------------------------------------
01057  May 1996: save the indices of the darkest and brightest overlays
01058  Dec 1997: moved into a separate routine
01059 ---------------------------------------------------------------------------*/
01060 
01061 void OVC_mostest( MCW_DCOV * ovc )
01062 {
01063    float bright_inten , dark_inten , red_inten , green_inten , blue_inten , inten ;
01064    int   bright_ii    , dark_ii    , red_ii    , green_ii    , blue_ii ;
01065    float yellow_inten ;
01066    int   yellow_ii    ;
01067    int   ii ;
01068 
01069    if( ovc == NULL || ovc->ncol_ov < 2 ) return ;
01070 
01071    bright_inten = dark_inten = XCOL_BRIGHTNESS( ovc->xcol_ov[1] ) ;
01072    bright_ii    = dark_ii    = 1 ;
01073 
01074    red_inten   = XCOL_REDNESS  ( ovc->xcol_ov[1] ) ;  /* June 1997 */
01075    green_inten = XCOL_GREENNESS( ovc->xcol_ov[1] ) ;
01076    blue_inten  = XCOL_BLUENESS ( ovc->xcol_ov[1] ) ;
01077    red_ii = green_ii = blue_ii = 1 ;
01078 
01079    yellow_ii = 1 ;
01080    yellow_inten = XCOL_YELLOWNESS( ovc->xcol_ov[1] ) ;  /* 28 Jan 2004 */
01081 
01082    for( ii=2 ; ii < ovc->ncol_ov ; ii++ ){
01083       inten = XCOL_BRIGHTNESS( ovc->xcol_ov[ii] ) ;
01084       if( inten > bright_inten ){
01085          bright_inten = inten ; bright_ii = ii ;
01086       } else if( inten < dark_inten ){
01087          dark_inten = inten ; dark_ii = ii ;
01088       }
01089 
01090       inten = XCOL_REDNESS( ovc->xcol_ov[ii] ) ;
01091       if( inten > red_inten ){
01092          red_inten = inten ; red_ii = ii ;
01093       }
01094 
01095       inten = XCOL_GREENNESS( ovc->xcol_ov[ii] ) ;
01096       if( inten > green_inten ){
01097          green_inten = inten ; green_ii = ii ;
01098       }
01099 
01100       inten = XCOL_BLUENESS( ovc->xcol_ov[ii] ) ;
01101       if( inten > blue_inten ){
01102          blue_inten = inten ; blue_ii = ii ;
01103       }
01104 
01105       inten = XCOL_YELLOWNESS( ovc->xcol_ov[ii] ) ;
01106       if( inten > yellow_inten ){
01107          yellow_inten = inten ; yellow_ii = ii ;
01108       }
01109    }
01110    ovc->ov_brightest = bright_ii ; ovc->pixov_brightest = ovc->pix_ov[bright_ii] ;
01111    ovc->ov_darkest   = dark_ii   ; ovc->pixov_darkest   = ovc->pix_ov[dark_ii] ;
01112    ovc->ov_reddest   = red_ii    ; ovc->pixov_reddest   = ovc->pix_ov[red_ii] ;
01113    ovc->ov_greenest  = green_ii  ; ovc->pixov_greenest  = ovc->pix_ov[green_ii] ;
01114    ovc->ov_bluest    = blue_ii   ; ovc->pixov_bluest    = ovc->pix_ov[blue_ii] ;
01115    ovc->ov_yellowest = yellow_ii ; ovc->pixov_yellowest = ovc->pix_ov[yellow_ii] ;
01116 }
01117 
01118 /*-------------------------------------------------------------------------------
01119    Store the colors needed for image display,
01120    based on the value of dc->use_xcol_im (colors for image, or grayscale?).
01121    This replaces the use of XStoreColors directly in the code above.
01122    22 Aug 1998 -- RWCox.
01123 ---------------------------------------------------------------------------------*/
01124 
01125 void DC_set_image_colors( MCW_DC * dc )
01126 {
01127    int ii , nc ;
01128    XColor * xc ;
01129 
01130    nc = dc->ncol_im ;
01131    xc = (dc->use_xcol_im) ? (dc->xcol_im) : (dc->xgry_im) ;
01132 
01133    if( dc->visual_class == PseudoColor ){      /* actually change colormap */
01134 
01135       XStoreColors( dc->display , dc->colormap , xc , nc ) ;
01136 
01137 #if 0
01138       if( dc->cdef != NULL ) reload_DC_colordef( dc ) ;  /* 11 Feb 1999 */
01139 #else
01140       /* FREE_DC_colordef(dc->cdef) ; */
01141 #endif
01142 
01143    } else if( dc->visual_class == TrueColor ){  /* change internal pixel array */
01144 
01145       for( ii=0 ; ii < nc ; ii++ ){
01146          if( dc->pix_im_ready )
01147             XFreeColors( dc->display, dc->colormap, dc->pix_im+ii, 1, 0 ) ;
01148 
01149          XAllocColor( dc->display , dc->colormap , xc+ii ) ;
01150          dc->pix_im[ii] = xc[ii].pixel ;
01151       }
01152       dc->pix_im_ready = 1 ;
01153 
01154    }
01155 
01156    /* 06 Mar 2001: save RGB of colors into arrays for quick use later */
01157 
01158    for( ii=0 ; ii < nc ; ii++ ){
01159       dc->r_im[ii] = INTEN_TO_BYTE( xc[ii].red   ) ;
01160       dc->g_im[ii] = INTEN_TO_BYTE( xc[ii].green ) ;
01161       dc->b_im[ii] = INTEN_TO_BYTE( xc[ii].blue  ) ;
01162 #if 0
01163       dc->gray_im[ii] = BRIGHTNESS( dc->r_im[ii] , dc->g_im[ii] , dc->b_im[ii] ) ;
01164 #endif
01165    }
01166 
01167    return ;
01168 }
01169 
01170 /*--------------------------------------------------------------
01171    Yoke the widget to the DC -- 14 Sep 1998
01172 ----------------------------------------------------------------*/
01173 
01174 void DC_yokify( Widget w , MCW_DC * dc )
01175 {
01176    if( w == NULL || dc == NULL || !XtIsWidget(w) ) return ;
01177 
01178    XtVaSetValues( w ,
01179                      XmNvisual   , dc->visual ,
01180                      XmNcolormap , dc->colormap ,
01181                      XmNdepth    , dc->depth ,
01182                      XmNscreen   , dc->screen ,
01183                      XmNbackground  , 0 ,
01184                      XmNborderColor , 0 ,
01185                   NULL ) ;
01186    return ;
01187 }
01188 
01189 /*---------------------------------------------------------------------
01190    Load the colordef structure in the DC -- 11 Feb 1999
01191 -----------------------------------------------------------------------*/
01192 
01193 void reload_DC_colordef( MCW_DC * dc )
01194 {
01195    XVisualInfo * vin ;
01196    DC_colordef * cd ;   /* will be the output */
01197 
01198 ENTRY("reload_DC_colordef") ;
01199 
01200    /*--- sanity check ---*/
01201 
01202    if( dc == NULL || dc->visual_info == NULL ){
01203       fprintf(stderr,"reload_DC_colordef: entry values are NULL\n") ;
01204       EXRETURN ;
01205    }
01206 
01207    vin = dc->visual_info ;
01208 
01209    /*--- PseudoColor case ---*/
01210 
01211 #if defined(__cplusplus) || defined(c_plusplus)
01212    if( vin->c_class == PseudoColor ){
01213 #else
01214    if( vin->class == PseudoColor ){
01215 #endif
01216 
01217       int iz , count , ii ;
01218       XColor * xcol ;
01219 
01220       /* create output */
01221 
01222       cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
01223       cd->classKRH = PseudoColor ;
01224       cd->depth = vin->depth ;
01225 
01226       /* get all the colors in the colormap */
01227 
01228       count = vin->colormap_size ;
01229       xcol  = (XColor *) malloc( sizeof(XColor) * count ) ;
01230       for( ii=0 ; ii < count ; ii++ ) xcol[ii].pixel = ii ;
01231 
01232       XQueryColors( dc->display , dc->colormap , xcol , count ) ;
01233 
01234       /* store them in the output, truncated to 8 bit resolution */
01235 
01236       cd->ncolors = count ;
01237       cd->rr      = (byte *) malloc( count ) ;
01238       cd->gg      = (byte *) malloc( count ) ;
01239       cd->bb      = (byte *) malloc( count ) ;
01240 
01241       for( ii=0 ; ii < count ; ii++ ){
01242          cd->rr[ii] = xcol[ii].red   >> 8 ;
01243          cd->gg[ii] = xcol[ii].green >> 8 ;
01244          cd->bb[ii] = xcol[ii].blue  >> 8 ;
01245       }
01246 
01247       /* find a pure white color, if any */
01248 
01249       for( iz=0 ; iz < count ; iz++ )
01250          if( cd->rr[iz] == 255 && cd->gg[iz] == 255 && cd->bb[iz] == 255 ) break ;
01251 
01252       cd->nwhite = (iz < count) ? iz : -1 ;
01253 
01254       /* find first all zero color; discard others at end of colormap */
01255 
01256       for( iz=0 ; iz < count ; iz++ )
01257          if( cd->rr[iz] == 0 && cd->gg[iz] == 0 && cd->bb[iz] == 0 ) break ;
01258 
01259       cd->nblack = (iz < count) ? iz : -1 ;
01260 
01261       if( iz < count-1 ){  /* if found one before the end */
01262 
01263          for( ii=count-1 ; ii > iz ; ii-- )  /* scan backwards */
01264             if( cd->rr[ii] != 0 || cd->gg[ii] != 0 || cd->bb[ii] != 0 ) break ;
01265 
01266          count = ii+1 ;  /* number of colors left */
01267 
01268          if( count == 1 ){ /* colormap is all black?! */
01269             free(xcol) ; FREE_DC_colordef(cd) ;
01270             fprintf(stderr,"reload_DC_colordef: colormap is all black?\n") ;
01271             EXRETURN ;
01272          }
01273 
01274          cd->ncolors = count ;
01275       }
01276 
01277       FREE_DC_colordef(dc->cdef) ;  /* if already present, kill it */
01278 
01279       free(xcol) ; dc->cdef = cd ; EXRETURN ;
01280    }
01281 
01282    /*--- TrueColor case ---*/
01283 
01284 #if defined(__cplusplus) || defined(c_plusplus)
01285    if( vin->c_class == TrueColor ){
01286 #else
01287    if( vin->class == TrueColor ){
01288 #endif
01289 
01290       unsigned long r , g , b ;
01291       byte          rr, gg, bb ;
01292 
01293       /* create output */
01294 
01295       cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ;
01296       cd->classKRH = TrueColor ;
01297       cd->depth = vin->depth ;
01298 
01299       cd->rrmask  = vin->red_mask ;            /* bit masks for color  */
01300       cd->ggmask  = vin->green_mask ;          /* storage inside pixel */
01301       cd->bbmask  = vin->blue_mask ;
01302       cd->rrshift = 7 - highbit(cd->rrmask) ;  /* shift puts high bit of  */
01303       cd->ggshift = 7 - highbit(cd->ggmask) ;  /* a color byte into place */
01304       cd->bbshift = 7 - highbit(cd->bbmask) ;  /* +shift == >> ; - == <<  */
01305 
01306       /* compute the all white pixel as a common case */
01307 
01308       rr = gg = bb = 255 ;
01309 
01310       r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
01311                           : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
01312 
01313       g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
01314                           : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
01315 
01316       b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
01317                           : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
01318 
01319       cd->whpix = r | g | b ;
01320 
01321       cd->rr = cd->gg = cd->bb = NULL ;        /* not used */
01322 
01323       FREE_DC_colordef(dc->cdef) ;  /* if already present, kill it */
01324 
01325       dc->cdef = cd ; EXRETURN ;
01326    }
01327 
01328    /*--- Illegal Visual class! [do nothing]---*/
01329 
01330 #if defined(__cplusplus) || defined(c_plusplus)
01331    fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
01332                   x11_vcl[vin->c_class] ) ;
01333 #else
01334    fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n",
01335                   x11_vcl[vin->class] ) ;
01336 #endif
01337    EXRETURN ;
01338 }
01339 
01340 /*---------------------------------------------------------------------
01341    Compute the Pixel that is closest to the given (r,g,b) color
01342 -----------------------------------------------------------------------*/
01343 
01344 Pixel DC_rgb_to_pixel( MCW_DC * dc, byte rr, byte gg, byte bb )
01345 {
01346    static MCW_DC * dcold=NULL ;
01347    DC_colordef * cd = dc->cdef ;
01348 
01349    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
01350 
01351    switch( cd->classKRH ){
01352 
01353       /*--- TrueColor case: make color by appropriate bit twiddling ---*/
01354 
01355       case TrueColor:{
01356          static unsigned long pold=0 ;
01357          static byte rold=0 , gold=0 , bold=0 ;
01358          unsigned long r , g , b ;
01359 
01360          if( rr == 0   && gg == 0   && bb == 0   ) return 0 ;          /* common */
01361          if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ;  /* cases  */
01362 
01363          if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */
01364             return (Pixel) pold ;
01365 
01366          rold = rr ; gold = gg ; bold = bb ; dcold = dc ;            /* OK, remember for next time */
01367 
01368          r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
01369                              : (rr>>cd->rrshift)   ; r = r & cd->rrmask ;
01370 
01371          g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
01372                              : (gg>>cd->ggshift)   ; g = g & cd->ggmask ;
01373 
01374          b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
01375                              : (bb>>cd->bbshift)   ; b = b & cd->bbmask ;
01376 
01377          pold = r | g | b ;  /* assemble color from components */
01378          return (Pixel) pold ;
01379       }
01380 
01381       /*--- PseudoColor case: find closest match in colormap.
01382             Red, green, and blue are weighted according
01383             to their importance to the human visual system. ---*/
01384 
01385       case PseudoColor:{
01386 
01387 #define RW 2  /* the weights alluded to above */
01388 #define GW 4
01389 #define BW 1
01390 #define RGBSUM 4  /* max allowed difference */
01391 
01392          static int iold=0 , rold=0,gold=0,bold=0 ;
01393          int ii , rdif,gdif,bdif,dif , ibest,dbest ;
01394 
01395          if( cd->nblack >= 0 && rr == 0 && gg == 0 && bb == 0 )       /* deal with  */
01396             return (Pixel) cd->nblack ;                               /* 2 special  */
01397                                                                       /* and common */
01398          if( cd->nwhite >= 0 && rr == 255 && gg == 255 && bb == 255 ) /* cases      */
01399             return (Pixel) cd->nwhite ;
01400 
01401          if( dc == dcold ){
01402             rdif = rold - rr ;
01403             gdif = gold - gg ;
01404             bdif = bold - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01405             if( dif <= RGBSUM ) return (Pixel) iold ;     /* Remembrance of Things Past? */
01406          }
01407 
01408          rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* No? Remember for next time. */
01409 
01410          rdif = cd->rr[0] - rr ;
01411          gdif = cd->gg[0] - gg ;
01412          bdif = cd->bb[0] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01413          if( dif <= RGBSUM ){ iold = 0 ; return 0 ; }
01414 
01415          ibest = 0 ; dbest = dif ;
01416          for( ii=1 ; ii < cd->ncolors ; ii++ ){
01417             rdif = cd->rr[ii] - rr ;
01418             gdif = cd->gg[ii] - gg ;
01419             bdif = cd->bb[ii] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01420             if( dif <= RGBSUM ){ iold  = ii ; return (Pixel) ii ; }
01421             if( dif < dbest   ){ ibest = ii ; dbest = dif ; }
01422          }
01423          iold = ibest ; return (Pixel) ibest ;
01424       }
01425    }
01426 
01427    /*--- Illegal case! ---*/
01428 
01429    return 0 ;  /* always valid (but useless) */
01430 }
01431 
01432 /*---------------------------------------------------------------------
01433    Compute the Pixel that is closest to the given (r,g,b) color,
01434    but if the pixel isn't gray (r=g=b), the color must be from
01435    the specified set of overlay colors.  [20 Dec 1999 - RW Cox]
01436 -----------------------------------------------------------------------*/
01437 
01438 Pixel DC_rgb_to_ovpix( MCW_DC * dc, byte rr, byte gg, byte bb )
01439 {
01440    static MCW_DC * dcold=NULL ;
01441    static Pixel pold=0 ;
01442    static int rold=0,gold=0,bold=0 ;
01443    int ii , rdif,gdif,bdif,dif , ibest,dbest ;
01444 
01445    if( rr == gg && rr == bb ) return DC_rgb_to_pixel(dc,rr,gg,bb) ;
01446 
01447    if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return 0 ;
01448 
01449    if( dc == dcold ){                   /* check if we just saw this */
01450       rdif = rold - rr ;
01451       gdif = gold - gg ;
01452       bdif = bold - bb ;
01453       dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01454       if( dif <= RGBSUM ) return pold ;
01455    }
01456 
01457    rold = rr ; gold = gg ; bold = bb ; dcold = dc ;  /* remember for next time */
01458 
01459    rdif = DCOV_REDBYTE(dc,0)   - rr ;
01460    gdif = DCOV_GREENBYTE(dc,0) - gg ;
01461    bdif = DCOV_BLUEBYTE(dc,0)  - bb ;
01462    dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01463    if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[0] ; return pold ; }
01464 
01465    ibest = 0 ; dbest = dif ;
01466    for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ ){
01467       rdif = DCOV_REDBYTE(dc,ii)   - rr ;
01468       gdif = DCOV_GREENBYTE(dc,ii) - gg ;
01469       bdif = DCOV_BLUEBYTE(dc,ii)  - bb ;
01470       dif  = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
01471       if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[ii] ; return pold ; }
01472       if( dif < dbest   ){ ibest = ii ; dbest = dif ; }
01473    }
01474    pold = dc->ovc->pix_ov[ibest] ; return pold ;
01475 }
01476 
01477 /*---------------------------------------------------------------------
01478    Convert color to triple in overlay color list that is closest.
01479 -----------------------------------------------------------------------*/
01480 
01481 void DC_rgb_to_ovrgb( MCW_DC * dc , int nlist , int * list , int shade ,
01482                                     byte *rrin , byte *ggin, byte *bbin )
01483 {
01484    int jj,jtop,ii , rdif,gdif,bdif,dif , ibest,dbest ;
01485    byte rr=*rrin , gg=*ggin , bb=*bbin , mm , rt,gt,bt , rtbest,gtbest,btbest;
01486    float brig , fac ;
01487 
01488    if( rr == gg && rr == bb ) return ;  /* if grayscale, is OK */
01489 
01490    if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return ;
01491 
01492    /* start with the gray color with the same brightness */
01493 
01494    brig = BRIGHTNESS(rr,gg,bb) ; mm = (byte)(brig + 0.499) ;
01495    dbest = RW*abs(mm-rr)+GW*abs(mm-gg)+BW*abs(mm-bb) ;    /* diff from gray */
01496    if( dbest <= RGBSUM ){
01497       *rrin = *ggin = *bbin = mm ; return ;
01498    }
01499    ibest = 0 ; rtbest = gtbest = btbest = mm ;
01500 
01501    /* now check the colors in the list given, or the entire set if no list */
01502 
01503    jtop = (nlist > 0) ? nlist : dc->ovc->ncol_ov ;
01504    for( jj=0 ; jj < jtop ; jj++ ){
01505       ii = (nlist > 0) ? list[jj] : jj ;
01506       if( ii <= 0 || ii >= dc->ovc->ncol_ov || dc->ovc->bright_ov[ii] <= 0.0 ) continue ;
01507 
01508       rt = DCOV_REDBYTE(dc,ii) ; gt = DCOV_GREENBYTE(dc,ii) ; bt = DCOV_BLUEBYTE(dc,ii) ;
01509       if( shade ){
01510         fac = brig / dc->ovc->bright_ov[ii] ;
01511         rt  = (byte)( fac*rt + 0.499 ) ;
01512         gt  = (byte)( fac*gt + 0.499 ) ;
01513         bt  = (byte)( fac*bt + 0.499 ) ;
01514       }
01515       dif = RW*abs(rt-rr)+GW*abs(gt-gg)+BW*abs(bt-bb) ;
01516       if( dif <= RGBSUM ){
01517          *rrin = rt ; *ggin = gt ; *bbin = bt ; return ;
01518       }
01519       if( dif < dbest ){
01520          ibest = ii ; dbest = dif ; rtbest = rt ; gtbest = gt ; btbest = bt ;
01521       }
01522    }
01523 
01524    *rrin = rtbest ; *ggin = gtbest ; *bbin = btbest ; return ;
01525 }
01526 
01527 /*---------------------------------------------------------------------
01528    Compute the (r,g,b) color corresponding to a given Pixel
01529 -----------------------------------------------------------------------*/
01530 
01531 void DC_pixel_to_rgb( MCW_DC * dc , Pixel ppp ,
01532                       byte * rr , byte * gg , byte * bb )
01533 {
01534    DC_colordef * cd = dc->cdef ;
01535 
01536    if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; }
01537 
01538    switch( cd->classKRH ){
01539 
01540       /*--- TrueColor case: unmake color by appropriate bit twiddling ---*/
01541 
01542       case TrueColor:{
01543          unsigned long r , g , b ;
01544 
01545          if( ppp == 0         ){ *rr = *bb = *gg = 0   ; return ; }  /* common cases */
01546          if( ppp == cd->whpix ){ *rr = *bb = *gg = 255 ; return ; }
01547 
01548          r   = ppp & cd->rrmask ;
01549          *rr = (cd->rrshift<0) ? (r>>(-cd->rrshift)) : (r<<cd->rrshift) ;
01550 
01551          g   = ppp & cd->ggmask ;
01552          *gg = (cd->ggshift<0) ? (g>>(-cd->ggshift)) : (g<<cd->ggshift) ;
01553 
01554          b   = ppp & cd->bbmask ;
01555          *bb = (cd->bbshift<0) ? (b>>(-cd->bbshift)) : (b<<cd->bbshift) ;
01556 
01557          return ;
01558       }
01559 
01560       /*--- PseudoColor case: extract from colormap ---*/
01561 
01562       case PseudoColor:{
01563          int ii = (int) ppp ;
01564          *rr = cd->rr[ii] ; *gg = cd->gg[ii] ; *bb = cd->bb[ii] ; return ;
01565       }
01566    }
01567 
01568    return ;
01569 }
01570 
01571 /*-------------------------------------------------------------------------
01572    21 Sep 2001: compute an (r,g,b) triple (floating point, 0..1)
01573                 for the given color string;
01574                 return value is 0 for good, 1 for bad
01575                 (if bad, *rr, *gg, *bb aren't touched)
01576 ---------------------------------------------------------------------------*/
01577 
01578 int DC_parse_color( MCW_DC *dc, char *str, float *rr, float *gg, float *bb )
01579 {
01580    XColor cell ; int ok ;
01581 
01582    if( str == NULL || *str == '\0' ) return 1 ;
01583 
01584    if( strncmp(str,"AJJ:",4) == 0 ){   /* 07 Feb 2003 */
01585      float ang=-6666.0 ;
01586      sscanf(str+4,"%f",&ang) ;
01587      if( ang != -6666.0 ){
01588        rgbyte col = DC_spectrum_AJJ( ang , 0.8 ) ;
01589        *rr = col.r / 255.0 ;
01590        *gg = col.g / 255.0 ;
01591        *bb = col.b / 255.0 ;
01592        return 0 ;
01593      }
01594      return 1 ;
01595    }
01596 
01597    ok = XParseColor( dc->display , dc->colormap , str, &cell ) ;
01598    if( ok ){
01599       *rr = cell.red   / 65535.0 ;
01600       *gg = cell.green / 65535.0 ;
01601       *bb = cell.blue  / 65535.0 ;
01602       return 0 ;
01603    }
01604    return 1 ;
01605 }
 

Powered by Plone

This site conforms to the following standards: