/***************************************************************************** Major portions of this software are copyrighted by the Medical College of Wisconsin, 1994-2000, and are released under the Gnu General Public License, Version 2. See the file README.Copyright for details. ******************************************************************************/ #include "display.h" #include "mrilib.h" static char * x11_vcl[] = { "StaticGray" , "GrayScale" , "StaticColor" , "PseudoColor" , "TrueColor" , "DirectColor" } ; MCW_DC *first_dc = NULL ; /* 26 Jun 2003 */ /*------------------------------------------------------------------------ Returns position of highest set bit in 'ul' as an integer (0-31), or returns -1 if no bit is set. --------------------------------------------------------------------------*/ static int highbit(unsigned long ul) { int i; unsigned long hb; hb = 0x80; hb = hb << 24; /* hb = 0x80000000UL */ for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1); return i; } /*------------------------------------------------------------------------- Setup the number of bytes per pixel. For depth 24, this might be 3 or 4, depending on the server. RWCox -- 23 Aug 1998. ---------------------------------------------------------------------------*/ static void setup_byper( MCW_DC * dc ) { XPixmapFormatValues * xpv ; int nxpv = 0 , ii ; xpv = XListPixmapFormats( dc->display , &nxpv ) ; if( xpv == NULL || nxpv == 0 ){ dc->byper = dc->depth / 8 ; dc->bypad = 1 ; /* defaults */ return ; } /* scan for this depth in the array of pixmap formats */ for( ii=0 ; ii < nxpv ; ii++ ){ if( xpv[ii].depth == dc->depth ){ dc->byper = xpv[ii].bits_per_pixel / 8 ; /* bytes, not bits */ dc->bypad = xpv[ii].scanline_pad / 8 ; XFree(xpv) ; return ; } } dc->byper = dc->depth / 8 ; dc->bypad = 1 ; /* defaults */ XFree(xpv) ; return ; } /*------------------------------------------------------------------------ Create and initialize a new MCW_DC structure. wid = widget used to get info about Display, etc. ncol = number of colors to use for images novr = number of overlay colors covr = array of strings of overlay color names [used for XAlloc...] lovr = array of strings of overlay color labels [used for display] gam = gamma value to use 22 Aug 1998: Modified to support TrueColor visuals, as well as the original PseudoColor -- RWCox. 14 Sep 1998: Modified to add argument newcmap = if nonzero, create a new Colormap; if zero, use the default Colormap for the display ------------------------------------------------------------------------*/ static MCW_DCOV * only_ovc = NULL ; /* Dec 1997 */ MCW_DC * MCW_new_DC( Widget wid , int ncol , int novr , char * covr[] , char * lovr[] , double gam , int newcmap ) { MCW_DC * dc ; int ok , ii , new_ovc ; unsigned int nplmsk = 0 ; /* dummy arguments for XAllocColorCells */ unsigned long plane_masks[1] ; ENTRY("MCW_new_DC") ; if( ncol < 4 || novr < 0 || ncol > MAX_COLORS || novr > MAX_COLORS ){ fprintf(stderr,"\n*** MCW_new_DC: ILLEGAL number of colors: %d %d\n",ncol,novr) ; ncol = 4 ; novr = 0 ; } dc = myXtNew(MCW_DC) ; dc->appcontext = XtWidgetToApplicationContext( wid ) ; dc->display = XtDisplay( wid ) ; dc->screen = XtScreen( wid ) ; dc->screen_num = XScreenNumberOfScreen( dc->screen ) ; dc->visual = DefaultVisualOfScreen( dc->screen ) ; dc->origGC = DefaultGCOfScreen( dc->screen ) ; dc->planes = PlanesOfScreen( dc->screen ) ; dc->depth = DefaultDepthOfScreen( dc->screen ) ; dc->cdef = NULL ; /* 11 Feb 1999: will be loaded later */ setup_byper(dc) ; /* 23 Aug 1998 */ dc->default_colormap = DefaultColormapOfScreen( dc->screen ) ; /* 01 Sep 1998 */ dc->colormap = DefaultColormapOfScreen( dc->screen ) ; /* may be changed later */ dc->parent_widget = wid ; /* 06 Oct 1996 */ dc->does_backingstore = DoesBackingStore(dc->screen) ; /* 27 Feb 2001 */ dc->does_saveunders = DoesSaveUnders(dc->screen) ; /** 07 Aug 1998: get more information about the visual **/ { XVisualInfo vinfo , * vinfo_list ; int count ; dc->visual_id = XVisualIDFromVisual( dc->visual ) ; vinfo.visualid = dc->visual_id ; vinfo_list = XGetVisualInfo(dc->display,VisualIDMask,&vinfo,&count) ; if( count > 0 && vinfo_list != NULL ){ dc->visual_info = vinfo_list ; dc->visual_redmask = dc->visual_info->red_mask ; dc->visual_greenmask = dc->visual_info->green_mask ; dc->visual_bluemask = dc->visual_info->blue_mask ; dc->visual_redshift = 7 - highbit(dc->visual_redmask) ; dc->visual_greenshift = 7 - highbit(dc->visual_greenmask) ; dc->visual_blueshift = 7 - highbit(dc->visual_bluemask) ; #if defined(__cplusplus) || defined(c_plusplus) dc->visual_class = dc->visual_info->c_class ; #else dc->visual_class = dc->visual_info->class ; #endif if( dc->visual_class != PseudoColor && dc->visual_class != TrueColor ){ fprintf(stderr,"\n\n" " ** The default X11 visual type on your computer is set to %s.\n" " ** AFNI programs only work with PseudoColor or TrueColor visuals.\n" " ** You must have your superuser modify your system's setup.\a\n" , x11_vcl[dc->visual_class] ) ; dc->visual_class = PseudoColor ; /* let the program fail later */ } #if 0 if( dc->visual_class == TrueColor ){ /* removed 28 Oct 1999 */ static int done = 0 ; if( !done ) fprintf(stderr, "\n" " ** The default X11 visual type on your computer is %d bit TrueColor.\n" " ** Support for this is experimental. AFNI was developed to use 4..12\n" " ** bit PseudoColor visuals for image display -- RW Cox, 22 Aug 1998.\n" , dc->depth ) ; done = 1 ; } #endif #if 0 fprintf(stderr,"\n" "DC: redmask=%lx greenmask=%lx bluemask=%lx\n" " redshift=%d greenshift=%d blueshift=%d\n" " class=%d=%s depth=%d\n", dc->visual_redmask , dc->visual_greenmask , dc->visual_bluemask , dc->visual_redshift , dc->visual_greenshift , dc->visual_blueshift , dc->visual_class , x11_vcl[dc->visual_class] , dc->depth ) ; #endif } else { /* should never occur! */ dc->visual_info = NULL ; dc->visual_class = PseudoColor ; /* we hope */ } } #if 0 { long reqmax ; reqmax = XMaxRequestSize(dc->display) ; printf("max X11 request size = %d\n",reqmax) ; } #endif #define DEPTH_BOT 4 #define DEPTH_TOP 32 if( dc->depth < DEPTH_BOT || dc->depth > DEPTH_TOP ){ fprintf(stderr,"\n\n" " ** Your X11 display is set to %d bitplanes for image display.\n" " ** AFNI programs can only deal with between %d and %d bitplanes.\n" " ** You must have your superuser modify your system's setup.\a\n" , dc->depth , DEPTH_BOT , DEPTH_TOP ) ; exit(1) ; } dc->width = WidthOfScreen( dc->screen ) ; dc->height = HeightOfScreen( dc->screen ) ; dc->ncol_im = ncol ; dc->gamma = dc->gamma_init = gam ; if( dc->visual_class == PseudoColor ){ /* 22 Aug 1998 */ if( newcmap ){ /* 14 Sep 1998 */ int ncold , cc ; XColor xcold ; /* make a new colormap */ dc->colormap = XCreateColormap( dc->display , RootWindowOfScreen(dc->screen) , dc->visual , AllocNone ) ; /* allocate some colors from the old one (to reduce flashing) */ #define NREUSE 9 ncold = dc->visual_info->colormap_size ; if( ncold > NREUSE ) ncold = NREUSE ; for( cc=0 ; cc < ncold ; cc++ ){ xcold.pixel = cc ; XQueryColors( dc->display , dc->default_colormap , &xcold , 1 ) ; XAllocColor( dc->display , dc->colormap , &xcold ) ; } } ok = XAllocColorCells( dc->display , dc->colormap , True , plane_masks , nplmsk , dc->pix_im , dc->ncol_im ) ; if( ! ok ){ fprintf(stderr, "\a\n** XAllocColorCells fails for %d colors\n",dc->ncol_im) ; fprintf(stderr, "\n** try the -ncolor option to reduce # of colors\n"); exit(1) ; } dc->pix_im_ready = 1 ; } else if( dc->visual_class == TrueColor ){ dc->pix_im_ready = 0 ; } DC_init_im_col( dc ) ; DC_init_im_gry( dc ) ; dc->use_xcol_im = False ; DC_set_image_colors( dc ) ; /* 22 Aug 1998: replaces XStoreColors */ /* set up overlay colors from list of names (since the XImage routines use negative indices to indicate overlays, the 0th overlay color is not used) */ /* Dec 1997: put all overlay stuff into a single place */ new_ovc = 0 ; if( only_ovc == NULL ){ only_ovc = myXtNew(MCW_DCOV) ; new_ovc = 1 ; } dc->ovc = only_ovc ; if( new_ovc ){ only_ovc->xcol_ov[0] = dc->xgry_im[0] ; only_ovc->pix_ov[0] = dc->pix_im[0] ; only_ovc->name_ov[0] = XtNewString("none") ; only_ovc->label_ov[0] = only_ovc->name_ov[0] ; only_ovc->ncol_ov = 1 ; only_ovc->bright_ov[0] = 0.0 ; /* 20 Dec 1999 */ dc->ovc->r_ov[0] = 0 ; /* 04 Mar 2002 */ dc->ovc->g_ov[0] = 0 ; dc->ovc->b_ov[0] = 0 ; } for( ii=0 ; ii < novr ; ii++ ){ ok = DC_add_overlay_color( dc , covr[ii] , lovr[ii] ) ; if( ok < 0 ) fprintf(stderr, "\n*** can't get X11 colormap entry for overlay color %s" , lovr[ii] ) ; #ifdef DISPLAY_DEBUG else { printf("\n*** overlay color %s has pixel %d at index %d" , dc->ovc->name_ov[ok] , (int)dc->ovc->pix_ov[ok] , ok ) ; fflush(stdout) ; } #endif } OVC_mostest( dc->ovc ) ; /*-- May 1996: create new GC for use with text and graphics --*/ { XGCValues gcv; int ifont ; XFontStruct * mfinfo = NULL ; char * xdef ; gcv.function = GXcopy ; dc->myGC = XCreateGC( dc->display, RootWindowOfScreen(dc->screen) , GCFunction , &gcv ) ; xdef = XGetDefault(dc->display,"AFNI","gfont") ; if( xdef != NULL ) mfinfo = XLoadQueryFont(dc->display,xdef) ; if( mfinfo == NULL ){ for( ifont=0 ; tfont_hopefuls[ifont] != NULL ; ifont++ ){ mfinfo = XLoadQueryFont(dc->display, tfont_hopefuls[ifont]) ; if( mfinfo != NULL ) break ; } } if( mfinfo == NULL ){ fprintf(stderr, "\n*** Cannot load any text fonts in display.c ***\n" ) ; } else { XSetFont( dc->display , dc->myGC , mfinfo->fid ) ; } XSetForeground(dc->display , dc->myGC , dc->ovc->pixov_darkest ) ; XSetBackground(dc->display , dc->myGC , dc->ovc->pixov_brightest ) ; dc->myFontStruct = mfinfo ; } dc->parent = dc->aux = NULL ; #ifdef DISPLAY_DEBUG printf("\n") ; #endif #if 0 reload_DC_colordef( dc ) ; /* 11 Feb 1999 */ #else dc->cdef = NULL ; #endif if( first_dc == NULL ) first_dc = dc ; /* 26 Jun 2003 */ RETURN(dc) ; } /*----------------------------------------------------------------------- Set the image display to grayscale -------------------------------------------------------------------------*/ void DC_palette_setgray( MCW_DC * dc ) { dc->use_xcol_im = False ; DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*----------------------------------------------------------------------- Set the image display to colorscale -------------------------------------------------------------------------*/ void DC_palette_setcolor( MCW_DC * dc ) { dc->use_xcol_im = True ; DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*----------------------------------------------------------------------- Restore the color and grayscale palettes to their defaults -------------------------------------------------------------------------*/ void DC_palette_restore( MCW_DC * dc , double new_gamma ) { dc->gamma = (new_gamma > 0 ) ? new_gamma : dc->gamma_init ; DC_init_im_col( dc ) ; DC_init_im_gry( dc ) ; DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ } /*----------------------------------------------------------------------- Initialize the grayscale image palette. Modified 22 Aug 1998 for TrueColor support. -------------------------------------------------------------------------*/ static double mypow( double x , double y ) /* replaces the math library pow */ { double b ; if( x <= 0.0 ) return 0.0 ; if( y == 1.0 ) return x ; b = log(x) ; b = exp( y*b ) ; return b ; } void DC_init_im_gry( MCW_DC * dc ) { int i, k, m, nc ; float a , gamm , b ; char * env ; /* 11 Apr 2000 */ float atop=255.0 , abot=55.0 ; #if 0 env = getenv("AFNI_GRAYSCALE_TOP") ; if( env != NULL ){ float val = strtod(env,NULL) ; if( val <= 255.0 && val >= 100.0 ) atop = val ; } #endif env = getenv("AFNI_GRAYSCALE_BOT") ; if( env != NULL ){ float val = strtod(env,NULL) ; if( val < atop && val >= 0.0 ) abot = val ; } nc = dc->ncol_im ; gamm = dc->gamma ; a = (atop-abot) / nc ; for (i=0; i < nc ; i++) { b = log( (a*i+abot)/255.0 ) ; /* The code that used to be here */ b = exp( gamm * b ) ; /* (using pow) was replaced due */ k = (int)( 255.0 * b + 0.5 ) ; /* to some bug in gcc on Linux. */ m = BYTE_TO_INTEN(k) ; dc->xint_im[i] = m ; dc->xgry_im[i].red = m ; dc->xgry_im[i].green = m ; dc->xgry_im[i].blue = m ; dc->xgry_im[i].flags = DoRed|DoGreen|DoBlue; if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */ dc->xgry_im[i].pixel = dc->pix_im[i]; } return ; } /*----------------------------------------------------------------------*/ /*! Return a color from the spectrum. Input "an" is between 0 and 360. Adapted from Ziad Saad. -- 01 Feb 2003 - RWCox. ------------------------------------------------------------------------*/ rgbyte DC_spectrum_ZSS( double an , double gamm ) { int r,g,b , m ; rgbyte color ; if( gamm <= 0.0 ) gamm = 1.0 ; while( an < 0.0 ) an += 360.0 ; while( an > 360.0 ) an -= 360.0 ; an = an / 90.0 ; if( an <= 1.0 ){ r = 255.*mypow(1.0-an,gamm)+0.5 ; g = 255.*mypow(0.5*an,gamm)+0.5 ; b = 255.*mypow(an ,gamm)+0.5 ; } else if( an <= 2.0 ){ r = 0 ; g = 255.*mypow(0.5*an,gamm)+0.5 ; b = 255.*mypow(2.0-an,gamm)+0.5 ; } else if( an <= 3.0 ){ r = 255.*mypow(an-2.0,gamm)+0.5 ; g = 255 ; b = 0 ; } else { r = 255 ; g = 255.*mypow(4.0-an,gamm)+0.5 ; b = 0 ; } #if 0 m = MAX(r,g) ; m = MAX(m,b) ; if( m < 255 ){ float s=255.0/m; r *= s; g *= s; b *= s; } #endif color.r = r ; color.g = g ; color.b = b ; return color ; } /*----------------------------------------------------------------------*/ /*! Return a color from the spectrum. Input "an" is between 0 and 360. Adapted from Andrzej Jesmanowicz. -- 30 Jan 2003 - RWCox. ------------------------------------------------------------------------*/ rgbyte DC_spectrum_AJJ( double an , double gamm ) { int r,g,b , m ; double ak,ab,s,c,sb,cb ; rgbyte color ; if( gamm <= 0.0 ) gamm = 1.0 ; #if 0 ak = 105.; s = 255.0-ak; c = s /60.; /* AJ's choices */ ab = 65.; sb = 255.0-ab; cb = sb/60.; #else ak = 5.; s = 255.0-ak; c = s /60.; /* RWC's choices */ ab = 5.; sb = 255.0-ab; cb = sb/60.; #endif while( an < 0.0 ) an += 360.0 ; while( an > 360.0 ) an -= 360.0 ; if( an < 120. ){ r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5; g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5; m = MAX(r,g) ; b = 0; } else if( an < 240. ){ r = 0; g = 255.*mypow((ak + MIN(s ,(240. - an)*c ))/255., gamm) +.5; b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5; m = MAX(g,b) ; } else { r = 255.*mypow((ak + MIN(s,(an - 240.)*c ))/255., gamm) +.5; g = 0; b = 255.*mypow((ab + MIN(s,(360. - an)*cb))/255., gamm) +.5; m = MAX(r,b) ; } #if 0 if( m < 255 ){ s = 255.0/m ; r *= s ; g *= s ; b *= s ; } #endif color.r = r ; color.g = g ; color.b = b ; return color ; } /*----------------------------------------------------------------------- Initialize the color image palette. Modified 22 Aug 1998 for TrueColor support. -------------------------------------------------------------------------*/ void DC_init_im_col( MCW_DC * dc ) { double da, an, c, s, sb, cb, ak, ab , a1,a2 , gamm ; int i, r, g, b , nc ; a1 = 0.0 ; /* range of spectrum -- hardwired for now */ a2 = 240.0 ; nc = dc->ncol_im ; gamm = dc->gamma ; ak = 105.; s = 150.; c = s/60.; ab = 65.; sb = 190.; cb = s/60.; an = a1; da = (a2 - a1)/nc ; an = an-da+360.; for( i=0 ; i < nc ; i++ ){ an += da; an = fmod(an,360.); if((an >= 0) && (an < 120.)) { r = 255.*mypow((ak + MIN(s,(120. - an)*c))/255., gamm) +.5; g = 255.*mypow((ak + MIN(s,an*c))/255., gamm) +.5; b = 0; } else if((an >= 120.) && (an < 240.)) { r = 0; g = 255.*mypow((ak + MIN(s ,(240. - an)*c))/255., gamm) +.5; b = 255.*mypow((ab + MIN(sb,(an - 120.)*cb))/255., gamm) +.5; } else if(an >= 240.) { r = 255.*mypow((ak + MIN(s,(an - 240.)*c))/255., gamm) +.5; g = 0; b = 255.*mypow((ak + MIN(s,(360. - an)*c))/255., gamm) +.5; } dc->xcol_im[i].red = BYTE_TO_INTEN(r) ; dc->xcol_im[i].green = BYTE_TO_INTEN(g) ; dc->xcol_im[i].blue = BYTE_TO_INTEN(b) ; dc->xcol_im[i].flags = DoRed|DoGreen|DoBlue; if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */ dc->xcol_im[i].pixel = dc->pix_im[i]; } return ; } #if 0 /*******************************************************************/ /* -------------------------------------------------------------------------- Given an triple of bytes (0..255), make a color and return its pixel value -----------------------------------------------------------------------------*/ Pixel RGB_byte_to_color( MCW_DC * dc , int r , int g , int b ) { XColor any_col; any_col.red = BYTE_TO_INTEN(r); any_col.green = BYTE_TO_INTEN(g); any_col.blue = BYTE_TO_INTEN(b); any_col.flags = DoRed | DoGreen | DoBlue; XAllocColor( dc->display , dc->colormap , &any_col ); return any_col.pixel ; } /*-------------------------------------------------------------------------- Given a color named by a string, allocate it and return its pixel value ----------------------------------------------------------------------------*/ Pixel Name_to_color( MCW_DC * dc , char * name ) { XColor cell , exact ; int ok ; ok = XAllocNamedColor( dc->display , dc->colormap , name , &cell , &exact ) ; if( ok ) return cell.pixel ; else return BlackPixelOfScreen( dc->screen ) ; } #endif /********************************************************************/ /*-------------------------------------------------------------------------- Given a color name, allocate it, put it into the DC overlay table, and return its index (negative if an error occurred) Dec 1997: modified to use read-write color cells, and recycle them if the same label is passed in. 22 Aug 1998: modified for TrueColor support ----------------------------------------------------------------------------*/ int DC_add_overlay_color( MCW_DC * dc , char * name , char * label ) { int ii , ok , newcol ; Pixel newpix ; XColor cell ; ENTRY("DC_add_overlay_color") ; if( name == NULL || strlen(name) == 0 ) RETURN(-1) ; /* error */ if( label == NULL ) label = name ; /** see if label is already in the table **/ for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ ) if( strcmp(label,dc->ovc->label_ov[ii]) == 0 ) break ; newcol = (ii == dc->ovc->ncol_ov) ; /** need a new color cell? **/ if( ii == dc->ovc->ncol_ov ){ /** Yes **/ unsigned int nplmsk = 0 ; unsigned long plane_masks[1] ; if( ii >= MAX_COLORS ) RETURN(-1) ; /* too many overlay colors! */ if( dc->visual_class == PseudoColor ){ /* 22 Aug 1998 */ ok = XAllocColorCells( dc->display , dc->colormap , True , plane_masks , nplmsk , &newpix , 1 ) ; if( !ok ) RETURN(-1) ; /* couldn't get a new cell */ cell.pixel = newpix ; } } else { /** Reusing an old cell **/ if( strcmp(name,dc->ovc->name_ov[ii]) == 0 ) RETURN(ii) ; /* no change! */ if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */ cell.pixel = dc->ovc->pix_ov[ii] ; else if( dc->visual_class == TrueColor ) XFreeColors( dc->display, dc->colormap, dc->ovc->pix_ov+ii, 1, 0 ) ; } ok = XParseColor( dc->display , dc->colormap , name, &cell ) ; if( !ok ) RETURN(-1) ; if( newcol ){ /** made a new cell **/ dc->ovc->ncol_ov++ ; } else { /** free old cell stuff **/ myXtFree( dc->ovc->name_ov[ii] ) ; myXtFree( dc->ovc->label_ov[ii] ) ; } if( dc->visual_class == PseudoColor ) /* 22 Aug 1998 */ XStoreColor( dc->display , dc->colormap , &cell ) ; else if( dc->visual_class == TrueColor ) XAllocColor( dc->display , dc->colormap , &cell ) ; dc->ovc->xcol_ov[ii] = cell ; /* save cell info */ dc->ovc->pix_ov[ii] = cell.pixel ; dc->ovc->name_ov[ii] = XtNewString(name) ; dc->ovc->label_ov[ii] = XtNewString(label) ; dc->ovc->r_ov[ii] = INTEN_TO_BYTE(cell.red) ; /* 06 Mar 2001 */ dc->ovc->g_ov[ii] = INTEN_TO_BYTE(cell.green) ; dc->ovc->b_ov[ii] = INTEN_TO_BYTE(cell.blue) ; if( dc->visual_class == PseudoColor ) /* 11 Feb 1999: */ FREE_DC_colordef(dc->cdef) ; /* will need to be recomputed */ dc->ovc->bright_ov[ii] = BRIGHTNESS( DCOV_REDBYTE(dc,ii) , /* 20 Dec 1999 */ DCOV_GREENBYTE(dc,ii) , DCOV_BLUEBYTE(dc,ii) ) ; RETURN(ii) ; } /*-------------------------------------------------------------------------*/ int DC_find_overlay_color( MCW_DC *dc , char *label ) { int ii ; if( dc == NULL || label == NULL ) return -1 ; for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ) if( strcasecmp(label,dc->ovc->label_ov[ii]) == 0 ) return ii ; return -1 ; } /*-------------------------------------------------------------------------*/ int DC_find_closest_overlay_color( MCW_DC *dc , char *cname ) { float rr,gg,bb ; int b_rr,b_gg,b_bb ; int ii , jj; if( dc == NULL || cname == NULL || *cname == '\0' ) return -1 ; ii = DC_find_overlay_color( dc , cname ) ; if( ii >= 0 ) return ii ; ii = DC_parse_color( dc, cname, &rr,&gg,&bb ) ; if( ii ) return -1 ; b_rr = (int)(255.9*rr) ; b_gg = (int)(255.9*gg) ; b_bb = (int)(255.9*bb) ; jj = 0 ; rr = 9999999.9 ; for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ){ gg = abs(b_rr-(int)dc->ovc->r_ov[ii]) +abs(b_gg-(int)dc->ovc->g_ov[ii]) +abs(b_bb-(int)dc->ovc->b_ov[ii]) ; if( gg < rr ){ jj = ii ; rr = gg ; } } return jj ; } /*------------------------------------------------------------------------- load the tmp? arrays (alas, GLOBAL data, a sin against God and Man) from an array of colors --------------------------------------------------------------------------*/ static unsigned short tmp1[MAX_COLORS] , tmp2[MAX_COLORS] , tmp3[MAX_COLORS] ; static int tmpi[MAX_COLORS] ; void load_tmp_colors( int nc , XColor *ccc ) { register int i ; for( i=0 ; i < nc ; i++ ){ tmp1[i] = ccc[i].red ; tmp2[i] = ccc[i].green ; tmp3[i] = ccc[i].blue ; } return ; } /*------------------------------------------------------------------------- rotate active palette k steps -------------------------------------------------------------------------*/ void DC_palette_rotate( MCW_DC * dc , int kk ) { register int i , j , nc , k ; XColor * xc ; nc = dc->ncol_im ; if( dc->use_xcol_im ){ xc = & ( dc->xcol_im[0] ) ; /* choose active palette */ k = -kk ; /* direction of rotation */ } else { xc = & ( dc->xgry_im[0] ) ; k = -kk ; } load_tmp_colors( nc , xc ) ; /* store RGB values in tmp? */ for( i=0 ; i < nc ; i++ ){ j = (i+nc+k) % nc ; xc[i].red = tmp1[j] ; xc[i].green = tmp2[j] ; xc[i].blue = tmp3[j] ; } if( ! dc->use_xcol_im ){ /* rotate xint_im as well for graymap */ for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ; for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[(i+nc+k)%nc] ; } DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*------------------------------------------------------------------------*/ void DC_palette_swap( MCW_DC * dc ) { register int i, k , nc ; XColor * xc ; nc = dc->ncol_im ; k = nc - 1 ; if( dc->use_xcol_im ){ xc = & ( dc->xcol_im[0] ) ; } else { xc = & ( dc->xgry_im[0] ) ; } load_tmp_colors( nc , xc ) ; for(i=0; i < nc ; i++) { xc[i].red = tmp1[k-i]; xc[i].green = tmp2[k-i]; xc[i].blue = tmp3[k-i]; } if( ! dc->use_xcol_im ){ /* swap xint_im as well for graymap */ for( i=0 ; i < nc ; i++ ) tmpi[i] = dc->xint_im[i] ; for( i=0 ; i < nc ; i++ ) dc->xint_im[i] = tmpi[k-i] ; } DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*-----------------------------------------------------------------------*/ void DC_palette_bright( MCW_DC * dc , int dd ) { if( dc->use_xcol_im ) DC_color_bright( dc , dd ) ; else DC_gray_change( dc , -2*dd ) ; return; } /*-----------------------------------------------------------------------*/ void DC_color_bright( MCW_DC * dc , int dlev ) { register int i ; double c ; int nc = dc->ncol_im ; XColor * xc = dc->xcol_im ; c = 1.0 - 0.005 * (double) dlev ; for( i=0 ; i < nc ; i++ ){ xc[i].red = CLIP_INTEN( c * xc[i].red ) ; xc[i].green = CLIP_INTEN( c * xc[i].green ) ; xc[i].blue = CLIP_INTEN( c * xc[i].blue ) ; } DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*------------------------------------------------------------------------*/ void DC_gray_change( MCW_DC * dc , int dlev ) { register int i, k, delta ; int nc = dc->ncol_im ; XColor * xc = dc->xgry_im ; int * in = dc->xint_im ; if( dc->use_xcol_im ) return ; delta = dlev * abs( (in[nc-1] - in[0]) / nc ) ; for( i=0 ; i < nc ; i++ ){ k = in[i] += delta ; xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ; } DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*------------------------------------------------------------------------*/ void DC_palette_squeeze( MCW_DC * dc , int dd ) { if( dc->use_xcol_im ) DC_color_squeeze( dc , dd ) ; else DC_gray_contrast( dc , -2*dd ) ; return; } /*------------------------------------------------------------------------*/ void DC_color_squeeze( MCW_DC * dc , int dlev ) { return ; /* not implemented */ } /*------------------------------------------------------------------------*/ void DC_gray_contrast( MCW_DC * dc , int dlev ) { register int i, k, delta ; int nc = dc->ncol_im ; XColor * xc = dc->xgry_im ; int * in = dc->xint_im ; if( dc->use_xcol_im ) return ; delta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ; if( delta == 0 ) delta = dlev ; for( i=0 ; i < nc ; i++ ){ k = in[i] += i * delta ; xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ; } DC_set_image_colors( dc ) ; /* 22 Aug 1998 */ return ; } /*------------------------------------------------------------------------*/ void DC_gray_conbrio( MCW_DC *dc , int dlev ) /* 23 Oct 2003 */ { register int i, k, bdelta,cdelta ; int nc = dc->ncol_im ; XColor * xc = dc->xgry_im ; int * in = dc->xint_im ; if( dc->use_xcol_im ) return ; bdelta = dlev * abs(in[nc-1] - in[0]) / nc ; cdelta = dlev * (abs(in[nc-1] - in[0]) >> 6) / nc ; if( cdelta == 0 ) cdelta = dlev ; for( i=0 ; i < nc ; i++ ){ k = in[i] += i * cdelta - bdelta ; xc[i].red = xc[i].green = xc[i].blue = CLIP_INTEN(k) ; } DC_set_image_colors( dc ) ; return ; } /*-------------------------------------------------------------------*/ Boolean MCW_check_iconsize( int width , int height , MCW_DC * dc ) { int ii ; Boolean good ; int nsl = 0 ; XIconSize * xsl = NULL ; /** elementary checks **/ if( width < 1 || height < 1 ) return False ; XGetIconSizes( dc->display , RootWindowOfScreen(dc->screen) , &xsl , &nsl ) ; if( xsl == NULL || nsl < 1 ) return True ; good = False ; for( ii=0 ; ii < nsl ; ii++ ){ if( width >= xsl[ii].min_width && width <= xsl[ii].max_width && height >= xsl[ii].min_height && height <= xsl[ii].max_height && (width - xsl[ii].min_width ) % xsl[ii].width_inc == 0 && (height - xsl[ii].min_height) % xsl[ii].height_inc == 0 ) { good = True ; break ; } } XFree(xsl) ; return good ; } /*--------------------------------------------------------------------------- Given a pixel index, return a pointer to its color (not very efficiently). 11 Feb 1999: if use_cmap != 0, use the colormap instead of the internal dc color arrays -----------------------------------------------------------------------------*/ XColor * DCpix_to_XColor( MCW_DC * dc , Pixel pp , int use_cmap ) { XColor * ulc , * ovc ; int ii ; if( use_cmap ){ /* 11 Feb 1999 */ static XColor xc ; byte rr,gg,bb ; DC_pixel_to_rgb( dc , pp , &rr,&gg,&bb ) ; xc.red = BYTE_TO_INTEN(rr) ; xc.green = BYTE_TO_INTEN(gg) ; xc.blue = BYTE_TO_INTEN(bb) ; return &xc ; } ulc = (dc->use_xcol_im) ? dc->xcol_im : dc->xgry_im ; ovc = dc->ovc->xcol_ov ; for( ii=0 ; ii < dc->ncol_im ; ii++ ) if( pp == dc->pix_im[ii] ) return (ulc+ii) ; for( ii=0 ; ii < dc->ovc->ncol_ov ; ii++ ) if( pp == dc->ovc->pix_ov[ii] ) return (ovc+ii) ; return ulc ; /* not found, but must return something */ } /*-------------------------------------------------------------------------*/ void DC_fg_color( MCW_DC * dc , int nov ) { XSetForeground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ; return ; } void DC_bg_color( MCW_DC * dc , int nov ) { XSetBackground( dc->display , dc->myGC , dc->ovc->pix_ov[nov] ) ; return ; } void DC_fg_colorpix( MCW_DC * dc , Pixel pix ) { XSetForeground( dc->display , dc->myGC , pix ) ; return ; } void DC_fg_colortext( MCW_DC * dc , char * cname ) { XColor any_col , rgb_col ; if( ! XAllocNamedColor( dc->display , dc->colormap , cname , &any_col, &rgb_col ) ){ fprintf(stderr,"\n** XAllocNamedColor problem: %s **\n",cname ) ; } else { XSetForeground( dc->display , dc->myGC , any_col.pixel ) ; } return ; } void DC_linewidth( MCW_DC * dc , int lw ) { XGCValues gcv ; if( lw >= 0 ){ gcv.line_width = lw ; gcv.join_style = JoinBevel ; XChangeGC( dc->display , dc->myGC , GCLineWidth | GCJoinStyle , &gcv ) ; } return ; } void DC_linestyle( MCW_DC * dc , int lw ) { XGCValues gcv ; gcv.line_style = lw ; XChangeGC( dc->display , dc->myGC , GCLineStyle , &gcv ) ; return ; } /*------------------------------------------------------------------------- May 1996: save the indices of the darkest and brightest overlays Dec 1997: moved into a separate routine ---------------------------------------------------------------------------*/ void OVC_mostest( MCW_DCOV * ovc ) { float bright_inten , dark_inten , red_inten , green_inten , blue_inten , inten ; int bright_ii , dark_ii , red_ii , green_ii , blue_ii ; float yellow_inten ; int yellow_ii ; int ii ; if( ovc == NULL || ovc->ncol_ov < 2 ) return ; bright_inten = dark_inten = XCOL_BRIGHTNESS( ovc->xcol_ov[1] ) ; bright_ii = dark_ii = 1 ; red_inten = XCOL_REDNESS ( ovc->xcol_ov[1] ) ; /* June 1997 */ green_inten = XCOL_GREENNESS( ovc->xcol_ov[1] ) ; blue_inten = XCOL_BLUENESS ( ovc->xcol_ov[1] ) ; red_ii = green_ii = blue_ii = 1 ; yellow_ii = 1 ; yellow_inten = XCOL_YELLOWNESS( ovc->xcol_ov[1] ) ; /* 28 Jan 2004 */ for( ii=2 ; ii < ovc->ncol_ov ; ii++ ){ inten = XCOL_BRIGHTNESS( ovc->xcol_ov[ii] ) ; if( inten > bright_inten ){ bright_inten = inten ; bright_ii = ii ; } else if( inten < dark_inten ){ dark_inten = inten ; dark_ii = ii ; } inten = XCOL_REDNESS( ovc->xcol_ov[ii] ) ; if( inten > red_inten ){ red_inten = inten ; red_ii = ii ; } inten = XCOL_GREENNESS( ovc->xcol_ov[ii] ) ; if( inten > green_inten ){ green_inten = inten ; green_ii = ii ; } inten = XCOL_BLUENESS( ovc->xcol_ov[ii] ) ; if( inten > blue_inten ){ blue_inten = inten ; blue_ii = ii ; } inten = XCOL_YELLOWNESS( ovc->xcol_ov[ii] ) ; if( inten > yellow_inten ){ yellow_inten = inten ; yellow_ii = ii ; } } ovc->ov_brightest = bright_ii ; ovc->pixov_brightest = ovc->pix_ov[bright_ii] ; ovc->ov_darkest = dark_ii ; ovc->pixov_darkest = ovc->pix_ov[dark_ii] ; ovc->ov_reddest = red_ii ; ovc->pixov_reddest = ovc->pix_ov[red_ii] ; ovc->ov_greenest = green_ii ; ovc->pixov_greenest = ovc->pix_ov[green_ii] ; ovc->ov_bluest = blue_ii ; ovc->pixov_bluest = ovc->pix_ov[blue_ii] ; ovc->ov_yellowest = yellow_ii ; ovc->pixov_yellowest = ovc->pix_ov[yellow_ii] ; } /*------------------------------------------------------------------------------- Store the colors needed for image display, based on the value of dc->use_xcol_im (colors for image, or grayscale?). This replaces the use of XStoreColors directly in the code above. 22 Aug 1998 -- RWCox. ---------------------------------------------------------------------------------*/ void DC_set_image_colors( MCW_DC * dc ) { int ii , nc ; XColor * xc ; nc = dc->ncol_im ; xc = (dc->use_xcol_im) ? (dc->xcol_im) : (dc->xgry_im) ; if( dc->visual_class == PseudoColor ){ /* actually change colormap */ XStoreColors( dc->display , dc->colormap , xc , nc ) ; #if 0 if( dc->cdef != NULL ) reload_DC_colordef( dc ) ; /* 11 Feb 1999 */ #else /* FREE_DC_colordef(dc->cdef) ; */ #endif } else if( dc->visual_class == TrueColor ){ /* change internal pixel array */ for( ii=0 ; ii < nc ; ii++ ){ if( dc->pix_im_ready ) XFreeColors( dc->display, dc->colormap, dc->pix_im+ii, 1, 0 ) ; XAllocColor( dc->display , dc->colormap , xc+ii ) ; dc->pix_im[ii] = xc[ii].pixel ; } dc->pix_im_ready = 1 ; } /* 06 Mar 2001: save RGB of colors into arrays for quick use later */ for( ii=0 ; ii < nc ; ii++ ){ dc->r_im[ii] = INTEN_TO_BYTE( xc[ii].red ) ; dc->g_im[ii] = INTEN_TO_BYTE( xc[ii].green ) ; dc->b_im[ii] = INTEN_TO_BYTE( xc[ii].blue ) ; #if 0 dc->gray_im[ii] = BRIGHTNESS( dc->r_im[ii] , dc->g_im[ii] , dc->b_im[ii] ) ; #endif } return ; } /*-------------------------------------------------------------- Yoke the widget to the DC -- 14 Sep 1998 ----------------------------------------------------------------*/ void DC_yokify( Widget w , MCW_DC * dc ) { if( w == NULL || dc == NULL || !XtIsWidget(w) ) return ; XtVaSetValues( w , XmNvisual , dc->visual , XmNcolormap , dc->colormap , XmNdepth , dc->depth , XmNscreen , dc->screen , XmNbackground , 0 , XmNborderColor , 0 , NULL ) ; return ; } /*--------------------------------------------------------------------- Load the colordef structure in the DC -- 11 Feb 1999 -----------------------------------------------------------------------*/ void reload_DC_colordef( MCW_DC * dc ) { XVisualInfo * vin ; DC_colordef * cd ; /* will be the output */ ENTRY("reload_DC_colordef") ; /*--- sanity check ---*/ if( dc == NULL || dc->visual_info == NULL ){ fprintf(stderr,"reload_DC_colordef: entry values are NULL\n") ; EXRETURN ; } vin = dc->visual_info ; /*--- PseudoColor case ---*/ #if defined(__cplusplus) || defined(c_plusplus) if( vin->c_class == PseudoColor ){ #else if( vin->class == PseudoColor ){ #endif int iz , count , ii ; XColor * xcol ; /* create output */ cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ; cd->classKRH = PseudoColor ; cd->depth = vin->depth ; /* get all the colors in the colormap */ count = vin->colormap_size ; xcol = (XColor *) malloc( sizeof(XColor) * count ) ; for( ii=0 ; ii < count ; ii++ ) xcol[ii].pixel = ii ; XQueryColors( dc->display , dc->colormap , xcol , count ) ; /* store them in the output, truncated to 8 bit resolution */ cd->ncolors = count ; cd->rr = (byte *) malloc( count ) ; cd->gg = (byte *) malloc( count ) ; cd->bb = (byte *) malloc( count ) ; for( ii=0 ; ii < count ; ii++ ){ cd->rr[ii] = xcol[ii].red >> 8 ; cd->gg[ii] = xcol[ii].green >> 8 ; cd->bb[ii] = xcol[ii].blue >> 8 ; } /* find a pure white color, if any */ for( iz=0 ; iz < count ; iz++ ) if( cd->rr[iz] == 255 && cd->gg[iz] == 255 && cd->bb[iz] == 255 ) break ; cd->nwhite = (iz < count) ? iz : -1 ; /* find first all zero color; discard others at end of colormap */ for( iz=0 ; iz < count ; iz++ ) if( cd->rr[iz] == 0 && cd->gg[iz] == 0 && cd->bb[iz] == 0 ) break ; cd->nblack = (iz < count) ? iz : -1 ; if( iz < count-1 ){ /* if found one before the end */ for( ii=count-1 ; ii > iz ; ii-- ) /* scan backwards */ if( cd->rr[ii] != 0 || cd->gg[ii] != 0 || cd->bb[ii] != 0 ) break ; count = ii+1 ; /* number of colors left */ if( count == 1 ){ /* colormap is all black?! */ free(xcol) ; FREE_DC_colordef(cd) ; fprintf(stderr,"reload_DC_colordef: colormap is all black?\n") ; EXRETURN ; } cd->ncolors = count ; } FREE_DC_colordef(dc->cdef) ; /* if already present, kill it */ free(xcol) ; dc->cdef = cd ; EXRETURN ; } /*--- TrueColor case ---*/ #if defined(__cplusplus) || defined(c_plusplus) if( vin->c_class == TrueColor ){ #else if( vin->class == TrueColor ){ #endif unsigned long r , g , b ; byte rr, gg, bb ; /* create output */ cd = (DC_colordef *) malloc( sizeof(DC_colordef) ) ; cd->classKRH = TrueColor ; cd->depth = vin->depth ; cd->rrmask = vin->red_mask ; /* bit masks for color */ cd->ggmask = vin->green_mask ; /* storage inside pixel */ cd->bbmask = vin->blue_mask ; cd->rrshift = 7 - highbit(cd->rrmask) ; /* shift puts high bit of */ cd->ggshift = 7 - highbit(cd->ggmask) ; /* a color byte into place */ cd->bbshift = 7 - highbit(cd->bbmask) ; /* +shift == >> ; - == << */ /* compute the all white pixel as a common case */ rr = gg = bb = 255 ; r = (cd->rrshift<0) ? (rr<<(-cd->rrshift)) : (rr>>cd->rrshift) ; r = r & cd->rrmask ; g = (cd->ggshift<0) ? (gg<<(-cd->ggshift)) : (gg>>cd->ggshift) ; g = g & cd->ggmask ; b = (cd->bbshift<0) ? (bb<<(-cd->bbshift)) : (bb>>cd->bbshift) ; b = b & cd->bbmask ; cd->whpix = r | g | b ; cd->rr = cd->gg = cd->bb = NULL ; /* not used */ FREE_DC_colordef(dc->cdef) ; /* if already present, kill it */ dc->cdef = cd ; EXRETURN ; } /*--- Illegal Visual class! [do nothing]---*/ #if defined(__cplusplus) || defined(c_plusplus) fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n", x11_vcl[vin->c_class] ) ; #else fprintf(stderr,"reload_DC_colordef: illegal Visual class %s\n", x11_vcl[vin->class] ) ; #endif EXRETURN ; } /*--------------------------------------------------------------------- Compute the Pixel that is closest to the given (r,g,b) color -----------------------------------------------------------------------*/ Pixel DC_rgb_to_pixel( MCW_DC * dc, byte rr, byte gg, byte bb ) { static MCW_DC * dcold=NULL ; DC_colordef * cd = dc->cdef ; if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; } switch( cd->classKRH ){ /*--- TrueColor case: make color by appropriate bit twiddling ---*/ case TrueColor:{ static unsigned long pold=0 ; static byte rold=0 , gold=0 , bold=0 ; unsigned long r , g , b ; if( rr == 0 && gg == 0 && bb == 0 ) return 0 ; /* common */ if( rr == 255 && gg == 255 && bb == 255 ) return cd->whpix ; /* cases */ if( dc == dcold && rr == rold && gg == gold && bb == bold ) /* Remembrance of Things Past? */ return (Pixel) pold ; rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* OK, remember for next time */ r = (cd->rrshift<0) ? (rr<<(-cd->rrshift)) : (rr>>cd->rrshift) ; r = r & cd->rrmask ; g = (cd->ggshift<0) ? (gg<<(-cd->ggshift)) : (gg>>cd->ggshift) ; g = g & cd->ggmask ; b = (cd->bbshift<0) ? (bb<<(-cd->bbshift)) : (bb>>cd->bbshift) ; b = b & cd->bbmask ; pold = r | g | b ; /* assemble color from components */ return (Pixel) pold ; } /*--- PseudoColor case: find closest match in colormap. Red, green, and blue are weighted according to their importance to the human visual system. ---*/ case PseudoColor:{ #define RW 2 /* the weights alluded to above */ #define GW 4 #define BW 1 #define RGBSUM 4 /* max allowed difference */ static int iold=0 , rold=0,gold=0,bold=0 ; int ii , rdif,gdif,bdif,dif , ibest,dbest ; if( cd->nblack >= 0 && rr == 0 && gg == 0 && bb == 0 ) /* deal with */ return (Pixel) cd->nblack ; /* 2 special */ /* and common */ if( cd->nwhite >= 0 && rr == 255 && gg == 255 && bb == 255 ) /* cases */ return (Pixel) cd->nwhite ; if( dc == dcold ){ rdif = rold - rr ; gdif = gold - gg ; bdif = bold - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ) return (Pixel) iold ; /* Remembrance of Things Past? */ } rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* No? Remember for next time. */ rdif = cd->rr[0] - rr ; gdif = cd->gg[0] - gg ; bdif = cd->bb[0] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ){ iold = 0 ; return 0 ; } ibest = 0 ; dbest = dif ; for( ii=1 ; ii < cd->ncolors ; ii++ ){ rdif = cd->rr[ii] - rr ; gdif = cd->gg[ii] - gg ; bdif = cd->bb[ii] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ){ iold = ii ; return (Pixel) ii ; } if( dif < dbest ){ ibest = ii ; dbest = dif ; } } iold = ibest ; return (Pixel) ibest ; } } /*--- Illegal case! ---*/ return 0 ; /* always valid (but useless) */ } /*--------------------------------------------------------------------- Compute the Pixel that is closest to the given (r,g,b) color, but if the pixel isn't gray (r=g=b), the color must be from the specified set of overlay colors. [20 Dec 1999 - RW Cox] -----------------------------------------------------------------------*/ Pixel DC_rgb_to_ovpix( MCW_DC * dc, byte rr, byte gg, byte bb ) { static MCW_DC * dcold=NULL ; static Pixel pold=0 ; static int rold=0,gold=0,bold=0 ; int ii , rdif,gdif,bdif,dif , ibest,dbest ; if( rr == gg && rr == bb ) return DC_rgb_to_pixel(dc,rr,gg,bb) ; if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return 0 ; if( dc == dcold ){ /* check if we just saw this */ rdif = rold - rr ; gdif = gold - gg ; bdif = bold - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ) return pold ; } rold = rr ; gold = gg ; bold = bb ; dcold = dc ; /* remember for next time */ rdif = DCOV_REDBYTE(dc,0) - rr ; gdif = DCOV_GREENBYTE(dc,0) - gg ; bdif = DCOV_BLUEBYTE(dc,0) - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[0] ; return pold ; } ibest = 0 ; dbest = dif ; for( ii=1 ; ii < dc->ovc->ncol_ov ; ii++ ){ rdif = DCOV_REDBYTE(dc,ii) - rr ; gdif = DCOV_GREENBYTE(dc,ii) - gg ; bdif = DCOV_BLUEBYTE(dc,ii) - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ; if( dif <= RGBSUM ){ pold = dc->ovc->pix_ov[ii] ; return pold ; } if( dif < dbest ){ ibest = ii ; dbest = dif ; } } pold = dc->ovc->pix_ov[ibest] ; return pold ; } /*--------------------------------------------------------------------- Convert color to triple in overlay color list that is closest. -----------------------------------------------------------------------*/ void DC_rgb_to_ovrgb( MCW_DC * dc , int nlist , int * list , int shade , byte *rrin , byte *ggin, byte *bbin ) { int jj,jtop,ii , rdif,gdif,bdif,dif , ibest,dbest ; byte rr=*rrin , gg=*ggin , bb=*bbin , mm , rt,gt,bt , rtbest,gtbest,btbest; float brig , fac ; if( rr == gg && rr == bb ) return ; /* if grayscale, is OK */ if( dc == NULL || dc->ovc == NULL || dc->ovc->ncol_ov == 0 ) return ; /* start with the gray color with the same brightness */ brig = BRIGHTNESS(rr,gg,bb) ; mm = (byte)(brig + 0.499) ; dbest = RW*abs(mm-rr)+GW*abs(mm-gg)+BW*abs(mm-bb) ; /* diff from gray */ if( dbest <= RGBSUM ){ *rrin = *ggin = *bbin = mm ; return ; } ibest = 0 ; rtbest = gtbest = btbest = mm ; /* now check the colors in the list given, or the entire set if no list */ jtop = (nlist > 0) ? nlist : dc->ovc->ncol_ov ; for( jj=0 ; jj < jtop ; jj++ ){ ii = (nlist > 0) ? list[jj] : jj ; if( ii <= 0 || ii >= dc->ovc->ncol_ov || dc->ovc->bright_ov[ii] <= 0.0 ) continue ; rt = DCOV_REDBYTE(dc,ii) ; gt = DCOV_GREENBYTE(dc,ii) ; bt = DCOV_BLUEBYTE(dc,ii) ; if( shade ){ fac = brig / dc->ovc->bright_ov[ii] ; rt = (byte)( fac*rt + 0.499 ) ; gt = (byte)( fac*gt + 0.499 ) ; bt = (byte)( fac*bt + 0.499 ) ; } dif = RW*abs(rt-rr)+GW*abs(gt-gg)+BW*abs(bt-bb) ; if( dif <= RGBSUM ){ *rrin = rt ; *ggin = gt ; *bbin = bt ; return ; } if( dif < dbest ){ ibest = ii ; dbest = dif ; rtbest = rt ; gtbest = gt ; btbest = bt ; } } *rrin = rtbest ; *ggin = gtbest ; *bbin = btbest ; return ; } /*--------------------------------------------------------------------- Compute the (r,g,b) color corresponding to a given Pixel -----------------------------------------------------------------------*/ void DC_pixel_to_rgb( MCW_DC * dc , Pixel ppp , byte * rr , byte * gg , byte * bb ) { DC_colordef * cd = dc->cdef ; if( cd == NULL ){ reload_DC_colordef(dc) ; cd = dc->cdef ; } switch( cd->classKRH ){ /*--- TrueColor case: unmake color by appropriate bit twiddling ---*/ case TrueColor:{ unsigned long r , g , b ; if( ppp == 0 ){ *rr = *bb = *gg = 0 ; return ; } /* common cases */ if( ppp == cd->whpix ){ *rr = *bb = *gg = 255 ; return ; } r = ppp & cd->rrmask ; *rr = (cd->rrshift<0) ? (r>>(-cd->rrshift)) : (r<rrshift) ; g = ppp & cd->ggmask ; *gg = (cd->ggshift<0) ? (g>>(-cd->ggshift)) : (g<ggshift) ; b = ppp & cd->bbmask ; *bb = (cd->bbshift<0) ? (b>>(-cd->bbshift)) : (b<bbshift) ; return ; } /*--- PseudoColor case: extract from colormap ---*/ case PseudoColor:{ int ii = (int) ppp ; *rr = cd->rr[ii] ; *gg = cd->gg[ii] ; *bb = cd->bb[ii] ; return ; } } return ; } /*------------------------------------------------------------------------- 21 Sep 2001: compute an (r,g,b) triple (floating point, 0..1) for the given color string; return value is 0 for good, 1 for bad (if bad, *rr, *gg, *bb aren't touched) ---------------------------------------------------------------------------*/ int DC_parse_color( MCW_DC *dc, char *str, float *rr, float *gg, float *bb ) { XColor cell ; int ok ; if( str == NULL || *str == '\0' ) return 1 ; if( strncmp(str,"AJJ:",4) == 0 ){ /* 07 Feb 2003 */ float ang=-6666.0 ; sscanf(str+4,"%f",&ang) ; if( ang != -6666.0 ){ rgbyte col = DC_spectrum_AJJ( ang , 0.8 ) ; *rr = col.r / 255.0 ; *gg = col.g / 255.0 ; *bb = col.b / 255.0 ; return 0 ; } return 1 ; } ok = XParseColor( dc->display , dc->colormap , str, &cell ) ; if( ok ){ *rr = cell.red / 65535.0 ; *gg = cell.green / 65535.0 ; *bb = cell.blue / 65535.0 ; return 0 ; } return 1 ; }