Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
Runput.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  * Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
19  * to have all "void" functions so declared.
20  */
21 /*
22  * Runput.c - General purpose Run Length Encoding.
23  *
24  * Author: Spencer W. Thomas
25  * Computer Science Dept.
26  * University of Utah
27  * Date: Mon Aug 9 1982
28  * Copyright (c) 1982,1986 Spencer W. Thomas
29  *
30  * $Id: Runput.c,v 3.0.1.1 1992/01/28 18:17:40 spencer Exp $
31  *
32  * Modified by: Todd W. Fuqua
33  * Date: Jul 22 1984
34  * convert to new RLE format to make room for larger frame buffers
35  */
36 
37 /* THIS IS WAY OUT OF DATE. See rle.5.
38  * The output file format is:
39  *
40  * Word 0: A "magic" number. The top byte of the word contains
41  * the letter 'R' or the letter 'W'. 'W' indicates that
42  * only black and white information was saved. The bottom
43  * byte is one of the following:
44  * ' ': Means a straight "box" save, -S flag was given.
45  * 'B': Image saved with background color, clear screen to
46  * background before restoring image.
47  * 'O': Image saved in overlay mode.
48  *
49  * Words 1-6: The structure
50  * { short xpos, Lower left corner
51  * ypos,
52  * xsize, Size of saved box
53  * ysize;
54  * char rgb[3]; Background color
55  * char map; flag for map presence
56  * }
57  *
58  * If the map flag is non-zero, then the color map will follow as
59  * 3*256 16 bit words, first the red map, then the green map, and
60  * finally the blue map.
61  *
62  * Following the setup information is the Run Length Encoded image.
63  * Each instruction consists of a 4-bit opcode, a 12-bit datum and
64  * possibly one or more following words (all words are 16 bits). The
65  * instruction opcodes are:
66  *
67  * SkipLines (1): The bottom 10 bits are an unsigned number to be added to
68  * current Y position.
69  *
70  * SetColor (2): The datum indicates which color is to be loaded with
71  * the data described by the following ByteData and
72  * RunData instructions. 0->red, 1->green, 2->blue. The
73  * operation also resets the X position to the initial
74  * X (i.e. a carriage return operation is performed).
75  *
76  * SkipPixels (3): The bottom 10 bits are an unsigned number to be
77  * added to the current X position.
78  *
79  * ByteData (5): The datum is one less than the number of bytes of
80  * color data following. If the number of bytes is
81  * odd, a filler byte will be appended to the end of
82  * the byte string to make an integral number of 16-bit
83  * words. The bytes are in PDP-11 order. The X
84  * position is incremented to follow the last byte of
85  * data.
86  *
87  * RunData (6): The datum is one less than the run length. The
88  * following word contains (in its lower 8 bits) the
89  * color of the run. The X position is incremented to
90  * follow the last byte in the run.
91  */
92 
93 #include "stdio.h"
94 #include "rle_put.h"
95 #include "rle.h"
96 #include "rle_code.h"
97 
98 #define UPPER 255 /* anything bigger ain't a byte */
99 
100 /*
101  * Macros to make writing instructions with correct byte order easier.
102  */
103 /* Write a two-byte value in little_endian order. */
104 #define put16(a) (putc((a)&0xff,rle_fd),putc(((a)>>8)&0xff,rle_fd))
105 
106 /* short instructions */
107 #define mk_short_1(oper,a1) /* one argument short */
108  putc(oper,rle_fd), putc((char)a1,rle_fd)
109 
110 #define mk_short_2(oper,a1,a2) /* two argument short */
111  putc(oper,rle_fd), putc((char)a1,rle_fd), put16(a2)
112 
113 /* long instructions */
114 #define mk_long_1(oper,a1) /* one argument long */
115  putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd), put16(a1)
116 
117 #define mk_long_2(oper,a1,a2) /* two argument long */
118  putc((char)(LONG|oper),rle_fd), putc('\0', rle_fd),
119  put16(a1), put16(a2)
120 
121 /* choose between long and short format instructions */
122 /* NOTE: these macros can only be used where a STATEMENT is legal */
123 
124 #define mk_inst_1(oper,a1) /* one argument inst */
125  if (a1>UPPER) (mk_long_1(oper,a1)); else (mk_short_1(oper,a1))
126 
127 #define mk_inst_2(oper,a1,a2) /* two argument inst */
128  if (a1>UPPER) (mk_long_2(oper,a1,a2)); else (mk_short_2(oper,a1,a2))
129 
130 /*
131  * Opcode definitions
132  */
133 #define RSkipLines(n) mk_inst_1(RSkipLinesOp,(n))
134 
135 #define RSetColor(c) mk_short_1(RSetColorOp,(c))
136  /* has side effect of performing */
137  /* "carriage return" action */
138 
139 #define RSkipPixels(n) mk_inst_1(RSkipPixelsOp,(n))
140 
141 #define RNewLine RSkipLines(1)
142 
143 #define RByteData(n) mk_inst_1(RByteDataOp,n)
144  /* followed by ((n+1)/2)*2 bytes */
145  /* of data. If n is odd, last */
146  /* byte will be ignored */
147  /* "cursor" is left at pixel */
148  /* following last pixel written */
149 
150 #define RRunData(n,c) mk_inst_2(RRunDataOp,(n),(c))
151  /* next word contains color data */
152  /* "cursor" is left at pixel after */
153  /* end of run */
154 
155 #define REOF mk_inst_1(REOFOp,0)
156  /* Really opcode only */
157 
158 extern char *vax_pshort();
159 
160 /*****************************************************************
161  * TAG( RunSetup )
162  * Put out initial setup data for RLE files.
163  */
164 void
166 register rle_hdr * the_hdr;
167 {
168  struct XtndRsetup setup;
169  register FILE * rle_fd = the_hdr->rle_file;
170 
171  put16( RLE_MAGIC );
172 
173  if ( the_hdr->background == 2 )
174  setup.h_flags = H_CLEARFIRST;
175  else if ( the_hdr->background == 0 )
176  setup.h_flags = H_NO_BACKGROUND;
177  else
178  setup.h_flags = 0;
179  if ( the_hdr->alpha )
180  setup.h_flags |= H_ALPHA;
181  if ( the_hdr->comments != NULL && *the_hdr->comments != NULL )
182  setup.h_flags |= H_COMMENT;
183 
184  setup.h_ncolors = the_hdr->ncolors;
185  setup.h_pixelbits = 8; /* Grinnell dependent */
186  if ( the_hdr->ncmap > 0 && the_hdr->cmap == NULL )
187  {
188  fprintf( stderr,
189  "%s: Color map of size %d*%d specified, but not supplied, writing %s\n",
190  the_hdr->cmd, the_hdr->ncmap, (1 << the_hdr->cmaplen),
191  the_hdr->file_name );
192  the_hdr->ncmap = 0;
193  }
194  setup.h_cmaplen = the_hdr->cmaplen; /* log2 of color map size */
195  setup.h_ncmap = the_hdr->ncmap; /* no of color channels */
196  vax_pshort(setup.hc_xpos,the_hdr->xmin);
197  vax_pshort(setup.hc_ypos,the_hdr->ymin);
198  vax_pshort(setup.hc_xlen,the_hdr->xmax - the_hdr->xmin + 1);
199  vax_pshort(setup.hc_ylen,the_hdr->ymax - the_hdr->ymin + 1);
200  fwrite((char *)&setup, SETUPSIZE, 1, rle_fd);
201  if ( the_hdr->background != 0 )
202  {
203  register int i;
204  register rle_pixel *background =
205  (rle_pixel *)malloc( (unsigned)(the_hdr->ncolors + 1) );
206  register int *bg_color;
207  /*
208  * If even number of bg color bytes, put out one more to get to
209  * 16 bit boundary.
210  */
211  bg_color = the_hdr->bg_color;
212  for ( i = 0; i < the_hdr->ncolors; i++ )
213  background[i] = *bg_color++;
214  /* Extra byte, if written, should be 0. */
215  background[i] = 0;
216  fwrite((char *)background, (the_hdr->ncolors / 2) * 2 + 1, 1, rle_fd);
217  free( background );
218  }
219  else
220  putc( '\0', rle_fd );
221  if (the_hdr->ncmap > 0)
222  {
223  /* Big-endian machines are harder */
224  register int i, nmap = (1 << the_hdr->cmaplen) *
225  the_hdr->ncmap;
226  register char *h_cmap = (char *)malloc( nmap * 2 );
227  if ( h_cmap == NULL )
228  {
229  fprintf( stderr,
230  "%s: Malloc failed for color map of size %d, writing %s\n",
231  the_hdr->cmd, nmap, the_hdr->file_name );
232  exit( 1 );
233  }
234  for ( i = 0; i < nmap; i++ )
235  vax_pshort( &h_cmap[i*2], the_hdr->cmap[i] );
236 
237  fwrite( h_cmap, nmap, 2, rle_fd );
238  free( h_cmap );
239  }
240 
241  /* Now write out comments if given */
242  if ( setup.h_flags & H_COMMENT )
243  {
244  int comlen;
245  register CONST_DECL char ** com_p;
246 
247  /* Get the total length of comments */
248  comlen = 0;
249  for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
250  comlen += 1 + strlen( *com_p );
251 
252  put16( comlen );
253  for ( com_p = the_hdr->comments; *com_p != NULL; com_p++ )
254  fwrite( *com_p, 1, strlen( *com_p ) + 1, rle_fd );
255 
256  if ( comlen & 1 ) /* if odd length, round up */
257  putc( '\0', rle_fd );
258  }
259 }
260 
261 /*****************************************************************
262  * TAG( RunSkipBlankLines )
263  * Skip one or more blank lines in the RLE file.
264  */
265 void
267 int nblank;
268 register rle_hdr * the_hdr;
269 {
270  register FILE * rle_fd = the_hdr->rle_file;
271  RSkipLines(nblank);
272 }
273 
274 /*****************************************************************
275  * TAG( RunSetColor )
276  * Select a color and do carriage return.
277  * color: 0 = Red, 1 = Green, 2 = Blue.
278  */
279 void
281 int c;
282 register rle_hdr * the_hdr;
283 {
284  register FILE * rle_fd = the_hdr->rle_file;
285  RSetColor(c);
286 }
287 
288 /*****************************************************************
289  * TAG( RunSkipPixels )
290  * Skip a run of background.
291  */
292 
293 /* ARGSUSED */
294 void
296 int nskip, last, wasrun;
297 register rle_hdr * the_hdr;
298 {
299  register FILE * rle_fd = the_hdr->rle_file;
300  if (! last && nskip > 0)
301  {
302  RSkipPixels(nskip);
303  }
304 }
305 
306 /*****************************************************************
307  * TAG( RunNewScanLine )
308  * Perform a newline action. Since CR is implied by the Set Color
309  * operation, only generate code if the newline flag is true.
310  */
311 void
313 int flag;
314 register rle_hdr * the_hdr;
315 {
316  register FILE * rle_fd = the_hdr->rle_file;
317  if (flag)
318  {
319  RNewLine;
320  }
321 }
322 
323 /*****************************************************************
324  * TAG( Runputdata )
325  * Put one or more pixels of byte data into the output file.
326  */
327 void
329 rle_pixel * buf;
330 int n;
331 register rle_hdr * the_hdr;
332 {
333  register FILE * rle_fd = the_hdr->rle_file;
334  if (n == 0)
335  return;
336 
337  RByteData(n-1);
338  fwrite((char *)buf, n, 1, rle_fd);
339  if ( n & 1 )
340  putc( 0, rle_fd );
341 }
342 
343 /*****************************************************************
344  * TAG( Runputrun )
345  * Output a single color run.
346  */
347 
348 /* ARGSUSED */
349 void
351 int color, n, last;
352 register rle_hdr * the_hdr;
353 {
354  register FILE * rle_fd = the_hdr->rle_file;
355  RRunData(n-1,color);
356 }
357 
358 
359 /*****************************************************************
360  * TAG( RunputEof )
361  * Output an EOF opcode
362  */
363 void
365 register rle_hdr * the_hdr;
366 {
367  register FILE * rle_fd = the_hdr->rle_file;
368  REOF;
369 }
void RunSetColor(int c, rle_hdr *the_hdr)
Definition: Runput.c:280
void Runputdata(rle_pixel *buf, int n, rle_hdr *the_hdr)
Definition: Runput.c:328
#define RSetColorOp
Definition: rle_code.h:38
#define RRunDataOp
Definition: rle_code.h:41
int xmin
Definition: rle.h:100
const char ** comments
Definition: rle.h:113
char h_ncmap
Definition: rle_code.h:55
#define H_COMMENT
Definition: rle_code.h:47
#define mk_inst_1(oper, a1)
Definition: Runput.c:124
#define RSkipLinesOp
Definition: rle_code.h:37
#define RRunData(n, c)
Definition: Runput.c:150
char h_cmaplen
Definition: rle_code.h:55
#define RLE_MAGIC
Definition: rle_code.h:67
rle_map * cmap
Definition: rle.h:112
#define REOF
Definition: Runput.c:155
#define mk_short_1(oper, a1)
Definition: Runput.c:107
int * bg_color
Definition: rle.h:100
void RunSkipBlankLines(int nblank, rle_hdr *the_hdr)
Definition: Runput.c:266
char hc_ylen[2]
Definition: rle_code.h:51
#define H_ALPHA
Definition: rle_code.h:46
#define RSkipPixels(n)
Definition: Runput.c:139
int ymin
Definition: rle.h:100
#define RSkipLines(n)
Definition: Runput.c:133
char hc_xlen[2]
Definition: rle_code.h:51
char h_ncolors
Definition: rle_code.h:55
#define REOFOp
Definition: rle_code.h:42
#define H_CLEARFIRST
Definition: rle_code.h:44
const char * cmd
Definition: rle.h:133
#define put16(a)
Definition: rle_cp.c:43
#define UPPER
Definition: Runput.c:98
int xmax
Definition: rle.h:100
char hc_ypos[2]
Definition: rle_code.h:51
void RunSkipPixels(int nskip, int last, int wasrun, rle_hdr *the_hdr)
Definition: Runput.c:295
#define RSkipPixelsOp
Definition: rle_code.h:39
char h_pixelbits
Definition: rle_code.h:55
#define mk_inst_2(oper, a1, a2)
Definition: Runput.c:127
#define RNewLine
Definition: Runput.c:141
#define CONST_DECL
Definition: rle_config.h:42
#define LONG
Definition: rle_code.h:36
#define mk_short_2(oper, a1, a2)
Definition: Runput.c:110
char * vax_pshort(char *msgp, unsigned short s)
Definition: vaxshort.c:46
int background
Definition: rle.h:100
#define mk_long_2(oper, a1, a2)
Definition: Runput.c:117
char hc_xpos[2]
Definition: rle_code.h:51
int ncmap
Definition: rle.h:100
int ymax
Definition: rle.h:100
void RunputEof(rle_hdr *the_hdr)
Definition: Runput.c:364
unsigned char rle_pixel
Definition: rle.h:56
#define RByteData(n)
Definition: Runput.c:143
int cmaplen
Definition: rle.h:100
int alpha
Definition: rle.h:100
void RunNewScanLine(int flag, rle_hdr *the_hdr)
Definition: Runput.c:312
#define SETUPSIZE
Definition: rle_code.h:61
char h_flags
Definition: rle_code.h:55
const char * file_name
Definition: rle.h:134
#define H_NO_BACKGROUND
Definition: rle_code.h:45
void RunSetup(rle_hdr *the_hdr)
Definition: Runput.c:165
void Runputrun(int color, int n, int last, rle_hdr *the_hdr)
Definition: Runput.c:350
FILE * rle_file
Definition: rle.h:114
int ncolors
Definition: rle.h:100
#define RSetColor(c)
Definition: Runput.c:135
#define RByteDataOp
Definition: rle_code.h:40
#define mk_long_1(oper, a1)
Definition: Runput.c:114