Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
getsun.c
Go to the documentation of this file.
1 /*
2  * getsun - display an rle image on a sun workstation running the
3  * sun window environment.
4  *
5  * Bug reports, or better yet fixes/enhancements, may be sent to the author.
6  * Author:
7  * Philip J. Klimbal
8  * RIACS
9  * MS 230-5
10  * NASA Ames Research Center
11  * Moffett Field, CA 94035
12  * ..!ames!riacs!klimbal
13  * klimbal@riacs.edu
14  *
15  * Copyright (c) 1987 Research Institute for Advanced Computer Science
16  * All rights reserved. No explicit or implicit warrenty provided.
17  *
18  * Based on getX - Put RLE images on X display,
19  * by Spencer W. Thomas, University of Utah.
20  * Copyright (c) 1986, University of Utah
21  *
22  *
23  * Utah Copyright Header (getX):
24  *
25  * This software is copyrighted as noted below. It may be freely copied,
26  * modified, and redistributed, provided that the copyright notice is
27  * preserved on all copies.
28  *
29  * There is no warranty or other guarantee of fitness for this software,
30  * it is provided solely "as is". Bug reports or fixes may be sent
31  * to the author, who may or may not act on them as he desires.
32  *
33  * You may not include this software in a program or other software product
34  * without supplying the source, or without informing the end-user that the
35  * source is available for no extra charge.
36  *
37  *
38  * cc .... -lrle -lsuntool -lsunwindow -lpixrect -lm
39  */
40 static char rcsid[] = "$Header: /l/spencer/src/urt/get/RCS/getsun.c,v 3.0.1.2 1992/04/30 14:05:10 spencer Exp $";
41 /*
42 getsun() Tag the file.
43 */
44 
45 #include <stdio.h>
46 #include <math.h>
47 #include <sys/file.h>
48 #include <suntool/sunview.h>
49 #include <suntool/canvas.h>
50 #include "rle.h"
51 
52 void get_pic(), create_window(), init_color(), map_rgb_to_bw();
53 void map_scanline(), put_scanline();
54 
55 /*
56  * Basic magic square for dithering
57  */
58 int dm16[16][16];
59 
60 /*
61  * Color map, gamma correction map, and lookup tables
62  */
64 int modN[256], divN[256];
65 int bwflag = 0; /* if non zero, dither in B&W
66  * Value of 2 means 1-bit system
67  */
68 
69 /*
70  * Number of color map levels, (square and cube), and number of gradations
71  * per level.
72  */
74 
75 /*
76  * Global variables
77  */
78 double disp_gam = 2.5; /* default gammas for display and image */
79 double img_gam = 1.0;
80 int iflag = 0; /* flag to tell if gamma was on command line */
81 
82 int nscan, nrow; /* size of window */
83 int nbyte; /* size of bitrow for 1-bit displays */
84 
85 int dbg = 0; /* set if debug mode */
86 
87 unsigned char *buffer; /* data storage pointers */
88 
89 Frame frame; /* sun window display frame */
90 Canvas canvas; /* display frame canvas */
91 Pixwin *pw; /* pixwin canvas */
92 
93 
94 /*****************************************************************
95  * TAG( main )
96  *
97  * Usage:
98  * getsun [-D] [-{wW}] [-{iI} gamma] [-g gamma] [-l levels] [file]
99  * Inputs:
100  * -D: Debug mode: print input file as read.
101  * -f: Don't fork after putting image on screen.
102  * -w: Black & white: reduce color images to B&W before
103  * display. Advantage is that smoother shading can
104  * be achieved.
105  * -i gamma: Specify gamma of image. (default 1.0)
106  * -I gamma: Specify gamma of display image was computed for.
107  * getsun will also read picture comments from the input file to determine
108  * the image gamma. These are
109  * image_gamma= gamma of image (equivalent to -i)
110  * display_gamma= gamma of display image was computed for.
111  * Command line arguments override values in the file.
112  * -g gamma: Specify gamma of display. (default 2.5)
113  * -l levels: Number of color levels.
114  * file: Input Run Length Encoded file. Uses stdin if not
115  * specified.
116  * Outputs:
117  * Puts image on screen.
118  * Assumptions:
119  * Input file is in RLE format.
120  * Algorithm:
121  * [None]
122  */
123 
124 void
126 int argc;
127 char **argv;
128 {
129  CONST_DECL char *infname = NULL;
130  FILE * infile;
131  int gflag = 0;
132  int forkflg = 0;
133 
134  if ( scanargs( argc, argv,
135  "% Ww%- D%- f%- l%-levels!d Ii%-gamma!F g%-gamma!F file%s",
136  &bwflag, &dbg, &forkflg,
137  &levels, &levels,
138  &iflag, &img_gam,
139  &gflag, &disp_gam,
140  &infname ) == 0 )
141  exit( 1 );
142 
143 
144  if ( levels != 0 && (levels > 6 || levels < 2)) {
145  fprintf(stderr,"Level must be in the range [2,6]; %d is invalid!\n", levels);
146  exit( 1 );
147  }
148  if ( iflag == 1 ) /* -i */
149  img_gam = 1.0 / img_gam;
150 
151  infile = rle_open_f("getsun", infname, "r");
152  if ( infile == stdin )
153  infname = "Standard Input";
154 
155  if ( !forkflg && fork() != 0 )
156  exit(0);
157  get_pic( infile, infname);
158  if ( infname != NULL) fclose( infile);
159 
160  if ( !forkflg )
161  {
162  fclose(stdin); /* Close stdio to release rshd. */
163  fclose(stdout);
164  fclose(stderr);
165  }
166 
167  window_main_loop(frame);
168  exit(0);
169 }
170 
171 
172 
173 
174 /*****************************************************************
175  * TAG( get_pic )
176  *
177  * Read in an RLE image, compute color map, and display it.
178  *
179  * Inputs:
180  * infile: File pointer for input.
181  * infname: Name of input file.
182  *
183  */
184 void
185 get_pic( infile, infname, cmdname )
186 FILE * infile;
187 char * infname, * cmdname;
188 {
189  register int i,
190  y;
191  int ncolors;
192  unsigned char *scan[3];
193  rle_hdr hdr;
194 
195  /*
196  * Read setup info from file.
197  */
198  hdr = *rle_hdr_init( (rle_hdr *)NULL );
199  rle_names( &hdr, cmdname, infname, 0 );
200 
201  hdr.rle_file = infile;
202  rle_get_setup_ok(&hdr, NULL, NULL);
203 
204  if ( dbg )
205  rle_debug( 1 );
206 
207  /* We're only interested in R, G, & B */
208  RLE_CLR_BIT(hdr, RLE_ALPHA);
209  for (i = 3; i < hdr.ncolors; i++)
210  RLE_CLR_BIT(hdr, i);
211  ncolors = hdr.ncolors > 3 ? 3 : hdr.ncolors;
212 
213  /*
214  * Compute image size and allocate storage.
215  */
216  nrow = (hdr.xmax - hdr.xmin + 1);
217  nscan = (hdr.ymax - hdr.ymin + 1);
218 
219  /*
220  * Get a window of the right size.
221  */
222  create_window(nrow, nscan, infname);
223 
224  if ( bwflag == 2 )
225  nbyte = ((nrow + 15) / 16) * 2; /* 1 bit display */
226  else
227  nbyte = ((nrow + 1) / 2) * 2;
228 
229  buffer = (unsigned char *) malloc(nbyte * nscan);
230  RLE_CHECK_ALLOC( hdr.cmd, buffer, "image memory" );
231 
232  /*
233  * Set up for rle_getrow. Pretend image x origin is 0.
234  */
235  for (i = 0; i < 3; i++)
236  scan[i] = (unsigned char *) malloc(nrow);
237  RLE_CHECK_ALLOC( hdr.cmd, scan[0]&&scan[1]&&scan[2], "input scan memory" );
238  hdr.xmax -= hdr.xmin;
239  hdr.xmin = 0;
240 
241  /* If no image gamma on command line, check comments in file */
242  if ( ! iflag )
243  {
244  char * v;
245  if ( (v = rle_getcom( "image_gamma", &hdr )) != NULL )
246  {
247  img_gam = atof( v );
248  /* Protect against bogus information */
249  if ( img_gam == 0.0 )
250  img_gam = 1.0;
251  else
252  img_gam = 1.0 / img_gam;
253  }
254  else if ( (v = rle_getcom( "display_gamma", &hdr )) != NULL )
255  {
256  img_gam = atof( v );
257  /* Protect */
258  if ( img_gam == 0.0 )
259  img_gam = 1.0;
260  }
261  }
262 
263  /*
264  * Set up the color map.
265  */
266  /* Input map, at least 3 channels */
267  in_cmap = buildmap( &hdr, 3, img_gam, 1.0 );
268 
269  init_color();
270 
271  /*
272  * For each scan line, dither it and display.
273  */
274  while ((y = rle_getrow(&hdr, scan)) <= hdr.ymax)
275  {
276  if ( bwflag && ncolors > 1 )
277  {
278  map_rgb_to_bw( scan[0], scan[1], scan[ncolors - 1], scan[0],
279  in_cmap, nrow );
280  /* Note: map_scanline only uses channel 0 for B&W */
281  }
282  else if ( bwflag )
283  for ( i = 0; i < nrow; i++ )
284  scan[0][i] = in_cmap[0][scan[0][i]];
285  else
286  for (i = 2; i >= ncolors; i--)
287  bcopy(scan[0], scan[i], nrow);
288  map_scanline(scan, nrow, 1, y,
289  &buffer[(hdr.ymax - y) * nbyte]);
290  put_scanline(&buffer[(hdr.ymax - y) * nbyte], nrow, 0,
291  hdr.ymax - y );
292  }
293  /*
294  * Free temp storage
295  */
296  for (i = 0; i < 3; i++)
297  free(scan[i]);
298 }
299 
300 
301 
302 
303 /*****************************************************************
304  * TAG( create_window )
305  *
306  * Create a sun window and place a pixwin canvas in it.
307  *
308  * Inputs:
309  * width: width of window.
310  * height: height of window.
311  * name: name of image file.
312  *
313  */
314 void
315 create_window( width, height, name)
316  int width, height;
317  char *name;
318 {
319  char buf[BUFSIZ];
320 
321  sprintf(buf,"\"%s\": %d X %d",
322  name, height, width);
323  frame = window_create(0, FRAME,
324  FRAME_SHOW_LABEL, TRUE,
325  FRAME_LABEL, buf,
326  FRAME_NO_CONFIRM, TRUE,
327  0);
328  canvas = window_create(frame, CANVAS,
329  WIN_HEIGHT, height,
330  WIN_WIDTH, width,
331  0);
332  window_fit(frame);
333  if ((pw = canvas_pixwin(canvas)) == NULL) {
334  perror("Cannot create pixwin");
335  exit( 1 );
336  }
337  if (pw->pw_pixrect->pr_depth == 1) bwflag=2;
338 }
339 
340 
341 
342 
343 /*****************************************************************
344  * TAG( map_scanline )
345  *
346  * Map a scanline to 8 bits through the dither matrix.
347  *
348  * Inputs:
349  * rgb: Pointers to buffers containing the red, green,
350  * and blue color rows.
351  * n: Length of row.
352  * s: Skip between pixels in original image.
353  * y: Y position of row (necessary for dither)
354  * line: Pointer to output buffer for dithered color data.
355  */
356 
357 #define DMAP(v,x,y) (modN[v]>dm16[x][y] ? divN[v] + 1 : divN[v])
358 void
360 unsigned char *rgb[3], *line;
361 int n, s, y;
362 {
363  register int i, col, row;
364 
365  if ( !bwflag )
366  {
367  register unsigned char *r, *g, *b;
368  for ( row = y % 16, col = 0, i = 0, r = rgb[0], g = rgb[1], b = rgb[2];
369  i < n; i++, r+=s, g+=s, b+=s, col = ((col + 1) & 15) )
370  line[i] = DMAP(in_cmap[0][*r], col, row) +
371  DMAP(in_cmap[1][*g], col, row) * levels +
372  DMAP(in_cmap[2][*b], col, row) * levelsq;
373  }
374  else if ( bwflag == 1 ) /* gray scale display */
375  {
376  register unsigned char *r;
377 
378  for ( row = y % 16, col = 0, i = 0, r = rgb[0];
379  i < n; i++, r+=s, col = ((col + 1) & 15) )
380  line[i] = DMAP(*r, col, row);
381  }
382  else /* bitmap display */
383  {
384  register unsigned short *l = (unsigned short *)line;
385  register unsigned char * r;
386 
387  for ( row = y % 16, col = 0, i = 0, r = rgb[0], *l = 0;
388  i < n; r+=s, col = ((col + 1) & 15) )
389  {
390  *l |= (*r > dm16[col][row] ? 0 : 1) << (15-(i % 16));
391  if ( (++i % 16) == 0 )
392  *++l = 0;
393  }
394  }
395 }
396 
397 
398 
399 
400 /*****************************************************************
401  * TAG( put_scanline )
402  *
403  * Output scanline into pixwin.
404  *
405  * Inputs:
406  * scan: pointer to scanline.
407  * width: width of scanline.
408  * x,y: coordinates of this scanline.
409  *
410  */
411 void
412 put_scanline( scan, width, x, y )
413  unsigned char *scan;
414  int width, x, y;
415 {
416  Pixrect *pix;
417 
418  if ((pix = mem_point(width,1,pw->pw_pixrect->pr_depth,scan)) == NULL) {
419  perror("Unable to allocate pixrect");
420  exit( 1 );
421  }
422 
423  pw_write(pw, x, y, width, 1, PIX_SRC, pix, 0, 0);
424  free(pix);
425 }
426 
427 
428 
429 
430 /*****************************************************************
431  * TAG( map_rgb_to_bw )
432  *
433  * Convert RGB to black and white through NTSC transform, but map
434  * RGB through a color map first.
435  * Inputs:
436  * red_row, green_row, blue_row: Given RGB pixel data.
437  * map: Array[3] of pointers to pixel arrays,
438  * representing color map.
439  * rowlen: Number of pixels in the rows.
440  * Outputs:
441  * bw_row: Output B&W data. May coincide with one of the
442  * inputs.
443  * Algorithm:
444  * BW = .35*map[0][R] + .55*map[1][G] + .10*map[2][B]
445  */
446 void
448 rle_pixel *red_row;
449 rle_pixel *green_row;
450 rle_pixel *blue_row;
451 rle_pixel *bw_row;
452 rle_pixel **map;
453 int rowlen;
454 {
455  register int x, bw;
456 
457  for (x=0; x<rowlen; x++)
458  {
459  /* 68000 won't store float > 127 into byte? */
460  /* HP compiler blows it */
461  bw = .35*map[0][red_row[x]] + .55*map[1][green_row[x]] +
462  .10*map[2][blue_row[x]];
463  bw_row[x] = bw;
464  }
465 }
466 
467 
468 
469 
470 /*****************************************************************
471  * TAG( init_color )
472  *
473  * Build color map and load it into the pixwin.
474  *
475  */
476 void
478 {
479  register int i;
480  int rgbmap[256][3], bwmap[256];
481  unsigned char colormap[3][256];
482  char buf[12];
483 
484  if ( !bwflag )
485  {
486  /*
487  * Figure out how many color map entries we can get
488  */
489  if ( levels == 0 )
490  levels = 5; /* default starting point */
491 
492  levelsq = levels * levels;
493  levelsc = levelsq * levels;
494 
496 
497  /*
498  * Copy the color map entries into something that sunwindows
499  * can work with.
500  */
501  for(i = 0; i < levelsc; i++) {
502  colormap[0][i] = (u_char)rgbmap[i][0]&0xff;
503  colormap[1][i] = (u_char)rgbmap[i][1]&0xff;
504  colormap[2][i] = (u_char)rgbmap[i][2]&0xff;
505  }
506  sprintf(buf,"getsun.c%1d",levels);
507  pw_setcmsname(pw, buf);
508  pw_putcolormap(pw, 0, 4<<levels,colormap[0],colormap[1],colormap[2]);
509  return;
510  }
511 
512  /* Get a B&W color map (gray scale) */
513  if ( bwflag == 1 )
514  {
515  if ( levels == 0 )
516  levels = 5;
517  levelsq = levels * levels;
518  levelsc = levelsq * levels;
520 
521  /*
522  * Copy the color map entries into something that sunwindows
523  * can work with.
524  */
525  for ( i = 0; i < levelsc; i++ )
526  {
527  colormap[0][i] = (u_char)bwmap[i]&0xff;
528  colormap[1][i] = (u_char)bwmap[i]&0xff;
529  colormap[2][i] = (u_char)bwmap[i]&0xff;
530  }
531  sprintf(buf,"getsun.g%1d",levels);
532  pw_setcmsname(pw, buf);
533  pw_putcolormap(pw, 0,4<<levels, colormap[0],colormap[1],colormap[2]);
534  return;
535  }
536 
537  /* If b&w 1-bit display, just use two colors */
538  if ( bwflag == 2 )
539  {
540  /* All we care about, really, is the magic square */
542  levels = levelsc = 2;
543  return;
544  }
545 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
int xmin
Definition: rle.h:100
void map_scanline(rgb, int n, int y,*line)
Definition: to8.c:239
int modN[256]
Definition: to8.c:45
void make_square(double N, divN, modN, magic)
Definition: dither.c:192
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 buffer[4096]
Definition: rlesetbg.c:35
int levels
Definition: getx10.c:79
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
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
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 nscan
Definition: getx10.c:101
int iflag
Definition: getsun.c:80
#define CONST_DECL
Definition: rle_config.h:42
void rle_get_setup_ok(rle_hdr *the_hdr, const char *prog_name, const char *file_name)
Definition: rle_getrow.c:254
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
#define RLE_CLR_BIT(glob, bit)
Definition: rle.h:124
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
Pixwin * pw
Definition: getsun.c:91
static char rcsid[]
Definition: getsun.c:40
double img_gam
Definition: to8.c:48
int levelsc
Definition: getx10.c:79
int nbyte
Definition: getx10.c:102
Canvas canvas
Definition: getsun.c:90
#define RLE_ALPHA
Definition: rle.h:65
void map_rgb_to_bw(image_information *img, rle_pixel **rows, register rle_pixel *bw_row)
int dbg
Definition: getx10.c:104
#define DMAP(v, x, y)
Definition: get_orion.c:310
Frame frame
Definition: getsun.c:89
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
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
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86