Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
getmex.c
Go to the documentation of this file.
1 /*
2  * getmex.c - Put RLE images on the Iris display under the window manager.
3  *
4  * Author: Russell D. Fish (Based on getX.c .)
5  * Computer Science Dept.
6  * University of Utah
7  * Date: Wed Nov 19 1986
8  * Copyright (c) 1986, University of Utah
9  *
10  */
11 
12 #include <stdio.h>
13 #include <math.h>
14 #include "gl.h"
15 #include "device.h"
16 #include "rle.h"
17 
18 #define MAX(i,j) ( (i) > (j) ? (i) : (j) )
19 #define MIN(i,j) ( (i) < (j) ? (i) : (j) )
20 
21 /* Global variables. */
22 Colorindex color_start = 512; /* Default color map start of 3/3/3 rgb cube. */
23 Colorindex bw_start = 128; /* Default color map start of 128 slot grey ramp. */
24 long window_number; /* Window number from MEX. */
25 int x_size, y_size; /* Size of image. */
26 int dbg = 0; /* Set if debug mode. */
27 int forkflg = 0; /* Set if not to run in background. */
28 int bwflag = 0; /* Set for greyscale output. */
29 Colorindex *image; /* Image data buffer pointer. */
30 
31 #define levels 8 /* Compute 3 bits per channel. */
32 int modN[256], divN[256]; /* Speed up with precomputed lookup tables. */
33 
34 int dm16[16][16]; /* 16x16 magic square, filled in by init_dither. */
35 
36 
37 /*****************************************************************
38  * TAG( main )
39  *
40  * Usage:
41  * getmex [-f] [-D] [-w] [file]
42  * Inputs:
43  * -f: Don't fork after putting image on screen.
44  * -D: Debug mode: print input file as read.
45  * -w: Black & white: reduce color images to B&W before display.
46  * Advantage is that smoother shading can be achieved.
47  * -m mapstart Where to start using the color map. 128 colors are
48  * used for B&W images, starting at 128 by default unless
49  * overridden by this flag. 512 colors are used for color images,
50  * starting at color map location 512.
51  * file: Input Run Length Encoded file. Uses stdin if not
52  * specified.
53  * Outputs:
54  * Puts image in a window on the screen.
55  * Assumptions:
56  * Input file is in RLE format.
57  */
58 
59 main(argc, argv)
60 char **argv;
61 {
62  int mapstart, mapflag = 0;
63  char *infname = NULL;
64  FILE * infile = stdin;
65 
66  /* Handle arguments. */
67  if ( scanargs( argc, argv, "% f%- w%- D%- m%-mapstart!d file%s\n(\
68 \tDisplay a URT image dithered in the window system.\n\
69 \t-f\tKeep program in foreground\n\
70 \t-w\tDisplay in black and white instead of color.\n\
71 \t-m\tStarting point in colormap (uses 512 entries for color).\n\
72 \tLeft mouse pans image, setup key recenters.)",
73  &forkflg, &bwflag, &dbg, &mapflag, &mapstart, &infname ) == 0 )
74  exit( 1 );
75  if ( mapflag )
76  if ( bwflag ) bw_start = mapstart; else color_start = mapstart;
77  infile = rle_open_f(cmd_name(argv), infname, "r");
78 
79  init_dither(); /* Set up the dither matrices. */
80  /* Read image and make a window for it. */
81  get_pic( infile, infname, cmd_name(argv) );
82  update_pic(); /* Keep drawing the window. */
83 }
84 
85 /*
86  * Read an image from the input file and display it.
87  */
88 get_pic( infile, infname, cmdname )
89 FILE * infile;
90 char * infname, cmdname;
91 {
92  register int i, y;
93  int ncolors;
94  unsigned char *scan[3];
95  rle_hdr hdr;
96 
97  /*
98  * Read setup info from file.
99  */
100  hdr = *rle_hdr_init( (rle_hdr *)NULL );
101  rle_names( &hdr, cmdname, infname, 0 );
102  hdr.rle_file = infile;
103  rle_get_setup_ok( &hdr, NULL, NULL );
104 
105  if ( dbg )
106  rle_debug( 1 );
107 
108  /* We`re only interested in R, G, & B */
109  RLE_CLR_BIT(hdr, RLE_ALPHA);
110  for (i = 3; i < hdr.ncolors; i++)
111  RLE_CLR_BIT(hdr, i);
112  ncolors = hdr.ncolors > 3 ? 3 : hdr.ncolors;
113  if ( ncolors == 1 ) bwflag = TRUE;
114 
115  /*
116  * Compute image size and allocate storage for colormapped image.
117  */
118  x_size = (hdr.xmax - hdr.xmin + 1);
119  y_size = (hdr.ymax - hdr.ymin + 1);
120  image = (Colorindex *) malloc(x_size * y_size * sizeof( Colorindex ));
121 
122  /*
123  * Set up for rle_getrow. Pretend image x origin is 0.
124  */
125  for (i = 0; i < 3; i++)
126  scan[i] = (unsigned char *) malloc(x_size);
127  hdr.xmax -= hdr.xmin;
128  hdr.xmin = 0;
129 
130  /* For each scan line, dither it into the image memory. */
131  while ((y = rle_getrow(&hdr, scan)) <= hdr.ymax)
132  {
133  if ( bwflag && ncolors > 1 )
134  {
135  rgb_to_bw( scan[0], scan[1], scan[ncolors - 1], scan[0], x_size );
136  /* Note: map_scanline only uses channel 0 for B&W */
137  }
138 
139  map_scanline( scan, x_size, y,
140  &image[(y - hdr.ymin) * x_size] );
141  }
142 
143  /*
144  * Free temp storage
145  */
146  for (i = 0; i < 3; i++)
147  free(scan[i]);
148 
149  /*
150  * Get a window of the right size (user positions it with the mouse).
151  */
152  if ( forkflg ) foreground(); /* Don`t fork. */
153  maxsize( x_size, y_size );
154  window_number = winopen( "getmex" );
155  if ( infname ) wintitle( infname );
156 
157  makemap(); /* Initialize the Iris color map. */
158 
159  qdevice( REDRAW );
160  qdevice( LEFTMOUSE ); /* Pan the image under mouse control. */
161  qdevice( SETUPKEY ); /* Reset panning. */
162  unqdevice( INPUTCHANGE ); /* We don`t pay attention to these. */
163 
164  /* There was a redraw event sent when the window was created,
165  * but we weren`t listening for them yet.
166  */
167  qenter( REDRAW, window_number );
168 }
169 
170 /*
171  * Track events & redraw image when necessary.
172  */
173 update_pic()
174 {
175  short data;
176  long event;
177  int window_x_size, window_y_size, window_x_origin, window_y_origin;
178  int x_min, x_max, y_min, y_max, x_start, y_start, x_end, y_end, x_len;
179  int x_origin, y_origin, new_x_center, new_y_center;
180  int x_center, y_center, saved_x_center, saved_y_center;
181 
182  register int y;
183  register Colorindex *y_ptr;
184 
185  /* Looking at the center, at first. */
186  x_center = saved_x_center = x_size / 2;
187  y_center = saved_y_center = y_size / 2;
188 
189  /* Redraw the window when necessary. */
190  while ( TRUE )
191  {
192  event = qread( &data );
193 # ifdef DEBUG
194  printf( "event %d, data %d\n", event, data );
195 #endif
196  switch ( event )
197  {
198  case REDRAW:
199  winset( window_number );
200  reshapeviewport();
201  color( 22 );
202  clear();
203 
204  /* Lower left corner of screen, in image coordinates.
205  * (Keep the center of the image in the center of the window.)
206  */
207  getsize( &window_x_size, &window_y_size );
208  x_min = x_center - window_x_size/2;
209  x_max = x_min + (window_x_size-1);
210  y_min = y_center - window_y_size/2;
211  y_max = y_min + (window_y_size-1);
212 
213  /* Coordinate bounds have half a pixel added all around. */
214  ortho2( x_min - .5, x_max + .5, y_min - .5, y_max + .5 );
215 
216  /* Draw just the part of the image in the window. */
217  x_start = MAX( x_min, 0 );
218  y_start = MAX( y_min, 0 );
219  x_end = MIN( x_max, x_size-1 );
220  y_end = MIN( y_max, y_size-1 );
221  x_len = x_end - x_start + 1;
222 
223  /* Dump the scanlines. Check once in a while for another
224  * redraw event queued up, and quit early if one is seen.
225  */
226  for ( y = y_start, y_ptr = image + y_start*x_size + x_start;
227  y <= y_end && (y%16 != 0 || qtest() != REDRAW);
228  y++, y_ptr += x_size )
229  {
230  cmov2i( x_start, y );
231  writepixels( x_len, y_ptr );
232  }
233  break;
234 
235  /* Setup key - Reset viewing to look at the center of the image.
236  * Shift-Setup - Restores a saved view center.
237  * Control-Setup - Saves the current view center for Shift-Setup.
238  */
239  case SETUPKEY:
240  if ( data == 1 ) /* Ignore button up events. */
241  {
242  if ( getbutton(RIGHTSHIFTKEY) || getbutton(LEFTSHIFTKEY) )
243  {
244  x_center = saved_x_center; /* Restore. */
245  y_center = saved_y_center;
246  qenter( REDRAW, window_number );
247  }
248  else if ( getbutton(CTRLKEY) )
249  {
250  saved_x_center = x_center; /* Save. */
251  saved_y_center = y_center;
252  }
253  else
254  {
255  x_center = x_size / 2; /* Reset. */
256  y_center = y_size / 2;
257  qenter( REDRAW, window_number );
258  }
259 
260  }
261  break;
262 
263  /* Pan a point picked with the left mouse button to the center
264  * of attention. Beep if cursor is not on the image.
265  */
266  case LEFTMOUSE:
267  if ( data == 1 ) /* Ignore button up events. */
268  {
269  getorigin( &x_origin, &y_origin );
270  new_x_center = getvaluator( MOUSEX ) - x_origin + x_min;
271  new_y_center = getvaluator( MOUSEY ) - y_origin + y_min;
272  if ( new_x_center >= x_start &&
273  new_x_center <= x_end &&
274  new_y_center >= y_start &&
275  new_y_center <= y_end )
276  {
277  x_center = new_x_center;
278  y_center = new_y_center;
279  qenter( REDRAW, window_number );
280  }
281  else
282  ringbell();
283  }
284  break;
285  }
286  }
287 }
288 
289 /*
290  * Map a scanline to 8 bits through the dither matrix.
291  *
292  * Inputs:
293  * rgb: Pointers to buffers containing the red, green,
294  * and blue color rows.
295  * n: Length of row.
296  * s: Skip between pixels in original image.
297  * y: Y position of row (necessary for dither)
298  * line: Pointer to output buffer for dithered color data.
299  */
300 map_scanline( rgb, n, y, line )
301 unsigned char *rgb[3];
302 Colorindex *line;
303 {
304  register int i, col;
305  int row, *row_ptr;
306 
307 # define DMAP(v,x) (modN[v]>row_ptr[x] ? divN[v] + 1 : divN[v])
308 
309  row = y % 16;
310  row_ptr = dm16[ row ]; /* Cache ptr to row of dither array. */
311 
312  if ( !bwflag ) /* Color display. */
313  {
314  register unsigned char *r, *g, *b;
315  for ( col = 0, i = 0, r = rgb[0], g = rgb[1], b = rgb[2];
316  i < n; i++, r++, g++, b++, col = ((col + 1) & 15) )
317  {
318  /* Combine 3 3-bit colors into a 3/3/3 color map index. */
319  line[i] = color_start + DMAP(*r, col) + (DMAP(*g, col)<<3) +
320  (DMAP(*b, col)<<6);
321  }
322  }
323  else /* Gray scale display. */
324  {
325  register unsigned char *bw;
326 
327  for ( i = 0, bw = rgb[0]; i < n; i++, bw++ )
328  line[i] = bw_start + (*bw>>1);
329  }
330 }
331 
332 #if 0
333 /* From Kitaoka's dithering code */
334 dmap(v,x,y)
335  register v;
336  int x,y ;
337 {
338  int d ;
339 
340  v = gammamap[v];
341  d = dm4[x%4][y%4] ;
342  if ((v%51)>d) return (v/51)+1 ; else return (v/51) ;
343 }
344 #endif
345 
346 init_dither() /* Miscellaneous global setup. */
347 {
348  int i, j, k, l, planes, pixels[216];
349  unsigned int value;
350  float N;
351 
352  make_square( 255.0 / (levels - 1), divN, modN, dm16 );
353 }
354 
355 /** NOTE: This is the makemap program from /usr/people/gifts/mextools/tools,
356  ** with the gamma and getset routines from /usr/people/gifts/mextools/portlib
357  ** appended. The only modification is that it only does the part of the map
358  ** required here, and expands the RGB map to 512 colors.
359  **/
360 /*
361  * Make the color map using the clues provided by ~/.desktop
362  * most of the mextools need the colors mapped by this program.
363  *
364  * Paul Haeberli - 1984
365  *
366  */
367 /** #include "gl.h" **/
368 /** #include "gl2/port.h" **/
369 
370 float getgamma();
371 
372 makemap()
373 {
374  register int i, j, v;
375  register int r, g, b, w;
376  int planes;
377 
378  planes = getplanes();
379 
380 /* if there are more than 8 planes make a ramp at 128 */
381 /** Position as specified, and only do it if showing a b&w image. **/
382  if (planes > 8 /**>**/ && bwflag /**<**/ )
383  for (i=0; i<128; i++) {
384  gammapcolor(i+ /**128>**/ bw_start /**<**/,i<<1,i<<1,i<<1);
385  }
386 
387 /* if there are more than 8 planes make an ordered color map at 256 */
388 /** but if more than 9 planes, make the map at 512, 512 colors long. **/
389  if (planes > 9 /**>**/ && ! bwflag /**<**/ ) /** => **/
390  for (i=0; i<512; i++) {
391  r = (i>>0) & 7;
392  g = (i>>3) & 7;
393  b = (i>>6) & 7;
394  r = (255*r)/7;
395  g = (255*g)/7;
396  b = (255*b)/7;
397  gammapcolor(i+ /**512>**/ color_start /**<**/,r,g,b);
398  }
399 }
400 
401 /*
402  * gamma -
403  * Some support for gamma correction when reading and writing
404  * color map entries.
405  *
406  * Paul Haeberli - 1984
407  *
408  */
409 /** #include "math.h" **/
410 /** #include "port.h" **/
411 /** #include "gl.h" **/
412 /** #include "stdio.h" **/
413 
414 FILE *configopen();
415 
416 float gammacorrect();
417 float ungammacorrect();
418 
419 static unsigned char rgamtable[256];
420 static unsigned char ggamtable[256];
421 static unsigned char bgamtable[256];
422 static unsigned char rungamtable[256];
423 static unsigned char gungamtable[256];
424 static unsigned char bungamtable[256];
425 static short firsted;
426 
427 gammapcolor(index,r,g,b)
428 register int index,r,g,b;
429 {
430  short i;
431 
432  if (!firsted) {
433  readgamtables();
434  firsted++;
435  }
436  r = rgamtable[r&0xff];
437  g = ggamtable[g&0xff];
438  b = bgamtable[b&0xff];
439  mapcolor(index,r,g,b);
440 }
441 
442 static makegamtables()
443 {
444  register float gamval;
445  register float val;
446  register short i;
447  int rbal, gbal, bbal;
448 
449  gamval = getgamma();
450  getcolorbal(&rbal,&gbal,&bbal);
451  for (i=0; i<256; i++) {
452  rgamtable[i] = 255*gammacorrect((rbal*i)/(255.0*255.0),gamval);
453  ggamtable[i] = 255*gammacorrect((gbal*i)/(255.0*255.0),gamval);
454  bgamtable[i] = 255*gammacorrect((bbal*i)/(255.0*255.0),gamval);
455  }
456  bzero(rungamtable,256);
457  bzero(gungamtable,256);
458  bzero(bungamtable,256);
459  for (i=0; i<256; i++) {
460  rungamtable[rgamtable[i]] = i;
461  gungamtable[ggamtable[i]] = i;
462  bungamtable[bgamtable[i]] = i;
463  }
464  fixup(rungamtable);
465  fixup(gungamtable);
466  fixup(bungamtable);
467 }
468 
469 static fixup(cptr)
470 register unsigned char *cptr;
471 {
472  register short i, lowval;
473 
474  for (i=256; i--; ) {
475  if (*cptr == 0)
476  *cptr = lowval;
477  else
478  lowval = *cptr;
479  }
480 }
481 
482 gamgetmcolor(index,r,g,b)
483 int index;
484 unsigned short *r, *g, *b;
485 {
486  static short firsted;
487  unsigned short tr, tg, tb;
488 
489  if (!firsted) {
490  readgamtables();
491  firsted++;
492  }
493  getmcolor(index,&tr,&tg,&tb);
494  *r = rungamtable[tr&0xff];
495  *g = gungamtable[tg&0xff];
496  *b = bungamtable[tb&0xff];
497 }
498 
499 float gammacorrect( i, gamma)
500 float i, gamma;
501 {
502  return pow(i,1.0/gamma);
503 }
504 
505 float ungammacorrect( i, gamma)
506 float i, gamma;
507 {
508  return pow(i,gamma);
509 }
510 
511 newgamma()
512 {
513  firsted = firsted = 0;
514 }
515 
516 newgamtables()
517 {
518  FILE *outf;
519 
520  if ((outf = configopen(".gamtables","w")) == 0) {
521  fprintf(stderr,"couldn't open .gamtables\n");
522  return;
523  }
524  makegamtables();
525  fwrite(rgamtable,256,1,outf);
526  fwrite(ggamtable,256,1,outf);
527  fwrite(bgamtable,256,1,outf);
528  fwrite(rungamtable,256,1,outf);
529  fwrite(gungamtable,256,1,outf);
530  fwrite(bungamtable,256,1,outf);
531  fclose(outf);
532 }
533 
534 readgamtables()
535 {
536  FILE *inf;
537 
538  if ((inf = configopen(".gamtables","r")) == 0) {
539  newgamtables();
540  if ((inf = configopen(".gamtables","r")) == 0) {
541  fprintf(stderr,"couldn't open .gamtables\n");
542  return;
543  }
544  }
545  fread(rgamtable,256,1,inf);
546  fread(ggamtable,256,1,inf);
547  fread(bgamtable,256,1,inf);
548  fread(rungamtable,256,1,inf);
549  fread(gungamtable,256,1,inf);
550  fread(bungamtable,256,1,inf);
551  fclose(inf);
552 }
553 
554 /*
555  * getset -
556  * Get and set values stored in ~/.desktop and ~/.gamma
557  *
558  * Paul Haeberli - 1984
559  *
560  */
561 /** #include "stdio.h" **/
562 /** #include "port.h" **/
563 /** #include "gl.h" **/
564 
565 FILE *configopen();
566 
567 /** savecolors and restorecolors **/
568 
569 float getgamma()
570 {
571  FILE *gamfile;
572  float gam;
573 
574  if ((gamfile = configopen(".gamma","r")) ) {
575  if (fscanf(gamfile,"%f\n",&gam) == 1) {
576  fclose(gamfile);
577  return gam;
578  } else
579  fclose(gamfile);
580  }
581  return 2.2;
582 }
583 
584 setgamma( gam )
585 float gam;
586 {
587  FILE *gamfile;
588 
589  if ((gamfile = configopen(".gamma","w")) == 0) {
590  fprintf(stderr,"couldn't open .gamma\n");
591  return;
592  }
593  fprintf(gamfile,"%f\n",gam);
594  fclose(gamfile);
595  newgamtables();
596 }
597 
598 getcolorbal(r,g,b)
599 unsigned int *r, *g, *b;
600 {
601  FILE *cbfile;
602 
603  if ((cbfile = configopen(".cbal","r")) ) {
604  if (fscanf(cbfile,"%d %d %d\n",r,g,b) == 3) {
605  if (*r>255)
606  *r = 255;
607  if (*g>255)
608  *g = 255;
609  if (*b>255)
610  *b = 255;
611  fclose(cbfile);
612  return;
613  } else
614  fclose(cbfile);
615  }
616  *r = 255;
617  *g = 255;
618  *b = 255;
619  return;
620 }
621 
622 setcolorbal(r,g,b)
623 int r, g, b;
624 {
625  FILE *cbfile;
626 
627  if ((cbfile = configopen(".cbal","w")) == 0) {
628  fprintf(stderr,"couldn't open .cbal\n");
629  return;
630  }
631  fprintf(cbfile,"%d %d %d\n",r,g,b);
632  fclose(cbfile);
633  newgamtables();
634 }
635 
636 FILE *configopen( name, mode )
637 char name[];
638 char mode[];
639 {
640  char homepath[100];
641  FILE *f;
642  char *cptr;
643 
644  cptr = (char *)getenv("HOME");
645  if (!cptr)
646  return 0;
647  strcpy(homepath,cptr);
648  strcat(homepath,"/");
649  strcat(homepath,name);
650  return fopen(homepath,mode);
651 }
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
int xmin
Definition: rle.h:100
Colorindex color_start
Definition: getmex.c:22
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_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
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
static unsigned char gungamtable[256]
Definition: getmex.c:423
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int divN[256]
Definition: to8.c:45
static unsigned char ggamtable[256]
Definition: getmex.c:420
int ymin
Definition: rle.h:100
Colorindex bw_start
Definition: getmex.c:23
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 scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
int dm16[16][16]
Definition: to8.c:42
int y_size
Definition: getmex.c:25
int xmax
Definition: rle.h:100
#define index
Definition: rle_config.h:96
#define levels
Definition: getmex.c:31
static unsigned char bungamtable[256]
Definition: getmex.c:424
void rle_get_setup_ok(rle_hdr *the_hdr, const char *prog_name, const char *file_name)
Definition: rle_getrow.c:254
#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 ymax
Definition: rle.h:100
Colorindex * image
Definition: getmex.c:29
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
#define DMAP(v, x, y)
Definition: get_orion.c:310
static short firsted
Definition: getmex.c:425
static unsigned char rgamtable[256]
Definition: getmex.c:419
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
static unsigned char bgamtable[256]
Definition: getmex.c:421
static unsigned char rungamtable[256]
Definition: getmex.c:422
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100