Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
getx10.c
Go to the documentation of this file.
1 /*
2  * This software is copyrighted as noted below. It may be freely copied,
3  * modified, and redistributed, provided that the copyright notice is
4  * preserved on all copies.
5  *
6  * There is no warranty or other guarantee of fitness for this software,
7  * it is provided solely "as is". Bug reports or fixes may be sent
8  * to the author, who may or may not act on them as he desires.
9  *
10  * You may not include this software in a program or other software product
11  * without supplying the source, or without informing the end-user that the
12  * source is available for no extra charge.
13  *
14  * If you modify this software, you should include a notice giving the
15  * name of the person performing the modification, the date of modification,
16  * and the reason for such modification.
17  */
18 /*
19  * getx10.c - Put RLE images on X display.
20  *
21  * Author: Spencer W. Thomas
22  * Computer Science Dept.
23  * University of Utah
24  * Date: Thu Feb 20 1986
25  * Copyright (c) 1986, University of Utah
26  *
27  */
28 #ifndef lint
29 static char rcs_ident[] = "$Id: getx10.c,v 3.0.1.1 1992/01/28 18:12:35 spencer Exp $";
30 #endif
31 
32 #include <stdio.h>
33 #include <math.h>
34 #include <X/Xlib.h>
35 #include "rle.h"
36 
37 /* Most that can be sent to X in one chunk */
38 #define MAXSEND 65535 /* 64K */
39 
40 /*
41  * Basic magic square for dithering
42  */
43 int dm16[16][16];
44 
45 /* define arrow cursor for zoom mode */
46 #define arrow_width 16
47 #define arrow_height 16
48 #define arrow_x_hot 4
49 #define arrow_y_hot 1
50 static short arrow_bits[] = {
51  0x0000, 0x0010, 0x0030, 0x0070,
52  0x00f0, 0x01f0, 0x03f0, 0x07f0,
53  0x0ff0, 0x01f0, 0x03b0, 0x0310,
54  0x0700, 0x0600, 0x0600, 0x0000};
55 #define arrow_mask_width 16
56 #define arrow_mask_height 16
57 static short arrow_mask_bits[] = {
58  0x0018, 0x0038, 0x0078, 0x00f8,
59  0x01f8, 0x03f8, 0x07f8, 0x0ff8,
60  0x1ff8, 0x1ff8, 0x07f8, 0x07b8,
61  0x0f98, 0x0f00, 0x0f00, 0x0f00};
63 
64 /*
65  * Color map, gamma correction map, and lookup tables
66  */
67 Color colmap[256];
68 int gammamap[256];
70 int modN[256], divN[256];
71 int bwflag = 0; /* if non zero, dither in B&W
72  * Value of 2 means 1-bit system
73  */
74 
75 /*
76  * Number of color map levels, (square and cube), and number of gradations
77  * per level.
78  */
80 
81 /*
82  * Global variables
83  */
84 rle_hdr hdr;
85 double disp_gam = 2.5; /* default gammas for display and image */
86 double img_gam = 1.0;
87 int iflag = 0; /* flag to tell if gamma was on command line */
88 int setbg = 0; /* set root background to image? */
89 int mapflg = 0; /* flag to just load color map */
90 int usemap = 0; /* Use given color map, don't dither */
91 int forkflg = 0; /* No fork allows zoom info (middle button) */
92 int zoomflg = 0; /* build zoom window */
93 
95 Window fbwin, iconwin, zoomwin;
97 int zoomfact = 8;
98 int zoom_x_dim = 15;
99 int zoom_y_dim = 15;
101 int nscan, nrow; /* size of window */
102 int nbyte; /* size of bitrow for 1-bit displays */
103 
104 int dbg = 0; /* set if debug mode */
105 
106 unsigned char *buffer, *iconbuf; /* data storage pointers */
107 
108 /*****************************************************************
109  * TAG( main )
110  *
111  * Usage:
112  * getx10 [-{bB}] [-z] [-m] [-f] [-p] [-D] [-d display]
113  * [-= window-geometry] [-{iI} gamma] [-g gamma] [file]
114  * Inputs:
115  * -b: Set the root window background to the resultant image.
116  * -B: Set the root background, but don't display the image
117  * in a separate window.
118  * -z: Create Zoom window also. Any button in image recenters
119  * zoom. Drag in image resizes zoom window to enclose
120  * region. Left in zoom window decreases zoom factor.
121  * Right increases zoom factor. Middle prints position
122  * info to the terminal, but only if -f is on.
123  * -m: Just load color map and exit.
124  * -f: Don't fork after putting image on screen.
125  * -p: Don't use off-screen memory to speed up redraw.
126  * -D: Debug mode: print input file as read.
127  * -w: Black & white: reduce color images to B&W before
128  * display. Advantage is that smoother shading can
129  * be achieved.
130  * -c: Use colors specified in color map. Will try to load
131  * entire color map. No dithering will be done
132  * when this option is specified. Actual number
133  * of entries in color map may be given as a
134  * picture comment:
135  * color_map_length=<number of entries in color map>.
136  * -d display: Specify display name.
137  * -= window_geometry:
138  * Specify window geometry (but min size set by file).
139  * -i gamma: Specify gamma of image. (default 1.0)
140  * -I gamma: Specify gamma of display image was computed for.
141  * getx10 will also read picture comments from the input file to determine
142  * the image gamma. These are
143  * image_gamma= gamma of image (equivalent to -i)
144  * display_gamma= gamma of display image was computed for.
145  * Command line arguments override values in the file.
146  *
147  * -g gamma: Specify gamma of display. (default 2.5)
148  * file: Input Run Length Encoded file. Uses stdin if not
149  * specified.
150  * Outputs:
151  * Puts image on screen.
152  * Assumptions:
153  * Input file is in RLE format.
154  * Algorithm:
155  * [None]
156  */
157 
158 main(argc, argv)
159 char **argv;
160 {
161  char ** infnames = NULL, *infname = NULL, *display_name = NULL,
162  * window_geometry = NULL;
163  FILE * infile = stdin;
164  int nfile = 0, use_pix = 0,
165  dflag = 0, gflag = 0, wflag = 0;
166 
167  if ( scanargs( argc, argv,
168  "% Bb%- m%- f%- p%- cWw%- D%- n%-levels!d d%-display!s \n\
169 \t=%-window-geometry!s Ii%-gamma!F g%-gamma!F z%- file%s",
170  &setbg, &mapflg, &forkflg, &use_pix, &bwflag, &dbg,
171  &levels, &levels,
172  &dflag, &display_name,
173  &wflag, &window_geometry,
174  &iflag, &img_gam,
175  &gflag, &disp_gam,
176  &zoomflg,
177  &infname ) == 0 )
178  exit( 1 );
179 
180  hdr = *rle_hdr_init( (rle_hdr *)NULL );
181  rle_names( &hdr, cmd_name( argv ), infname );
182 
183  use_pix = ! use_pix;
184  if ( setbg & !use_pix )
185  {
186  fprintf( stderr, "Can't specify -p with -b, -p ignored\n" );
187  use_pix = 1;
188  }
189  if ( setbg == 2 )
190  forkflg = 1;
191 
192  if ( iflag == 1 ) /* -i */
193  img_gam = 1.0 / img_gam;
194 
195  if ( bwflag == 4 ) /* -c */
196  {
197  bwflag = 0;
198  usemap = 1;
199  }
200 
201  /* Would like to be able to use multiple files, but haven't
202  * figured how to get X to let us. So, use this kludge for now.
203  */
204  if ( infname != NULL )
205  {
206  infnames = &infname;
207  nfile = 1;
208  }
209 
210  /*
211  * For each file, display it.
212  */
213  do {
214  if ( nfile > 0 )
215  {
216  infile = rle_open_f(hdr.cmd, *infnames, "r");
217  get_pic( infile, *infnames, display_name,
218  window_geometry );
219  fclose( infile );
220  infnames++;
221  nfile--;
222  }
223  else
224  get_pic( stdin, NULL, display_name,
225  window_geometry );
226  if ( ! forkflg )
227  {
228  if ( fork() == 0 )
229  {
230  /*
231  * Get rid of std fds so rshd will go
232  * away.
233  */
234  close( 0 );
235  close( 1 );
236  close( 2 );
237  update_pic( use_pix );
238  break;
239  }
240  }
241  else
242  {
243  update_pic( use_pix );
244  }
245  } while ( nfile > 0 );
246  exit( 0 );
247  /* XCloseDisplay( dpy );*/
248 }
249 
250 /*
251  * Read an image from the input file and display it.
252  */
253 get_pic( infile, infname, display_name, window_geometry )
254 FILE * infile;
255 char * infname;
256 char * display_name;
257 char * window_geometry;
258 {
259  register int i,
260  y;
261  int ncolors,
262  xmin_original;
263  unsigned char *scan[3];
264 
265  /*
266  * Read setup info from file.
267  */
268  hdr.rle_file = infile;
269  if ( !mapflg || usemap )
270  rle_get_setup_ok(&hdr, NULL, NULL);
271 
272  if ( dbg )
273  rle_debug( 1 );
274 
275  /* We're only interested in R, G, & B */
277  for (i = 3; i < hdr.ncolors; i++)
278  RLE_CLR_BIT(hdr, i);
279  ncolors = hdr.ncolors > 3 ? 3 : hdr.ncolors;
280 
281  /*
282  * Open display first time through.
283  */
284  if (dpy == NULL)
285  {
286  dpy = XOpenDisplay(display_name);
287  if (dpy == NULL)
288  {
289  fprintf(stderr, "%s: Can't open display %s\n",
290  hdr.cmd, display_name ? "" : display_name);
291  exit(1);
292  }
293  if ( DisplayPlanes() == 1 ) /* b&w display */
294  bwflag = 2;
295  }
296 
297  /* If no image gamma on command line, check comments in file */
298  if ( ! iflag )
299  {
300  char * v;
301  if ( (v = rle_getcom( "image_gamma", &hdr )) != NULL )
302  {
303  img_gam = atof( v );
304  /* Protect against bogus information */
305  if ( img_gam == 0.0 )
306  img_gam = 1.0;
307  else
308  img_gam = 1.0 / img_gam;
309  }
310  else if ( (v = rle_getcom( "display_gamma", &hdr )) != NULL )
311  {
312  img_gam = atof( v );
313  /* Protect */
314  if ( img_gam == 0.0 )
315  img_gam = 1.0;
316  }
317  }
318 
319  /*
320  * Set up the color map.
321  */
322  /* Input map, at least 3 channels */
323  in_cmap = buildmap( &hdr, 3, img_gam, 1.0 );
324  /* Get X color map */
325  if ( usemap )
326  load_x_map();
327  else
328  init_color();
329 
330  if ( mapflg )
331  exit( 0 );
332 
333  /*
334  * Compute image size and allocate storage.
335  */
336  nrow = (hdr.xmax - hdr.xmin + 1);
337  if ( bwflag == 2 )
338  nbyte = ((nrow + 15) / 16) * 2; /* 1 bit display */
339  else
340  nbyte = nrow;
341  nscan = (hdr.ymax - hdr.ymin + 1);
342  buffer = (unsigned char *) malloc(nbyte * nscan);
343 
344  /*
345  * Icon wants to be about 50 x 50. Figure out how much smaller than the
346  * image this is.
347  */
348  iconfact = nrow / 50;
349  if (iconfact < nscan / 50)
350  iconfact = nscan / 50;
351  if ( iconfact == 0 )
352  iconfact = 1;
353  iconrow = (1 + nrow / iconfact);
354  iconscan = (1 + nscan / iconfact);
355  if ( bwflag == 2 )
356  {
357  iconbuf = (unsigned char *)
358  malloc(BitmapSize( (1 + nrow / iconfact),
359  (1 + nscan / iconfact) ));
360  iconbyte = 2 * ((iconrow + 15) / 16);
361  }
362  else
363  {
364  iconbuf = (unsigned char *) malloc((1 + nrow / iconfact) *
365  (1 + nscan / iconfact));
366  iconbyte = iconrow;
367  }
368 
369  /*
370  * Set up for rle_getrow. Pretend image x origin is 0.
371  */
372  for (i = 0; i < 3; i++)
373  scan[i] = (unsigned char *) malloc(nrow);
374  hdr.xmax -= hdr.xmin;
375  xmin_original = hdr.xmin;
376  hdr.xmin = 0;
377 
378  /*
379  * Get a window of the right size (user positions it with the mouse).
380  */
381  if ( setbg < 2 )
382  create_window(nrow, nscan, window_geometry);
383 
384  /*
385  * For each scan line, dither it and display.
386  */
387  while ((y = rle_getrow(&hdr, scan)) <= hdr.ymax)
388  {
389  if ( bwflag && ncolors > 1 )
390  {
391  map_rgb_to_bw( scan[0], scan[1], scan[ncolors - 1], scan[0],
392  in_cmap, nrow );
393  /* Note: map_scanline only uses channel 0 for B&W */
394  }
395  else if ( bwflag )
396  for ( i = 0; i < nrow; i++ )
397  scan[0][i] = in_cmap[0][scan[0][i]];
398  else
399  for (i = 2; i >= ncolors; i--)
400  bcopy(scan[0], scan[i], nrow);
401  map_scanline(scan, nrow, 1, y,
402  &buffer[(hdr.ymax - y) * nbyte]);
403  /* Subsample image to create icon */
404  if ( (hdr.ymax - y) % iconfact == 0 )
405  map_scanline( scan, iconrow, iconfact,
406  (hdr.ymax - y) / iconfact,
407  &iconbuf[((hdr.ymax - y) / iconfact) *
408  iconbyte] );
409  if ( setbg < 2 )
410  put_scanline(&buffer[(hdr.ymax - y) * nbyte], nrow, 0,
411  hdr.ymax - y );
412  }
413  /*
414  * Free temp storage
415  */
416  for (i = 0; i < 3; i++)
417  free(scan[i]);
418 
419  hdr.xmin = xmin_original;
420  hdr.xmax += xmin_original;
421 }
422 /*
423  * Track events & redraw image when necessary.
424  */
425 update_pic( use_pix )
426 {
427  int i,
428  npix,
429  pixscan,
430  lastscan,
431  gotpix;
432  long bufsize,
433  pixsize;
434  XEvent rep;
435  XButtonEvent xkey;
436  XExposeEvent xex;
437  int zoom_x_press, zoom_y_press;
438 
439  Pixmap(*pix)[] = 0;
440  Bitmap bm;
441 
442  if (zoomflg)
443  {
444  zoom_x_center = nrow / 2;
445  zoom_y_center = nscan / 2;
446  update_zoom();
447  }
448 
449  /*
450  * If requested, use off screen pixmap to speed image redisplay. Need to
451  * allocate it in slices, since can't write whole image to X at once.
452  */
453  if (use_pix)
454  {
455  npix = 1 + (nscan * nbyte) / MAXSEND;
456  pixscan = MAXSEND / nbyte;
457  pixsize = pixscan * nbyte;
458  lastscan = nscan % pixscan;
459 
460  pix = (Pixmap(*)[]) malloc(npix * sizeof(Pixmap));
461  for (i = 0; i < npix; i++)
462  if ( bwflag != 2 )
463  (*pix)[i] = XStorePixmapZ(nrow,
464  (i == npix - 1) ? lastscan : pixscan,
465  &buffer[i * nrow * pixscan]);
466  else
467  {
468  bm = XStoreBitmap(nrow,
469  (i == npix - 1) ? lastscan : pixscan,
470  &buffer[i * nbyte * pixscan]);
471  (*pix)[i] = XMakePixmap( bm, 1, 0 );
472  XFreeBitmap( bm );
473  }
474  }
475 
476  if ( setbg )
477  {
478  XChangeBackground( RootWindow, (*pix)[0] );
479  XClear( RootWindow );
480  XFlush();
481  if ( setbg == 2 )
482  exit( 0 );
483  }
484 
485  /*
486  * Basic event loop: handle expose events on window & icon, and exit on
487  * (shifted) mouse button event.
488  */
489  for (;;)
490  {
491  XNextEvent(&rep);
492  if (rep.type == ButtonPressed)
493  {
494  xkey = *(XButtonEvent *) &rep;
495  if (zoomflg && (xkey.window == fbwin))
496  {
497  zoom_x_press = xkey.x;
498  zoom_y_press = xkey.y;
499  }
500  }
501  else if (rep.type == ButtonReleased)
502  {
503  xkey = *(XButtonEvent *) &rep;
504  if ( xkey.detail & ShiftMask )
505  {
506  if (zoomflg && (xkey.window == zoomwin))
507  {
508  /* get rid of just zoom window if shiftclicked */
509  XDestroyWindow(zoomwin);
510  zoomflg = 0;
511  }
512  else
513  {
514  /* Shiftclick in fbwin means exit. */
515  break;
516  }
517  }
518  if (zoomflg && (xkey.window == fbwin))
519  {
520  zoom_x_center = xkey.x;
521  zoom_y_center = xkey.y;
522  if ((zoom_x_center != zoom_x_press) &&
523  (zoom_y_center != zoom_y_press))
524  {
525  /* drag to define zoom region */
526  if (zoom_x_press < zoom_x_center)
527  {
528  zoom_x_dim = (zoom_x_center - zoom_x_press);
529  zoom_x_center = zoom_x_press + (zoom_x_dim / 2);
530  }
531  else
532  {
533  zoom_x_dim = (zoom_x_press - zoom_x_center);
534  zoom_x_center = zoom_x_center + (zoom_x_dim / 2);
535  }
536  if (zoom_y_press < zoom_y_center)
537  {
538  zoom_y_dim = (zoom_y_center - zoom_y_press);
539  zoom_y_center = zoom_y_press + (zoom_y_dim / 2);
540  }
541  else
542  {
543  zoom_y_dim = (zoom_y_press - zoom_y_center);
544  zoom_y_center = zoom_y_center + (zoom_y_dim / 2);
545  }
546  XChangeWindow(zoomwin, zoomfact * zoom_x_dim,
547  zoomfact * zoom_y_dim);
548  XSetResizeHint( zoomwin, 0, 0, zoomfact, zoomfact );
549  }
550  update_zoom();
551  }
552  else if (zoomflg && (xkey.window == zoomwin))
553  {
554  if (xkey.detail & RightMask)
555  {
556  /* increase zoom factor */
557  zoomfact += 1;
558  XChangeWindow(zoomwin, zoomfact * zoom_x_dim,
559  zoomfact * zoom_y_dim);
560  XSetResizeHint( zoomwin, 0, 0, zoomfact, zoomfact );
561  }
562  else if (xkey.detail & LeftMask)
563  {
564  /* decrease zoom factor */
565  if (zoomfact > 1)
566  {
567  zoomfact -= 1;
568  XChangeWindow(zoomwin, zoomfact * zoom_x_dim,
569  zoomfact * zoom_y_dim);
570  XSetResizeHint( zoomwin, 0, 0, zoomfact, zoomfact );
571  }
572  }
573  else if (xkey.detail & MiddleMask)
574  {
575  if (forkflg)
576  {
577  /* can only report pixel status when not forking */
578  fprintf(stderr, "Position: (%d, %d)\n",
579  hdr.xmin +
580  xkey.x / zoomfact + (zoom_x_center
581  - (zoom_x_dim / 2)),
582  (hdr.ymax
583  - xkey.y / zoomfact
584  - (zoom_y_center - (zoom_y_dim / 2))));
585  fprintf(stderr, "Image crop: (%d, %d) to (%d, %d)\n",
586  hdr.xmin, hdr.ymin,
587  hdr.xmax, hdr.ymax);
588  fprintf(stderr, "Zoom crop: (%d, %d) to (%d, %d)\n",
589  hdr.xmin +
590  (zoom_x_center - (zoom_x_dim / 2)),
591  (hdr.ymax - (zoom_y_dim - 1)
592  - (zoom_y_center - (zoom_y_dim / 2))),
593  hdr.xmin + (zoom_x_dim - 1)
594  + (zoom_x_center - (zoom_x_dim / 2)),
595  (hdr.ymax
596  - (zoom_y_center - (zoom_y_dim / 2))));
597 
598 
599  }
600  }
601  }
602  }
603  else if (rep.type == ExposeWindow || rep.type == ExposeRegion)
604  {
605  xex = *((XExposeEvent *) & rep);
606  /*
607  * For icon exposure, just redraw whole thing - it's quick and
608  * much easier.
609  */
610  if (xex.window == iconwin)
611  if ( bwflag != 2 )
612  XPixmapBitsPutZ(iconwin, 0, 0, iconrow, iconscan,
613  iconbuf, 0, GXcopy, AllPlanes);
614  else
615  XBitmapBitsPut(iconwin, 0, 0, iconrow, iconscan,
616  iconbuf, 1, 0, 0, GXcopy, AllPlanes);
617  else if (zoomflg && (xex.window == zoomwin))
618  {
619  resize_zoom_window();
620  update_zoom();
621  }
622  else
623  {
624  /*
625  * If window has been resized (bigger), don't bother redrawing
626  * the area outside the image.
627  */
628  if (xex.y + xex.height >= nscan)
629  xex.height = nscan - xex.y;
630  /*
631  * If bitmap, round beginning pixel to beginning of word
632  */
633  if ( bwflag == 2 )
634  {
635  xex.width += xex.x; /* remember ending pixel */
636  xex.x = (xex.x / 16) * 16; /* round down */
637  xex.width -= xex.x; /* new width */
638  }
639  if (xex.x + xex.width >= nrow)
640  xex.width = nrow - xex.x;
641  /*
642  * If no pixmap, do it the slow way.
643  */
644  if (pix == 0)
645  if ( bwflag == 2 )
646  for (i = xex.y; i < xex.y + xex.height; i++)
647  put_scanline( &buffer[i * nbyte + xex.x / 8],
648  xex.width, xex.x, i );
649  else
650  for (i = xex.y; i < xex.y + xex.height; i++)
651  put_scanline( &buffer[i * nbyte + xex.x],
652  xex.width, xex.x, i );
653  else
654  {
655  /*
656  * Pixmaps exist, figure out how many slices are affected
657  * and which portion of each.
658  */
659  int start = xex.y / pixscan,
660  end = (xex.y + xex.height) / pixscan,
661  y = xex.y,
662  ytop;
663  register int j;
664 
665  for (i = start; i <= end; i++)
666  {
667  ytop = (i == end) ? xex.y + xex.height
668  : (i + 1) * pixscan;
669  /*
670  * if this slice has a pixmap, blit it. If not, do it
671  * slow from the buffer.
672  */
673  if ((*pix)[i] != 0)
674  XPixmapPut(fbwin, xex.x, y - i * pixscan,
675  xex.x, y,
676  xex.width, ytop - y, (*pix)[i],
677  GXcopy, AllPlanes);
678  else
679  if ( bwflag == 2 )
680  for (j = y; j < ytop; j++)
681  put_scanline( &buffer[j * nbyte +
682  xex.x / 8],
683  xex.width, xex.x, j );
684  else
685  for (j = y; j < ytop; j++)
686  put_scanline( &buffer[j * nbyte + xex.x],
687  xex.width, xex.x, j );
688  y = ytop;
689  }
690  }
691  }
692  }
693  else if ( rep.type != ButtonPressed )
694  fprintf(stderr, "%s: Event type %x?\n", hdr.cmd, rep.type);
695  }
696 
697  /*
698  * Window goes away when we do.
699  */
700  XDestroyWindow(fbwin);
701  if (zoomflg) XDestroyWindow(zoomwin);
702 }
703 
704 update_zoom()
705 {
706  unsigned char the_pix;
707  int i,j;
708  int zoomx, zoomy;
709  int x_bottom, x_top;
710  int y_bottom, y_top;
711  int zoom_x_corner, zoom_y_corner;
712 
713  x_bottom = zoom_x_center - (zoom_x_dim / 2);
714  x_top = x_bottom + zoom_x_dim - 1;
715  y_bottom = zoom_y_center - (zoom_y_dim / 2);
716  y_top = y_bottom + zoom_y_dim - 1;
717 
718  for (j=y_bottom; j<=y_top; j++)
719  {
720  zoom_y_corner = (j - y_bottom) * zoomfact;
721  if ((j < 0) || (j >= nscan))
722  {
723  /* dump a blank line */
724  XPixSet( zoomwin, 0, zoom_y_corner, zoomfact * zoom_x_dim,
725  zoomfact, colmap[0].pixel );
726  }
727  else
728  {
729  for ( i= x_bottom; i<=x_top; i++)
730  {
731  zoom_x_corner = (i - x_bottom) * zoomfact;
732  if ((i < 0) || (i >= nrow))
733  {
734  /* dump a black pixel */
735  XPixSet( zoomwin, zoom_x_corner, zoom_y_corner,
736  zoomfact, zoomfact, colmap[0].pixel );
737  }
738  else
739  {
740  if ( bwflag != 2 )
741  the_pix = buffer[j * nbyte + i];
742  else
743  the_pix = buffer[j * nbyte + i/8] & (1 << (i % 8)) ?
744  1 : 0;
745  XPixSet( zoomwin, zoom_x_corner, zoom_y_corner,
746  zoomfact, zoomfact, the_pix );
747  }
748  }
749  }
750  }
751 }
752 
753 /*
754  * Create a window with help from user.
755  */
756 create_window( width, height, window_geometry )
757 {
758  OpaqueFrame frame;
759  char geometry[30];
760  int zoomwidth, zoomheight;
761 
762  /*
763  * Now, make the window.
764  */
765  sprintf( geometry, "=%dx%d+0+0", nrow, nscan );
766  frame.bdrwidth = 3;
767  frame.border = WhitePixmap;
768  frame.background = BlackPixmap;
769  if ( (fbwin = XCreate( hdr.cmd, hdr.cmd, window_geometry, geometry,
770  &frame, nrow, nscan )) == NULL )
771  {
772  fprintf( stderr, "%s: Window Create failed\n", hdr.cmd );
773  exit( 1 );
774  }
775  XMapWindow( fbwin );
776  XGetHardwareColor( &colmap[0] ); /* Assume black! */
777  XPixSet( fbwin, 0, 0, width, height, colmap[0].pixel );
778  XSetResizeHint( fbwin, width, height, 1, 1 );
779  XSelectInput( fbwin, ButtonPressed|ButtonReleased|ExposeRegion );
780 
781  if (zoomflg)
782  {
783  arrow_curs = XCreateCursor(arrow_width,arrow_height,arrow_bits,
784  arrow_mask_bits, arrow_x_hot, arrow_y_hot,
785  BlackPixel, WhitePixel, GXcopy);
786  XDefineCursor(fbwin,arrow_curs);
787  }
788 
789  iconwin = XCreateWindow( RootWindow, 1, 1,
790  width / iconfact, height / iconfact, 0, 0, 0 );
791  XTileRelative( iconwin );
792  XSetIconWindow( fbwin, iconwin );
793  XSelectInput( iconwin, ButtonPressed|ButtonReleased|ExposeWindow );
794 
795  if (zoomflg)
796  {
797  zoomwidth = zoomfact * zoom_x_dim;
798  zoomheight = zoomfact * zoom_y_dim;
799  sprintf( geometry, "=%dx%d+0+0", zoomwidth, zoomheight );
800  frame.bdrwidth = 3;
801  frame.border = WhitePixmap;
802  frame.background = BlackPixmap;
803  if ( (zoomwin = XCreate( "getx10 zoom", hdr.cmd, window_geometry,
804  geometry,
805  &frame, zoomwidth, zoomheight )) == NULL )
806  {
807  fprintf( stderr, "%s: Zoom window Create failed\n", hdr.cmd );
808  exit( 1 );
809  }
810  resize_zoom_window();
811  XMapWindow( zoomwin );
812  XPixSet( zoomwin, 0, 0, zoomfact * zoom_x_dim, zoomfact * zoom_y_dim,
813  colmap[0].pixel );
814  XSetResizeHint( zoomwin, 0, 0, zoomfact, zoomfact );
815  XSelectInput( zoomwin, ButtonPressed|ButtonReleased|ExposeRegion );
816  XDefineCursor(zoomwin,arrow_curs);
817  }
818 }
819 
820 /*
821  * Map a scanline to 8 bits through the dither matrix.
822  *
823  * Inputs:
824  * rgb: Pointers to buffers containing the red, green,
825  * and blue color rows.
826  * n: Length of row.
827  * s: Skip between pixels in original image.
828  * y: Y position of row (necessary for dither)
829  * line: Pointer to output buffer for dithered color data.
830  */
831 #define DMAP(v,x,y) (modN[v]>dm16[x][y] ? divN[v] + 1 : divN[v])
832 
834 unsigned char *rgb[3], *line;
835 {
836  register int i, col, row;
837 
838  if ( usemap )
839  {
840  register unsigned char *r;
841 
842  for ( r = rgb[0], i = 0; i < n; i++, r += s )
843  line[i] = colmap[*r].pixel;
844  }
845  else if ( !bwflag )
846  {
847  register unsigned char *r, *g, *b;
848  for ( row = y % 16, col = 0, i = 0, r = rgb[0], g = rgb[1], b = rgb[2];
849  i < n; i++, r+=s, g+=s, b+=s, col = ((col + 1) & 15) )
850  line[i] = colmap[DMAP(in_cmap[0][*r], col, row) +
851  DMAP(in_cmap[1][*g], col, row) * levels +
852  DMAP(in_cmap[2][*b], col, row) * levelsq].pixel;
853  }
854  else if ( bwflag == 1 ) /* gray scale display */
855  {
856  register unsigned char *r;
857 
858  for ( row = y % 16, col = 0, i = 0, r = rgb[0];
859  i < n; i++, r+=s, col = ((col + 1) & 15) )
860  line[i] = colmap[DMAP(*r, col, row)].pixel;
861  }
862  else /* bitmap display */
863  {
864  register unsigned short *l = (unsigned short *)line;
865  register unsigned char * r;
866 
867  for ( row = y % 16, col = 0, i = 0, r = rgb[0], *l = 0;
868  i < n; r+=s, col = ((col + 1) & 15) )
869  {
870  *l |= (*r > dm16[col][row] ? 1 : 0) << (i % 16);
871  if ( (++i % 16) == 0 && i < n )
872  *++l = 0;
873  }
874  }
875 }
876 
877 put_scanline( scan, width, x, y )
878 unsigned char *scan;
879 {
880  if ( bwflag != 2 )
881  XPixmapBitsPutZ( fbwin, x, y, width, 1, scan, 0, GXcopy, AllPlanes );
882  else
883  XBitmapBitsPut( fbwin, x, y, width, 1, scan, 1, 0, 0, GXcopy,
884  AllPlanes );
885 }
886 
887 /*****************************************************************
888  * TAG( map_rgb_to_bw )
889  *
890  * Convert RGB to black and white through NTSC transform, but map
891  * RGB through a color map first.
892  * Inputs:
893  * red_row, green_row, blue_row: Given RGB pixel data.
894  * map: Array[3] of pointers to pixel arrays,
895  * representing color map.
896  * rowlen: Number of pixels in the rows.
897  * Outputs:
898  * bw_row: Output B&W data. May coincide with one of the
899  * inputs.
900  * Algorithm:
901  * BW = .35*map[0][R] + .55*map[1][G] + .10*map[2][B]
902  */
904 rle_pixel *red_row;
905 rle_pixel *green_row;
906 rle_pixel *blue_row;
907 rle_pixel *bw_row;
908 rle_pixel **map;
909 {
910  register int x, bw;
911 
912  for (x=0; x<rowlen; x++)
913  {
914  /* 68000 won't store float > 127 into byte? */
915  /* HP compiler blows it */
916  bw = .35*map[0][red_row[x]] + .55*map[1][green_row[x]] +
917  .10*map[2][blue_row[x]];
918  bw_row[x] = bw;
919  }
920 }
921 
922 
923 /*
924  * This routine builds the color map (for X window system, details may
925  * differ in your system. Note particularly the two level color
926  * mapping: X will give back 216 color map entries, but there is no
927  * guarantee they are sequential. The dithering code above wants to
928  * compute a number in 0 - 215, so we must map from this to the X color
929  * map entry id.
930  */
931 /*
932  * Initialize the 8 bit color map. Use gamma corrected map.
933  */
934 
936 {
937  int i, rgbmap[256][3], bwmap[256];
938 #ifdef DEBUG
939  int j;
940 #endif
941 
942  if ( !bwflag )
943  {
944  /*
945  * Figure out how many color map entries we can get
946  */
947  if ( levels == 0 )
948  levels = 6; /* default starting point */
949  for ( ; levels >= 2; levels-- )
950  if ( levels*levels*levels < DisplayCells() )
951  break;
952  if ( levels < 2 )
953  {
954  fprintf(stderr,
955  "%s: This display doesn't have enough color resolution.\
956 \nWill produce black and white image instead.\n",hdr.cmd);
957  bwflag = 1;
958  levels = 0;
959  }
960  /*
961  * levels is the maximum number we can get. Now we have to try to
962  * actually acquire the color map entries.
963  */
964  while ( levels >= 2 )
965  {
966  levelsq = levels * levels;
967  levelsc = levelsq * levels;
968 
970 
971  /*
972  * Set up the color map entries. We don't yet know the location
973  * in the map at which each will reside, so init it to 0.
974  */
975  for(i = 0; i < levelsc; i++) {
976  colmap[i].pixel = 0;
977  colmap[i].red = rgbmap[i][0] << 8;
978  colmap[i].green = rgbmap[i][1] << 8;
979  colmap[i].blue = rgbmap[i][2] << 8;
980  }
981 
982  /* Get a color map entry for each color. Assume enough exist! */
983  for ( i = 0; i < levelsc; i++ )
984  {
985  if ( XGetHardwareColor( &colmap[i] ) == 0 )
986  break;
987  }
988 
989  /* Check if the colors are available */
990  if ( i < levelsc )
991  {
992  levels--;
993  /* Free the colors already obtained */
994  for ( i--; i >= 0; i-- )
995  XFreeColors( &colmap[i].pixel, 1, 0 );
996  continue;
997  }
998  break; /* succeeded */
999  }
1000  if ( levels < 2 && bwflag == 0 )
1001  {
1002  fprintf( stderr,
1003  "%s: Sorry, not enough color map entries are available.\
1004 \nWill make black & white image instead.\n",hdr.cmd);
1005  bwflag = 1;
1006  levels = 0;
1007  }
1008  }
1009 
1010  /* Get a B&W color map */
1011  if ( bwflag == 1 )
1012  {
1013  /* Try for lots of levels, give up by factors of 2 until success */
1014  if ( levels == 0 )
1015  if ( DisplayCells() > 16 )
1016  levels = DisplayCells() / 2;
1017  else
1018  levels = DisplayCells() - 4; /* assume this many taken */
1019  for ( ; levels > 1; (levels > 16) ? (levels /= 2) : (levels -= 1) )
1020  {
1022 
1023  /*
1024  * Set up the color map entries. We don't yet know the location
1025  * in the map at which each will reside, so init it to 0.
1026  */
1027  for ( i = 0; i < levels; i++ )
1028  {
1029  colmap[i].pixel = 0;
1030  colmap[i].red = bwmap[i] << 8;
1031  colmap[i].green = colmap[i].red;
1032  colmap[i].blue = colmap[i].red;
1033  }
1034 
1035  /* Get a color map entry for each color. Assume enough exist! */
1036  for ( i = 0; i < levels; i++ )
1037  {
1038  if ( XGetHardwareColor( &colmap[i] ) == 0 )
1039  break;
1040  }
1041 
1042  /* Check if the colors are available */
1043  if ( i < levels )
1044  {
1045  /* Free the colors already obtained */
1046  for ( i--; i >= 0; i-- )
1047  XFreeColors( &colmap[i].pixel, 1, 0 );
1048  continue;
1049  }
1050  break; /* succeeded */
1051  }
1052  if ( levels < 2 )
1053  bwflag = 2; /* use 1 bit dithering */
1054  else
1055  levelsc = levels; /* remember full range */
1056  }
1057 
1058  /* If b&w 1-bit display, just use two colors */
1059  if ( bwflag == 2 )
1060  {
1061  /* All we care about, really, is the magic square */
1062  make_square( 255.0, divN, modN, dm16 );
1063  levels = levelsc = 2;
1064  }
1065 
1066 #ifdef DEBUG
1067  printf( "Magic square for %d levels:\n", levels );
1068  for ( i = 0; i < 16; i++ )
1069  {
1070  for ( j = 0; j < 16; j++ )
1071  printf( "%4d", dm16[i][j] );
1072  printf( "\n" );
1073  }
1074  printf( "divN array:\n" );
1075  for ( i = 0; i < 256; i++ )
1076  printf( "%4d%s", divN[i], i % 16 == 15 ? "\n" : "" );
1077  printf( "modN array:\n" );
1078  for ( i = 0; i < 256; i++ )
1079  printf( "%4d%s", modN[i], i % 16 == 15 ? "\n" : "" );
1080 #endif
1081 }
1082 
1083 /*****************************************************************
1084  * TAG( load_x_map )
1085  *
1086  * Loads the color map from the input RLE file directly into X window
1087  * system.
1088  * Inputs:
1089  * in_cmap: Global variable containing gamma corrected color
1090  * map from input file.
1091  * Outputs:
1092  * Loads color map (further gamma corrected for display) into
1093  * display. If not enough display map entries are available,
1094  * prints a message and exits the program.
1095  * Assumptions:
1096  * [None]
1097  * Algorithm:
1098  * [None]
1099  */
1100 load_x_map()
1101 {
1102  int nmap = 0, i, j;
1103  char * mapcom;
1104  int gammamap[256];
1105 
1106  if ( (mapcom = rle_getcom( "color_map_length", &hdr )) )
1107  nmap = atoi( mapcom );
1108  if ( nmap == 0 )
1109  nmap = 1 << hdr.cmaplen;
1110 
1111  /* We won't be using in_cmap, so gamma correct it in place */
1112  for ( i = 0; i < 256; i++ )
1113  gammamap[i] = (int)(0.5 + 255 * pow( i / 255.0, 1.0/disp_gam ));
1114 
1115  for ( i = 0; i < nmap; i++ )
1116  for ( j = 0; j < 3; j++ )
1117  in_cmap[j][i] = gammamap[in_cmap[j][i]];
1118 
1119  /*
1120  * Set up the color map entries. We don't yet know the location
1121  * in the map at which each will reside, so init it to 0.
1122  */
1123  for(i = 0; i < nmap; i++) {
1124  colmap[i].pixel = 0;
1125  colmap[i].red = in_cmap[0][i] << 8;
1126  colmap[i].green = in_cmap[1][i] << 8;
1127  colmap[i].blue = in_cmap[2][i] << 8;
1128  if ( XGetHardwareColor( &colmap[i] ) == 0 )
1129  {
1130  fprintf( stderr,
1131  "%s: Sorry, need at least %d color map entries, only got %d.\n\
1132 Will display image anyway.\n",
1133  hdr.cmd, nmap, i );
1134  break;
1135  }
1136  }
1137  for ( ; i < 256; i++ )
1138  colmap[i].pixel = 0; /* for "undefined" colors */
1139 }
1140 
1141 resize_zoom_window()
1142 {
1143  WindowInfo info;
1144  int xs, ys;
1145 
1146  XQueryWindow( zoomwin, &info );
1147 
1148  /* truncate to multiple of zoomfact */
1149  xs = zoomfact * ( info.width / zoomfact );
1150  ys = zoomfact * ( info.height / zoomfact );
1151 
1152  if ( xs != info.width || ys != info.height )
1153  XChangeWindow( zoomwin, xs, ys );
1154 
1155  zoom_x_dim = xs / zoomfact;
1156  zoom_y_dim = ys / zoomfact;
1157 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
int usemap
Definition: getx10.c:90
rle_hdr hdr
Definition: getx10.c:84
#define arrow_x_hot
Definition: getx10.c:48
int zoom_y_dim
Definition: getx10.c:99
int xmin
Definition: rle.h:100
void map_scanline(rgb, int n, int y,*line)
Definition: to8.c:239
int iconrow
Definition: getx10.c:96
Cursor arrow_curs
Definition: getx10.c:62
int modN[256]
Definition: to8.c:45
void make_square(double N, divN, modN, magic)
Definition: dither.c:192
int forkflg
Definition: getx10.c:91
void rle_debug(int on_off)
Definition: rle_getrow.c:293
int iconbyte
Definition: getx10.c:96
int iconscan
Definition: getx10.c:96
char buffer[4096]
Definition: rlesetbg.c:35
int levels
Definition: getx10.c:79
Display * dpy
Definition: getx10.c:94
void main(int argc, char **argv)
Definition: aliastorle.c:121
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int divN[256]
Definition: to8.c:45
int ymin
Definition: rle.h:100
rle_pixel ** in_cmap
Definition: to8.c:40
#define MAXSEND
Definition: getx10.c:38
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
int iconfact
Definition: getx10.c:96
void dithermap(int levels, double gamma, rgbmap, divN, modN, magic)
Definition: dither.c:80
void init_color(register image_information *img)
int dm16[16][16]
Definition: to8.c:42
rle_pixel ** buildmap(rle_hdr *the_hdr, int minmap, double orig_gamma, double new_gamma)
Definition: buildmap.c:56
const char * cmd
Definition: rle.h:133
double disp_gam
Definition: to8.c:47
int xmax
Definition: rle.h:100
int nrow
Definition: getx10.c:101
int zoomflg
Definition: getx10.c:92
int nscan
Definition: getx10.c:101
#define arrow_y_hot
Definition: getx10.c:49
int zoom_x_dim
Definition: getx10.c:98
int iflag
Definition: getsun.c:80
int zoom_x_center
Definition: getx10.c:100
Window fbwin
Definition: getx10.c:95
void rle_get_setup_ok(rle_hdr *the_hdr, const char *prog_name, const char *file_name)
Definition: rle_getrow.c:254
int zoomfact
Definition: getx10.c:97
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
int setbg
Definition: getx10.c:88
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
#define arrow_height
Definition: getx10.c:47
#define arrow_width
Definition: getx10.c:46
int ymax
Definition: rle.h:100
int levelsq
Definition: getx10.c:79
unsigned char rle_pixel
Definition: rle.h:56
int bwflag
Definition: getx10.c:71
int mapflg
Definition: getx10.c:89
double img_gam
Definition: to8.c:48
int cmaplen
Definition: rle.h:100
int levelsc
Definition: getx10.c:79
int nbyte
Definition: getx10.c:102
static short arrow_bits[]
Definition: getx10.c:50
int gammamap[256]
Definition: getx10.c:68
#define RLE_ALPHA
Definition: rle.h:65
void map_rgb_to_bw(image_information *img, rle_pixel **rows, register rle_pixel *bw_row)
unsigned char * iconbuf
Definition: getx10.c:106
int dbg
Definition: getx10.c:104
#define DMAP(v, x, y)
Definition: get_orion.c:310
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
static short arrow_mask_bits[]
Definition: getx10.c:57
static char rcs_ident[]
Definition: getx10.c:29
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
void bwdithermap(int levels, double gamma, bwmap, divN, modN, magic)
Definition: dither.c:142
int zoom_y_center
Definition: getx10.c:100