| 1 |
greg |
2.1 |
#ifndef lint
|
| 2 |
greg |
2.58 |
static const char RCSid[] = "$Id: rpiece.c,v 2.57 2018/08/21 17:46:09 greg Exp $";
|
| 3 |
greg |
2.1 |
#endif
|
| 4 |
|
|
/*
|
| 5 |
|
|
* Generate sections of a picture.
|
| 6 |
|
|
*/
|
| 7 |
|
|
|
| 8 |
schorsch |
2.43 |
|
| 9 |
|
|
#include <stdio.h>
|
| 10 |
|
|
#include <signal.h>
|
| 11 |
|
|
#include <sys/types.h>
|
| 12 |
schorsch |
2.49 |
|
| 13 |
|
|
#include "platform.h"
|
| 14 |
schorsch |
2.45 |
#ifndef NON_POSIX /* XXX need abstraction for process management */
|
| 15 |
|
|
#include <sys/wait.h>
|
| 16 |
|
|
#endif
|
| 17 |
schorsch |
2.43 |
|
| 18 |
greg |
2.44 |
#include "standard.h"
|
| 19 |
schorsch |
2.43 |
#include "color.h"
|
| 20 |
|
|
#include "view.h"
|
| 21 |
|
|
#include "rtprocess.h"
|
| 22 |
greg |
2.16 |
|
| 23 |
|
|
#ifndef F_SETLKW
|
| 24 |
|
|
|
| 25 |
schorsch |
2.43 |
int
|
| 26 |
|
|
main(
|
| 27 |
|
|
int argc,
|
| 28 |
|
|
char *argv[]
|
| 29 |
|
|
)
|
| 30 |
greg |
2.16 |
{
|
| 31 |
|
|
fprintf(stderr, "%s: no NFS lock manager on this machine\n", argv[0]);
|
| 32 |
|
|
exit(1);
|
| 33 |
|
|
}
|
| 34 |
|
|
|
| 35 |
|
|
#else
|
| 36 |
|
|
|
| 37 |
greg |
2.12 |
#ifndef NFS
|
| 38 |
|
|
#define NFS 1
|
| 39 |
|
|
#endif
|
| 40 |
greg |
2.55 |
|
| 41 |
|
|
#ifndef RHAS_FORK_EXEC
|
| 42 |
|
|
#undef MAXFORK
|
| 43 |
|
|
#define MAXFORK 0
|
| 44 |
|
|
#endif
|
| 45 |
greg |
2.9 |
#ifndef MAXFORK
|
| 46 |
greg |
2.12 |
#if NFS
|
| 47 |
greg |
2.10 |
#define MAXFORK 3 /* allotment of duped processes */
|
| 48 |
greg |
2.12 |
#else
|
| 49 |
|
|
#define MAXFORK 0
|
| 50 |
greg |
2.9 |
#endif
|
| 51 |
greg |
2.12 |
#endif
|
| 52 |
greg |
2.18 |
/* protection from SYSV signals(!) */
|
| 53 |
greg |
2.27 |
#if defined(sgi)
|
| 54 |
greg |
2.18 |
#define guard_io() sighold(SIGALRM)
|
| 55 |
|
|
#define unguard() sigrelse(SIGALRM)
|
| 56 |
|
|
#endif
|
| 57 |
|
|
#ifndef guard_io
|
| 58 |
schorsch |
2.43 |
#define guard_io()
|
| 59 |
|
|
#define unguard()
|
| 60 |
greg |
2.18 |
#endif
|
| 61 |
gregl |
2.34 |
|
| 62 |
greg |
2.37 |
extern char *strerror();
|
| 63 |
gregl |
2.34 |
|
| 64 |
greg |
2.1 |
/* rpict command */
|
| 65 |
greg |
2.23 |
char *rpargv[128] = {"rpict", "-S", "1"};
|
| 66 |
|
|
int rpargc = 3;
|
| 67 |
greg |
2.1 |
FILE *torp, *fromrp;
|
| 68 |
greg |
2.8 |
COLR *pbuf;
|
| 69 |
greg |
2.1 |
/* our view parameters */
|
| 70 |
|
|
VIEW ourview = STDVIEW;
|
| 71 |
greg |
2.4 |
double pixaspect = 1.0;
|
| 72 |
greg |
2.23 |
int hres = 1024, vres = 1024, hmult = 4, vmult = 4;
|
| 73 |
greg |
2.1 |
/* output file */
|
| 74 |
|
|
char *outfile = NULL;
|
| 75 |
|
|
int outfd;
|
| 76 |
|
|
long scanorig;
|
| 77 |
greg |
2.25 |
FILE *syncfp = NULL; /* synchronization file pointer */
|
| 78 |
|
|
int synclst = F_UNLCK; /* synchronization file lock status */
|
| 79 |
greg |
2.9 |
int nforked = 0;
|
| 80 |
greg |
2.1 |
|
| 81 |
greg |
2.25 |
#define sflock(t) if ((t)!=synclst) dolock(fileno(syncfp),synclst=t)
|
| 82 |
|
|
|
| 83 |
greg |
2.1 |
char *progname;
|
| 84 |
|
|
int verbose = 0;
|
| 85 |
greg |
2.53 |
int nowarn = 0;
|
| 86 |
greg |
2.31 |
unsigned timelim = 0;
|
| 87 |
greg |
2.25 |
int rvrlim = -1;
|
| 88 |
greg |
2.1 |
|
| 89 |
greg |
2.6 |
int gotalrm = 0;
|
| 90 |
schorsch |
2.38 |
void onalrm(int i) { gotalrm++; }
|
| 91 |
greg |
2.1 |
|
| 92 |
schorsch |
2.43 |
static void dolock(int fd, int ltyp);
|
| 93 |
|
|
static void init(int ac, char **av);
|
| 94 |
|
|
static int nextpiece(int *xp, int *yp);
|
| 95 |
|
|
static int rvrpiece(int *xp, int *yp);
|
| 96 |
|
|
static int cleanup(int rstat);
|
| 97 |
|
|
static void rpiece(void);
|
| 98 |
|
|
static int putpiece(int xpos, int ypos);
|
| 99 |
|
|
static void filerr(char *t);
|
| 100 |
greg |
2.6 |
|
| 101 |
schorsch |
2.43 |
|
| 102 |
|
|
int
|
| 103 |
|
|
main(
|
| 104 |
|
|
int argc,
|
| 105 |
|
|
char *argv[]
|
| 106 |
|
|
)
|
| 107 |
greg |
2.1 |
{
|
| 108 |
greg |
2.55 |
int i, rval;
|
| 109 |
greg |
2.1 |
|
| 110 |
|
|
progname = argv[0];
|
| 111 |
|
|
for (i = 1; i < argc; i++) {
|
| 112 |
greg |
2.22 |
/* expand arguments */
|
| 113 |
greg |
2.37 |
while ((rval = expandarg(&argc, &argv, i)) > 0)
|
| 114 |
|
|
;
|
| 115 |
|
|
if (rval < 0) {
|
| 116 |
greg |
2.50 |
fprintf(stderr, "%s: cannot expand '%s'\n",
|
| 117 |
greg |
2.37 |
argv[0], argv[i]);
|
| 118 |
|
|
exit(1);
|
| 119 |
|
|
}
|
| 120 |
greg |
2.1 |
if (argv[i][0] == '-')
|
| 121 |
|
|
switch (argv[i][1]) {
|
| 122 |
greg |
2.53 |
case 'w':
|
| 123 |
|
|
if (!argv[i][2])
|
| 124 |
|
|
nowarn = !nowarn;
|
| 125 |
|
|
else if (argv[i][2] == '+')
|
| 126 |
|
|
nowarn = 0;
|
| 127 |
|
|
else if (argv[i][2] == '-')
|
| 128 |
|
|
nowarn = 1;
|
| 129 |
|
|
break;
|
| 130 |
greg |
2.1 |
case 'v':
|
| 131 |
|
|
switch (argv[i][2]) {
|
| 132 |
|
|
case '\0': /* verbose option */
|
| 133 |
|
|
verbose = !verbose;
|
| 134 |
|
|
continue;
|
| 135 |
|
|
case 'f': /* view file */
|
| 136 |
|
|
if (viewfile(argv[++i], &ourview, NULL) <= 0) {
|
| 137 |
|
|
fprintf(stderr,
|
| 138 |
|
|
"%s: not a view file\n", argv[i]);
|
| 139 |
|
|
exit(1);
|
| 140 |
|
|
}
|
| 141 |
|
|
continue;
|
| 142 |
|
|
default: /* view option? */
|
| 143 |
|
|
rval = getviewopt(&ourview, argc-i, argv+i);
|
| 144 |
|
|
if (rval >= 0) {
|
| 145 |
|
|
i += rval;
|
| 146 |
|
|
continue;
|
| 147 |
|
|
}
|
| 148 |
|
|
break;
|
| 149 |
|
|
}
|
| 150 |
|
|
break;
|
| 151 |
|
|
case 'p': /* pixel aspect ratio? */
|
| 152 |
greg |
2.51 |
if (argv[i][2] == 'm') {
|
| 153 |
|
|
fprintf(stderr, "%s: -pm unsupported\n",
|
| 154 |
|
|
argv[0]);
|
| 155 |
|
|
++i;
|
| 156 |
|
|
continue;
|
| 157 |
|
|
}
|
| 158 |
greg |
2.23 |
if (argv[i][2] != 'a' || argv[i][3])
|
| 159 |
|
|
break;
|
| 160 |
gregl |
2.35 |
pixaspect = atof(argv[++i]);
|
| 161 |
greg |
2.23 |
continue;
|
| 162 |
greg |
2.31 |
case 'T': /* time limit (hours) */
|
| 163 |
|
|
if (argv[i][2])
|
| 164 |
|
|
break;
|
| 165 |
|
|
timelim = atof(argv[++i])*3600. + .5;
|
| 166 |
greg |
2.51 |
continue;
|
| 167 |
greg |
2.23 |
case 'x': /* overall x resolution */
|
| 168 |
|
|
if (argv[i][2])
|
| 169 |
|
|
break;
|
| 170 |
|
|
hres = atoi(argv[++i]);
|
| 171 |
|
|
continue;
|
| 172 |
|
|
case 'y': /* overall y resolution */
|
| 173 |
|
|
if (argv[i][2])
|
| 174 |
|
|
break;
|
| 175 |
|
|
vres = atoi(argv[++i]);
|
| 176 |
|
|
continue;
|
| 177 |
greg |
2.1 |
case 'X': /* horizontal multiplier */
|
| 178 |
|
|
if (argv[i][2])
|
| 179 |
|
|
break;
|
| 180 |
|
|
hmult = atoi(argv[++i]);
|
| 181 |
|
|
continue;
|
| 182 |
|
|
case 'Y': /* vertical multiplier */
|
| 183 |
|
|
if (argv[i][2])
|
| 184 |
|
|
break;
|
| 185 |
|
|
vmult = atoi(argv[++i]);
|
| 186 |
|
|
continue;
|
| 187 |
greg |
2.25 |
case 'R': /* recover */
|
| 188 |
|
|
if (argv[i][2])
|
| 189 |
|
|
break;
|
| 190 |
|
|
rvrlim = 0;
|
| 191 |
|
|
/* fall through */
|
| 192 |
greg |
2.5 |
case 'F': /* syncronization file */
|
| 193 |
|
|
if (argv[i][2])
|
| 194 |
|
|
break;
|
| 195 |
greg |
2.28 |
if ((syncfp =
|
| 196 |
|
|
fdopen(open(argv[++i],O_RDWR|O_CREAT,0666),"r+")) == NULL) {
|
| 197 |
greg |
2.5 |
fprintf(stderr, "%s: cannot open\n",
|
| 198 |
|
|
argv[i]);
|
| 199 |
|
|
exit(1);
|
| 200 |
|
|
}
|
| 201 |
|
|
continue;
|
| 202 |
greg |
2.15 |
case 'z': /* z-file ist verbotten */
|
| 203 |
|
|
fprintf(stderr, "%s: -z option not allowed\n",
|
| 204 |
|
|
argv[0]);
|
| 205 |
|
|
exit(1);
|
| 206 |
greg |
2.1 |
case 'o': /* output file */
|
| 207 |
|
|
if (argv[i][2])
|
| 208 |
|
|
break;
|
| 209 |
|
|
outfile = argv[++i];
|
| 210 |
|
|
continue;
|
| 211 |
greg |
2.53 |
}
|
| 212 |
|
|
else if (i >= argc-1)
|
| 213 |
|
|
break;
|
| 214 |
greg |
2.1 |
rpargv[rpargc++] = argv[i];
|
| 215 |
|
|
}
|
| 216 |
greg |
2.23 |
if (i >= argc) {
|
| 217 |
|
|
fprintf(stderr, "%s: missing octree argument\n", argv[0]);
|
| 218 |
|
|
exit(1);
|
| 219 |
|
|
}
|
| 220 |
greg |
2.1 |
if (outfile == NULL) {
|
| 221 |
|
|
fprintf(stderr, "%s: missing output file\n", argv[0]);
|
| 222 |
|
|
exit(1);
|
| 223 |
|
|
}
|
| 224 |
|
|
init(argc, argv);
|
| 225 |
|
|
rpiece();
|
| 226 |
greg |
2.15 |
exit(cleanup(0));
|
| 227 |
greg |
2.1 |
}
|
| 228 |
|
|
|
| 229 |
|
|
|
| 230 |
schorsch |
2.43 |
static void
|
| 231 |
|
|
dolock( /* lock or unlock a file */
|
| 232 |
|
|
int fd,
|
| 233 |
|
|
int ltyp
|
| 234 |
|
|
)
|
| 235 |
greg |
2.25 |
{
|
| 236 |
|
|
static struct flock fls; /* static so initialized to zeroes */
|
| 237 |
|
|
|
| 238 |
|
|
fls.l_type = ltyp;
|
| 239 |
|
|
if (fcntl(fd, F_SETLKW, &fls) < 0) {
|
| 240 |
greg |
2.28 |
fprintf(stderr, "%s: cannot lock/unlock file: %s\n",
|
| 241 |
greg |
2.37 |
progname, strerror(errno));
|
| 242 |
greg |
2.54 |
_exit(1);
|
| 243 |
greg |
2.25 |
}
|
| 244 |
|
|
}
|
| 245 |
|
|
|
| 246 |
|
|
|
| 247 |
schorsch |
2.43 |
static void
|
| 248 |
|
|
init( /* set up output file and start rpict */
|
| 249 |
|
|
int ac,
|
| 250 |
|
|
char **av
|
| 251 |
|
|
)
|
| 252 |
greg |
2.1 |
{
|
| 253 |
greg |
2.23 |
static char hrbuf[16], vrbuf[16];
|
| 254 |
greg |
2.2 |
extern char VersionID[];
|
| 255 |
greg |
2.1 |
char *err;
|
| 256 |
|
|
FILE *fp;
|
| 257 |
|
|
int hr, vr;
|
| 258 |
schorsch |
2.39 |
SUBPROC rpd; /* since we don't close_process(), this can be local */
|
| 259 |
greg |
2.1 |
/* set up view */
|
| 260 |
|
|
if ((err = setview(&ourview)) != NULL) {
|
| 261 |
|
|
fprintf(stderr, "%s: %s\n", progname, err);
|
| 262 |
|
|
exit(1);
|
| 263 |
|
|
}
|
| 264 |
greg |
2.25 |
if (syncfp != NULL) {
|
| 265 |
|
|
sflock(F_RDLCK);
|
| 266 |
|
|
fscanf(syncfp, "%d %d", &hmult, &vmult);
|
| 267 |
|
|
sflock(F_UNLCK);
|
| 268 |
greg |
2.5 |
}
|
| 269 |
greg |
2.23 |
/* compute piece size */
|
| 270 |
greg |
2.53 |
hr = hres; vr = vres;
|
| 271 |
|
|
if (pixaspect > FTINY)
|
| 272 |
|
|
normaspect(viewaspect(&ourview), &pixaspect, &hr, &vr);
|
| 273 |
greg |
2.23 |
hres /= hmult;
|
| 274 |
|
|
vres /= vmult;
|
| 275 |
greg |
2.46 |
if (hres <= 0 || vres <= 0) {
|
| 276 |
greg |
2.47 |
fprintf(stderr, "%s: illegal resolution/subdivision\n", progname);
|
| 277 |
greg |
2.46 |
exit(1);
|
| 278 |
|
|
}
|
| 279 |
greg |
2.1 |
normaspect(viewaspect(&ourview)*hmult/vmult, &pixaspect, &hres, &vres);
|
| 280 |
greg |
2.53 |
if (!nowarn && (hr != hres*hmult) | (vr != vres*vmult))
|
| 281 |
|
|
fprintf(stderr,
|
| 282 |
greg |
2.57 |
"%s: warning - changed resolution from %dx%d to %dx%d\n",
|
| 283 |
greg |
2.53 |
progname, hr, vr, hres*hmult, vres*vmult);
|
| 284 |
greg |
2.23 |
sprintf(hrbuf, "%d", hres);
|
| 285 |
|
|
rpargv[rpargc++] = "-x"; rpargv[rpargc++] = hrbuf;
|
| 286 |
|
|
sprintf(vrbuf, "%d", vres);
|
| 287 |
|
|
rpargv[rpargc++] = "-y"; rpargv[rpargc++] = vrbuf;
|
| 288 |
|
|
rpargv[rpargc++] = "-pa"; rpargv[rpargc++] = "0";
|
| 289 |
|
|
rpargv[rpargc++] = av[ac-1];
|
| 290 |
|
|
rpargv[rpargc] = NULL;
|
| 291 |
greg |
2.1 |
/* open output file */
|
| 292 |
|
|
if ((outfd = open(outfile, O_WRONLY|O_CREAT|O_EXCL, 0666)) >= 0) {
|
| 293 |
greg |
2.25 |
dolock(outfd, F_WRLCK);
|
| 294 |
greg |
2.1 |
if ((fp = fdopen(dup(outfd), "w")) == NULL)
|
| 295 |
|
|
goto filerr;
|
| 296 |
greg |
2.29 |
newheader("RADIANCE", fp); /* create header */
|
| 297 |
|
|
printargs(ac, av, fp);
|
| 298 |
greg |
2.2 |
fprintf(fp, "SOFTWARE= %s\n", VersionID);
|
| 299 |
greg |
2.1 |
fputs(VIEWSTR, fp);
|
| 300 |
|
|
fprintview(&ourview, fp);
|
| 301 |
|
|
putc('\n', fp);
|
| 302 |
greg |
2.52 |
fputnow(fp);
|
| 303 |
greg |
2.1 |
if (pixaspect < .99 || pixaspect > 1.01)
|
| 304 |
|
|
fputaspect(pixaspect, fp);
|
| 305 |
|
|
fputformat(COLRFMT, fp);
|
| 306 |
|
|
putc('\n', fp);
|
| 307 |
|
|
fprtresolu(hres*hmult, vres*vmult, fp);
|
| 308 |
|
|
} else if ((outfd = open(outfile, O_RDWR)) >= 0) {
|
| 309 |
greg |
2.25 |
dolock(outfd, F_RDLCK);
|
| 310 |
greg |
2.1 |
if ((fp = fdopen(dup(outfd), "r+")) == NULL)
|
| 311 |
|
|
goto filerr;
|
| 312 |
greg |
2.13 |
getheader(fp, NULL, NULL); /* skip header */
|
| 313 |
greg |
2.15 |
if (!fscnresolu(&hr, &vr, fp) || /* check resolution */
|
| 314 |
greg |
2.1 |
hr != hres*hmult || vr != vres*vmult) {
|
| 315 |
greg |
2.8 |
fprintf(stderr, "%s: resolution mismatch on file \"%s\"\n",
|
| 316 |
|
|
progname, outfile);
|
| 317 |
greg |
2.1 |
exit(1);
|
| 318 |
|
|
}
|
| 319 |
|
|
} else {
|
| 320 |
greg |
2.8 |
fprintf(stderr, "%s: cannot open file \"%s\"\n",
|
| 321 |
|
|
progname, outfile);
|
| 322 |
greg |
2.1 |
exit(1);
|
| 323 |
|
|
}
|
| 324 |
|
|
scanorig = ftell(fp); /* record position of first scanline */
|
| 325 |
|
|
if (fclose(fp) == -1) /* done with stream i/o */
|
| 326 |
|
|
goto filerr;
|
| 327 |
greg |
2.25 |
dolock(outfd, F_UNLCK);
|
| 328 |
greg |
2.1 |
/* start rpict process */
|
| 329 |
greg |
2.58 |
rpd = sp_inactive;
|
| 330 |
schorsch |
2.39 |
if (open_process(&rpd, rpargv) <= 0) {
|
| 331 |
greg |
2.3 |
fprintf(stderr, "%s: cannot start %s\n", progname, rpargv[0]);
|
| 332 |
greg |
2.1 |
exit(1);
|
| 333 |
|
|
}
|
| 334 |
schorsch |
2.39 |
if ((fromrp = fdopen(rpd.r, "r")) == NULL ||
|
| 335 |
|
|
(torp = fdopen(rpd.w, "w")) == NULL) {
|
| 336 |
greg |
2.1 |
fprintf(stderr, "%s: cannot open stream to %s\n",
|
| 337 |
|
|
progname, rpargv[0]);
|
| 338 |
|
|
exit(1);
|
| 339 |
|
|
}
|
| 340 |
greg |
2.23 |
if ((pbuf = (COLR *)bmalloc(hres*vres*sizeof(COLR))) == NULL) {
|
| 341 |
greg |
2.1 |
fprintf(stderr, "%s: out of memory\n", progname);
|
| 342 |
|
|
exit(1);
|
| 343 |
|
|
}
|
| 344 |
greg |
2.6 |
signal(SIGALRM, onalrm);
|
| 345 |
greg |
2.31 |
if (timelim)
|
| 346 |
|
|
alarm(timelim);
|
| 347 |
greg |
2.1 |
return;
|
| 348 |
|
|
filerr:
|
| 349 |
greg |
2.8 |
fprintf(stderr, "%s: i/o error on file \"%s\"\n", progname, outfile);
|
| 350 |
greg |
2.1 |
exit(1);
|
| 351 |
|
|
}
|
| 352 |
|
|
|
| 353 |
|
|
|
| 354 |
schorsch |
2.43 |
static int
|
| 355 |
|
|
nextpiece( /* get next piece assignment */
|
| 356 |
|
|
int *xp,
|
| 357 |
|
|
int *yp
|
| 358 |
|
|
)
|
| 359 |
greg |
2.5 |
{
|
| 360 |
greg |
2.6 |
if (gotalrm) /* someone wants us to quit */
|
| 361 |
|
|
return(0);
|
| 362 |
greg |
2.25 |
if (syncfp != NULL) { /* use sync file */
|
| 363 |
|
|
/*
|
| 364 |
|
|
* So we don't necessarily have to lock and unlock the file
|
| 365 |
|
|
* multiple times (very slow), we establish an exclusive
|
| 366 |
|
|
* lock at the beginning on our synchronization file and
|
| 367 |
|
|
* maintain it in the subroutine rvrpiece().
|
| 368 |
|
|
*/
|
| 369 |
|
|
sflock(F_WRLCK);
|
| 370 |
|
|
fseek(syncfp, 0L, 0); /* read position */
|
| 371 |
|
|
if (fscanf(syncfp, "%*d %*d %d %d", xp, yp) < 2) {
|
| 372 |
greg |
2.8 |
*xp = hmult-1;
|
| 373 |
|
|
*yp = vmult;
|
| 374 |
|
|
}
|
| 375 |
greg |
2.25 |
if (rvrlim == 0) /* initialize recovery limit */
|
| 376 |
|
|
rvrlim = *xp*vmult + *yp;
|
| 377 |
|
|
if (rvrpiece(xp, yp)) { /* do stragglers first */
|
| 378 |
|
|
sflock(F_UNLCK);
|
| 379 |
|
|
return(1);
|
| 380 |
|
|
}
|
| 381 |
greg |
2.8 |
if (--(*yp) < 0) { /* decrement position */
|
| 382 |
greg |
2.5 |
*yp = vmult-1;
|
| 383 |
greg |
2.25 |
if (--(*xp) < 0) { /* all done */
|
| 384 |
|
|
sflock(F_UNLCK);
|
| 385 |
greg |
2.5 |
return(0);
|
| 386 |
|
|
}
|
| 387 |
|
|
}
|
| 388 |
greg |
2.25 |
fseek(syncfp, 0L, 0); /* write new position */
|
| 389 |
|
|
fprintf(syncfp, "%4d %4d\n%4d %4d\n\n", hmult, vmult, *xp, *yp);
|
| 390 |
|
|
fflush(syncfp);
|
| 391 |
|
|
sflock(F_UNLCK); /* release sync file */
|
| 392 |
greg |
2.5 |
return(1);
|
| 393 |
|
|
}
|
| 394 |
greg |
2.26 |
return(scanf("%d %d", xp, yp) == 2); /* use stdin */
|
| 395 |
greg |
2.5 |
}
|
| 396 |
|
|
|
| 397 |
|
|
|
| 398 |
schorsch |
2.43 |
static int
|
| 399 |
|
|
rvrpiece( /* check for recoverable pieces */
|
| 400 |
greg |
2.55 |
int *xp,
|
| 401 |
|
|
int *yp
|
| 402 |
schorsch |
2.43 |
)
|
| 403 |
greg |
2.25 |
{
|
| 404 |
|
|
static char *pdone = NULL; /* which pieces are done */
|
| 405 |
|
|
static long readpos = -1; /* how far we've read */
|
| 406 |
greg |
2.56 |
int px, py, i;
|
| 407 |
greg |
2.25 |
/*
|
| 408 |
|
|
* This routine is called by nextpiece() with an
|
| 409 |
|
|
* exclusive lock on syncfp and the file pointer at the
|
| 410 |
|
|
* appropriate position to read in the finished pieces.
|
| 411 |
|
|
*/
|
| 412 |
|
|
if (rvrlim < 0)
|
| 413 |
|
|
return(0); /* only check if asked */
|
| 414 |
|
|
if (pdone == NULL) /* first call */
|
| 415 |
greg |
2.56 |
pdone = (char *)calloc(hmult*vmult, sizeof(char));
|
| 416 |
greg |
2.30 |
if (pdone == NULL) {
|
| 417 |
|
|
fprintf(stderr, "%s: out of memory\n", progname);
|
| 418 |
|
|
exit(1);
|
| 419 |
|
|
}
|
| 420 |
greg |
2.25 |
if (readpos != -1) /* mark what's been done */
|
| 421 |
|
|
fseek(syncfp, readpos, 0);
|
| 422 |
greg |
2.56 |
while (fscanf(syncfp, "%d %d", &px, &py) == 2)
|
| 423 |
|
|
pdone[px*vmult+py] = 1;
|
| 424 |
greg |
2.25 |
if (!feof(syncfp)) {
|
| 425 |
|
|
fprintf(stderr, "%s: format error in sync file\n", progname);
|
| 426 |
|
|
exit(1);
|
| 427 |
|
|
}
|
| 428 |
|
|
readpos = ftell(syncfp);
|
| 429 |
|
|
i = hmult*vmult; /* find an unaccounted for piece */
|
| 430 |
|
|
while (i-- > rvrlim)
|
| 431 |
|
|
if (!pdone[i]) {
|
| 432 |
|
|
*xp = i / vmult;
|
| 433 |
|
|
*yp = i % vmult;
|
| 434 |
|
|
pdone[i] = 1; /* consider it done */
|
| 435 |
|
|
return(1);
|
| 436 |
|
|
}
|
| 437 |
|
|
rvrlim = -1; /* nothing left to recover */
|
| 438 |
|
|
free(pdone);
|
| 439 |
|
|
pdone = NULL;
|
| 440 |
|
|
return(0);
|
| 441 |
|
|
}
|
| 442 |
|
|
|
| 443 |
|
|
|
| 444 |
schorsch |
2.43 |
static int
|
| 445 |
|
|
cleanup( /* close rpict process and clean up */
|
| 446 |
|
|
int rstat
|
| 447 |
|
|
)
|
| 448 |
greg |
2.1 |
{
|
| 449 |
greg |
2.10 |
int status;
|
| 450 |
greg |
2.1 |
|
| 451 |
greg |
2.23 |
bfree((char *)pbuf, hres*vres*sizeof(COLR));
|
| 452 |
greg |
2.1 |
fclose(torp);
|
| 453 |
|
|
fclose(fromrp);
|
| 454 |
greg |
2.10 |
while (wait(&status) != -1)
|
| 455 |
greg |
2.9 |
if (rstat == 0)
|
| 456 |
|
|
rstat = status>>8 & 0xff;
|
| 457 |
|
|
return(rstat);
|
| 458 |
greg |
2.1 |
}
|
| 459 |
|
|
|
| 460 |
|
|
|
| 461 |
schorsch |
2.43 |
static void
|
| 462 |
|
|
rpiece(void) /* render picture piece by piece */
|
| 463 |
greg |
2.1 |
{
|
| 464 |
|
|
VIEW pview;
|
| 465 |
|
|
int xorg, yorg;
|
| 466 |
greg |
2.11 |
/* compute view parameters */
|
| 467 |
schorsch |
2.40 |
pview = ourview;
|
| 468 |
greg |
2.11 |
switch (ourview.type) {
|
| 469 |
|
|
case VT_PER:
|
| 470 |
greg |
2.48 |
pview.horiz = (2.*180./PI)*atan(
|
| 471 |
|
|
tan((PI/180./2.)*ourview.horiz)/hmult );
|
| 472 |
|
|
pview.vert = (2.*180./PI)*atan(
|
| 473 |
|
|
tan((PI/180./2.)*ourview.vert)/vmult );
|
| 474 |
greg |
2.11 |
break;
|
| 475 |
|
|
case VT_PAR:
|
| 476 |
|
|
case VT_ANG:
|
| 477 |
|
|
pview.horiz = ourview.horiz / hmult;
|
| 478 |
|
|
pview.vert = ourview.vert / vmult;
|
| 479 |
|
|
break;
|
| 480 |
greg |
2.32 |
case VT_CYL:
|
| 481 |
|
|
pview.horiz = ourview.horiz / hmult;
|
| 482 |
greg |
2.48 |
pview.vert = (2.*180./PI)*atan(
|
| 483 |
|
|
tan((PI/180./2.)*ourview.vert)/vmult );
|
| 484 |
greg |
2.32 |
break;
|
| 485 |
greg |
2.11 |
case VT_HEM:
|
| 486 |
greg |
2.48 |
pview.horiz = (2.*180./PI)*asin(
|
| 487 |
|
|
sin((PI/180./2.)*ourview.horiz)/hmult );
|
| 488 |
|
|
pview.vert = (2.*180./PI)*asin(
|
| 489 |
|
|
sin((PI/180./2.)*ourview.vert)/vmult );
|
| 490 |
|
|
break;
|
| 491 |
|
|
case VT_PLS:
|
| 492 |
|
|
pview.horiz = sin((PI/180./2.)*ourview.horiz) /
|
| 493 |
|
|
(1.0 + cos((PI/180./2.)*ourview.horiz)) / hmult;
|
| 494 |
|
|
pview.horiz *= pview.horiz;
|
| 495 |
|
|
pview.horiz = (2.*180./PI)*acos((1. - pview.horiz) /
|
| 496 |
|
|
(1. + pview.horiz));
|
| 497 |
|
|
pview.vert = sin((PI/180./2.)*ourview.vert) /
|
| 498 |
|
|
(1.0 + cos((PI/180./2.)*ourview.vert)) / vmult;
|
| 499 |
|
|
pview.vert *= pview.vert;
|
| 500 |
|
|
pview.vert = (2.*180./PI)*acos((1. - pview.vert) /
|
| 501 |
|
|
(1. + pview.vert));
|
| 502 |
greg |
2.11 |
break;
|
| 503 |
|
|
default:
|
| 504 |
|
|
fprintf(stderr, "%s: unknown view type '-vt%c'\n",
|
| 505 |
|
|
progname, ourview.type);
|
| 506 |
|
|
exit(cleanup(1));
|
| 507 |
|
|
}
|
| 508 |
|
|
/* render each piece */
|
| 509 |
greg |
2.5 |
while (nextpiece(&xorg, &yorg)) {
|
| 510 |
gregl |
2.33 |
pview.hoff = ourview.hoff*hmult + xorg - 0.5*(hmult-1);
|
| 511 |
|
|
pview.voff = ourview.voff*vmult + yorg - 0.5*(vmult-1);
|
| 512 |
greg |
2.1 |
fputs(VIEWSTR, torp);
|
| 513 |
|
|
fprintview(&pview, torp);
|
| 514 |
|
|
putc('\n', torp);
|
| 515 |
greg |
2.11 |
fflush(torp); /* assigns piece to rpict */
|
| 516 |
greg |
2.1 |
putpiece(xorg, yorg); /* place piece in output */
|
| 517 |
|
|
}
|
| 518 |
|
|
}
|
| 519 |
|
|
|
| 520 |
|
|
|
| 521 |
schorsch |
2.43 |
static int
|
| 522 |
|
|
putpiece( /* get next piece from rpict */
|
| 523 |
|
|
int xpos,
|
| 524 |
|
|
int ypos
|
| 525 |
|
|
)
|
| 526 |
greg |
2.1 |
{
|
| 527 |
greg |
2.7 |
struct flock fls;
|
| 528 |
greg |
2.9 |
int pid, status;
|
| 529 |
greg |
2.1 |
int hr, vr;
|
| 530 |
greg |
2.55 |
int y;
|
| 531 |
greg |
2.8 |
/* check bounds */
|
| 532 |
schorsch |
2.41 |
if ((xpos < 0) | (ypos < 0) | (xpos >= hmult) | (ypos >= vmult)) {
|
| 533 |
greg |
2.5 |
fprintf(stderr, "%s: requested piece (%d,%d) out of range\n",
|
| 534 |
|
|
progname, xpos, ypos);
|
| 535 |
greg |
2.10 |
exit(cleanup(1));
|
| 536 |
greg |
2.5 |
}
|
| 537 |
greg |
2.8 |
/* check header from rpict */
|
| 538 |
greg |
2.18 |
guard_io();
|
| 539 |
greg |
2.13 |
getheader(fromrp, NULL, NULL);
|
| 540 |
schorsch |
2.41 |
if (!fscnresolu(&hr, &vr, fromrp) || (hr != hres) | (vr != vres)) {
|
| 541 |
greg |
2.3 |
fprintf(stderr, "%s: resolution mismatch from %s\n",
|
| 542 |
|
|
progname, rpargv[0]);
|
| 543 |
greg |
2.10 |
exit(cleanup(1));
|
| 544 |
greg |
2.1 |
}
|
| 545 |
greg |
2.24 |
if (verbose) { /* notify caller */
|
| 546 |
|
|
printf("%d %d begun\n", xpos, ypos);
|
| 547 |
|
|
fflush(stdout);
|
| 548 |
|
|
}
|
| 549 |
greg |
2.18 |
unguard();
|
| 550 |
greg |
2.8 |
/* load new piece into buffer */
|
| 551 |
greg |
2.18 |
for (y = 0; y < vr; y++) {
|
| 552 |
|
|
guard_io();
|
| 553 |
greg |
2.8 |
if (freadcolrs(pbuf+y*hr, hr, fromrp) < 0) {
|
| 554 |
greg |
2.3 |
fprintf(stderr, "%s: read error from %s\n",
|
| 555 |
|
|
progname, rpargv[0]);
|
| 556 |
greg |
2.10 |
exit(cleanup(1));
|
| 557 |
greg |
2.1 |
}
|
| 558 |
greg |
2.18 |
unguard();
|
| 559 |
|
|
}
|
| 560 |
greg |
2.9 |
#if MAXFORK
|
| 561 |
|
|
/* fork so we don't slow rpict down */
|
| 562 |
|
|
if ((pid = fork()) > 0) {
|
| 563 |
greg |
2.10 |
if (++nforked >= MAXFORK) {
|
| 564 |
greg |
2.9 |
wait(&status); /* reap a child */
|
| 565 |
|
|
if (status)
|
| 566 |
greg |
2.10 |
exit(cleanup(status>>8 & 0xff));
|
| 567 |
greg |
2.9 |
nforked--;
|
| 568 |
|
|
}
|
| 569 |
|
|
return(pid);
|
| 570 |
|
|
}
|
| 571 |
|
|
#else
|
| 572 |
|
|
pid = -1; /* no forking */
|
| 573 |
|
|
#endif
|
| 574 |
greg |
2.19 |
fls.l_start = scanorig +
|
| 575 |
|
|
((long)(vmult-1-ypos)*vres*hmult+xpos)*hres*sizeof(COLR);
|
| 576 |
greg |
2.12 |
#if NFS
|
| 577 |
greg |
2.19 |
fls.l_len = ((long)(vres-1)*hmult+1)*hres*sizeof(COLR);
|
| 578 |
greg |
2.8 |
/* lock file section so NFS doesn't mess up */
|
| 579 |
|
|
fls.l_whence = 0;
|
| 580 |
|
|
fls.l_type = F_WRLCK;
|
| 581 |
greg |
2.54 |
#if 0
|
| 582 |
greg |
2.26 |
if (fcntl(outfd, F_SETLKW, &fls) < 0)
|
| 583 |
|
|
filerr("lock");
|
| 584 |
greg |
2.54 |
#else
|
| 585 |
|
|
dolock(outfd, F_WRLCK);
|
| 586 |
|
|
#endif
|
| 587 |
greg |
2.12 |
#endif
|
| 588 |
greg |
2.8 |
/* write new piece to file */
|
| 589 |
greg |
2.42 |
if (lseek(outfd, (off_t)fls.l_start, SEEK_SET) < 0)
|
| 590 |
greg |
2.26 |
filerr("seek");
|
| 591 |
greg |
2.9 |
if (hmult == 1) {
|
| 592 |
|
|
if (writebuf(outfd, (char *)pbuf,
|
| 593 |
|
|
vr*hr*sizeof(COLR)) != vr*hr*sizeof(COLR))
|
| 594 |
greg |
2.26 |
filerr("write");
|
| 595 |
greg |
2.9 |
} else
|
| 596 |
|
|
for (y = 0; y < vr; y++) {
|
| 597 |
|
|
if (writebuf(outfd, (char *)(pbuf+y*hr),
|
| 598 |
|
|
hr*sizeof(COLR)) != hr*sizeof(COLR))
|
| 599 |
greg |
2.26 |
filerr("write");
|
| 600 |
greg |
2.9 |
if (y < vr-1 && lseek(outfd,
|
| 601 |
greg |
2.37 |
(off_t)(hmult-1)*hr*sizeof(COLR),
|
| 602 |
greg |
2.42 |
SEEK_CUR) < 0)
|
| 603 |
greg |
2.26 |
filerr("seek");
|
| 604 |
greg |
2.1 |
}
|
| 605 |
greg |
2.25 |
#if NFS
|
| 606 |
|
|
fls.l_type = F_UNLCK; /* release lock */
|
| 607 |
greg |
2.54 |
#if 0
|
| 608 |
greg |
2.26 |
if (fcntl(outfd, F_SETLKW, &fls) < 0)
|
| 609 |
|
|
filerr("lock");
|
| 610 |
greg |
2.54 |
#else
|
| 611 |
|
|
dolock(outfd, F_UNLCK);
|
| 612 |
|
|
#endif
|
| 613 |
greg |
2.25 |
#endif
|
| 614 |
greg |
2.32 |
if (verbose) { /* notify caller */
|
| 615 |
|
|
printf("%d %d done\n", xpos, ypos);
|
| 616 |
|
|
fflush(stdout);
|
| 617 |
|
|
}
|
| 618 |
greg |
2.25 |
if (syncfp != NULL) { /* record what's been done */
|
| 619 |
|
|
sflock(F_WRLCK);
|
| 620 |
|
|
fseek(syncfp, 0L, 2); /* append index */
|
| 621 |
|
|
fprintf(syncfp, "%4d %4d\n", xpos, ypos);
|
| 622 |
|
|
fflush(syncfp);
|
| 623 |
|
|
/*** Unlock not necessary, since
|
| 624 |
|
|
sflock(F_UNLCK); _exit() or nextpiece() is next ***/
|
| 625 |
greg |
2.20 |
}
|
| 626 |
greg |
2.25 |
if (pid == -1) /* didn't fork or fork failed */
|
| 627 |
greg |
2.9 |
return(0);
|
| 628 |
greg |
2.25 |
_exit(0); /* else exit child process (releasing locks) */
|
| 629 |
greg |
2.26 |
}
|
| 630 |
|
|
|
| 631 |
|
|
|
| 632 |
schorsch |
2.43 |
static void
|
| 633 |
|
|
filerr( /* report file error and exit */
|
| 634 |
|
|
char *t
|
| 635 |
|
|
)
|
| 636 |
greg |
2.26 |
{
|
| 637 |
|
|
fprintf(stderr, "%s: %s error on file \"%s\": %s\n",
|
| 638 |
greg |
2.37 |
progname, t, outfile, strerror(errno));
|
| 639 |
greg |
2.9 |
_exit(1);
|
| 640 |
greg |
2.1 |
}
|
| 641 |
greg |
2.16 |
|
| 642 |
|
|
#endif
|