Utah Raster Toolkit  9999-git
URT Development version (post-3.1b)
to8.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  * to8.c - Convert color images to 8 bit dithered.
20  *
21  * Author: Spencer W. Thomas
22  * Computer Science Dept.
23  * University of Utah
24  * Date: Fri Feb 28 1986
25  * Copyright (c) 1986, University of Utah
26  *
27  */
28 #ifndef lint
29 static char rcs_ident[] = "$Header: /tmp_mnt/n/itn/hendrix/u/spencer/RCS/to8.c,v 3.0.1.4 1992/04/30 14:14:43 spencer Exp spencer $";
30 #endif
31 
32 #include <stdio.h>
33 #include <math.h>
34 #include "rle.h"
35 
36 void init_color(), map_scanline();
37 
38 short map[3][256]; /* Output color map. */
39 int colmap[216][3];
40 rle_pixel ** in_cmap; /* color map in input file */
41 
42 int dm16[16][16];
43 
44 
45 int modN[256], divN[256];
46 
47 double disp_gam = 2.5;
48 double img_gam = 1.0;
49 
50 /*****************************************************************
51  * TAG( main )
52  *
53  * Usage: to8 [-{iI} gamma] [-g gamma] [-o outfile] [infile]
54  *
55  * Inputs:
56  * -i gamma: Specify gamma of image. (default 1.0)
57  * -I gamma: Specify gamma of display image was computed for.
58  * to8 will also read picture comments from the input file to determine
59  * the image gamma. These are
60  * image_gamma= gamma of image (equivalent to -i)
61  * display_gamma= gamma of display image was computed for.
62  * Command line arguments override values in the file.
63  *
64  * -g gamma: Specify gamma of display. (default 2.5)
65  * infile: Input (color) RLE file. Stdin used if not
66  * specified.
67  * Outputs:
68  * outfile: Output dithered RLE file. Stdout used
69  * if not specified.
70  * Assumptions:
71  * [None]
72  * Algorithm:
73  * [None]
74  */
75 
76 void
78 int argc;
79 char **argv;
80 {
81  char * infname = NULL, * outfname = NULL;
82  char comment[80]; /* for gamma comment */
83  FILE * outfile = stdout;
84  int oflag = 0, y, nrow, iflag = 0, gflag = 0;
85  rle_hdr in_hdr, out_hdr;
86  unsigned char ** scan, *outscan[2];
87  unsigned char * buffer;
88  int rle_cnt, rle_err;
89 
90  in_hdr = *rle_hdr_init( NULL );
91  out_hdr = *rle_hdr_init( NULL );
92 
93  if ( scanargs( argc, argv,
94  "% Ii%-gamma!F g%-gamma!F o%-outfile!s infile%s",
95  &iflag, &img_gam, &gflag, &disp_gam,
96  &oflag, &outfname, &infname ) == 0 )
97  exit( 1 );
98  in_hdr.rle_file = rle_open_f(cmd_name( argv ), infname, "r");
99  rle_names( &in_hdr, cmd_name( argv ), infname, 0 );
100  rle_names( &out_hdr, in_hdr.cmd, outfname, 0 );
101 
102  for ( rle_cnt = 0;
103  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
104  rle_cnt++ )
105  {
106 
107  if ( in_hdr.ncolors == 1 )
108  {
109  fprintf( stderr, "%s is already black & white\n",
110  infname ? infname : "stdin" );
111  exit( 1 );
112  }
113  if ( in_hdr.ncolors < 3 )
114  {
115  fprintf( stderr, "%s is not RGB",
116  infname ? infname : "stdin" );
117  exit( 1 );
118  }
119 
120  /* If no image gamma on command line, check comments in file */
121  if ( ! iflag )
122  {
123  char * v;
124  if ( (v = rle_getcom( "image_gamma", &in_hdr )) != NULL )
125  {
126  img_gam = atof( v );
127  /* Protect against bogus information */
128  if ( img_gam == 0.0 )
129  img_gam = 1.0;
130  else
131  img_gam = 1.0 / img_gam;
132  }
133  else if ( (v = rle_getcom( "display_gamma", &in_hdr )) != NULL )
134  {
135  img_gam = atof( v );
136  /* Protect */
137  if ( img_gam == 0.0 )
138  img_gam = 1.0;
139  }
140  }
141 
142  (void)rle_hdr_cp( &in_hdr, &out_hdr );
143  if ( rle_cnt == 0 )
144  outfile = rle_open_f(cmd_name( argv ), outfname, "w");
145  in_hdr.xmax -= in_hdr.xmin;
146  in_hdr.xmin = 0;
147  nrow = in_hdr.xmax + 1;
148  buffer = (unsigned char *)malloc( nrow );
149  RLE_CHECK_ALLOC( cmd_name( argv ), buffer, 0 );
150  if ( rle_row_alloc( &in_hdr, &scan ) < 0 )
151  RLE_CHECK_ALLOC( cmd_name( argv ), 0, 0 );
152 
153  if ( in_hdr.alpha )
154  {
155  outscan[0] = scan[-1];
156  }
157  outscan[1] = buffer;
158 
159  /* Use input color map, too */
160  in_cmap = buildmap( &in_hdr, 3, img_gam, 1.0 );
161 
162  init_color();
163  out_hdr.ncolors = 1;
164  out_hdr.ncmap = 3;
165  out_hdr.cmaplen = 8; /* 256 entries */
166  out_hdr.cmap = (rle_map *)map;
167  /* Delete color map length comment, if present. */
168  rle_delcom( "color_map_length", &out_hdr );
169 
170  /* Record gamma color map was computed for */
171  sprintf( comment, "display_gamma=%g", disp_gam );
172  rle_putcom( comment, &out_hdr );
173 
174  /*
175  * Give it a background color of black, since the real background
176  * will be dithered anyway.
177  */
178  if ( in_hdr.background != 0 )
179  {
180  out_hdr.bg_color = (int *)malloc( sizeof( int ) );
181  RLE_CHECK_ALLOC( cmd_name( argv ), out_hdr.bg_color, 0 );
182  out_hdr.bg_color[0] = 0;
183  }
184 
185  out_hdr.rle_file = outfile;
186 
187  rle_addhist( argv, &in_hdr, &out_hdr );
188 
189  rle_put_setup( &out_hdr );
190 
191  while ( (y = rle_getrow( &in_hdr, scan )) <=
192  in_hdr.ymax )
193  {
194  map_scanline( scan, nrow, y, buffer );
195  rle_putrow( &outscan[1], nrow, &out_hdr );
196  }
197 
198  rle_puteof( &out_hdr );
199 
200  rle_row_free( &in_hdr, scan );
201  }
202 
203  /* Check for an error. EOF or EMPTY is ok if at least one image
204  * has been read. Otherwise, print an error message.
205  */
206  if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
207  rle_get_error( rle_err, cmd_name( argv ), infname );
208 
209  exit( 0 );
210 }
211 
212 
213 /*
214  * Initialize the 8 bit color map. Choice of
215  * "alpha-1" (perceptual flavor) or linear maps
216  */
217 void
219 {
220  int i;
221 
223 
224  for (i = 0; i < 216; i++)
225  {
226  map[0][i] = colmap[i][0] << 8;
227  map[1][i] = colmap[i][1] << 8;
228  map[2][i] = colmap[i][2] << 8;
229  }
230 
231 }
232 
233 /*
234  * Map a scanline to 8 bits through the dither matrix.
235  */
236 #define DMAP(v,x,y) (modN[v]>dm16[x][y] ? divN[v] + 1 : divN[v])
237 
238 void
240 unsigned char *rgb[3], *line;
241 int n, y;
242 {
243  register unsigned char *r, *g, *b;
244  register int i, col, row;
245  for ( row = y % 16, col = 0, i = 0, r = rgb[0], g = rgb[1], b = rgb[2];
246  i < n; i++, r++, g++, b++, col = ((col + 1) & 15) )
247  line[i] = DMAP(in_cmap[0][*r], col, row) +
248  DMAP(in_cmap[1][*g], col, row) * 6 +
249  DMAP(in_cmap[2][*b], col, row) * 36;
250 }
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
rle_hdr * rle_hdr_cp(rle_hdr *from_hdr, rle_hdr *to_hdr)
Definition: rle_hdr.c:119
int modN[256]
Definition: to8.c:45
void rle_names(rle_hdr *the_hdr, const char *pgmname, const char *fname, int img_num)
Definition: rle_hdr.c:48
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
rle_map * cmap
Definition: rle.h:112
int rle_row_alloc(rle_hdr *the_hdr, rle_pixel ***scanp)
Definition: rle_row_alc.c:56
static char rcs_ident[]
Definition: to8.c:29
int rle_getrow(rle_hdr *the_hdr, scanline)
Definition: rle_getrow.c:333
int divN[256]
Definition: to8.c:45
int * bg_color
Definition: rle.h:100
#define RLE_SUCCESS
Definition: rle.h:70
int rle_get_error(int code, const char *pgmname, const char *fname)
Definition: rle_error.c:76
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
void rle_puteof(rle_hdr *the_hdr)
Definition: rle_putrow.c:474
double disp_gam
Definition: to8.c:47
void rle_putrow(rows, int rowlen, rle_hdr *the_hdr)
Definition: rle_putrow.c:96
int xmax
Definition: rle.h:100
const char * rle_delcom(char *name, the_hdr) const
Definition: rle_putcom.c:140
short map[3][256]
Definition: to8.c:38
#define RLE_EOF
Definition: rle.h:74
void rle_addhist(argv, rle_hdr *in_hdr, rle_hdr *out_hdr)
Definition: rle_addhist.c:54
char * rle_getcom(char *name, rle_hdr *the_hdr) const
Definition: rle_getcom.c:81
int background
Definition: rle.h:100
int colmap[216][3]
Definition: to8.c:39
int ncmap
Definition: rle.h:100
int ymax
Definition: rle.h:100
unsigned char rle_pixel
Definition: rle.h:56
void rle_put_setup(rle_hdr *the_hdr)
Definition: rle_putrow.c:453
const char * rle_putcom(char *value, rle_hdr *the_hdr) const
Definition: rle_putcom.c:82
double img_gam
Definition: to8.c:48
int cmaplen
Definition: rle.h:100
int alpha
Definition: rle.h:100
#define DMAP(v, x, y)
Definition: get_orion.c:310
unsigned short rle_map
Definition: rle.h:57
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
#define RLE_CHECK_ALLOC(pgm, ptr, name)
Definition: rle.h:86