Back to index

radiance  4R0+20100331
image.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: image.c,v 2.35 2008/12/12 22:05:38 greg Exp $";
00003 #endif
00004 /*
00005  *  image.c - routines for image generation.
00006  *
00007  *  External symbols declared in view.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include  <ctype.h>
00013 #include  "rtio.h"
00014 #include  "rtmath.h"
00015 #include  "paths.h"
00016 #include  "view.h"
00017 
00018 
00019 #define  FEQ(x,y)    (fabs((x)-(y)) <= FTINY)
00020 #define  VEQ(v,w)    (FEQ((v)[0],(w)[0]) && FEQ((v)[1],(w)[1]) \
00021                             && FEQ((v)[2],(w)[2]))
00022 
00023 VIEW  stdview = STDVIEW;           /* default view parameters */
00024 
00025 static gethfunc gethview;
00026 
00027 
00028 char *
00029 setview(             /* set hvec and vvec, return message on error */
00030 VIEW  *v
00031 )
00032 {
00033        static char  ill_horiz[] = "illegal horizontal view size";
00034        static char  ill_vert[] = "illegal vertical view size";
00035        
00036        if (v->vaft < -FTINY || (v->vaft > FTINY && v->vaft <= v->vfore))
00037               return("illegal fore/aft clipping plane");
00038 
00039        if (v->vdist <= FTINY)
00040               return("illegal view distance");
00041        v->vdist *= normalize(v->vdir);           /* normalize direction */
00042        if (v->vdist == 0.0)
00043               return("zero view direction");
00044 
00045        if (normalize(v->vup) == 0.0)             /* normalize view up */
00046               return("zero view up vector");
00047 
00048        fcross(v->hvec, v->vdir, v->vup);  /* compute horiz dir */
00049 
00050        if (normalize(v->hvec) == 0.0)
00051               return("view up parallel to view direction");
00052 
00053        fcross(v->vvec, v->hvec, v->vdir); /* compute vert dir */
00054 
00055        if (v->horiz <= FTINY)
00056               return(ill_horiz);
00057        if (v->vert <= FTINY)
00058               return(ill_vert);
00059 
00060        switch (v->type) {
00061        case VT_PAR:                       /* parallel view */
00062               v->hn2 = v->horiz;
00063               v->vn2 = v->vert;
00064               break;
00065        case VT_PER:                       /* perspective view */
00066               if (v->horiz >= 180.0-FTINY)
00067                      return(ill_horiz);
00068               if (v->vert >= 180.0-FTINY)
00069                      return(ill_vert);
00070               v->hn2 = 2.0 * tan(v->horiz*(PI/180.0/2.0));
00071               v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0));
00072               break;
00073        case VT_CYL:                       /* cylindrical panorama */
00074               if (v->horiz > 360.0+FTINY)
00075                      return(ill_horiz);
00076               if (v->vert >= 180.0-FTINY)
00077                      return(ill_vert);
00078               v->hn2 = v->horiz * (PI/180.0);
00079               v->vn2 = 2.0 * tan(v->vert*(PI/180.0/2.0));
00080               break;
00081        case VT_ANG:                       /* angular fisheye */
00082               if (v->horiz > 360.0+FTINY)
00083                      return(ill_horiz);
00084               if (v->vert > 360.0+FTINY)
00085                      return(ill_vert);
00086               v->hn2 = v->horiz * (PI/180.0);
00087               v->vn2 = v->vert * (PI/180.0);
00088               break;
00089        case VT_HEM:                       /* hemispherical fisheye */
00090               if (v->horiz > 180.0+FTINY)
00091                      return(ill_horiz);
00092               if (v->vert > 180.0+FTINY)
00093                      return(ill_vert);
00094               v->hn2 = 2.0 * sin(v->horiz*(PI/180.0/2.0));
00095               v->vn2 = 2.0 * sin(v->vert*(PI/180.0/2.0));
00096               break;
00097        case VT_PLS:                       /* planispheric fisheye */
00098               if (v->horiz >= 360.0-FTINY)
00099                      return(ill_horiz);
00100               if (v->vert >= 360.0-FTINY)
00101                      return(ill_vert);
00102               v->hn2 = 2.*sin(v->horiz*(PI/180.0/2.0)) /
00103                             (1.0 + cos(v->horiz*(PI/180.0/2.0)));
00104               v->vn2 = 2.*sin(v->vert*(PI/180.0/2.0)) /
00105                             (1.0 + cos(v->vert*(PI/180.0/2.0)));
00106               break;
00107        default:
00108               return("unknown view type");
00109        }
00110        if (v->type != VT_ANG && v->type != VT_PLS) {
00111               if (v->type != VT_CYL) {
00112                      v->hvec[0] *= v->hn2;
00113                      v->hvec[1] *= v->hn2;
00114                      v->hvec[2] *= v->hn2;
00115               }
00116               v->vvec[0] *= v->vn2;
00117               v->vvec[1] *= v->vn2;
00118               v->vvec[2] *= v->vn2;
00119        }
00120        v->hn2 *= v->hn2;
00121        v->vn2 *= v->vn2;
00122 
00123        return(NULL);
00124 }
00125 
00126 
00127 void
00128 normaspect(                        /* fix pixel aspect or resolution */
00129 double  va,                 /* view aspect ratio */
00130 double  *ap,                /* pixel aspect in (or out if 0) */
00131 int  *xp,
00132 int  *yp                    /* x and y resolution in (or out if *ap!=0) */
00133 )
00134 {
00135        if (*ap <= FTINY)
00136               *ap = va * *xp / *yp;              /* compute pixel aspect */
00137        else if (va * *xp > *ap * *yp)
00138               *xp = *yp / va * *ap + .5;  /* reduce x resolution */
00139        else
00140               *yp = *xp * va / *ap + .5;  /* reduce y resolution */
00141 }
00142 
00143 
00144 double
00145 viewray(                           /* compute ray origin and direction */
00146 FVECT  orig,
00147 FVECT  direc,
00148 VIEW  *v,
00149 double  x,
00150 double  y
00151 )
00152 {
00153        double d, z;
00154        
00155        x += v->hoff - 0.5;
00156        y += v->voff - 0.5;
00157 
00158        switch(v->type) {
00159        case VT_PAR:                /* parallel view */
00160               orig[0] = v->vp[0] + v->vfore*v->vdir[0]
00161                             + x*v->hvec[0] + y*v->vvec[0];
00162               orig[1] = v->vp[1] + v->vfore*v->vdir[1]
00163                             + x*v->hvec[1] + y*v->vvec[1];
00164               orig[2] = v->vp[2] + v->vfore*v->vdir[2]
00165                             + x*v->hvec[2] + y*v->vvec[2];
00166               VCOPY(direc, v->vdir);
00167               return(v->vaft > FTINY ? v->vaft - v->vfore : 0.0);
00168        case VT_PER:                /* perspective view */
00169               direc[0] = v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
00170               direc[1] = v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
00171               direc[2] = v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
00172               orig[0] = v->vp[0] + v->vfore*direc[0];
00173               orig[1] = v->vp[1] + v->vfore*direc[1];
00174               orig[2] = v->vp[2] + v->vfore*direc[2];
00175               d = normalize(direc);
00176               return(v->vaft > FTINY ? (v->vaft - v->vfore)*d : 0.0);
00177        case VT_HEM:                /* hemispherical fisheye */
00178               z = 1.0 - x*x*v->hn2 - y*y*v->vn2;
00179               if (z < 0.0)
00180                      return(-1.0);
00181               z = sqrt(z);
00182               direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
00183               direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
00184               direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
00185               orig[0] = v->vp[0] + v->vfore*direc[0];
00186               orig[1] = v->vp[1] + v->vfore*direc[1];
00187               orig[2] = v->vp[2] + v->vfore*direc[2];
00188               return(v->vaft > FTINY ? v->vaft - v->vfore : 0.0);
00189        case VT_CYL:                /* cylindrical panorama */
00190               d = x * v->horiz * (PI/180.0);
00191               z = cos(d);
00192               x = sin(d);
00193               direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
00194               direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
00195               direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
00196               orig[0] = v->vp[0] + v->vfore*direc[0];
00197               orig[1] = v->vp[1] + v->vfore*direc[1];
00198               orig[2] = v->vp[2] + v->vfore*direc[2];
00199               d = normalize(direc);
00200               return(v->vaft > FTINY ? (v->vaft - v->vfore)*d : 0.0);
00201        case VT_ANG:                /* angular fisheye */
00202               x *= (1.0/180.0)*v->horiz;
00203               y *= (1.0/180.0)*v->vert;
00204               d = x*x + y*y;
00205               if (d > 1.0)
00206                      return(-1.0);
00207               d = sqrt(d);
00208               z = cos(PI*d);
00209               d = d <= FTINY ? PI : sqrt(1.0 - z*z)/d;
00210               x *= d;
00211               y *= d;
00212               direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
00213               direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
00214               direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
00215               orig[0] = v->vp[0] + v->vfore*direc[0];
00216               orig[1] = v->vp[1] + v->vfore*direc[1];
00217               orig[2] = v->vp[2] + v->vfore*direc[2];
00218               return(v->vaft > FTINY ? v->vaft - v->vfore : 0.0);
00219        case VT_PLS:                /* planispheric fisheye */
00220               x *= sqrt(v->hn2);
00221               y *= sqrt(v->vn2);
00222               d = x*x + y*y;
00223               z = (1. - d)/(1. + d);
00224               d = d <= FTINY*FTINY ? PI : sqrt((1.0 - z*z)/d);
00225               x *= d;
00226               y *= d;
00227               direc[0] = z*v->vdir[0] + x*v->hvec[0] + y*v->vvec[0];
00228               direc[1] = z*v->vdir[1] + x*v->hvec[1] + y*v->vvec[1];
00229               direc[2] = z*v->vdir[2] + x*v->hvec[2] + y*v->vvec[2];
00230               orig[0] = v->vp[0] + v->vfore*direc[0];
00231               orig[1] = v->vp[1] + v->vfore*direc[1];
00232               orig[2] = v->vp[2] + v->vfore*direc[2];
00233               return(v->vaft > FTINY ? v->vaft - v->vfore : 0.0);
00234        }
00235        return(-1.0);
00236 }
00237 
00238 
00239 void
00240 viewloc(                    /* find image location for point */
00241 FVECT  ip,
00242 VIEW  *v,
00243 FVECT  p
00244 )
00245 {
00246        double  d, d2;
00247        FVECT  disp;
00248 
00249        VSUB(disp, p, v->vp);
00250 
00251        switch (v->type) {
00252        case VT_PAR:                /* parallel view */
00253               ip[2] = DOT(disp,v->vdir) - v->vfore;
00254               break;
00255        case VT_PER:                /* perspective view */
00256               d = DOT(disp,v->vdir);
00257               ip[2] = VLEN(disp);
00258               if (d < 0.0) {              /* fold pyramid */
00259                      ip[2] = -ip[2];
00260                      d = -d;
00261               }
00262               if (d > FTINY) {
00263                      d = 1.0/d;
00264                      disp[0] *= d;
00265                      disp[1] *= d;
00266                      disp[2] *= d;
00267               }
00268               ip[2] *= (1.0 - v->vfore*d);
00269               break;
00270        case VT_HEM:                /* hemispherical fisheye */
00271               d = normalize(disp);
00272               if (DOT(disp,v->vdir) < 0.0)
00273                      ip[2] = -d;
00274               else
00275                      ip[2] = d;
00276               ip[2] -= v->vfore;
00277               break;
00278        case VT_CYL:                /* cylindrical panorama */
00279               d = DOT(disp,v->hvec);
00280               d2 = DOT(disp,v->vdir);
00281               ip[0] = 180.0/PI * atan2(d,d2) / v->horiz + 0.5 - v->hoff;
00282               d = 1.0/sqrt(d*d + d2*d2);
00283               ip[1] = DOT(disp,v->vvec)*d/v->vn2 + 0.5 - v->voff;
00284               ip[2] = VLEN(disp);
00285               ip[2] *= (1.0 - v->vfore*d);
00286               return;
00287        case VT_ANG:                /* angular fisheye */
00288               ip[0] = 0.5 - v->hoff;
00289               ip[1] = 0.5 - v->voff;
00290               ip[2] = normalize(disp) - v->vfore;
00291               d = DOT(disp,v->vdir);
00292               if (d >= 1.0-FTINY)
00293                      return;
00294               if (d <= -(1.0-FTINY)) {
00295                      ip[0] += 180.0/v->horiz;
00296                      return;
00297               }
00298               d = (180.0/PI)*acos(d) / sqrt(1.0 - d*d);
00299               ip[0] += DOT(disp,v->hvec)*d/v->horiz;
00300               ip[1] += DOT(disp,v->vvec)*d/v->vert;
00301               return;
00302        case VT_PLS:                /* planispheric fisheye */
00303               ip[0] = 0.5 - v->hoff;
00304               ip[1] = 0.5 - v->voff;
00305               ip[2] = normalize(disp) - v->vfore;
00306               d = DOT(disp,v->vdir);
00307               if (d >= 1.0-FTINY)
00308                      return;
00309               if (d <= -(1.0-FTINY))
00310                      return;              /* really an error */
00311               d = sqrt(1.0 - d*d) / (1.0 + d);
00312               ip[0] += DOT(disp,v->hvec)*d/sqrt(v->hn2);
00313               ip[1] += DOT(disp,v->vvec)*d/sqrt(v->vn2);
00314               return;
00315        }
00316        ip[0] = DOT(disp,v->hvec)/v->hn2 + 0.5 - v->hoff;
00317        ip[1] = DOT(disp,v->vvec)/v->vn2 + 0.5 - v->voff;
00318 }
00319 
00320 
00321 void
00322 pix2loc(             /* compute image location from pixel pos. */
00323 RREAL  loc[2],
00324 RESOLU  *rp,
00325 int  px,
00326 int  py
00327 )
00328 {
00329        register int  x, y;
00330 
00331        if (rp->rt & YMAJOR) {
00332               x = px;
00333               y = py;
00334        } else {
00335               x = py;
00336               y = px;
00337        }
00338        if (rp->rt & XDECR)
00339               x = rp->xr-1 - x;
00340        if (rp->rt & YDECR)
00341               y = rp->yr-1 - y;
00342        loc[0] = (x+.5)/rp->xr;
00343        loc[1] = (y+.5)/rp->yr;
00344 }
00345 
00346 
00347 void
00348 loc2pix(                    /* compute pixel pos. from image location */
00349 int  pp[2],
00350 RESOLU  *rp,
00351 double  lx,
00352 double  ly
00353 )
00354 {
00355        register int  x, y;
00356 
00357        x = lx * rp->xr;
00358        y = ly * rp->yr;
00359        if (rp->rt & XDECR)
00360               x = rp->xr-1 - x;
00361        if (rp->rt & YDECR)
00362               y = rp->yr-1 - y;
00363        if (rp->rt & YMAJOR) {
00364               pp[0] = x;
00365               pp[1] = y;
00366        } else {
00367               pp[0] = y;
00368               pp[1] = x;
00369        }
00370 }
00371 
00372 
00373 int
00374 getviewopt(                        /* process view argument */
00375 VIEW  *v,
00376 int  ac,
00377 char  *av[]
00378 )
00379 {
00380 #define check(c,l)   if ((av[0][c]&&av[0][c]!=' ') || \
00381                      badarg(ac-1,av+1,l)) return(-1)
00382 
00383        if (ac <= 0 || av[0][0] != '-' || av[0][1] != 'v')
00384               return(-1);
00385        switch (av[0][2]) {
00386        case 't':                   /* type */
00387               if (!av[0][3] || av[0][3]==' ')
00388                      return(-1);
00389               check(4,"");
00390               v->type = av[0][3];
00391               return(0);
00392        case 'p':                   /* point */
00393               check(3,"fff");
00394               v->vp[0] = atof(av[1]);
00395               v->vp[1] = atof(av[2]);
00396               v->vp[2] = atof(av[3]);
00397               return(3);
00398        case 'd':                   /* direction */
00399               check(3,"fff");
00400               v->vdir[0] = atof(av[1]);
00401               v->vdir[1] = atof(av[2]);
00402               v->vdir[2] = atof(av[3]);
00403               v->vdist = 1.;
00404               return(3);
00405        case 'u':                   /* up */
00406               check(3,"fff");
00407               v->vup[0] = atof(av[1]);
00408               v->vup[1] = atof(av[2]);
00409               v->vup[2] = atof(av[3]);
00410               return(3);
00411        case 'h':                   /* horizontal size */
00412               check(3,"f");
00413               v->horiz = atof(av[1]);
00414               return(1);
00415        case 'v':                   /* vertical size */
00416               check(3,"f");
00417               v->vert = atof(av[1]);
00418               return(1);
00419        case 'o':                   /* fore clipping plane */
00420               check(3,"f");
00421               v->vfore = atof(av[1]);
00422               return(1);
00423        case 'a':                   /* aft clipping plane */
00424               check(3,"f");
00425               v->vaft = atof(av[1]);
00426               return(1);
00427        case 's':                   /* shift */
00428               check(3,"f");
00429               v->hoff = atof(av[1]);
00430               return(1);
00431        case 'l':                   /* lift */
00432               check(3,"f");
00433               v->voff = atof(av[1]);
00434               return(1);
00435        default:
00436               return(-1);
00437        }
00438 #undef check
00439 }
00440 
00441 
00442 int
00443 sscanview(                         /* get view parameters from string */
00444 VIEW  *vp,
00445 char  *s
00446 )
00447 {
00448        int  ac;
00449        char  *av[4];
00450        int  na;
00451        int  nvopts = 0;
00452 
00453        while (isspace(*s))
00454               if (!*s++)
00455                      return(0);
00456        while (*s) {
00457               ac = 0;
00458               do {
00459                      if (ac || *s == '-')
00460                             av[ac++] = s;
00461                      while (*s && !isspace(*s))
00462                             s++;
00463                      while (isspace(*s))
00464                             s++;
00465               } while (*s && ac < 4);
00466               if ((na = getviewopt(vp, ac, av)) >= 0) {
00467                      if (na+1 < ac)
00468                             s = av[na+1];
00469                      nvopts++;
00470               } else if (ac > 1)
00471                      s = av[1];
00472        }
00473        return(nvopts);
00474 }
00475 
00476 
00477 void
00478 fprintview(                        /* write out view parameters */
00479 VIEW  *vp,
00480 FILE  *fp
00481 )
00482 {
00483        fprintf(fp, " -vt%c", vp->type);
00484        fprintf(fp, " -vp %.6g %.6g %.6g", vp->vp[0], vp->vp[1], vp->vp[2]);
00485        fprintf(fp, " -vd %.6g %.6g %.6g", vp->vdir[0]*vp->vdist,
00486                                           vp->vdir[1]*vp->vdist,
00487                                           vp->vdir[2]*vp->vdist);
00488        fprintf(fp, " -vu %.6g %.6g %.6g", vp->vup[0], vp->vup[1], vp->vup[2]);
00489        fprintf(fp, " -vh %.6g -vv %.6g", vp->horiz, vp->vert);
00490        fprintf(fp, " -vo %.6g -va %.6g", vp->vfore, vp->vaft);
00491        fprintf(fp, " -vs %.6g -vl %.6g", vp->hoff, vp->voff);
00492 }
00493 
00494 
00495 char *
00496 viewopt(                           /* translate to minimal view string */
00497 VIEW  *vp
00498 )
00499 {
00500        static char  vwstr[128];
00501        register char  *cp = vwstr;
00502 
00503        *cp = '\0';
00504        if (vp->type != stdview.type) {
00505               sprintf(cp, " -vt%c", vp->type);
00506               cp += strlen(cp);
00507        }
00508        if (!VEQ(vp->vp,stdview.vp)) {
00509               sprintf(cp, " -vp %.6g %.6g %.6g",
00510                             vp->vp[0], vp->vp[1], vp->vp[2]);
00511               cp += strlen(cp);
00512        }
00513        if (!FEQ(vp->vdist,stdview.vdist) || !VEQ(vp->vdir,stdview.vdir)) {
00514               sprintf(cp, " -vd %.6g %.6g %.6g",
00515                             vp->vdir[0]*vp->vdist,
00516                             vp->vdir[1]*vp->vdist,
00517                             vp->vdir[2]*vp->vdist);
00518               cp += strlen(cp);
00519        }
00520        if (!VEQ(vp->vup,stdview.vup)) {
00521               sprintf(cp, " -vu %.6g %.6g %.6g",
00522                             vp->vup[0], vp->vup[1], vp->vup[2]);
00523               cp += strlen(cp);
00524        }
00525        if (!FEQ(vp->horiz,stdview.horiz)) {
00526               sprintf(cp, " -vh %.6g", vp->horiz);
00527               cp += strlen(cp);
00528        }
00529        if (!FEQ(vp->vert,stdview.vert)) {
00530               sprintf(cp, " -vv %.6g", vp->vert);
00531               cp += strlen(cp);
00532        }
00533        if (!FEQ(vp->vfore,stdview.vfore)) {
00534               sprintf(cp, " -vo %.6g", vp->vfore);
00535               cp += strlen(cp);
00536        }
00537        if (!FEQ(vp->vaft,stdview.vaft)) {
00538               sprintf(cp, " -va %.6g", vp->vaft);
00539               cp += strlen(cp);
00540        }
00541        if (!FEQ(vp->hoff,stdview.hoff)) {
00542               sprintf(cp, " -vs %.6g", vp->hoff);
00543               cp += strlen(cp);
00544        }
00545        if (!FEQ(vp->voff,stdview.voff)) {
00546               sprintf(cp, " -vl %.6g", vp->voff);
00547               cp += strlen(cp);
00548        }
00549        return(vwstr);
00550 }
00551 
00552 
00553 int
00554 isview(                                   /* is this a view string? */
00555 char  *s
00556 )
00557 {
00558        static char  *altname[]={NULL,VIEWSTR,"rpict","rview","rvu","rpiece","pinterp",NULL};
00559        extern char  *progname;
00560        register char  *cp;
00561        register char  **an;
00562                                    /* add program name to list */
00563        if (altname[0] == NULL) {
00564               for (cp = progname; *cp; cp++)
00565                      ;
00566               while (cp > progname && !ISDIRSEP(cp[-1]))
00567                      cp--;
00568               altname[0] = cp;
00569        }
00570                                    /* skip leading path */
00571        cp = s;
00572        while (*cp && *cp != ' ')
00573               cp++;
00574        while (cp > s && !ISDIRSEP(cp[-1]))
00575               cp--;
00576        for (an = altname; *an != NULL; an++)
00577               if (!strncmp(*an, cp, strlen(*an)))
00578                      return(1);
00579        return(0);
00580 }
00581 
00582 
00583 struct myview {
00584        VIEW   *hv;
00585        int    ok;
00586 };
00587 
00588 
00589 static int
00590 gethview(                          /* get view from header */
00591        char  *s,
00592        void  *v
00593 )
00594 {
00595        if (isview(s) && sscanview(((struct myview*)v)->hv, s) > 0)
00596               ((struct myview*)v)->ok++;
00597        return(0);
00598 }
00599 
00600 
00601 int
00602 viewfile(                          /* get view from file */
00603 char  *fname,
00604 VIEW  *vp,
00605 RESOLU  *rp
00606 )
00607 {
00608        struct myview mvs;
00609        FILE  *fp;
00610 
00611        if (fname == NULL || !strcmp(fname, "-"))
00612               fp = stdin;
00613        else if ((fp = fopen(fname, "r")) == NULL)
00614               return(-1);
00615 
00616        mvs.hv = vp;
00617        mvs.ok = 0;
00618 
00619        getheader(fp, gethview, &mvs);
00620 
00621        if (rp != NULL && !fgetsresolu(rp, fp))
00622               mvs.ok = 0;
00623 
00624        fclose(fp);
00625 
00626        return(mvs.ok);
00627 }