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