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  * rletorast.c - Convert RLE to sun rasterfile.
20  *
21  * Author:	Rod Bogart, John W. Peterson & Ed Falk (SMI)
22  * 		Computer Science Dept.
23  * 		University of Utah
24  * Date:	Tue Nov  4 1986
25  * Copyright (c) 1986 Rod Bogart
26  * History:
27  *   6 September 1990: Clark: fix colormap output when hrle_dflt_dr.ncolors == 1 and
28  *                            hrle_dflt_dr.ncmap != 0 (i.e. pseudo_color image).
29  *   10 September 1990: Clark: fix bug in pointer calculation (optr = image + ...).
30  *
31  * Based on "tobw.c" by Spencer Thomas, and
32  * "rps" by Marc Majka (UBC Vision lab)
33  *
34  * If an input file isn't specified, it reads from stdin.  An output file
35  * can be specified with -o (otherwise it writes to stdout).
36  */
37 #include <stdio.h>
38 #include <math.h>
39 #include <rasterfile.h>
40 #include "rle.h"
41 
42 typedef	enum { GREY, GREY_ALPHA, COLOR, COLOR_ALPHA } Input_Type ;
43 
44 int
main(argc,argv)45 main( argc, argv )
46 int argc;
47 char **argv;
48 {
49     char       *infname = NULL,
50     	       *outfname = NULL;
51     FILE       *outfile = stdout;
52     rle_hdr	hdr;
53     int 	oflag = 0;
54     int 	y, ncol, nscan, nchan, nochan, i;
55     unsigned char **scan;
56     unsigned char *buffer;
57     struct rasterfile header ;
58     unsigned char *image ;
59     Input_Type 	input_type ;
60     int 	linebytes ;
61 
62     if ( scanargs( argc, argv,
63 	    "% o%-outfile!s infile%s",
64 	    &oflag, &outfname, &infname ) == 0 )
65 	exit( 1 );
66 
67     /* Open RLE file and get header information */
68     /* Initialize header. */
69     hdr = *rle_hdr_init( (rle_hdr *)NULL );
70     rle_names( &hdr, cmd_name( argv ), infname, 0 );
71 
72     hdr.rle_file = rle_open_f( hdr.cmd, infname, "r" );
73     rle_get_setup_ok( &hdr, NULL, NULL );
74 
75     if ( ( hdr.ncolors != 3 ) && ( hdr.ncolors != 1))
76     {
77 	fprintf( stderr, "%s is not RGB or b&w image",
78 		    infname ? infname : "stdin" );
79 	exit( 0 );
80     }
81 
82     outfile = rle_open_f( "rletorast", outfname, "w" );
83 
84     /*
85      * Spencer trick: save space by sliding the input image over to the
86      * left margin.
87      */
88     hdr.xmax -= hdr.xmin ;
89     hdr.xmin = 0 ;
90     ncol = hdr.xmax + 1;
91     nscan = hdr.ymax - hdr.ymin + 1;
92     nchan = hdr.ncolors + (hdr.alpha ? 1 : 0) ;
93 
94     if( hdr.alpha )
95     {
96       if( hdr.ncolors == 1 )
97 	input_type = GREY_ALPHA ;
98       else
99 	input_type = COLOR_ALPHA ;
100     }
101     else
102     {
103       if( hdr.ncolors == 1 )
104 	input_type = GREY ;
105       else
106 	input_type = COLOR ;
107     }
108 
109     /* Allocate scanline memory */
110     /*
111      * buffer = space for one scanline of one color
112      * scan = space for pointers to ncolors+alpha buffers
113      * scan[i] = pointer to space for one scanline of one color
114      */
115 
116     buffer = (unsigned char *)malloc( ncol );
117     rle_row_alloc( &hdr, &scan );
118 
119     header.ras_magic = RAS_MAGIC ;
120     header.ras_width = ncol ;
121     header.ras_height = nscan ;
122     switch(input_type)
123     {
124       case GREY: nochan = 1 ; break ;
125       case COLOR: nochan = 3 ; break ;
126       case GREY_ALPHA: case COLOR_ALPHA: nochan = 4 ; break ;
127       default: nochan = 4; break;
128     }
129     header.ras_depth = 8 * nochan ;
130     linebytes = header.ras_width * nochan ;
131     linebytes += linebytes % 2 ;
132     header.ras_length = linebytes * header.ras_height ;
133     header.ras_type = RT_STANDARD ;
134     if( hdr.ncmap != 0 )
135     {
136       header.ras_maptype = RMT_EQUAL_RGB ;
137       header.ras_maplength = (1 << hdr.cmaplen) * 3 ;
138     }
139     else
140     {
141       header.ras_maptype = RMT_NONE ;
142       header.ras_maplength = 0 ;
143     }
144 
145     fwrite( &header, sizeof(header), 1, outfile );
146 
147     if( header.ras_maptype == RMT_EQUAL_RGB )
148     {
149       register rle_map *iptr ;
150       unsigned char out ;
151       register int chan;
152       int nch, nco ;
153 
154       if( hdr.ncolors == 1 )
155       {
156 	nch = 3 ;
157 	nco = (1 << hdr.cmaplen) ;
158       }
159       else
160       {
161 	nch = 1 ;
162 	nco = header.ras_maplength ;
163       }
164 
165       for(chan=0; chan<nch; ++chan)
166       {
167 	iptr = hdr.cmap + (chan<<8) ;
168 	for(i=0; i<nco; ++i)
169 	{
170 	  out = (*iptr++ + 0x80) >> 8 ;
171 	  fwrite(&out, 1,1, outfile) ;
172 	}
173       }
174     }
175 
176     if( hdr.comments != NULL )
177     {
178       register CONST_DECL char **comment = hdr.comments ;
179       while(*comment != NULL)
180       {
181 	fprintf(stderr,"%s\n", *comment) ;
182 	++comment ;
183       }
184     }
185 
186   image = (unsigned char *) malloc(linebytes * header.ras_height) ;
187 
188   if( hdr.background != 0 )
189   {
190     register int row,col,chan ;
191     register unsigned char *ptr ;
192     register int *bptr ;
193     for(row=0; row<nscan; ++row)
194     {
195       ptr = image + row*linebytes ;
196       for(col=ncol; --col >= 0; )
197       {
198 	if( hdr.alpha )
199 	  *ptr++ = 0 ;
200 	bptr = hdr.bg_color ;
201 	for(chan=hdr.ncolors; --chan >= 0; )
202 	  *ptr++ = *bptr++ ;
203       }
204     }
205   }
206 
207 
208 
209   while ( (y = rle_getrow( &hdr, scan )) <=
210 	  hdr.ymax )
211   {
212     register unsigned char *optr, *a,*r,*g,*b ;
213     register int col ;
214 
215     optr = image + (nscan-y-1+hdr.ymin)*linebytes ;
216     switch( input_type )
217     {
218       case GREY:
219 	r = scan[RLE_RED] ;
220 	for(col=ncol; --col >= 0; )
221 	  *optr++ = *r++ ;
222 	break ;
223 
224       case GREY_ALPHA:
225 	a = scan[RLE_ALPHA] ;
226 	r = scan[RLE_RED] ;
227 	for(col=ncol; --col >= 0; )
228 	{
229 	  *optr++ = *a++ ;
230 	  *optr++ = *optr++ = *optr++ = *r++ ;
231 	}
232 	break ;
233 
234       case COLOR:
235 	r = scan[RLE_RED] ;
236 	g = scan[RLE_GREEN] ;
237 	b = scan[RLE_BLUE] ;
238 	for(col=ncol; --col >= 0; )
239 	{
240 	  *optr++ = *r++ ;
241 	  *optr++ = *g++ ;
242 	  *optr++ = *b++ ;
243 	}
244 	break ;
245 
246       case COLOR_ALPHA:
247 	a = scan[RLE_ALPHA] ;
248 	r = scan[RLE_RED] ;
249 	g = scan[RLE_GREEN] ;
250 	b = scan[RLE_BLUE] ;
251 	for(col=ncol; --col >= 0; )
252 	{
253 	  *optr++ = *a++ ;
254 	  *optr++ = *r++ ;
255 	  *optr++ = *g++ ;
256 	  *optr++ = *b++ ;
257 	}
258 	break ;
259     }
260   }
261   fwrite(image, linebytes * header.ras_height, 1, outfile) ;
262 
263   exit( 0 );
264 }
265