Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rlezoom.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 /*
19  * rlezoom.c - Zoom an RLE file.
20  *
21  * Author: Spencer W. Thomas
22  * Computer Science Dept.
23  * University of Utah
24  * Date: Thu Feb 26 1987
25  * Copyright (c) 1987, University of Utah
26  */
27 
28 #include <stdio.h>
29 #include "rle.h"
30 #include "rle_raw.h"
31 
32 #define ROUND(x) ((int)((x) + 0.5))
33 
34 static void integer_zoom(), expand_raw(), float_zoom(), build_row();
35 static int advance_fp();
36 
37 /*****************************************************************
38  * TAG( main )
39  *
40  * Zoom an RLE file by an integral factor.
41  *
42  * Usage:
43  * rlezoom [-f] factor [y-factor] [-o outfile] [rlefile]
44  * Inputs:
45  * -f: If specified, output image will have same
46  * dimensions as
47  * fant -p 0 0 -s factor y-factor
48  * would produce.
49  * factor: Factor to zoom by. Must be positive.
50  * y-factor: If provided, Y axis will be zoomed by this
51  * factor, X axis by 'factor'.
52  * rlefile: Input RLE file. Default is stdin.
53  * Outputs:
54  * Writes magnified RLE file to standard output or file specified by
55  * the -o flag.
56  * Assumptions:
57  * ...
58  * Algorithm:
59  * Read input file in raw mode. For each line, expand it by the
60  * X expansion factor. If the factor is > 3, convert pixel data
61  * into runs. Write each line a number of times equal to the Y
62  * factor.
63  */
64 void
66 int argc;
67 char **argv;
68 {
69  float xfact, yfact = 0;
70  rle_hdr in_hdr, out_hdr;
71  char * rlename = NULL, * out_fname = NULL;
72  FILE *outfile = stdout;
73  int oflag = 0, fflag = 0;
74  int rle_cnt, rle_err;
75 
76  in_hdr = *rle_hdr_init( NULL );
77  out_hdr = *rle_hdr_init( NULL );
78 
79  if ( scanargs( argc, argv,
80  "% f%- o%-outfile!s factor!f y-factor%f rlefile%s",
81  &fflag, &oflag, &out_fname, &xfact, &yfact, &rlename )
82  == 0 )
83  exit( 1 );
84 
85  /* Error check */
86  if ( xfact <= 0 )
87  {
88  fprintf( stderr, "%s: Zoom factor (%g) must be >= 0\n",
89  cmd_name( argv ), xfact );
90  exit( 1 );
91  }
92  if ( yfact < 0 )
93  {
94  fprintf( stderr, "%s: Y zoom factor (%g) must be >= 0\n",
95  cmd_name( argv ), yfact );
96  exit( 1 );
97  }
98 
99  /* If yfact is 0, it wasn't specified, set it to xfact */
100  if ( yfact == 0 )
101  yfact = xfact;
102 
103  /* Open input rle file and read header */
104  in_hdr.rle_file = rle_open_f(cmd_name( argv ), rlename, "r");
105  rle_names( &in_hdr, cmd_name( argv ), rlename, 0 );
106  rle_names( &out_hdr, in_hdr.cmd, out_fname, 0 );
107 
108  for ( rle_cnt = 0;
109  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
110  rle_cnt++ )
111  {
112 
113  /* Figure out output file size and parameters */
114  (void)rle_hdr_cp( &in_hdr, &out_hdr );
115  if ( rle_cnt == 0 )
116  outfile = rle_open_f( cmd_name( argv ), out_fname, "w" );
117  out_hdr.rle_file = outfile;
118 
119  rle_addhist( argv, &in_hdr, &out_hdr );
120 
121  /* more error checks */
122  if ( (float)(out_hdr.xmax + 1) * xfact > 32767 )
123  {
124  fprintf( stderr,
125  "%s: X zoom factor (%g) makes image too large (%g)\n",
126  cmd_name( argv ), xfact,
127  (float)(out_hdr.xmax + 1) * xfact );
128  exit( 1 );
129  }
130  if ( (float)(out_hdr.ymax + 1) * yfact > 32767 )
131  {
132  fprintf( stderr,
133  "%s: Y zoom factor (%g) makes image too large (%g)\n",
134  cmd_name( argv ), yfact,
135  (float)(out_hdr.ymax + 1) * (float)yfact );
136  exit( 1 );
137  }
138  if ( fflag )
139  {
140  /* Use 'fant' arithmetic. */
141  out_hdr.xmin = ROUND( in_hdr.xmin * xfact );
142  out_hdr.ymin = ROUND( in_hdr.ymin * yfact );
143  out_hdr.xmax = ROUND( in_hdr.xmax * xfact );
144  out_hdr.ymax = ROUND( in_hdr.ymax * xfact );
145  }
146  else
147  {
148  out_hdr.xmin = ROUND( xfact * in_hdr.xmin );
149  out_hdr.xmax = ROUND( xfact * (in_hdr.xmax - in_hdr.xmin + 1) ) +
150  out_hdr.xmin - 1;
151  out_hdr.ymin = ROUND( yfact * in_hdr.ymin );
152  out_hdr.ymax = ROUND( yfact * (in_hdr.ymax - in_hdr.ymin + 1) ) +
153  out_hdr.ymin - 1;
154  }
155  rle_put_setup( &out_hdr );
156 
157  if ( xfact == (float)(int)xfact && yfact == (float)(int)yfact )
158  integer_zoom( &in_hdr, (int)xfact, (int)yfact, &out_hdr );
159  else
160  float_zoom( &in_hdr, xfact, yfact, &out_hdr );
161  }
162 
163  /* Check for an error. EOF or EMPTY is ok if at least one image
164  * has been read. Otherwise, print an error message.
165  */
166  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
167  rle_get_error( rle_err, cmd_name( argv ), rlename );
168 
169  exit( 0 );
170 }
171 
172 /*****************************************************************
173  * TAG( integer_zoom )
174  *
175  * Zoom the input image by an integer factor.
176  * Inputs:
177  * in_hdr: Input image header.
178  * xfact, yfact: X and Y expansion factors.
179  * Outputs:
180  * out_hdr: Output image header.
181  * Assumptions:
182  * xfact, yfact > 0.
183  * Algorithm:
184  * Read input file in "raw" form, expand pixels and runs, write
185  * output file in "raw" form. If xfact >= 4, each input pixel
186  * expands to an output run.
187  */
188 static void
190 rle_hdr *in_hdr;
191 int xfact;
192 int yfact;
193 rle_hdr *out_hdr;
194 {
195  int y, ynext, i;
196  rle_op ** in_raw, ** out_raw;
197  int * in_nraw, * out_nraw;
198 
199  /* Create raw arrays for input and output files */
200  if ( rle_raw_alloc( in_hdr, &in_raw, &in_nraw ) < 0 ||
201  rle_raw_alloc( out_hdr, &out_raw, &out_nraw ) < 0 )
202  RLE_CHECK_ALLOC( in_hdr->cmd, 0, 0 );
203 
204  y = in_hdr->ymin;
205  while ( (ynext = rle_getraw( in_hdr, in_raw, in_nraw )) != 32768 )
206  {
207  if ( ynext - y > 1 )
208  rle_skiprow( out_hdr, yfact * (ynext - y) );
209  expand_raw( in_hdr, in_raw, in_nraw, xfact, out_raw, out_nraw );
210  for ( i = 0; i < yfact; i++ )
211  rle_putraw( out_raw, out_nraw, out_hdr );
212  rle_freeraw( in_hdr, in_raw, in_nraw );
213  rle_freeraw( out_hdr, out_raw, out_nraw );
214  y = ynext;
215  }
216  rle_puteof( out_hdr );
217 
218  rle_raw_free( in_hdr, in_raw, in_nraw );
219  rle_raw_free( out_hdr, out_raw, out_nraw );
220 }
221 
222 
223 /*****************************************************************
224  * TAG( expand_raw )
225  *
226  * Zoom the input scanline by an integer factor.
227  * Inputs:
228  * the_hdr: Used for ncolors and alpha channel indication.
229  * in_raw: Input raw opcodes.
230  * in_nraw: Input raw opcode counts.
231  * xfact: Magnification factor.
232  * Outputs:
233  * out_raw: Output raw opcodes.
234  * out_nraw: Output counts.
235  * Assumptions:
236  *
237  * Algorithm:
238  * Replicate pixels by xfact. If xfact > 3, turn pixel data into
239  * runs.
240  */
241 static void
243 rle_hdr * the_hdr;
244 rle_op **in_raw;
245 int xfact;
246 int *in_nraw;
247 rle_op **out_raw;
248 int *out_nraw;
249 {
250  register rle_op * inp, * outp;
251  register rle_pixel * inc, * outc;
252  int chan, i, j, k;
253 
254  for ( chan = -the_hdr->alpha; chan < the_hdr->ncolors; chan++ )
255  {
256  for ( inp = in_raw[chan], outp = out_raw[chan], i = in_nraw[chan];
257  i > 0; i--, inp++ )
258  {
259  *outp = *inp; /* copy, then modify */
260  outp->xloc *= xfact;
261  if ( inp->opcode == RRunDataOp )
262  {
263  /* Just change length */
264  outp->length *= xfact;
265  outp++;
266  }
267  else /* must be byte data */
268  if ( xfact < 4 )
269  {
270  /* Be cheap, replicate pixel data for small zooms */
271  outp->length *= xfact;
272  outp->u.pixels =
273  (rle_pixel *)malloc( outp->length * sizeof(rle_pixel));
274  RLE_CHECK_ALLOC( the_hdr->cmd, outp->u.pixels, 0 );
275  for ( inc = inp->u.pixels, outc = outp->u.pixels,
276  j = inp->length;
277  j > 0; j--, inc++ )
278  for ( k = 0; k < xfact; k++ )
279  *outc++ = *inc;
280  outp++;
281  }
282  else
283  {
284  /*
285  * Change pixels to runs, coalesce adjacent
286  * identical pixels
287  */
288  for ( inc = inp->u.pixels, j = 0;
289  j < inp->length; j++, inc++ )
290  if ( j > 0 && outp[-1].u.run_val == *inc )
291  outp[-1].length += xfact;
292  else
293  {
294  outp->opcode = RRunDataOp;
295  outp->xloc = (inp->xloc + j) * xfact;
296  outp->length = xfact;
297  outp->u.run_val = *inc;
298  outp++;
299  }
300  }
301  }
302  /* Remember how many in this row */
303  out_nraw[chan] = outp - out_raw[chan];
304  }
305 }
306 
307 
308 /*****************************************************************
309  * TAG( float_zoom )
310  *
311  * Expand (or contract) input image by floating point amount.
312  * Inputs:
313  * in_hdr: Header for input image.
314  * xfact: X scaling factor.
315  * yfact: Y scaling factor.
316  * Outputs:
317  * out_hdr: Header for output image.
318  * Assumptions:
319  * xfact, yfact > 0.
320  * Algorithm:
321  * Simple sub/super-sampling based on DDA line drawing algorithm.
322  */
323 static void
325 rle_hdr *in_hdr;
326 float xfact;
327 float yfact;
328 rle_hdr *out_hdr;
329 {
330  rle_pixel **in_scan, **out_scan;
331  rle_pixel **out_rows;
332  int curr_row, in_row;
333  int wid, i;
334 
335  if (rle_row_alloc( in_hdr, &in_scan ) < 0 ||
336  rle_row_alloc( out_hdr, &out_scan ) < 0 )
337  RLE_CHECK_ALLOC( in_hdr->cmd, 0, 0 );
338 
339  /* Set up pointers for rle_putrow to use. The problem is that
340  * rle_putrow expects pointers to the [xmin] element of each
341  * scanline, while rle_getrow expects pointers to the [0] element
342  * of each scanline.
343  */
344  out_rows = (rle_pixel **)calloc( (out_hdr->ncolors + out_hdr->alpha),
345  sizeof(rle_pixel *) );
346  RLE_CHECK_ALLOC( in_hdr->cmd, out_rows, 0 );
347  out_rows += out_hdr->alpha;
348  for ( i = -out_hdr->alpha; i < out_hdr->ncolors; i++ )
349  out_rows[i] = out_hdr->xmin + out_scan[i];
350 
351  wid = out_hdr->xmax - out_hdr->xmin + 1;
352 
353  curr_row = -1; /* Current input row (in in_scan). */
354  for ( i = out_hdr->ymin; i <= out_hdr->ymax; i++ )
355  {
356  in_row = (int)(i / yfact);
357  if ( curr_row < in_row )
358  {
359  curr_row = advance_fp( in_hdr, in_row, in_scan );
360  build_row( out_hdr, xfact, in_scan, out_scan );
361  }
362  rle_putrow( out_rows, wid, out_hdr );
363  }
364  rle_puteof( out_hdr );
365 
366  /* If any input left, skip over it. */
367  while (rle_getskip( in_hdr ) < 32768 )
368  ;
369 
370  rle_row_free( in_hdr, in_scan );
371  rle_row_free( out_hdr, out_scan );
372  out_rows -= out_hdr->alpha;
373  free( out_rows );
374 }
375 
376 /*****************************************************************
377  * TAG( advance_fp )
378  *
379  * Advance the input to the specified row.
380  * Inputs:
381  * hdr: Input image header.
382  * des_row: The desired row.
383  * Outputs:
384  * in_scan: Input scanline data array.
385  * Returns scanline number of last row read.
386  * Assumptions:
387  * [None]
388  * Algorithm:
389  * Read scanlines until des_row is reached; return scanline
390  * number of row last read (should = des_row).
391  */
392 static int
394 rle_hdr *hdr;
395 int des_row;
396 rle_pixel **in_scan;
397 {
398  int row;
399 
400  while ( (row = rle_getrow( hdr, in_scan )) < des_row )
401  ;
402  return row;
403 }
404 
405 /*****************************************************************
406  * TAG( build_row )
407  *
408  * Build zoomed output scanline from an input scanline.
409  * Inputs:
410  * hdr: Output image header.
411  * fact: Scaling factor.
412  * in_scan: Input scanline data.
413  * Outputs:
414  * out_scan: Output scanline data.
415  * Assumptions:
416  * Input scanline data runs from hdr->xmin/fact to hdr->xmax/fact.
417  * Algorithm:
418  * For each output pixel, determine the input pixel it comes from
419  * by a trivial mapping.
420  */
421 static void
423 rle_hdr *hdr;
424 float fact;
425 rle_pixel **in_scan;
426 rle_pixel **out_scan;
427 {
428  register rle_pixel *is, *os;
429  register int i;
430  int c;
431  int m = hdr->xmax;
432 
433  for ( c = -hdr->alpha; c < hdr->ncolors; c++ )
434  {
435  is = in_scan[c];
436  os = out_scan[c];
437  for ( i = hdr->xmin; i <= m; i++ )
438  os[i] = is[(int)(i / fact)];
439  }
440 }
FILE * rle_open_f(char *prog_name, char *file_name, char *mode)
Definition: rle_open_f.c:216
#define RRunDataOp
Definition: rle_code.h:41
int xmin
Definition: rle.h:100
rle_hdr * rle_hdr_cp(rle_hdr *from_hdr, rle_hdr *to_hdr)
Definition: rle_hdr.c:119
void rle_freeraw(rle_hdr *the_hdr, scanraw, nraw)
Definition: rle_getraw.c:268
int length
Definition: rle_raw.h:51
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
int rle_raw_alloc(rle_hdr *the_hdr, rle_op ***scanp, int **nrawp)
Definition: rle_raw_alc.c:60
int opcode
Definition: rle_raw.h:49
void rle_row_free(rle_hdr *the_hdr, rle_pixel **scanp)
Definition: rle_row_alc.c:114
#define RLE_EMPTY
Definition: rle.h:73
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_row_alloc(rle_hdr *the_hdr, rle_pixel ***scanp)
Definition: rle_row_alc.c:56
void rle_putraw(rle_op **scanraw, int *nraw, rle_hdr *the_hdr)
Definition: rle_putraw.c:60
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
#define RLE_SUCCESS
Definition: rle.h:70
int ymin
Definition: rle.h:100
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
int scanargs(int argc, char **argv, const char *format,...)
Definition: scanargs.c:94
int xloc
Definition: rle_raw.h:50
const char * cmd
Definition: rle.h:133
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
static void integer_zoom(rle_hdr *in_hdr, int xfact, int yfact, rle_hdr *out_hdr)
Definition: rlezoom.c:189
#define RLE_EOF
Definition: rle.h:74
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
unsigned int rle_getskip(rle_hdr *the_hdr)
Definition: rle_getskip.c:57
static void float_zoom(rle_hdr *in_hdr, float xfact, float yfact, rle_hdr *out_hdr)
Definition: rlezoom.c:324
void rle_skiprow(rle_hdr *the_hdr, int nrow)
Definition: rle_putrow.c:393
static void build_row(rle_hdr *hdr, float fact, rle_pixel **in_scan, rle_pixel **out_scan)
Definition: rlezoom.c:422
int ymax
Definition: rle.h:100
static void expand_raw(rle_hdr *the_hdr, rle_op **in_raw, int *in_nraw, int xfact, rle_op **out_raw, int *out_nraw)
Definition: rlezoom.c:242
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
static int advance_fp(rle_hdr *hdr, int des_row, rle_pixel **in_scan)
Definition: rlezoom.c:393
#define ROUND(x)
Definition: fant.c:78
int alpha
Definition: rle.h:100
void rle_raw_free(rle_hdr *the_hdr, rle_op **scanp, nrawp)
Definition: rle_raw_alc.c:131
rle_hdr * rle_hdr_init(rle_hdr *the_hdr)
Definition: rle_hdr.c:267
FILE * rle_file
Definition: rle.h:114
unsigned int rle_getraw(rle_hdr *the_hdr, scanraw, nraw)
Definition: rle_getraw.c:78
int ncolors
Definition: rle.h:100
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86