Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
get4d.c
Go to the documentation of this file.
1 /*
2  * get4d.c - Put RLE images on the Iris/4D display under the window manager.
3  *
4  * Author: Russell D. Fish (Based on getmex.c .)
5  * Computer Science Dept.
6  * University of Utah
7  * Date: Thu May 26 20:49:11 1988
8  * Copyright (c) 1988, University of Utah
9  *
10  */
11 /* modified for Personal Iris with only 8 bit planes (no RGB mode)
12  * as well as the other Iris displays.
13  * Michael Hart - September 1991
14  * forced limitations - B&W display only, -G option forced
15  */
16 
17 #include <stdio.h>
18 #include <math.h>
19 #include "gl.h"
20 #include "device.h"
21 #include "rle.h"
22 
23 #define MAX(i,j) ( (i) > (j) ? (i) : (j) )
24 #define MIN(i,j) ( (i) < (j) ? (i) : (j) )
25 
26 /* Global variables. */
27 long window_number; /* Window number from MAX. */
28 int x_size, y_size; /* Size of image. */
29 int i; /* General loop counter */
30 int dbg = 0; /* Set if debug mode. */
31 int forkflg = 0; /* Set if not to run in background. */
32 int bwflag = 0; /* Set for greyscale output. */
33 int NoBorder = 0; /* Turn off border */
34 int gt; /* Whether we're using GT fast rectangle drawing. */
35 double disp_gamma = 1.0; /* Gamma of Iris display. */
36 double img_gamma = 0.0; /* Gamma of input image. */
37 short colmap[128][3]; /* Area to hold the old colormap */
38 long bitsavail; /* 0 if not enough for RGB mode */
39 
40 /* Window preferences. */
42 
43 unsigned long *rect_image; /* GT Image data buffer pointer. */
44 unsigned char *rgb_image; /* Non-GT Image data buffer pointer. */
45 
46 rle_hdr hdr;
48 
49 /*****************************************************************
50  * TAG( main )
51  *
52  * Usage:
53  * get4d [-G][-S] [-p xpos ypos] [-f] [-D] [-w] [file]
54  * Inputs:
55  * -D: Debug mode: print input file as read.
56  * -f: Don't fork after putting image on screen.
57  * -G: GT mode: single fast rectangle, panning disabled.
58  * (GT mode is the default on GT, GTX, and Personal Iris 4Ds.)
59  * -S: Slow mode: Allows resizing the window, and panning with the
60  * mouse. (Slow mode is the default on non-GT 4Ds.)
61  * -g disp_gamma: Gamma of the output display.
62  * -i image_gamma: Gamma the image was calculated for.
63  * -I image_gamma: Gamma of the image pixels (1.0 / (-i gamma)).
64  * -n: No border will be drawn.
65  * -p xpos ypos: Position of the lower left corner of the window.
66  * -s xsize ysize: Initial size of the window (slow mode only.)
67  *
68  * -w: Black & white: reduce color images to B&W before display.
69  * Advantage is that smoother shading can be achieved.
70  *
71  * file: Input Run Length Encoded file. Uses stdin if not
72  * specified.
73  * Outputs:
74  * Puts image in a window on the screen.
75  * Assumptions:
76  * Input file is in RLE format.
77  */
78 
79 main(argc, argv)
80 char **argv;
81 {
82  char *infname = NULL;
83  FILE * infile = stdin;
84  char vbuff[50];
85  char *var;
86  int gtflag = 0, slowflag = 0, gflag = 0, iflag = 0;
87 
88  hdr = *rle_hdr_init( (rle_hdr *)NULL );
89  rle_names( &hdr, cmd_name( argv ), NULL, 0 );
90 
91  /* Handle arguments. */
92  if ( scanargs( argc, argv,
93  "% D%- f%- GS%- g%-disp_gamma!F iI%-image_gamma!F n%- \n\
94  p%-xpos!dypos!d s%-xsize!dysize!d w%- file%s",
95  &dbg, &forkflg,
96  &gtflag,
97  &gflag, &disp_gamma,
98  &iflag, &img_gamma,
99  &NoBorder,
102  &bwflag,
103  &infname ) == 0 )
104  exit( 1 );
105 
106  if ( gtflag ) /* Mode args override if specified. */
107  gt = gtflag - 1; /* -G->2 means yes GT, -S->1 means no GT. */
108  else
109  {
110 #ifndef _IBMR2
111  /* See if we`re on a GT. For this purpose, a Personal Iris is a GT. */
112  gversion( vbuff ); /* String like "GL4DGTX-3.1". */
113  gt = strncmp( vbuff+4, "GT", 2 ) == 0 ||
114  strncmp( vbuff+4, "PI", 2 ) == 0;
115 #else
116  gt = 1;
117 #endif
118  }
119 
120  /* Diddle with gammas. */
121  if ( iflag == 2 ) /* -i flag. */
122  if ( img_gamma != 0.0 ) /* Paranoid. */
123  img_gamma = 1.0 / img_gamma;
124 
125 #ifndef _IBMR2
126  /* Look at home for .gamma file. */
127  if ( !gflag )
128  {
129  char *var = getenv( "HOME" );
130  char buf[BUFSIZ];
131  FILE *gamfile;
132  float flt_gam = 0; /* Just in case of 68000 iris botch. */
133 
134  if ( var != NULL && *var != '\0' )
135  {
136  sprintf( buf, "%s/.gamma", var );
137  if ( (gamfile = fopen( buf, "r" )) != NULL )
138  {
139  fscanf( gamfile, "%f", &flt_gam );
140  if ( flt_gam != 0 )
141  disp_gamma = 2.4/flt_gam;/* SGI displays have gamma 2.4. */
142  fclose( gamfile );
143  }
144  }
145  }
146 #endif
147  /* check machine graphics capability */
148  bitsavail = getgdesc(GD_BITS_NORM_SNG_GREEN); /* Can it support RGB mode */
149  if(bitsavail==0)
150  {
151  /* set configuration to force reading in B&W and -G ode disp */
152  bwflag = 1;
153  gt = 1;
154  }
155  infile = rle_open_f(hdr.cmd, infname, "r");
156  get_pic( infile, infname ); /* Read image and make a window for it. */
157  if(bitsavail==0) /* modify gey levels if necessary */
158  convertgreylevels();
159  update_pic(); /* Keep drawing the window. */
160 }
161 
162 /*
163  * Read an image from the input file and display it.
164  */
165 get_pic( infile, infname )
166 FILE * infile;
167 char * infname;
168 {
169  register int i, y;
170  int ncolors;
171  unsigned char *scan[3];
172 
173  /*
174  * Read setup info from file.
175  */
177  rle_names( &hdr, hdr.cmd, infile, 0 );
178  hdr.rle_file = infile;
179  if ( rle_get_setup( &hdr ) < 0 )
180  {
181  fprintf(stderr, "%s: Error reading setup information from %s\n",
182  hdr.cmd, infname ? infname : "stdin");
183  exit(1);
184  }
185 
186  if ( dbg )
187  rle_debug( 1 );
188 
189  /* We`re only interested in R, G, & B */
191  for (i = 3; i < hdr.ncolors; i++)
192  RLE_CLR_BIT(hdr, i);
193  ncolors = hdr.ncolors > 3 ? 3 : hdr.ncolors;
194 
195  /* Do nicer b&w rendering if only one color channel in input. */
196  if ( ncolors == 1 && hdr.ncmap <= 1 )
197  bwflag = 1;
198 
199  /*
200  * Compute image size and allocate storage for colormapped image.
201  */
202  x_size = (hdr.xmax - hdr.xmin + 1);
203  y_size = (hdr.ymax - hdr.ymin + 1);
204  if ( gt )
205  rect_image = (unsigned long *) malloc(x_size * y_size * sizeof( long ));
206  else
207  rgb_image = (unsigned char *) malloc(x_size * y_size * 3 * sizeof( char ));
208 
209  /*
210  * Set up for rle_getrow. Pretend image x origin is 0.
211  */
212  for (i = 0; i < 3; i++)
213  scan[i] = (unsigned char *) malloc(x_size);
214  hdr.xmax -= hdr.xmin;
215  hdr.xmin = 0;
216 
218 
219  /* For each scan line, pack RGBs into the image memory. */
220  while ((y = rle_getrow(&hdr, scan)) <= hdr.ymax)
221  {
222  switch ( ncolors )
223  {
224  case 1:
225  /* Colormapped image */
226  for (i = 0; i < x_size; i++) {
227  scan[2][i] = cmap[2][scan[0][i]];
228  scan[1][i] = cmap[1][scan[0][i]];
229  scan[0][i] = cmap[0][scan[0][i]];
230  }
231  break;
232 
233  case 2:
234  /* Weird image. */
235  for (i = 0; i < x_size; i++) {
236  scan[2][i] = cmap[2][scan[1][i]];
237  scan[1][i] = cmap[1][scan[1][i]];
238  scan[0][i] = cmap[0][scan[0][i]];
239  }
240  break;
241  case 3:
242  /* Normal image. */
243  for (i = 0; i < x_size; i++) {
244  scan[2][i] = cmap[2][scan[2][i]];
245  scan[1][i] = cmap[1][scan[1][i]];
246  scan[0][i] = cmap[0][scan[0][i]];
247  }
248  break;
249  }
250  if ( bwflag )
251  {
252  if (ncolors == 1)
253  rgb_to_bw (scan[0], scan[1], scan[2], scan[0], x_size );
254  else
255  rgb_to_bw( scan[0], scan[1], scan[ncolors - 1],
256  scan[0], x_size );
257  /* Note: pack_scanline only uses channel 0 for B&W */
258  }
259 
260  if ( gt )
261  pack_rect_scanline( scan, x_size,
262  &rect_image[(y - hdr.ymin) * x_size] );
263  else
264  pack_rgb_scanline( scan, x_size,
265  &rgb_image[(y - hdr.ymin) * x_size * 3] );
266  }
267 
268  /*
269  * Free temp storage
270  */
271  for (i = 0; i < 3; i++)
272  free(scan[i]);
273 
274  /* Size flag can cut down the window size, except in GT rectangle mode. */
275  w_xsize = sizeflag && !gt ? MIN( w_xsize, x_size ) : x_size;
276  w_ysize = sizeflag && !gt ? MIN( w_ysize, y_size ) : y_size;
277 
278  /* Window should be completely on the screen in GT rectangle mode. */
279  if ( posflag && gt )
280  {
281  w_xpos = MIN( w_xpos, XMAXSCREEN - w_xsize );
282  w_ypos = MIN( w_ypos, YMAXSCREEN - w_ysize);
283  }
284 
285  w_xpos = MAX( 0, w_xpos ); /* Be positive. */
286  w_ypos = MAX( 0, w_ypos );
287 
288  /* Register our preferences for the window size and location. */
289  if ( posflag )
290  prefposition( w_xpos, w_xpos + w_xsize - 1,
291  w_ypos, w_ypos + w_ysize - 1 );
292  else if ( sizeflag || gt )
293  /* Have to keep the window full size to use the fast pixel commands. */
294  prefsize( w_xsize, w_ysize );
295  else
296  maxsize( x_size, y_size );
297 
298  /*
299  * Get a window of the right size (user positions it with the mouse).
300  */
301 #ifndef _IBMR2
302  if ( forkflg ) foreground(); /* Don`t fork. */
303 #endif
304  if ( NoBorder ) noborder();
305  window_number = winopen( hdr.cmd );
306  if ( infname ) wintitle( infname );
307 
308  /* Loosen the constraints once the window is created. */
309  if ( !gt )
310  maxsize( x_size, y_size );
311  winconstraints();
312 
313  if(bitsavail==0)
314  { /* only color map available so make a grey scale */
315  for(i=0;i<=127;i++)
316  {
317  getmcolor((i+128),&colmap[i][0],&colmap[i][1],&colmap[i][2]);
318  mapcolor((i+128),(i*2),(i*2),(i*2));
319  }
320  }
321  else /* do the normal thing */
322  RGBmode();
323  gconfig();
324 
325  qdevice( ESCKEY );
326  qdevice ( WINQUIT );
327  qdevice( REDRAW );
328  unqdevice( INPUTCHANGE ); /* We don`t pay attention to these. */
329 
330  if ( !gt ) /* Disable panning when in gt rectangle mode. */
331  {
332  qdevice( LEFTMOUSE ); /* Pan the image under mouse control. */
333  qdevice( LEFTALTKEY ); /* Reset panning. */
334  qdevice( RIGHTALTKEY );
335  qdevice( F9KEY );
336  }
337 
338  /* There was a redraw event sent when the window was created,
339  * but we weren`t listening for them yet.
340  */
341  qenter( REDRAW, window_number );
342 }
343 
344 /*
345  * Track events & redraw image when necessary.
346  */
347 update_pic()
348 {
349  short data;
350  long event;
351  long window_x_size, window_y_size, window_x_origin, window_y_origin;
352  int x_min, x_max, y_min, y_max, x_start, y_start, x_end, y_end, x_len;
353  long x_origin, y_origin, new_x_center, new_y_center;
354  int x_center, y_center, saved_x_center, saved_y_center;
355 
356  register int y;
357  register unsigned char *y_ptr;
358 
359  /* Looking at the center, at first. */
360  x_center = saved_x_center = x_size / 2;
361  y_center = saved_y_center = y_size / 2;
362 
363  /* Redraw the window when necessary. */
364  while ( TRUE )
365  {
366  event = qread( &data );
367 # ifdef DEBUG
368  printf( "event %d, data %d\n", event, data );
369 #endif
370  switch ( event )
371  {
372  case ESCKEY:
373  case WINQUIT:
374  if(bitsavail==0) /* restore colormap */
375  for(i=0;i<=127;i++)
376  mapcolor((i+128),colmap[i][0],colmap[i][1],colmap[i][2]);
377  gexit();
378  exit(0);
379  break;
380  case REDRAW:
381  winset( window_number );
382  reshapeviewport();
383 
384  if ( gt )
385  {
386  /* On a GT, just blast out the whole rectangle. If the
387  * origin is off the screen to the left, it kills the
388  * window server. Could duplicate the slow output logic
389  * below, but avoid the complication for now...
390  */
391  getorigin( &x_origin, &y_origin );
392  if ( x_origin < 0 )
393  {
394  RGBcolor( 128, 128, 128 ); /* Punt. */
395  clear();
396  }
397  else
398  lrectwrite( 0, 0, x_size-1, y_size-1, rect_image );
399  }
400  else
401  {
402  /* Do panning in a resizable window. (Slow mode.) */
403  RGBcolor( 128, 128, 128 );
404  clear();
405 
406  /* Lower left corner of screen, in image coordinates.
407  * (Keep the center of the image in the center of the
408  * window.)
409  */
410  getsize( &window_x_size, &window_y_size );
411  x_min = x_center - window_x_size/2;
412  x_max = x_min + (window_x_size-1);
413  y_min = y_center - window_y_size/2;
414  y_max = y_min + (window_y_size-1);
415 
416  /* Coordinate bounds have half a pixel added all around. */
417  ortho2( x_min - .5, x_max + .5, y_min - .5, y_max + .5 );
418 
419  /* Draw just the part of the image in the window. */
420  x_start = MAX( x_min, 0 );
421  y_start = MAX( y_min, 0 );
422  x_end = MIN( x_max, x_size-1 );
423  y_end = MIN( y_max, y_size-1 );
424  x_len = x_end - x_start + 1;
425 
426  /* Dump the scanlines. Check once in a while for another
427  * redraw event queued up, and quit early if one is seen.
428  */
429  y_ptr = rgb_image + y_start*x_size*3 + x_start;
430  for ( y = y_start;
431  y <= y_end && (y%16 != 0 || qtest() != REDRAW);
432  y++, y_ptr += x_size * 3 )
433  {
434  cmov2i( x_start, y );
435  writeRGB( x_len,
436  y_ptr, y_ptr + x_size, y_ptr + x_size * 2 );
437  }
438  }
439  break;
440 
441  /* Alt key - Reset viewing to look at the center of the image.
442  * Shift-Alt - Restores a saved view center.
443  * Control-alt - Saves the current view center for Shift-Setup.
444  * F9 is the same as the Alt keys.
445  */
446  case LEFTALTKEY:
447  case RIGHTALTKEY:
448  case F9KEY:
449  if ( data == 1 ) /* Ignore button up events. */
450  {
451  if ( getbutton(RIGHTSHIFTKEY) || getbutton(LEFTSHIFTKEY) )
452  {
453  x_center = saved_x_center; /* Restore. */
454  y_center = saved_y_center;
455  qenter( REDRAW, window_number );
456  }
457  else if ( getbutton(CTRLKEY) )
458  {
459  saved_x_center = x_center; /* Save. */
460  saved_y_center = y_center;
461  }
462  else
463  {
464  x_center = x_size / 2; /* Reset. */
465  y_center = y_size / 2;
466  qenter( REDRAW, window_number );
467  }
468 
469  }
470  break;
471 
472  /* Pan a point picked with the left mouse button to the center
473  * of attention. Beep if cursor is not on the image.
474  */
475  case LEFTMOUSE:
476  if ( data == 1 ) /* Ignore button up events. */
477  {
478  getorigin( &x_origin, &y_origin );
479  new_x_center = getvaluator( MOUSEX ) - x_origin + x_min;
480  new_y_center = getvaluator( MOUSEY ) - y_origin + y_min;
481  if ( new_x_center >= x_start &&
482  new_x_center <= x_end &&
483  new_y_center >= y_start &&
484  new_y_center <= y_end )
485  {
486  x_center = new_x_center;
487  y_center = new_y_center;
488  qenter( REDRAW, window_number );
489  }
490  else
491  ringbell();
492  }
493  break;
494  }
495  }
496 }
497 
498 /*
499  * Pack a scanline into a vector of RGB longs.
500  *
501  * Inputs:
502  * rgb: Pointers to buffers containing the red, green,
503  * and blue color rows.
504  * n: Length of row.
505  * line: Pointer to output buffer for packed color data.
506  */
507 pack_rect_scanline( rgb, n, line )
508 unsigned char *rgb[3];
509 int n;
510 long *line;
511 {
512  register int i;
513  register long *dest = line;
514 
515  if ( !bwflag ) /* Color display. */
516  {
517  register unsigned char *r, *g, *b;
518 
519  for ( i = 0, r = rgb[0], g = rgb[1], b = rgb[2];
520  i < n; i++, r++, g++, b++ )
521  /* Combine 3 8-bit colors into a long. */
522  *dest++ = *r + (*g<<8) + (*b<<16);
523  }
524  else /* Gray scale display. */
525  {
526  register unsigned char *bw;
527 
528  for ( i = 0, bw = rgb[0]; i < n; i++, bw++ )
529  *dest++ = *bw + (*bw<<8) + (*bw<<16);
530  }
531 }
532 
533 /*
534  * Pack a scanline into an RGB trio of vectors of bytes.
535  *
536  * Inputs:
537  * rgb: Pointers to buffers containing the red, green,
538  * and blue color rows.
539  * n: Length of row.
540  * line: Pointer to output buffer for packed color data.
541  */
542 pack_rgb_scanline( rgb, n, lines )
543 unsigned char *rgb[3];
544 int n;
545 unsigned char *lines;
546 {
547  int chnl;
548  register int i;
549  register unsigned char *src, *dest;
550 
551  for ( chnl = 0, dest = lines; chnl < 3; chnl++ )
552  {
553  src = rgb[ bwflag ? 0 : chnl ]; /* Use just channel 0 for greyscale. */
554  for ( i = 0; i < n; i++ )
555  *dest++ = *src++;
556  }
557 }
558 
559 /*
560  * This routine is called only if the color map is required. It converts
561  * the 8 bit grey scale levels to 7 bit grey scale levels starting at 128
562  * and going through to 255. We can't use the full 256 grey levels to
563  * display the image because the windows and text of other applications
564  * can't be seen if they are remapped to a grey scale.
565  */
566 convertgreylevels(void)
567 {
568  for(i=0;i<(x_size*y_size);i++)
569  (*(rect_image+i)) = (((*(rect_image+i))&255)>>1)|128;
570 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
#define MIN(x, y)
Definition: rletopaint.c:53
rle_hdr hdr
Definition: getx10.c:84
int w_ysize
Definition: get4d.c:41
int xmin
Definition: rle.h:100
int w_xsize
Definition: get4d.c:41
int forkflg
Definition: getx10.c:91
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
int w_xpos
Definition: get4d.c:41
void rle_debug(int on_off)
Definition: rle_getrow.c:293
char * cmd_name(char **argv)
Definition: cmd_name.c:31
void main(int argc, char **argv)
Definition: aliastorle.c:121
int rle_get_setup(rle_hdr *the_hdr)
Definition: rle_getrow.c:74
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int sizeflag
Definition: get4d.c:41
int i
Definition: get4d.c:29
int ymin
Definition: rle.h:100
void rgb_to_bw(rle_pixel *red_row, rle_pixel *green_row, rle_pixel *blue_row, rle_pixel *bw_row, int rowlen)
Definition: rle_putrow.c:680
int w_ypos
Definition: get4d.c:41
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
double img_gamma
Definition: get4d.c:36
int y_size
Definition: getmex.c:25
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
int xmax
Definition: rle.h:100
int posflag
Definition: get4d.c:41
double disp_gamma
Definition: get4d.c:35
unsigned long * rect_image
Definition: get4d.c:43
int gt
Definition: get4d.c:34
#define MAX(i, j)
Definition: get4d.c:23
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
long window_number
Definition: getmex.c:24
int colmap[216][3]
Definition: to8.c:39
int ncmap
Definition: rle.h:100
int ymax
Definition: rle.h:100
long bitsavail
Definition: get4d.c:38
unsigned char rle_pixel
Definition: rle.h:56
int bwflag
Definition: getx10.c:71
int x_size
Definition: getmex.c:25
#define RLE_ALPHA
Definition: rle.h:65
int dbg
Definition: getx10.c:104
int NoBorder
Definition: get4d.c:33
rle_pixel ** cmap
Definition: get4d.c:47
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
unsigned char * rgb_image
Definition: get4d.c:44
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100