1 /*
2  * rlehisto.c - Create histogram image of an RLE file.
3  *
4  * Author:	Gregg Townsend
5  *		Department of Computer Science
6  *		University of Arizona
7  * Date:	June 23, 1990
8  *
9  * Original version:
10  * Author:	Rod Bogart
11  * 		Computer Science Dept.
12  * 		University of Utah
13  * Date:	Thu Nov  6 1986
14  * Copyright (c) 1986 Rod Bogart
15  *
16  * Flags:
17  *    -b	Don't count background color values for scaling.
18  *    		Ineffective when -c specified.
19  *    -c	Output cumulative values instead of discrete values.
20  *    -t	Print totals of each value in each channel.
21  *    -h npix	Set height of image.
22  *    -o fname	Direct output to file.
23  */
24 #ifndef lint
25 static char rcs_ident[] = "$Id: rlehisto.c,v 3.0.1.2 1992/02/11 21:36:13 spencer Exp $";
26 #endif
27 
28 #include <stdio.h>
29 #include "rle.h"
30 
31 #define MAXCHAN 10
32 
33 int
main(argc,argv)34 main(argc, argv)
35 int	argc;
36 char	*argv[];
37 {
38     FILE *outfile = stdout;
39     int i, j, bflag=0, cflag=0, tflag=0, oflag=0;
40     int hist_height = 256;
41     rle_hdr 	in_hdr, out_hdr;
42     rle_pixel ** rows, ** rowsout;
43     rle_pixel *pixptr;
44     long *pixelcount[256];
45     long maxcount;
46     long n;
47     int	chan, nchan;
48     int rle_cnt, rle_err;
49     char *infname = NULL, *outfname = NULL;
50 
51     in_hdr = *rle_hdr_init( NULL );
52     out_hdr = *rle_hdr_init( NULL );
53 
54     if ( scanargs( argc, argv,
55 		   "% b%- c%- t%- h%-height!d o%-outfile!s infile%s",
56 		   &bflag, &cflag, &tflag,
57 		   &i, &hist_height,
58 		   &oflag, &outfname, &infname ) == 0 )
59 	exit( 1 );
60 
61     in_hdr.rle_file  = rle_open_f(cmd_name( argv ), infname, "r");
62     rle_names( &in_hdr, cmd_name( argv ), infname, 0 );
63     rle_names( &out_hdr, in_hdr.cmd, outfname, 0 );
64 
65     for ( rle_cnt = 0;
66 	  (rle_err = rle_get_setup( &in_hdr )) == RLE_SUCCESS;
67 	  rle_cnt++ )
68     {
69 	if ( rle_cnt == 0 )
70 	    outfile = rle_open_f(cmd_name( argv ), outfname, "w");
71 
72 	/* Only pay attention to bflag if background color is defined. */
73 	bflag = (bflag && in_hdr.bg_color != NULL);
74 
75 	in_hdr.xmax -= in_hdr.xmin;
76 	in_hdr.xmin = 0;
77 
78 	(void)rle_hdr_cp( &in_hdr, &out_hdr );
79 	out_hdr.cmap = (rle_map *)NULL;
80 	out_hdr.ncmap = 0;
81 	out_hdr.cmaplen = 0;
82 	out_hdr.background = 2;
83 	out_hdr.bg_color = (int *)calloc( in_hdr.ncolors, sizeof(int) );
84 	RLE_CHECK_ALLOC( cmd_name( argv ), out_hdr.bg_color,
85 			 "background" );
86 	out_hdr.alpha = 0;
87 	out_hdr.xmin = 0;
88 	out_hdr.xmax = 255;
89 	out_hdr.ymin = 0;
90 	out_hdr.ymax = hist_height - 1;
91 	out_hdr.rle_file = outfile;
92 
93 	nchan = in_hdr.ncolors;
94 
95 	if (!tflag)
96 	{
97 	    rle_addhist( argv, &in_hdr, &out_hdr );
98 	    rle_put_setup( &out_hdr );
99 	}
100 
101 	if ( rle_row_alloc( &out_hdr, &rowsout ) < 0 ||
102 	     rle_row_alloc( &in_hdr, &rows ) < 0 )
103 	    RLE_CHECK_ALLOC( cmd_name( argv ), 0, 0 );
104 
105 	for ( j = 0; j < 256; j++)
106 	{
107 	    if ( rle_cnt == 0 )
108 	    {
109 		pixelcount[j] = (long *) malloc(sizeof(long) * nchan);
110 		RLE_CHECK_ALLOC( cmd_name( argv ), pixelcount[j], 0 );
111 	    }
112 	    for (chan=0; chan < nchan; chan++)
113 	    {
114 		pixelcount[j][chan] = 0;
115 	    }
116 	}
117 	maxcount = 0;
118 
119 	for (j=in_hdr.ymin; j <= in_hdr.ymax; j++)
120 	{
121 	    rle_getrow(&in_hdr, rows);
122 	    for (chan=0; chan < nchan; chan++)
123 	    {
124 		pixptr = rows[chan];
125 		for (i=0; i < in_hdr.xmax + 1; i++)
126 		    pixelcount[ *pixptr++ ][ chan ] += 1;
127 	    }
128 	}
129 
130 	/* create cumulative figures if those are wanted. */
131 	if (cflag)
132 	{
133 	    for (chan = 0; chan < nchan; chan++)
134 	    {
135 		for (j = 1; j < 256; j++)
136 		    pixelcount[j][chan] += pixelcount[j-1][chan];
137 		if (pixelcount[255][chan] > maxcount)
138 		    maxcount = pixelcount[255][chan];
139 	    }
140 	}
141 	else
142 	    for ( chan = 0; chan < nchan; chan++ )
143 		for ( j = 0; j < 256; j++ )
144 		    if ( bflag && j == in_hdr.bg_color[chan] )
145 			continue;
146 		    else
147 			if ( pixelcount[j][chan] > maxcount )
148 			    maxcount = pixelcount[j][chan];
149 
150 	/* after entire image has been read in, output the histogram */
151 
152 	if (tflag)
153 	{
154 	    if ( rle_cnt > 0 )
155 		fprintf( outfile, "\n\n" );
156 	    for (j = 0; j < 256; j++)
157 	    {
158 		for (chan = 0; chan < nchan; chan++)
159 		    if (j > 0 && cflag) {
160 			if (pixelcount[j][chan] != pixelcount[j-1][chan])
161 			    break;
162 		    } else {
163 			if (pixelcount[j][chan] != 0)
164 			    break;
165 		    }
166 		if (chan == nchan)     /* if all entries zero, suppress line */
167 		    continue;
168 		fprintf(outfile, "%3d.", j);
169 		for (chan = 0; chan < nchan; chan++)
170 		    fprintf(outfile, "\t%ld", pixelcount[j][chan]);
171 		fprintf(outfile, "\n");
172 	    }
173 	}
174 	else
175 	{
176 	    for (i = 0; i < hist_height; i++)
177 	    {
178 		n = (maxcount * i) / (hist_height - 2);
179 		for (chan = 0; chan < nchan; chan++)
180 		{
181 		    for (j = 0; j < 256; j++)
182 		    {
183 			if (pixelcount[j][chan] > n)
184 			    rowsout[chan][j] = 255;
185 			else
186 			    rowsout[chan][j] = 0;
187 		    }
188 		}
189 		rle_putrow( rowsout, 256, &out_hdr);
190 	    }
191 	    rle_puteof( &out_hdr );
192 	}
193 
194 	/* Free memory. */
195 	rle_row_free( &out_hdr, rowsout );
196 	rle_row_free( &in_hdr, rows );
197     }
198     /* Check for an error.  EOF or EMPTY is ok if at least one image
199      * has been read.  Otherwise, print an error message.
200      */
201     if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
202 	 rle_get_error( rle_err, cmd_name( argv ), infname );
203 
204     exit( 0 );
205 }
206