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  * crop.c - Crop an image to the given size.
20  *
21  * Author:	Rod Bogart & John W. Peterson
22  * 		Computer Science Dept.
23  * 		University of Utah
24  * Date:	Mon Jun 23 1986
25  * Copyright (c) 1986, University of Utah
26  *
27  */
28 #ifndef lint
29 static char rcs_ident[] = "$Header: /l/spencer/src/urt/tools/RCS/crop.c,v 3.0.1.2 1992/04/30 14:09:40 spencer Exp $";
30 #endif
31 
32 #include <stdio.h>
33 #include "rle.h"
34 
35 extern void rle_box();
36 int pos_box_vals();
37 
38 int
main(argc,argv)39 main(argc, argv)
40 int	argc;
41 char	*argv[];
42 {
43     rle_pixel **scanline, **rows, **outrows;
44     int xlen, i, j;
45     int xmin = -1, ymin = -1, xmax = -1, ymax = -1;
46     char *infilename = NULL, *out_fname = NULL;
47     FILE *outfile = stdout;
48     int oflag = 0, bflag = 0, bottom_row;
49     rle_hdr 	in_hdr, out_hdr;
50     int rle_cnt, rle_err;
51     long start;
52 
53     in_hdr = *rle_hdr_init( NULL );
54     out_hdr = *rle_hdr_init( NULL );
55 
56     if (scanargs( argc, argv,
57 		  "% b%- xmin%d ymin%d xmax%d ymax%d o%-outfile!s infile%s",
58 		  &bflag, &xmin, &ymin, &xmax, &ymax, &oflag,  &out_fname,
59 		  &infilename ) == 0)
60     {
61 	exit(-1);
62     }
63 
64     in_hdr.rle_file = rle_open_f( cmd_name( argv ), infilename, "r" );
65     rle_names( &in_hdr, cmd_name( argv ), infilename, 0 );
66     rle_names( &out_hdr, in_hdr.cmd, out_fname, 0 );
67     for ( rle_cnt = 0; ; rle_cnt++ )
68     {
69 	start = ftell( in_hdr.rle_file );
70 	if ( (rle_err = rle_get_setup( &in_hdr )) != RLE_SUCCESS )
71 	    break;
72 
73 	(void)rle_hdr_cp( &in_hdr, &out_hdr );
74 	rle_addhist( argv, &in_hdr, &out_hdr );
75 
76 	if ( rle_cnt == 0 )
77 	    outfile = rle_open_f( cmd_name( argv ), out_fname, "w" );
78 	out_hdr.rle_file = outfile;
79 
80 	/* If bflag, then pre-scan file to get bounding box. */
81 	if (bflag != 0)
82 	{
83 	    if (xmin == -1 && start >= 0)
84 	    {
85 		/* Common code with rlebox program. */
86 		rle_box( &in_hdr, &xmin, &xmax, &ymin, &ymax );
87 
88 		/* Rewind and start over. */
89 		fseek( in_hdr.rle_file, start, 0 );
90 		rle_get_setup( &in_hdr );	/* Should work fine this time. */
91 	    }
92 	    else
93 	    {
94 		/* error message and exit: -b flag and box values or piped input */
95 		if (xmin != -1)
96 		    fprintf( stderr,
97 			     "%s: You cannot specify the -b flag and box values together\n",
98 			     cmd_name( argv ) );
99 		else
100 		    fprintf( stderr,
101 			     "%s: No piped input allowed with the -b flag\n",
102 			     cmd_name( argv ) );
103 		exit(-1);
104 	    }
105 	}
106 	else if ( pos_box_vals( xmin, ymin, xmax, ymax ) != 0 )
107 	{
108 	    fprintf( stderr,
109 		     "%s: You must specify either all the box coordinates or the -b flag\n",
110 		     cmd_name( argv ) );
111 	    exit(-1);
112 	}
113 
114 	xlen = xmax - xmin + 1;
115 
116 	if ( (xmin > xmax) || (ymin > ymax) )
117 	{
118 	    fprintf( stderr, "%s: Illegal size: %d, %d to %d, %d\n",
119 		     cmd_name( argv ), xmin, ymin, xmax, ymax );
120 	    exit(-1);
121 	}
122 
123 	/* should check for disjoint regions */
124 
125 	out_hdr.xmin = xmin;
126 	out_hdr.ymin = ymin;
127 	out_hdr.xmax = xmax;
128 	out_hdr.ymax = ymax;
129 
130 	rle_put_setup( &out_hdr );
131 
132 	if (out_hdr.xmax > in_hdr.xmax)
133 	    RLE_CHECK_ALLOC( cmd_name( argv ),
134 			     rle_row_alloc( &out_hdr, &scanline ) == 0,
135 			     "image data" );
136 	else
137 	    RLE_CHECK_ALLOC( cmd_name( argv ),
138 			     rle_row_alloc( &in_hdr, &scanline ) == 0,
139 			     "image data" );
140 
141 	rows = (rle_pixel **)
142 	    malloc((in_hdr.ncolors + in_hdr.alpha) * sizeof( rle_pixel * ));
143 	RLE_CHECK_ALLOC( cmd_name( argv ), rows, "input image data" );
144 
145 	outrows = (rle_pixel **)
146 	    malloc((in_hdr.ncolors + in_hdr.alpha) * sizeof( rle_pixel * ));
147 	RLE_CHECK_ALLOC( cmd_name( argv ), outrows, "output image data" );
148 
149 	if ( in_hdr.alpha )
150 	{
151 	    rows++;		/* So alpha is rows[-1] */
152 	    outrows++;
153 	}
154 
155 	for( i = -in_hdr.alpha; i < in_hdr.ncolors; i++ )
156 	    rows[i] = scanline[i];
157 
158 	for( i = -in_hdr.alpha; i < in_hdr.ncolors; i++ )
159 	    outrows[i] = &scanline[i][xmin];
160 
161 	/* Fill scanline with background color in case output is
162 	 * larger than input.
163 	 */
164 	for ( j = -in_hdr.alpha; j < in_hdr.ncolors; j++ )
165 	    if ( in_hdr.bg_color && j >= 0 && in_hdr.bg_color[j] != 0 )
166 	    {
167 		int c = in_hdr.bg_color[j];
168 		register rle_pixel *pix;
169 		for ( i = out_hdr.xmin, pix = &scanline[j][i];
170 		      i <= out_hdr.xmax;
171 		      i++, pix++ )
172 		    *pix = c;
173 	    }
174 	    else
175 		bzero( (char *)&scanline[j][out_hdr.xmin],
176 		       out_hdr.xmax - out_hdr.xmin + 1 );
177 
178 	bottom_row = in_hdr.ymin;
179 	if (in_hdr.ymin > out_hdr.ymin)
180 	{
181 	    /* Output blank scanlines if crop region is larger than data */
182 	    rle_skiprow(&out_hdr, in_hdr.ymin - out_hdr.ymin);
183 	    bottom_row = in_hdr.ymin;
184 	}
185 	else
186 	    if (in_hdr.ymin < out_hdr.ymin)
187 	    {
188 		/* Read past extra lower scanlines */
189 		for (i = in_hdr.ymin; i < out_hdr.ymin; i++)
190 		    rle_getrow(&in_hdr, rows );
191 		bottom_row = out_hdr.ymin;
192 	    }
193 
194 	/* Read in image */
195 	for (j = bottom_row; j <= out_hdr.ymax; j++)
196 	{
197 	    rle_getrow(&in_hdr, rows );
198 
199 	    rle_putrow( outrows, xlen, &out_hdr );
200 	}
201 	rle_puteof( &out_hdr );
202 
203 	/* Skip extra upper scanlines. */
204 	while ( rle_getskip( &in_hdr ) != 32768 )
205 	    ;
206 
207 	/* Clean up for next time around. */
208 	rle_row_free( (out_hdr.xmax > in_hdr.xmax) ? &out_hdr : &in_hdr,
209 		      scanline );
210 	free( rows - in_hdr.alpha );
211 	free( outrows - in_hdr.alpha );
212 
213 	if ( bflag )
214 	    xmin = xmax = ymin = ymax = -1;
215     }
216 
217     /* Check for an error.  EOF or EMPTY is ok if at least one image
218      * has been read.  Otherwise, print an error message.
219      */
220     if ( rle_cnt == 0 || (rle_err != RLE_EOF && rle_err != RLE_EMPTY) )
221 	rle_get_error( rle_err, cmd_name( argv ), infilename );
222 
223 
224     exit( 0 );
225 }
226 
227 /* Return 0 if all parameters >= 0, else -1. */
228 int
pos_box_vals(x1,y1,x2,y2)229 pos_box_vals(x1, y1, x2, y2)
230 int x1, y1, x2, y2;
231 {
232   if ((x1 < 0) || (y1 < 0) || (x2 < 0) || (y2 < 0))
233     return -1;
234   else
235     return 0;
236 }
237