Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
XtndRunget.c
Go to the documentation of this file.
1 /*
2  * XtndRunget.c - Extended Run Length Encoded retrieval.
3  *
4  * Author: Spencer W. Thomas
5  * Computer Science Dept.
6  * University of Utah
7  * Date: Tue Aug 10 1982
8  * Copyright (c) 1982 Spencer W. Thomas
9  * $Id: XtndRunget.c,v 3.0.1.1 90/11/19 16:45:12 spencer Exp $
10  * $Log: XtndRunget.c,v $
11  * Revision 3.0.1.1 90/11/19 16:45:12 spencer
12  * patch2: Add rle_config.h.
13  *
14  * Revision 3.0 90/08/03 15:26:10 spencer
15  * Establish version 3.0 base.
16  *
17  * Revision 1.3 90/07/13 15:21:42 spencer
18  * Add void*malloc(). Cast malloc calls.
19  *
20  * Revision 1.2 90/06/18 23:53:24 spencer
21  * Get rid of sv_ names.
22  *
23  * Revision 1.1 90/06/18 23:50:31 spencer
24  * Initial revision
25  *
26  * Revision 2.10 86/10/08 13:10:55 thomas
27  * typo fix.
28  *
29  * Revision 2.9 86/10/08 13:01:57 thomas
30  * Add ability to read (and print) picture comments.
31  * Recognize EOF opcode.
32  *
33  * Revision 2.8 86/03/10 15:45:29 thomas
34  * Fix up getchan/putchan.
35  *
36  * Revision 2.7 86/02/27 10:03:39 thomas
37  * fprintf on stderr, not on a string.
38  *
39  * Revision 2.6 86/02/25 17:31:13 thomas
40  * Add channel munging (get single channel capability).
41  *
42  * Revision 2.5 85/04/26 15:04:46 thomas
43  * Lint fixes.
44  * New flags and variable length background color.
45  *
46  * Revision 2.4 85/04/06 01:21:42 thomas
47  * Was only right justifying first channel of color map.
48  *
49  * Revision 2.3 85/04/02 00:41:26 thomas
50  * Move "comment" code in Byte and Run code.
51  *
52  * Revision 2.2 85/03/05 21:17:28 thomas
53  * Make sure to not put more than 510 bytes in a byte unpacker operation.
54  *
55  * Revision 2.1 85/03/05 15:59:17 thomas
56  * *** empty log message ***
57  *
58  * Revision 1.3 84/03/12 21:29:15 thomas
59  * Add "bread" routine, reduce output buffer size.
60  *
61  */
62 
63 #include "rle_config.h"
64 #include "stdio.h"
65 #include "getfb.h"
66 #include "rle_code.h"
67 #include <fb.h>
68 #ifndef VOID_STAR
69 extern char * malloc();
70 #else
71 extern void *malloc();
72 #endif
73 
74 #define BREAD(type, var, len)
75  if ( fd->_cnt < len )
76  bread( (char *)&var, len, fd );
77  else
78  {
79  var = *(type *)fd->_ptr;
80  fd->_ptr += len;
81  fd->_cnt -= len;
82  }
83 
84 #define OPCODE(inst) (inst.opcode & ~LONG)
85 #define LONGP(inst) (inst.opcode & LONG)
86 #define DATUM(inst) (0x00ff & inst.datum)
87 
88 #ifdef BIGENDIAN
89 #define SWAB(shrt) (shrt = ((shrt >> 8) & 0xff) | ((shrt << 8) & 0xff00))
90 #else
91 #define SWAB(shrt)
92 #endif
93 
94 extern int cflag, getchan, putchan; /* to load single channel */
95 
96 
97 /* ARGSUSED */
98 XtndRunGet(magic)
99 short magic;
100 {
101  struct XtndRsetup setup;
102  unsigned char * bg_color;
103  register short * fbptr;
104  register struct fd_file * fbbuf =
105  (struct fd_file *) ((char *) buffer + 1024);
106  register int fbx, fby, n;
107  int i, j, len;
108  int fbbufsize = (sizeof buffer - 1024) / sizeof(short);
109  short word, long_data;
110  long maplen;
111  struct inst {
112  short opcode:8,
113  datum:8;
114  } inst;
115  char * comment_buf, ** comments;
116 
117  if ( fbbufsize > 2048 ) fbbufsize = 2048; /* make it look faster */
118  if (bread ((char *)&setup, SETUPSIZE, fd) < 1)
119  {
120  fprintf (stderr, "getgmr: Couldn't read setup information\n");
121  exit (1);
122  }
123  /*
124  * Machines with big-endian byte order need to swap some bytes on
125  * input.
126  */
127  SWAB( setup.h_xpos );
128  SWAB( setup.h_ypos );
129  SWAB( setup.h_xlen );
130  SWAB( setup.h_ylen );
131 
132  /*
133  * Get background colors if present.
134  */
135  if ( !(setup.h_flags & H_NO_BACKGROUND) )
136  {
137  bg_color = (unsigned char *)malloc( 1 + (setup.h_ncolors/2) * 2 );
138  bread( (char *)bg_color, 1 + (setup.h_ncolors/2) * 2, fd );
139  }
140  else
141  bread( (char *)&word, 1, fd ); /* skip filler byte */
142 
143  /*
144  * Read color map if present
145  */
146  if (setup.h_ncmap)
147  {
148  maplen = 1 << setup.h_cmaplen;
149  if ( maplen * setup.h_ncmap > (sizeof buffer) )
150  {
151  fprintf( stderr,
152  "Color map too big (%d entries total), giving up\n",
153  maplen * setup.h_ncmap );
154  }
155  for ( i = 0; i < setup.h_ncmap; i++ )
156  {
157  bread((char *)&buffer[maplen*i], sizeof(short) * maplen, fd);
158  for ( j = 0; j < 256; j++ )
159  if ( j >= maplen )
160  buffer[j + 256*i] = 0; /* fill in short map */
161  else
162  buffer[j + 256*i] = ( buffer[j + 256*i] >> 8 ) & 0xff;
163  }
164  /*
165  * If < 3 channels in color map, copy from the first into the
166  * missing ones.
167  */
168  for ( ; i < 3; i++ )
169  for ( j = 0; j < 255; j++ )
170  buffer[j + 256 * i] = buffer[j];
171  }
172 
173  /*
174  * Read comments if present
175  */
176  if ( setup.h_flags & H_COMMENT )
177  {
178  short comlen, evenlen;
179  register char * cp;
180 
181  /* get comment length */
182  BREAD( short, comlen, sizeof comlen ); /* get comment length */
183  SWAB( comlen );
184  evenlen = (comlen + 1) & ~1; /* make it even */
185  comment_buf = (char *)malloc( (unsigned) evenlen );
186  if ( comment_buf == NULL )
187  {
188  fprintf( stderr,
189  "getgmr: Malloc failed for comment buffer of size %d\n",
190  comlen );
191  return -2;
192  }
193  fread( comment_buf, 1, evenlen, fd );
194  /* Count the comments */
195  for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ )
196  if ( *cp == 0 )
197  i++;
198  i++; /* extra for NULL pointer at end */
199  /* Get space to put pointers to comments */
200  comments = (char **)malloc( (unsigned)(i * sizeof(char *)) );
201  if ( comments == NULL )
202  {
203  fprintf( stderr,
204  "getgmr: Malloc failed for %d comment pointers\n",
205  i );
206  return -2;
207  }
208  /* Get pointers to the comments */
209  *comments = comment_buf;
210  for ( i = 1, cp = comment_buf + 1; cp < comment_buf + comlen; cp++ )
211  if ( *(cp - 1) == 0 )
212  comments[i++] = cp;
213  }
214 
215 
216  if (query)
217  {
218  if ( setup.h_ncolors != 3 )
219  fprintf( stderr, "%d color channels were saved.\n",
220  setup.h_ncolors);
221  if ( setup.h_flags & H_ALPHA )
222  fprintf( stderr, "Alpha channel was saved.\n" );
223  fprintf (stderr, "Originally positioned at (%d, %d), size (%d %d)\n",
224  setup.h_xpos, setup.h_ypos, setup.h_xlen, setup.h_ylen);
225  if ( setup.h_flags & H_CLEARFIRST )
226  fprintf( stderr, "Screen will be cleared to " );
227  else if ( !(setup.h_flags & H_NO_BACKGROUND) )
228  fprintf( stderr, "Saved in overlay mode with original " );
229  if ( setup.h_flags & H_NO_BACKGROUND )
230  fprintf( stderr, "No background color was saved.\n" );
231  else
232  {
233  fprintf (stderr, "background color" );
234  for ( i = 0; i < setup.h_ncolors; i++ )
235  fprintf( stderr, " %d", bg_color[i] );
236  fprintf( stderr, "\n" );
237  }
238 
239  if (setup.h_ncmap)
240  {
241  fprintf (stderr,
242  "%d channels of color map %d entries long were saved.\n",
243  setup.h_ncmap, 1 << setup.h_cmaplen );
244  }
245 
246  if ( setup.h_flags & H_COMMENT )
247  {
248  fprintf( stderr, "Comments:\n" );
249  for ( i = 0; comments[i] != NULL; i++ )
250  fprintf( stderr, "%s\n", comments[i] );
251  }
252  exit (0);
253  }
254 
255  Fbinit();
256 
257  /*
258  * Handle -c getchan [putchan] option.
259  *
260  * If both getchan & putchan are specified, take the input data in
261  * the channel (getchan) and place it on the fb in the channel
262  * (putchan). If only getchan is specified, put the data from the
263  * input channel into the same color channel in the fb.
264  *
265  * As a special case, -c getchan acts as -c 0 getchan for a B&W
266  * image (this accounts for much of the extra complexity of the
267  * following block).
268  */
269 
270  if ( cflag )
271  {
272  if ( getchan > setup.h_ncolors && setup.h_ncolors > 1 )
273  {
274  fprintf( stderr,
275  "Requested channel (%d) not in input file (%d channels)\n",
276  getchan, setup.h_ncolors );
277  exit( 1 );
278  }
279  if ( getchan < 0 && (setup.h_flags & H_ALPHA) == 0 )
280  {
281  fprintf( stderr, "getgmr: No alpha channel in input file\n" );
282  exit( 1 );
283  }
284  if ( putchan == -1 )
285  putchan = getchan;
286  if ( putchan < 0 || putchan > 2 )
287  {
288  fprintf( stderr,
289  "getgmr: Requested output channel (%d) doesn't exist.\n",
290  putchan );
291  exit( 1 );
292  }
293  if ( setup.h_ncolors == 1 && getchan > 0 )
294  getchan = 0;
295  }
296 
297  if (posflag)
298  {
299  fprintf (stderr, "Originally positioned at (%d, %d)\n",
300  setup.h_xpos, setup.h_ypos);
301  if (posflag == 1) /* incremental positioning */
302  {
303  setup.h_xpos = (x + setup.h_xpos) & 0777;
304  setup.h_ypos = (y + setup.h_ypos) & 0777;
305  }
306  else
307  {
308  setup.h_xpos = x & 0777;
309  setup.h_ypos = y & 0777;
310  }
311  }
312  if (background == 0)
313  {
314  if (setup.h_flags & H_CLEARFIRST)
315  background = 2;
316  else
317  background = 1;
318  }
319 
320  if ( setup.h_ncmap )
321  Fmbput(0, buffer); /* write color map */
322 
323  Fdstart(fbbuf, fbbufsize, 0);
324  /* do some output buffering */
325  if (background == 2)
326  {
327  if ( cflag )
328  {
329  Fchn( 1 << putchan );
330  Frvput( 0, 511, 0, 511, bg_color[getchan] );
331  }
332  else
333  if ( setup.h_ncolors >= 3 )
334  Fr3put(0, 511, 0, 511, bg_color[0], bg_color[1], bg_color[2]);
335  else
336  Fr3put(0, 511, 0, 511, bg_color[0], bg_color[0], bg_color[0]);
337  }
338 
339  fbx = setup.h_xpos;
340  fby = setup.h_ypos;
341 
342  /* This is a middle exit loop */
343  for (;;)
344  {
345  BREAD(struct inst, inst, 2 );
346  if ( feof(fd) ) break;
347 
348  switch( OPCODE(inst) )
349  {
350  case RSkipLinesOp:
351  if ( LONGP(inst) )
352  {
353  BREAD( short, long_data, sizeof long_data );
354  SWAB( long_data );
355  fby += long_data;
356  if (debug)
357  fprintf(stderr, "Skip Lines %d\n", long_data);
358  }
359  else
360  {
361  fby += DATUM(inst);
362  if (debug)
363  fprintf(stderr, "Skip Lines %d\n", inst.datum);
364  }
365  break;
366 
367  case RSetColorOp:
368  if ( cflag )
369  {
370  if ( (getchan&0xff) == DATUM(inst) )
371  Fchn( 1 << putchan );
372  else
373  Fchn( 0 );
374  }
375  else
376  {
377  if (setup.h_ncolors == 1)
378  Fchn(7);
379  else
380  Fchn(1<<DATUM(inst)); /* select color channel */
381  }
382  fbx = setup.h_xpos;
383  if (debug)
384  fprintf(stderr, "Set Color %d\n", inst.datum);
385  break;
386 
387  case RSkipPixelsOp:
388  if ( LONGP(inst) )
389  {
390  BREAD( short, long_data, sizeof long_data );
391  SWAB( long_data );
392  fbx += long_data;
393  if (debug)
394  fprintf(stderr, "Skip Pixels %d\n", long_data);
395  }
396  else
397  {
398  fbx += DATUM(inst);
399  if (debug)
400  fprintf(stderr, "Skip Pixels %d\n", DATUM(inst));
401  }
402  break;
403 
404  case RByteDataOp:
405  if ( LONGP(inst) )
406  {
407  BREAD( short, long_data, sizeof long_data );
408  SWAB( long_data );
409  n = (int)long_data;
410  }
411  else
412  {
413  n = DATUM(inst);
414  }
415 /* Fbvput( fbx, fbx+n, fby, fby, buffer ); */
416  n++;
417  if (debug)
418  fprintf(stderr, "Byte Data, length %d\n", n);
419  do {
420  len = n <= 510 ? n : 510; /* blasted byteunpacker */
421  _Fdreserve( (len+1)/2 + 7 );
422  fbptr = &fbbuf->fd_list[fbbuf->fd_len];
424  *fbptr++ = LoadEA | (fbx & 0777);
425  *fbptr++ = LoadEB | 1;
426  *fbptr++ = LoadLA | (fby & 0777);
427  *fbptr++ = LoadUpdateMode | A_AB;
428  *fbptr++ = LoadPRegister | (1<<9) | ((len & 1) << 8) |
429  ((len + 1) >> 1);
430  bread((char *)fbptr, (len+1) & ~1, fd); /* Round up to multiple of 2 */
431  fbptr += (len+1)/2;
432  fbx += len;
433  fbbuf->fd_len = fbptr - fbbuf->fd_list;
434  n -= len;
435  } while ( n > 0 );
436  break;
437 
438  case RRunDataOp:
439  if ( LONGP(inst) )
440  {
441  BREAD( short, long_data, sizeof long_data );
442  SWAB( long_data );
443  n = long_data;
444  }
445  else
446  {
447  n = DATUM(inst);
448  }
449  BREAD( short, word, sizeof(short) );
450 /* Frvput(fbx, fbx+n, fby, fby, word);*/
451  _Fdreserve( 5 );
452  fbptr = &fbbuf->fd_list[fbbuf->fd_len];
453  *fbptr++ = LoadEA | (fbx & 0777);
454  *fbptr++ = LoadEB | n;
455  *fbptr++ = LoadLA | (fby & 0777);
456  *fbptr++ = LoadSubchannelMask | (word & 07777);
457  *fbptr++ = LoadLB | GoWrite;
458  fbbuf->fd_len = fbptr - fbbuf->fd_list;
459  fbx += n+1;
460  if (debug)
461  fprintf(stderr, "Run, length %d, color %d\n", n+1, word);
462  break;
463 
464  case REOFOp:
465  break;
466 
467  default:
468  fprintf(stderr, "getgmr: Unrecognized opcode: %d\n", OPCODE(inst));
469  Fdstop();
470  Fddraw(fbbuf); /* flush the buffer */
471  exit(1);
472  }
473  if ( OPCODE( inst ) == REOFOp )
474  break; /* end of input here */
475  }
476  Fdstop();
477  Fddraw(fbbuf); /* flush the buffer */
478 }
#define RSetColorOp
Definition: rle_code.h:38
#define RRunDataOp
Definition: rle_code.h:41
int cflag
Definition: getgmr.c:19
#define LoadEA
Definition: fb.h:100
char h_ncmap
Definition: rle_code.h:55
#define H_COMMENT
Definition: rle_code.h:47
char buffer[4096]
Definition: rlesetbg.c:35
int query
Definition: getgmr.c:18
#define RSkipLinesOp
Definition: rle_code.h:37
char h_cmaplen
Definition: rle_code.h:55
#define LONGP(inst)
Definition: XtndRunget.c:85
#define SWAB(shrt)
Definition: XtndRunget.c:91
#define H_ALPHA
Definition: rle_code.h:46
int fd_len
Definition: fb.h:152
char h_ncolors
Definition: rle_code.h:55
#define REOFOp
Definition: rle_code.h:42
#define H_CLEARFIRST
Definition: rle_code.h:44
int debug
Definition: getgmr.c:18
int putchan
Definition: getgmr.c:19
#define BREAD(type, var, len)
Definition: XtndRunget.c:74
#define SelectPeripheralDevice
Definition: fb.h:108
int posflag
Definition: get4d.c:41
#define LoadSubchannelMask
Definition: fb.h:64
#define RSkipPixelsOp
Definition: rle_code.h:39
#define LoadUpdateMode
Definition: fb.h:76
int getchan
Definition: getgmr.c:19
#define LoadPRegister
Definition: fb.h:132
short fd_list[1]
Definition: fb.h:156
#define LONG
Definition: rle_code.h:36
#define ByteUnpacker
Definition: fb.h:126
#define GoWrite
Definition: fb.h:92
#define VOID_STAR
Definition: rle_config.h:28
#define DATUM(inst)
Definition: XtndRunget.c:86
FILE * fd
Definition: getfb.h:18
#define A_AB
Definition: fb.h:82
#define LoadLA
Definition: fb.h:104
#define LoadEB
Definition: fb.h:101
#define SETUPSIZE
Definition: rle_code.h:61
Definition: fb.h:151
char h_flags
Definition: rle_code.h:55
#define H_NO_BACKGROUND
Definition: rle_code.h:45
#define OPCODE(inst)
Definition: XtndRunget.c:84
#define LoadLB
Definition: fb.h:105
#define RByteDataOp
Definition: rle_code.h:40
int background
Definition: getgmr.c:18