/*****************************************************************************
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 ;
#if 0
if( strcmp(cname,"none") == 0 ) return -1 ;
#endif
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<<cd->rrshift) ;
g = ppp & cd->ggmask ;
*gg = (cd->ggshift<0) ? (g>>(-cd->ggshift)) : (g<<cd->ggshift) ;
b = ppp & cd->bbmask ;
*bb = (cd->bbshift<0) ? (b>>(-cd->bbshift)) : (b<<cd->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 ;
}
syntax highlighted by Code2HTML, v. 0.9.1