From: dwb@IMD.Sterling.COM (David Boyd)
Subject: Re: An Open Challenge (it can't be done!)
Keywords: xor cursors images biscuits
Reply-To: dwb@IMD.Sterling.COM
Organization: Sterling Software
Date: Wed, 23 Dec 1992 23:32:56 GMT
X-Md4-Signature: 3c08d3220ad68d2743770df3b564de13

In article <78716@hydra.gatech.EDU>, gt4417a@prism.gatech.EDU (SKELTON,JOEL
PHILLIP) writes:
|> This is okay if the image is
|> all one color but for a complex satellite image or a noisy image 
|> an xor'ed line is nearly invisible. 
	We have fought the same problem in doing rubber banding over images and
digitized maps.
|> 
|> Here's the short form:
|>  - 8 bit image in backing pixmap used to update window
|>  - Image drawn in 8 bit X window
|>  - Want to draw diagonal lines on top of image that can
|>    be removed quickly (i.e. replace them with the data they so
|>    recently covered)
|>  - Can't do server extensions (too many platforms to support)
	To get around the visibility problem with XOR mode I use the
following function to get the pixel value for foreground which will when
XORed with the image pixels have the greatest contrast with most number of
image pixel values.  The code as provided, has a delay at start up do
read back the XImage from our source window.  If your background window
changes infrequently then the overhead of retrieving the XImage may be 
acceptable.  This code will also work fairly well even if you do not
take into account the frequency of the pixel values in your image.  This 
code can be speeded up quite a bit depending on what information you may
already have accessable in your program.  This could also be combined with
Oliver Jones suggestion about drawning/redrawing dashed lines.  Here the code:
/*++ _GetBestXorColor 
 *
 *   &PURPOSE:
 *
 *   Scans the colormap for a window a computes the best color for
 *   the XORed rubber band line.
 *
 *   &PROCESSING:
 *	
 *   Gets the window attributes to identify the colormap.  Querys the
 *   color map for the allocated colors and computes the best pixel
 *   value for the Xor rubberband line.
 *
 *   &PARAMETERS:
 *
 *   w		Widget		input		window to perform 
 *						rubberbanding in.	
 *   
 *   fg_color   unsigned long *  output          foreground color for GC
 *
 *   bg_color   unsigned long *  output          background color for GC
 *
--*/
static void _GetBestXorColor(w,fg_color, bg_color )
Widget w;
unsigned long *fg_color;
unsigned long *bg_color;
{
XWindowAttributes win_atts;
Colormap my_colormap;
int    max_cells = CellsOfScreen(XtScreen(w));
XColor *color_cells = (XColor *)calloc(max_cells,sizeof(XColor));
int	*num_colors = (int *)calloc(max_cells,sizeof(XColor));
unsigned long best_pick_fg; 
double rgb_diff, best_diff;
int i,j,k;
XImage *win_image;

   SL_PUSH("_GetBestXorColor");

   XGetWindowAttributes(XtDisplay(w), XtWindow(w), &win_atts);
   if (win_atts.colormap == None)
      my_colormap = DefaultColormapOfScreen(XtScreen(w));
   else
      my_colormap = win_atts.colormap;

   for (i=0; i<max_cells; i++)
       color_cells[i].pixel = i;

   XQueryColors( XtDisplay(w), my_colormap, color_cells, max_cells);

   /* Now find out which colors are used in the window */
   win_image = XGetImage(XtDisplay(w), XtWindow(w), 0, 0,
		win_atts.width, win_atts.height, AllPlanes, ZPixmap);

   for (j=0; j<win_atts.width; j++)
       for (k=0; k<win_atts.height; k++)
           {
           unsigned long a_pixel = XGetPixel(win_image, j, k);
	   num_colors[a_pixel] ++;
           };

   XDestroyImage(win_image);

   best_diff = 0.0;

   for (i=0; i<max_cells; i++)
       {
       rgb_diff = 0.0;
       for (j=0; j<max_cells; j++)
           {
           unsigned int tmp;
           if (num_colors[j])
              {
              tmp = (i ^ j) % max_cells;
              rgb_diff += 1.0 * (abs (((long)color_cells[tmp].red) -
                          ((long)color_cells[j].red)) +
	     	   abs (((long)color_cells[tmp].green) -
                          ((long)color_cells[j].green)) +
		   abs (((long)color_cells[tmp].blue) -
                          ((long)color_cells[j].blue))) * num_colors[j];
               }
           }
        
        if (rgb_diff > best_diff)
           {
           best_diff = rgb_diff;
           best_pick_fg = i;
           }
        }
 
   *fg_color = best_pick_fg;
   *bg_color = best_pick_fg ^ win_atts.backing_pixel;

   free(color_cells);
   free(num_colors);

   SL_POPVOID(); 
}


-- 
David W. Boyd	             UUCP:     uunet!sparky!dwb
Sterling Software IMD        INTERNET: dwb@IMD.Sterling.COM
1404 Ft. Crook Rd. South     Phone:    (402) 291-8300 
Bellevue, NE. 68005-2969     FAX:      (402) 291-4362