Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
rlesortmap.c
Go to the documentation of this file.
1 /*
2  * rlesortmap.c - Sort the colormap using a n-d peano curve.
3  *
4  * Author: Spencer W. Thomas
5  * EECS Dept.
6  * University of Michigan
7  * Date: Fri Feb 15 1991
8  * Copyright (c) 1991, University of Michigan
9  */
10 
11 #include <stdio.h>
12 #include "rle.h"
13 #include "rle_raw.h"
14 
15 #define map_pixel( pix, cmaplen, cmap ) ((pix) > cmaplen ? (pix) :
16  cmap[pix])
17 
18 /* This is global so that the pcompar function can see it. */
19 static rle_map ** cmap = NULL;
20 static int ncolor;
21 
22 /* pcompar compares two colormap entries using the Peano ordering. */
23 extern pcompar();
24 
25 /*****************************************************************
26  * TAG( main )
27  *
28  * Usage:
29  * rlesortmap [-o outfile] [infile]
30  * Inputs:
31  * infile: Input file to have its colormap sorted.
32  * Defaults to stdin.
33  * Outputs:
34  * outfile: Result of sorting the colormap.
35  * Defaults to stdout.
36  * Assumptions:
37  * [None]
38  * Algorithm:
39  * Uses a Peano curve ordering to sort the elements in the input
40  * colormap. Keeps track of where each original element went,
41  * and then remaps the input data accordingly. This makes most
42  * sense for pseudo-color input files, but the program will work
43  * on any input file.
44  */
45 void
47 int argc;
48 char **argv;
49 {
50  register int i, c, j;
51  char * infname = NULL, * outfname = NULL;
52  FILE *outfile = stdout;
53  int oflag = 0, y, nskip, nrow;
54  int rle_cnt, rle_err;
55  rle_hdr in_hdr, out_hdr;
56  rle_op ** scan, ** outscan;
57  int * nraw;
58  int cmaplen;
59  rle_map *mapp, **scmap;
60  int *sortindex, *isort;
61 
62  in_hdr = *rle_hdr_init( NULL );
63  out_hdr = *rle_hdr_init( NULL );
64 
65  if ( scanargs( argc, argv, "% o%-outfile!s infile%s",
66  &oflag, &outfname, &infname ) == 0 )
67  exit( 1 );
68  /* Open input file and read RLE header */
69  in_hdr.rle_file = rle_open_f(cmd_name( argv ), infname, "r");
70  rle_names( &in_hdr, cmd_name( argv ), infname, 0 );
71  rle_names( &out_hdr, in_hdr.cmd, outfname, 0 );
72 
73  for ( rle_cnt = 0;
74  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
75  rle_cnt++ )
76  {
77  /* Copy header data from the input file */
78  (void)rle_hdr_cp( &in_hdr, &out_hdr );
79  rle_addhist( argv, &in_hdr, &out_hdr );
80 
81  /* Open the output file */
82  if ( rle_cnt == 0 )
83  outfile = rle_open_f( cmd_name( argv ), outfname, "w" );
84  out_hdr.rle_file = outfile;
85 
86  nrow = in_hdr.xmax - in_hdr.xmin + 1; /* how wide is it? */
87 
88  if ( in_hdr.ncmap > 0 )
89  {
90  char *map_cmt;
91 
92  cmaplen = 1 << in_hdr.cmaplen; /* length of the color map */
93  /* Get pointers to the individual rows of the color map */
94  cmap = (rle_map **) malloc( in_hdr.ncmap * sizeof(rle_map *) );
95  RLE_CHECK_ALLOC( in_hdr.cmd, cmap, "color map" );
96  for ( c = 0; c < in_hdr.ncmap; c++ )
97  cmap[c] = &in_hdr.cmap[c * cmaplen];
98 
99  /* Pointers for storing sorted colormap. */
100  scmap = (rle_map **) malloc( in_hdr.ncmap * sizeof(rle_map *) );
101  mapp = (rle_map *)malloc( in_hdr.ncmap * cmaplen * sizeof(rle_map) );
102  RLE_CHECK_ALLOC( in_hdr.cmd, scmap && mapp, "color map" );
103  for ( c = 0; c < in_hdr.ncmap; c++ )
104  scmap[c] = &mapp[c * cmaplen];
105 
106  /* If usable colormap length given, use it. */
107  if ( (map_cmt = rle_getcom( "color_map_length", &in_hdr )) &&
108  atoi( map_cmt ) > 0 )
109  cmaplen = atoi( map_cmt );
110  }
111  else
112  cmaplen = 0;
113 
114  if ( cmaplen > 0 )
115  {
116  /* Allocate space for the sort indices. */
117  sortindex = (int *)malloc( sizeof(int) * cmaplen );
118  RLE_CHECK_ALLOC( in_hdr.cmd, sortindex, 0 );
119 
120  /* And initialize them to the identity mapping. */
121  for ( i = 0; i < cmaplen; i++ )
122  sortindex[i] = i;
123 
124  ncolor = in_hdr.ncmap;
125  /* Do the sort. */
126  qsort( sortindex, cmaplen, sizeof(int), pcompar );
127 
128  /* Compute the inverse sort map. */
129  isort = (int *)malloc( sizeof(int) * cmaplen );
130  RLE_CHECK_ALLOC( in_hdr.cmd, isort, 0 );
131  for ( i = 0; i < cmaplen; i++ )
132  isort[sortindex[i]] = i;
133 
134 #if 0
135  /* Collapse identical entries. */
136  for ( i = 1, j = 0; i < cmaplen; i++ )
137  {
138  int xi, xi1;
139  xi = sortindex[i];
140  xi1 = sortindex[i-1];
141 
142  for ( c = 0; c < ncolor; c++ )
143  if ( cmap[c][xi] != cmap[c][xi1] )
144  break;
145  /* If loop broke, colors are different. */
146  if ( c != ncolor )
147  j++;
148  if ( i != j )
149  sortindex[j] = sortindex[i];
150  }
151  cmaplen = j + 1;
152 #endif
153 
154  /* Rearrange the physical colormap. */
155  for ( i = 0; i < cmaplen; i++ )
156  {
157  int xi = sortindex[i];
158 
159  for ( c = 0; c < ncolor; c++ )
160  scmap[c][i] = cmap[c][xi];
161  }
162 
163  /* And put the sorted colormap into the output file. */
164  out_hdr.cmap = mapp;
165  if ( cmaplen < (1 << out_hdr.cmaplen ) )
166  {
167  char buf[80];
168 
169  sprintf( buf, "color_map_length=%d", cmaplen );
170  rle_putcom( buf, &out_hdr );
171  }
172  }
173 
174  /* Allocate space for the rle opcode information */
175  if ( rle_raw_alloc( &in_hdr, &scan, &nraw ) < 0 )
176  RLE_CHECK_ALLOC( in_hdr.cmd, 0, "image data" );
177 
178  if ( in_hdr.ncmap > 0 && in_hdr.background )
179  for ( i = 0; i < out_hdr.ncolors; i++ )
180  in_hdr.bg_color[i] = map_pixel( in_hdr.bg_color[i],
181  cmaplen, isort );
182 
183  /* Start the output file */
184  rle_put_setup( &out_hdr );
185 
186  y = in_hdr.ymin - 1;
187  while ( (nskip = rle_getraw( &in_hdr, scan, nraw )) != 32768 )
188  {
189  nskip -= y; /* figure out difference from previous line */
190  y += nskip;
191  if ( nskip > 1 )
192  rle_skiprow( &out_hdr, nskip - 1 );
193  if ( cmaplen > 0 )
194  {
195  for ( c = 0; c < in_hdr.ncolors; c++ )
196  if ( c < in_hdr.ncmap )
197  for ( i = 0; i < nraw[c]; i++ )
198  switch( scan[c][i].opcode )
199  {
200  case RRunDataOp:
201  scan[c][i].u.run_val =
202  map_pixel( scan[c][i].u.run_val,
203  cmaplen, isort );
204  break;
205  case RByteDataOp:
206  for ( j = 0; j < scan[c][i].length;
207  j++ )
208  scan[c][i].u.pixels[j] =
209  map_pixel( scan[c][i].u.pixels[j],
210  cmaplen, isort);
211  break;
212  }
213  }
214  rle_putraw( scan, nraw, &out_hdr );
215  rle_freeraw( &in_hdr, scan, nraw );
216  }
217  rle_puteof( &out_hdr );
218 
219  if ( in_hdr.ncmap > 0 )
220  {
221  free( cmap );
222  free( scmap );
223  free( mapp );
224  }
225 
226  rle_raw_free( &in_hdr, scan, nraw );
227  }
228 
229  /* Check for an error. EOF or EMPTY is ok if at least one image
230  * has been read. Otherwise, print an error message.
231  */
232  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
233  rle_get_error( rle_err, cmd_name( argv ), infname );
234 
235  exit( 0 );
236 }
237 
238 /*****************************************************************
239  * TAG( pcompar )
240  *
241  * Compares the indicated colormap entries using the Peano ordering.
242  * Inputs:
243  * a, b: Indices into the sortindex array (which indexes the
244  * colormap itself.)
245  * Outputs:
246  * Returns -1 if cmap[sortindex[a]] < cmap[sortindex[b]],
247  * 0 if they are equal, and
248  * 1 if a ">" b.
249  * Assumptions:
250  * (global) ncolors <= 4.
251  * Algorithm:
252  * Uses the Peano curve ordering for n=ncolors and m=8 to get a
253  * linear ordering for the n-dimensional colors.
254  */
255 int
257 int *ap, *bp;
258 {
259  int a = *ap, b = *bp;
260  unsigned long int ai, bi;
261  int c[4];
262 
263  switch( ncolor )
264  {
265  case 4: c[3] = cmap[3][a] >> 8;
266  case 3: c[2] = cmap[2][a] >> 8;
267  case 2: c[1] = cmap[1][a] >> 8;
268  case 1: c[0] = cmap[0][a] >> 8;
269  }
270  hilbert_c2i( ncolor, 8, c, &ai );
271 
272  switch( ncolor )
273  {
274  case 4: c[3] = cmap[3][b] >> 8;
275  case 3: c[2] = cmap[2][b] >> 8;
276  case 2: c[1] = cmap[1][b] >> 8;
277  case 1: c[0] = cmap[0][b] >> 8;
278  }
279  hilbert_c2i( ncolor, 8, c, &bi );
280 
281  if ( ai < bi )
282  return -1;
283  else if ( ai == bi )
284  return 0;
285  else
286  return 1;
287 }
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
#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
rle_map * cmap
Definition: rle.h:112
void hilbert_c2i(int n, int m, a, long int *r)
Definition: hilbert.c:245
void rle_putraw(rle_op **scanraw, int *nraw, rle_hdr *the_hdr)
Definition: rle_putraw.c:60
int * bg_color
Definition: rle.h:100
#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
static rle_map ** cmap
Definition: rlesortmap.c:19
const char * cmd
Definition: rle.h:133
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
int xmax
Definition: rle.h:100
int pcompar(int *ap, int *bp)
Definition: rlesortmap.c:256
static int ncolor
Definition: rlesortmap.c:20
#define RLE_EOF
Definition: rle.h:74
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
void rle_skiprow(rle_hdr *the_hdr, int nrow)
Definition: rle_putrow.c:393
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
int background
Definition: rle.h:100
int ncmap
Definition: rle.h:100
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
#define map_pixel(pix, cmaplen, cmap)
Definition: applymap.c:44
const char * rle_putcom(char *value, rle_hdr *the_hdr) const
Definition: rle_putcom.c:82
int cmaplen
Definition: rle.h:100
unsigned short rle_map
Definition: rle.h:57
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 RByteDataOp
Definition: rle_code.h:40
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86