ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/RpictSimulManager.cpp
(Generate patch)

Comparing ray/src/rt/RpictSimulManager.cpp (file contents):
Revision 2.2 by greg, Sun Aug 18 00:37:13 2024 UTC vs.
Revision 2.10 by greg, Sun Aug 25 17:24:48 2024 UTC

# Line 9 | Line 9 | static const char RCSid[] = "$Id$";
9   *  Created by Greg Ward on 07/11/2024.
10   */
11  
12 + #define DEBUG   1       // XXX temporary!
13 +
14   #include <ctype.h>
15   #include "platform.h"
16   #include "RpictSimulManager.h"
# Line 196 | Line 198 | RpictSimulManager::SetTile(const int ti[2])
198   bool
199   RpictSimulManager::ComputePixel(int x, int y)
200   {
201 <        static const SCOLOR     scBlack = {0};
201 >        DCHECK(doneMap.OffBitMap(x,y),
202 >                        CONSISTENCY, "illegal pixel index in ComputPixel()");
203          int     i;
204          FVECT   rodir[2];
205          double  hpos = (x+pixjitter())/TWidth();
206          double  vpos = (y+pixjitter())/THeight();
207          double  dlim = viewray(rodir[0], rodir[1], &tvw, hpos, vpos);
208          if (dlim < -FTINY) {    // off view?
209 <                pacc.SetPixel(x, y, scBlack);
209 >                pacc.SetPixel(x, y, scblack);
210                  doneMap.Set(x, y);
211                  return true;
212          }
# Line 233 | Line 236 | RpictSimulManager::ComputePixel(int x, int y)
236  
237   // Check if neighbor differences are below pixel sampling threshold
238   bool
239 < RpictSimulManager::BelowSampThresh(int x, int y, const int noff[4][2]) const
239 > RpictSimulManager::BelowSampThresh(const int x, const int y, const int noff[4][2]) const
240   {
241          SCOLOR  pval[4];
242          float   dist[4];
243          int     i, j;
244  
245          for (i = 4; i--; ) {            // get pixels from tile store
246 <                int     px = x + noff[i][0];
247 <                int     py = y + noff[i][1];
246 >                const int       px = x + noff[i][0];
247 >                const int       py = y + noff[i][1];
248                  if (!doneMap.Check(px, py) ||
249                                  !pacc.GetPixel(px, py, pval[i], &dist[i]))
250                          return false;
251          }
252 <        const bool      spectr = (pacc.NC() > 3);
253 <        for (i = 4; --i; )              // do pairwise comparisons
254 <            for (j = i; j--; ) {
255 <                if (pacc.DepthType() &&
253 <                                (dist[i] - dist[j] > maxdiff*dist[j]) |
252 >                                        // do pairwise comparisons
253 >        for (i = (pacc.DepthType() != RDTnone)*4; --i > 0; )
254 >            for (j = i; j--; )
255 >                if ((dist[i] - dist[j] > maxdiff*dist[j]) |
256                                  (dist[j] - dist[i] > maxdiff*dist[i]))
257                          return false;
258 <                if (spectr ? sbigsdiff(pval[i], pval[j], maxdiff) :
259 <                                bigdiff(pval[i], pval[j], maxdiff))
258 >        if (pacc.NC() > 3) {
259 >            for (i = 4; --i; )
260 >                for (j = i; j--; )
261 >                    if (sbigsdiff(pval[i], pval[j], maxdiff))
262                          return false;
263 <            }
264 <        return true;                    // linear interpolation OK
263 >        } else {
264 >            for (i = 4; --i; )
265 >                for (j = i; j--; )
266 >                    if (bigdiff(pval[i], pval[j], maxdiff))
267 >                        return false;
268 >        }
269 >        return true;
270   }
271  
272   // Fill an interior square patch with interpolated values
# Line 268 | Line 277 | RpictSimulManager::FillSquare(const int x, const int y
277          float   dist[4];
278          int     i, j;
279                                          // assumes 4 corners are valid!
280 <        for (i = 4; i--; )
280 >        for (i = 4; i--; ) {
281 >                DCHECK(!doneMap.Check(x+noff[i][0], y+noff[i][1]),
282 >                        CONSISTENCY, "inclusion of bad pixel in FillSquare()");
283                  pacc.GetPixel(x+noff[i][0], y+noff[i][1], pval[i], &dist[i]);
284 <
284 >        }
285          i = abs(noff[1][0]-noff[0][0]);
286          j = abs(noff[1][1]-noff[0][1]); // i==j for diamond fill
287          const int       slen =  (i > j) ? i : j;
# Line 328 | Line 339 | RpictSimulManager::FillSquare(const int x, const int y
339  
340   // helper function to set up quincunx sampling
341   static void
342 < SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, const bool odd)
342 > SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int spc, bool odd, int x0, int y)
343   {
344 <        for (int y = 0; y < bmp2->Height(); y += spc>>1)
334 <            for (int x = (odd^(y&1))*(spc>>1); x < bmp2->Width(); x += spc)
335 <                bmp2->Set(x, y);
336 <                                        // order neighbors CCW
337 <        if (odd) {
344 >        if (odd) {                      // order neighbors CCW
345                  noff[0][0] = spc>>1; noff[0][1] = 0;
346                  noff[1][0] = 0; noff[1][1] = spc>>1;
347                  noff[2][0] = -(spc>>1); noff[2][1] = 0;
# Line 345 | Line 352 | SetQuincunx(ABitMap2 *bmp2, int noff[4][2], const int
352                  noff[2][0] = -(spc>>1); noff[2][1] = -(spc>>1);
353                  noff[3][0] = spc>>1; noff[3][1] = -(spc>>1);
354          }
355 +        int     nsteps;                 // non-negative range
356 +        if (x0 < -(spc>>1)) {
357 +                nsteps = (spc-1 - x0 - (spc>>1))/spc;
358 +                x0 += nsteps*spc;
359 +        }
360 +        if (y < 0) {                    // get past y==0
361 +                nsteps = ((spc>>1)-1 - y)/(spc>>1);
362 +                y += nsteps*(spc>>1);
363 +                odd ^= nsteps&1;
364 +        }
365 +        while (y < bmp2->Height()) {
366 +            for (int x = x0 + odd*(spc>>1); x < bmp2->Width(); x += spc)
367 +                bmp2->Set(x, y);
368 +            y += spc>>1;
369 +            odd = !odd;
370 +        }
371   }
372  
373   // Render (or finish rendering) current tile
374   bool
375 < RpictSimulManager::RenderRect()
375 > RpictSimulManager::RenderRect(const int x0, const int y0)
376   {
377          if (!tvw.type || !Ready()) {
378                  error(INTERNAL, "need octree and view for RenderRect()");
# Line 359 | Line 382 | RpictSimulManager::RenderRect()
382          int             sp2 = ceil(log2((TWidth()>THeight() ? TWidth() : THeight()) - 1.));
383          int             layer = 0;
384          int             x, y;
362 fprintf(stderr, "Rendering %dx%d tile with psample=%d, maxdiff=%.3f ...\n",
363 TWidth(), THeight(), psample, maxdiff);
385          while (sp2 > 0) {
386                  ABitMap2        sampMap(TWidth(), THeight());
387                  int             noff[4][2];
388                  if ((prCB != NULL) & (barPix == NULL))
389                          (*prCB)(100.*doneMap.SumTotal()/doneMap.Width()/doneMap.Height());
390 <                SetQuincunx(&sampMap, noff, 1<<sp2, layer&1);
390 >                SetQuincunx(&sampMap, noff, 1<<sp2, layer&1, x0, y0);
391                  sampMap -= doneSamples; // avoid resampling pixels
392                  // Are we into adaptive sampling realm?
393                  if (noff[0][0]*noff[0][0] + noff[0][1]*noff[0][1] < psample*psample) {
# Line 380 | Line 401 | TWidth(), THeight(), psample, maxdiff);
401                          const ABitMap2  origSampMap = sampMap;
402                          for (x = 4; x--; ) {
403                                  ABitMap2        stamp = origSampMap;
404 <                                stamp.Shift(noff[x][0], noff[x][1]);
404 >                                stamp.Shift(noff[x][0] + noff[(x+1)&3][0],
405 >                                                noff[x][1] + noff[(x+1)&3][1]);
406                                  sampMap |= stamp;
407                          }               // ...but don't resample what's done
408                          sampMap -= doneSamples;
409                                          // interpolate smooth regions
410                          fillMap -= sampMap;
411 +                        fillMap -= doneSamples;
412                          for (x = y = 0; fillMap.Find(&x, &y); x++)
413                                  FillSquare(x, y, noff);
414                          doneSamples |= doneMap;
# Line 394 | Line 417 | TWidth(), THeight(), psample, maxdiff);
417                          if (!ComputePixel(x, y))
418                                  return false;
419                  doneSamples |= sampMap; // samples now done or at least queued
397 fprintf(stderr, "Sampled %ld pixels at (sp2,layer)=(%d,%d)\n",
398 (long)sampMap.SumTotal(), sp2, layer);
399 fprintf(stderr, "\t%ld pixels (%.3f%%) completed (+%ld in process)\n",
400 (long)doneMap.SumTotal(), 100.*doneMap.SumTotal()/doneMap.Width()/doneMap.Height(),
401 (long)(doneSamples.SumTotal()-doneMap.SumTotal()));
420                  sp2 -= layer++ & 1;     // next denser sampling
421          }
422          if (FlushQueue() < 0)           // make sure we got everyone
423                  return false;
424          x = y = 0;
425          if (doneMap.Find(&x, &y, false)) {
426 <                sprintf(errmsg, "missed %ld tile pixels, e.g. (%d,%d)",
427 <                                (long)doneMap.Width()*doneMap.Height() -
428 <                                        doneMap.SumTotal(), x, y);
426 >                sprintf(errmsg, "missed %.4f%% of pixels in rectangle\n",
427 >                                100. - 100.*doneMap.SumTotal() /
428 >                                        doneMap.Width() / doneMap.Height());
429                  error(WARNING, errmsg);
430          }
431          if ((prCB != NULL) & (barPix == NULL))
# Line 433 | Line 451 | RpictSimulManager::RenderTile(COLORV *rp, int ystride,
451                  pacc.SetColorSpace(RDTxyz);
452          else if (prims)
453                  pacc.SetColorSpace(RDTrgb, prims);
454 <                
454 >
455          return SetTile(tile) && RenderRect();
456   }
457  
# Line 471 | Line 489 | RpictSimulManager::RenderTile(COLRV *bp, int ystride,
489          return SetTile(tile) && RenderRect();
490   }
491  
492 + // Back to float color with 16-bit depth
493 + bool
494 + RpictSimulManager::RenderTile(COLORV *rp, int ystride, short *dp, const int *tile)
495 + {
496 +        if (!rp | (GetWidth() <= 0) | (GetHeight() <= 0) | !vw.type)
497 +                return false;
498 +        if (!ystride)                   // contiguous rows?
499 +                ystride = TWidth();
500 +        pacc.Init(rp, ystride, dp);
501 +        if (prims == xyzprims)
502 +                pacc.SetColorSpace(RDTxyz);
503 +        else if (prims)
504 +                pacc.SetColorSpace(RDTrgb, prims);
505 +
506 +        return SetTile(tile) && RenderRect();
507 + }
508 +
509   // Allocate a new render bar
510   void
511   RpictSimulManager::NewBar(int ht)
# Line 501 | Line 536 | RpictSimulManager::NewBar(int ht)
536  
537   // Shift render bar area the specified amount down the frame
538   bool
539 < RpictSimulManager::LowerBar(int v)
539 > RpictSimulManager::LowerBar(int v, int ytop)
540   {
506        if (v <= 0) return !v;
541          if (!barPix | !barDepth | (v > THeight()) | !tvw.type)
542                  return false;
543 +        if (v <= 0) return !v;
544 +        if ((ytop -= v) <= 0)
545 +                return true;
546          tvw.voff -= double(v)/THeight();
547          ptvw.voff -= double(v)/THeight();
548          if (v == THeight()) {
# Line 518 | Line 555 | RpictSimulManager::LowerBar(int v)
555                          sizeof(COLORV)*NC*TWidth()*(THeight()-v));
556          memmove(barDepth, barDepth + TWidth()*v,
557                          sizeof(float)*TWidth()*(THeight()-v));
558 +        if (ytop < THeight())                   // mark what we won't do as finished
559 +                doneMap.ClearRect(0, 0, TWidth(), THeight()-ytop, true);
560          return true;
561   }
562  
# Line 540 | Line 579 | RpictSimulManager::RenderBelow(int ytop, const int vst
579                          cropview(&ptvw, 0., double(ytop-THeight())/GetHeight(),
580                                                  1., double(ytop)/GetHeight()))
581                  ptvw.type = 0;
582 <                                                // set up spectral sampling
582 >                                                // update spectral sampling
583          if (setspectrsamp(CNDX, WLPART) <= 0) {
584                  error(USER, "unsupported spectral sampling");
585                  return false;
# Line 559 | Line 598 | RpictSimulManager::RenderBelow(int ytop, const int vst
598          }
599          int             lastOut = ytop;         // render down frame
600          while (ytop > 0) {
562 fprintf(stderr, "At y=%d, source drawing %s...\n", ytop, parr ? "ON" : "OFF");
563                if (ytop < THeight())           // mark what we won't do as finished
564                        doneMap.ClearRect(0, 0, TWidth(), THeight()-ytop, true);
601                  if (prCB)
602                          (*prCB)(100.*(GetHeight()-ytop)/GetHeight());
603 <                if (!RenderRect())              // render this bar
603 >                if (!RenderRect(0, THeight()-ytop))     // render this bar
604                          return false;
605                  int     nlines = lastOut - ytop + THeight();
606                  if (nlines > ytop)
# Line 612 | Line 648 | fprintf(stderr, "At y=%d, source drawing %s...\n", yto
648                  if (fflush(pfp) == EOF || (dfp && fflush(dfp) == EOF))
649                          error(SYSTEM, "output write error");
650                                                  // advance down the frame
651 <                if (lastOut > 0 && !LowerBar(vstep))
651 >                if (lastOut > 0 && !LowerBar(vstep, ytop))
652                          return false;
653                  ytop -= vstep;
654          }
# Line 623 | Line 659 | fprintf(stderr, "At y=%d, source drawing %s...\n", yto
659          return true;
660   }
661  
662 < /*
627 < * Render and write a frame to the named file
628 < * Include any header lines set prior to call
629 < * Picture file must not already exist
630 < * Write pixels to stdout if !pfname
631 < * Write depth to a command if dfname[0]=='!'
632 < */
662 > // Open new output picture file (and optional depth file)
663   RenderDataType
664 < RpictSimulManager::RenderFrame(const char *pfname, RenderDataType dt, const char *dfname)
664 > RpictSimulManager::NewOutput(FILE *pdfp[2], const char *pfname,
665 >                                RenderDataType dt, const char *dfname)
666   {
667 <        int     fd = 1;
637 <        FILE *  pfp = NULL;
638 <        FILE *  dfp = NULL;
639 <
667 >        pdfp[0] = pdfp[1] = NULL;
668          if (!RDTcolorT(dt))
669 <                error(INTERNAL, "botched color output type in RenderFrame()");
669 >                error(INTERNAL, "missing color output type in NewOutput()");
670          if (NCSAMP == 3) {
671                  if (RDTcolorT(dt) == RDTscolr)
672                          dt = RDTnewCT(dt, prims==xyzprims ? RDTxyze : RDTrgbe);
# Line 646 | Line 674 | RpictSimulManager::RenderFrame(const char *pfname, Ren
674                          dt = RDTnewCT(dt, prims==xyzprims ? RDTxyz : RDTrgb);
675          }
676          if (!RDTdepthT(dt) ^ !dfname)
677 <                error(INTERNAL, "depth output requires file name and type in RenderFrame()");
677 >                error(INTERNAL, "depth output requires file name and type in NewOutput()");
678 >        int     fd = 1;
679          if (pfname) {                           // open picture output file
680                  if (pfname[0] == '!') {
681                          error(INTERNAL, "writing picture to a command not supported");
# Line 659 | Line 688 | RpictSimulManager::RenderFrame(const char *pfname, Ren
688                          sprintf(errmsg, "cannot open picture file '%s'", pfname);
689                          error(SYSTEM, errmsg);
690                  }
691 <                return RDTnone;                 // expected in parallel sequence
691 >                return RDTnone;                 // may be expected in sequence run
692          }
693          if (fd == 1)
694 <                pfp = stdout;
695 <        else if (!(pfp = fdopen(fd, "w")))
694 >                pdfp[0] = stdout;
695 >        else if (!(pdfp[0] = fdopen(fd, "w")))
696                  error(SYSTEM, "failure calling fdopen()");
697 <        SET_FILE_BINARY(pfp);                   // write picture header
698 <        if ((pfp != stdout) | (frameNo <= 1)) {
699 <                newheader("RADIANCE", pfp);
700 <                fputs(GetHeader(), pfp);
697 >        SET_FILE_BINARY(pdfp[0]);               // write picture header
698 >        if ((pdfp[0] != stdout) | (frameNo <= 1)) {
699 >                newheader("RADIANCE", pdfp[0]);
700 >                fputs(GetHeader(), pdfp[0]);
701          }
702 <        fputs(VIEWSTR, pfp); fprintview(&vw, pfp); fputc('\n', pfp);
702 >        fputs(VIEWSTR, pdfp[0]); fprintview(&vw, pdfp[0]); fputc('\n', pdfp[0]);
703          if (frameNo > 0)
704 <                fprintf(pfp, "FRAME=%d\n", frameNo);
704 >                fprintf(pdfp[0], "FRAME=%d\n", frameNo);
705          double  pasp = viewaspect(&vw) * GetWidth() / GetHeight();
706          if ((0.99 > pasp) | (pasp > 1.01))
707 <                fputaspect(pasp, pfp);
708 <        fputnow(pfp);
707 >                fputaspect(pasp, pdfp[0]);
708 >        fputnow(pdfp[0]);
709          switch (RDTcolorT(dt)) {                // set primaries and picture format
710          case RDTrgbe:
711                  if (!prims | (prims == xyzprims)) prims = stdprims;
712 <                fputprims(prims, pfp);
713 <                fputformat(COLRFMT, pfp);
712 >                fputprims(prims, pdfp[0]);
713 >                fputformat(COLRFMT, pdfp[0]);
714                  break;
715          case RDTxyze:
716                  prims = xyzprims;
717 <                fputformat(CIEFMT, pfp);
717 >                fputformat(CIEFMT, pdfp[0]);
718                  break;
719          case RDTscolr:
720                  prims = NULL;
721 <                fputwlsplit(WLPART, pfp);
722 <                fputncomp(NCSAMP, pfp);
723 <                fputformat(SPECFMT, pfp);
721 >                fputwlsplit(WLPART, pdfp[0]);
722 >                fputncomp(NCSAMP, pdfp[0]);
723 >                fputformat(SPECFMT, pdfp[0]);
724                  break;
725          case RDTrgb:
726                  if (!prims | (prims == xyzprims)) prims = stdprims;
727 <                fputprims(prims, pfp);
728 <                fputncomp(3, pfp);
729 <                fputendian(pfp);
730 <                fputformat("float", pfp);
727 >                fputprims(prims, pdfp[0]);
728 >                fputncomp(3, pdfp[0]);
729 >                fputendian(pdfp[0]);
730 >                fputformat("float", pdfp[0]);
731                  break;
732          case RDTxyz:
733                  prims = xyzprims;
734 <                fputprims(prims, pfp);
735 <                fputncomp(3, pfp);
736 <                fputendian(pfp);
737 <                fputformat("float", pfp);
734 >                fputprims(prims, pdfp[0]);
735 >                fputncomp(3, pdfp[0]);
736 >                fputendian(pdfp[0]);
737 >                fputformat("float", pdfp[0]);
738                  break;
739          case RDTscolor:
740                  prims = NULL;
741 <                fputwlsplit(WLPART, pfp);
742 <                fputncomp(NCSAMP, pfp);
743 <                fputendian(pfp);
744 <                fputformat("float", pfp);
741 >                fputwlsplit(WLPART, pdfp[0]);
742 >                fputncomp(NCSAMP, pdfp[0]);
743 >                fputendian(pdfp[0]);
744 >                fputformat("float", pdfp[0]);
745                  break;
746 <        default:;
746 >        default:;       // pro forma - caught this above
747          }
748 <        fputc('\n', pfp);                       // end picture header
749 <        fprtresolu(GetWidth(), GetHeight(), pfp);
750 <        if (dfname) {
748 >        fputc('\n', pdfp[0]);                   // flush picture header
749 >        if (fflush(pdfp[0]) == EOF) {
750 >                sprintf(errmsg, "cannot write header to picture '%s'", pfname);
751 >                error(SYSTEM, errmsg);
752 >                fclose(pdfp[0]);
753 >                pdfp[0] = NULL;
754 >                return RDTnone;
755 >        }
756 >        if (dfname) {                           // open depth output
757                  if (dfname[0] == '!')
758 <                        dfp = popen(dfname+1, "w");
758 >                        pdfp[1] = popen(dfname+1, "w");
759                  else
760 <                        dfp = fopen(dfname, "w");
761 <                if (!dfp) {
760 >                        pdfp[1] = fopen(dfname, "w");
761 >                if (!pdfp[1]) {
762                          sprintf(errmsg, "cannot open depth output '%s'", dfname);
763                          error(SYSTEM, errmsg);
764 +                        fclose(pdfp[0]);
765 +                        pdfp[0] = NULL;
766                          return RDTnone;
767                  }
768 <                SET_FILE_BINARY(dfp);
768 >                SET_FILE_BINARY(pdfp[1]);
769          }
770          if (RDTdepthT(dt) == RDTdshort) {       // write header for 16-bit depth?
771 <                newheader("RADIANCE", dfp);
772 <                fputs(GetHeader(), dfp);
773 <                fputs(VIEWSTR, dfp); fprintview(&vw, dfp); fputc('\n', dfp);
774 <                fputs(DEPTHSTR, dfp); fputs(dunit, dfp); fputc('\n', dfp);
775 <                fputformat(DEPTH16FMT, dfp);
776 <                fputc('\n', dfp);               // end-of-info
777 <                fprtresolu(GetWidth(), GetHeight(), dfp);
771 >                newheader("RADIANCE", pdfp[1]);
772 >                fputs(GetHeader(), pdfp[1]);
773 >                fputs(VIEWSTR, pdfp[1]); fprintview(&vw, pdfp[1]); fputc('\n', pdfp[1]);
774 >                fputs(DEPTHSTR, pdfp[1]); fputs(dunit, pdfp[1]); fputc('\n', pdfp[1]);
775 >                fputformat(DEPTH16FMT, pdfp[1]);
776 >                fputc('\n', pdfp[1]);           // end-of-info
777 >                if (fflush(pdfp[1]) == EOF) {
778 >                        sprintf(errmsg, "cannot write header to '%s'", dfname);
779 >                        error(SYSTEM, errmsg);
780 >                        fclose(pdfp[0]); fclose(pdfp[1]);
781 >                        pdfp[0] = pdfp[1] = NULL;
782 >                        return RDTnone;
783 >                }
784          }
785 <        const int       bheight = (psample > 1) ? int(2*psample+.99) : 4;
786 <        const int       vstep =  bheight >> (psample > 1);
785 >        return dt;                              // ready to roll
786 > }
787  
788 + /*
789 + * Render and write a frame to the named file
790 + * Include any header lines set prior to call
791 + * Picture file must not exist
792 + * Write pixels to stdout if !pfname
793 + * Write depth to a command if dfname[0]=='!'
794 + */
795 + RenderDataType
796 + RpictSimulManager::RenderFrame(const char *pfname, RenderDataType dt, const char *dfname)
797 + {
798 +        FILE    *pdfp[2];
799 +                                                // prepare output file(s)
800 +        dt = NewOutput(pdfp, pfname, dt, dfname);
801 +        if (dt == RDTnone)
802 +                return RDTnone;
803 +                                                // add resolution string(s)
804 +        fprtresolu(GetWidth(), GetHeight(), pdfp[0]);
805 +        if (RDTdepthT(dt) == RDTdshort)
806 +                fprtresolu(GetWidth(), GetHeight(), pdfp[1]);
807 +
808 +        const int       bheight = (psample > 1) ? int(8*psample+.99) : 16;
809 +        const int       vstep = bheight >> (psample > 1);
810 +
811          NewBar(bheight);                        // render frame if we can
812 <        if (!RenderBelow(GetHeight(), vstep, pfp, dt, dfp)) {
813 <                fclose(pfp);
814 <                if (dfp) (dfname[0] == '!') ? pclose(dfp) : fclose(dfp);
812 >        if (!RenderBelow(GetHeight(), vstep, pdfp[0], dt, pdfp[1])) {
813 >                fclose(pdfp[0]);
814 >                if (pdfp[1]) (dfname[0] == '!') ? pclose(pdfp[1]) : fclose(pdfp[1]);
815                  Cleanup();
816                  return RDTnone;
817          }
818          NewBar();                               // clean up and return
819 <        if (pfp != stdout)
820 <                fclose(pfp);
821 <        if (dfp) {
819 >        if (pdfp[0] != stdout)
820 >                fclose(pdfp[0]);
821 >        if (pdfp[1]) {
822                  if (dfname[0] == '!') {
823 <                        int     status = pclose(dfp);
823 >                        int     status = pclose(pdfp[1]);
824                          if (status) {
825                                  sprintf(errmsg, "depth output (%s) error status: %d",
826                                                  dfname, status);
# Line 762 | Line 828 | RpictSimulManager::RenderFrame(const char *pfname, Ren
828                                  return RDTnone;
829                          }
830                  } else
831 <                        fclose(dfp);
831 >                        fclose(pdfp[1]);
832          }
833          return dt;
834   }
835  
836   // passed struct for header line callback
837 < struct HeaderInfo {
837 > static struct HeaderInfo {
838          char            fmt[MAXFMTLEN];
839          char            depth_unit[32];
840          int             ncomp;
# Line 789 | Line 855 | struct HeaderInfo {
855                                  gotview = false;
856                                  endianMatch = true;
857                          }
858 < };
858 > }       hinfo;          // XXX single copy to hold custom primitives
859  
860   // helper function checks header line and records req. info.
861   static int
# Line 831 | Line 897 | head_check(char *s, void *p)
897          return 0;
898   }
899  
900 < // Resume partially finished rendering
835 < // Picture file must exist
900 > // Reopen output file(s), leaving pointers at end of (each) header
901   RenderDataType
902 < RpictSimulManager::ResumeFrame(const char *pfname, const char *dfname)
902 > RpictSimulManager::ReopenOutput(FILE *pdfp[2], const char *pfname, const char *dfname)
903   {
904 <        if (!pfname || pfname[0] == '!')
840 <                return RDTnone;
904 >        extern const char       HDRSTR[];
905  
906 +        if (!pfname || pfname[0] == '!') {
907 +                pdfp[0] = pdfp[1] = NULL;
908 +                return RDTnone;
909 +        }
910          RenderDataType  dt = RDTnone;
911 <        FILE *          dfp = NULL;
912 <        FILE *          pfp = fopen(pfname, "r+");
913 <        if (!pfp) {
911 >        pdfp[1] = NULL;
912 >        pdfp[0] = fopen(pfname, "r+");
913 >        if (!pdfp[0]) {
914                  sprintf(errmsg, "cannot reopen output picture '%s'", pfname);
915                  error(SYSTEM, errmsg);
916                  return RDTnone;
917          }
918 <        SET_FILE_BINARY(pfp);
919 <        HeaderInfo      hinfo;          // read header information & dimensions
920 <        RESOLU          res;
921 <        if (getheader(pfp, head_check, &hinfo) < 0) {
854 <                fclose(pfp);
918 >        SET_FILE_BINARY(pdfp[0]);       // read header information
919 >        if (getheader(pdfp[0], head_check, &hinfo) < 0) {
920 >                fclose(pdfp[0]);
921 >                pdfp[0] = NULL;
922                  return RDTnone;
923          }
857        if (!fgetsresolu(&res, pfp) || res.rt != PIXSTANDARD) {
858                sprintf(errmsg, "missing/bad resolution for '%s'", pfname);
859                error(USER, errmsg);
860                fclose(pfp);
861                return RDTnone;
862        }
924          if (!hinfo.gotview) {
925                  sprintf(errmsg, "missing view for '%s'", pfname);
926                  error(USER, errmsg);
927 <                fclose(pfp);
927 >                fclose(pdfp[0]);
928 >                pdfp[0] = NULL;
929                  return RDTnone;
930          }
931          if (hinfo.ncomp < 3) {
932                  sprintf(errmsg, "bad # components (%d) in '%s'", hinfo.ncomp, pfname);
933                  error(USER, errmsg);
934 <                fclose(pfp);
934 >                fclose(pdfp[0]);
935 >                pdfp[0] = NULL;
936                  return RDTnone;
937          }
938 <        int     bytesPer = 0;           // complicated part to set rendering/output space
938 >                                        // set rendering/output space
939          if (!strcmp(hinfo.fmt, COLRFMT)) {
940 <                prims = hinfo.prims;
940 >                prims = hinfo.prims;    // XXX static array
941                  int     n = 8*hinfo.gotprims;
942                  while (n--)
943                          if (!FABSEQ(hinfo.prims[0][n], stdprims[0][n]))
# Line 890 | Line 953 | RpictSimulManager::ResumeFrame(const char *pfname, con
953                          sprintf(errmsg, "incompatible sample count (%d) in '%s'",
954                                          hinfo.ncomp, pfname);
955                          error(USER, errmsg);
956 <                        fclose(pfp);
956 >                        fclose(pdfp[0]);
957 >                        pdfp[0] = NULL;
958                          return RDTnone;
959                  }
960 <                NCSAMP = hinfo.ncomp;   // overrides global setting
960 >                NCSAMP = hinfo.ncomp;           // overrides global setting
961                  prims = NULL;
962                  dt = RDTnewCT(dt, RDTscolr);
899                bytesPer = hinfo.ncomp + 1;     // XXX assumes no compression
963          } else if (!strcmp(hinfo.fmt, "float")) {
964                  if (!hinfo.endianMatch) {
965                          sprintf(errmsg, "incompatible byte ordering in '%s'", pfname);
966                          error(USER, errmsg);
967 <                        fclose(pfp);
967 >                        fclose(pdfp[0]);
968 >                        pdfp[0] = NULL;
969                          return RDTnone;
970                  }
971                  if (hinfo.ncomp == 3) {
972 <                        prims = hinfo.prims;            // custom primaries?
972 >                        prims = hinfo.prims;    // custom primaries?
973                          int     n = 8*hinfo.gotprims;
974                          while (n--)
975                                  if (!FABSEQ(hinfo.prims[0][n], stdprims[0][n]))
976                                          break;
977 <                        if (n < 0)                      // standard primaries?
977 >                        if (n < 0)              // standard primaries?
978                                  prims = stdprims;
979                          else if (hinfo.gotprims) {      // or check if XYZ
980                                  for (n = 8; n--; )
# Line 928 | Line 992 | RpictSimulManager::ResumeFrame(const char *pfname, con
992                          prims = NULL;
993                          dt = RDTnewCT(dt, RDTscolor);
994                  }
931                bytesPer = sizeof(float)*hinfo.ncomp;
995          } else {
996                  sprintf(errmsg, "unknown format (%s) for '%s'", hinfo.fmt, pfname);
997                  error(USER, errmsg);
998 <                fclose(pfp);
998 >                fclose(pdfp[0]);
999 >                pdfp[0] = NULL;
1000                  return RDTnone;
1001          }
1002 +        if (!dfname)                            // no depth file?
1003 +                return dt;
1004 +
1005 +        if (dfname[0] == '!') {
1006 +                error(USER, "depth data cannot be reloaded from command");
1007 +                fclose(pdfp[0]);
1008 +                pdfp[0] = NULL;
1009 +                return RDTnone;
1010 +        }
1011 +        pdfp[1] = fopen(dfname, "r+");
1012 +        if (!pdfp[1]) {
1013 +                sprintf(errmsg, "cannot reopen depth file '%s'", dfname);
1014 +                error(SYSTEM, errmsg);
1015 +                fclose(pdfp[0]);
1016 +                pdfp[0] = NULL;
1017 +                return RDTnone;
1018 +        }
1019 +        SET_FILE_BINARY(pdfp[1]);
1020 +        int     n, len = strlen(HDRSTR);
1021 +        char    buf[32];                // sniff for 16-bit header
1022 +        if (getbinary(buf, 1, len+1, pdfp[1]) < len+1) {
1023 +                sprintf(errmsg, "empty depth file '%s'", dfname);
1024 +                error(SYSTEM, errmsg);
1025 +                fclose(pdfp[0]); fclose(pdfp[1]);
1026 +                pdfp[0] = pdfp[1] = NULL;
1027 +                return RDTnone;
1028 +        }
1029 +        for (n = 0; n < len; n++)
1030 +                if (buf[n] != HDRSTR[n])
1031 +                        break;          // not a Radiance header
1032 +        rewind(pdfp[1]);
1033 +        if ((n < len) | !isprint(buf[len]))
1034 +                return RDTnewDT(dt, RDTdfloat);
1035 +
1036 +        HeaderInfo      dinfo;          // thinking it's 16-bit encoded
1037 +        if (getheader(pdfp[1], head_check, &dinfo) < 0)
1038 +                sprintf(errmsg, "bad header in encoded depth file '%s'",
1039 +                                dfname);
1040 +        else if (strcmp(dinfo.fmt, DEPTH16FMT))
1041 +                sprintf(errmsg, "wrong format (%s) for depth file '%s'",
1042 +                                dinfo.fmt, dfname);
1043 +        else if (!SetReferenceDepth(dinfo.depth_unit))
1044 +                sprintf(errmsg, "bad/missing reference depth (%s) in '%s'",
1045 +                                dinfo.depth_unit, dfname);
1046 +        else
1047 +                errmsg[0] = '\0';
1048 +
1049 +        if (errmsg[0]) {
1050 +                error(USER, errmsg);
1051 +                fclose(pdfp[1]); fclose(pdfp[0]);
1052 +                pdfp[0] = pdfp[1] = NULL;
1053 +                return RDTnone;
1054 +        }
1055 +        return RDTnewDT(dt, RDTdshort);
1056 + }
1057 +
1058 + // Resume partially finished rendering
1059 + // Picture file must exist
1060 + RenderDataType
1061 + RpictSimulManager::ResumeFrame(const char *pfname, const char *dfname)
1062 + {
1063 +        FILE            *pdfp[2];
1064 +
1065 +        RenderDataType  dt = ReopenOutput(pdfp, pfname, dfname);
1066 +        if (dt == RDTnone)
1067 +                return RDTnone;
1068 +
1069 +        int     bytesPer = 0;           // figure out how far we got...
1070 +        switch (RDTcolorT(dt)) {
1071 +        case RDTrgbe:
1072 +        case RDTxyze:
1073 +                break;
1074 +        case RDTscolr:
1075 +                bytesPer = hinfo.ncomp + 1;     // XXX assumes no compression
1076 +                break;
1077 +        case RDTrgb:
1078 +        case RDTxyz:
1079 +                bytesPer = sizeof(float)*3;
1080 +                break;
1081 +        case RDTscolor:
1082 +                bytesPer = sizeof(float)*hinfo.ncomp;
1083 +                break;
1084 +        default:
1085 +                sprintf(errmsg, "unknown format (%s) for '%s'", hinfo.fmt, pfname);
1086 +                error(USER, errmsg);
1087 +                fclose(pdfp[0]);
1088 +                if (pdfp[1]) fclose(pdfp[1]);
1089 +                return RDTnone;
1090 +        }
1091 +        RESOLU  res;
1092 +        if (!fgetsresolu(&res, pdfp[0]) || res.rt != PIXSTANDARD) {
1093 +                sprintf(errmsg, "missing/bad resolution for '%s'", pfname);
1094 +                error(USER, errmsg);
1095 +                fclose(pdfp[0]);
1096 +                if (pdfp[1]) fclose(pdfp[1]);
1097 +                return RDTnone;
1098 +        }
1099          vw.type = 0;                            // set up new (unreferenced) frame
1100          frameNo = 0;
1101          int     hvdim[2] = {res.xr, res.yr};
1102          double  noAdj = 0;
1103          if (!NewFrame(hinfo.vw, hvdim, &noAdj) ||
1104                          (hvdim[0] != res.xr) | (hvdim[1] != res.yr)) {
1105 <                fclose(pfp);
1105 >                error(CONSISTENCY, "unexpected resolution change in ResumeFrame()");
1106 >                fclose(pdfp[0]);
1107 >                if (pdfp[1]) fclose(pdfp[1]);
1108                  return RDTnone;
1109          }
1110 <        long    dataStart = ftell(pfp);         // picture starting point
1110 >        long    dataStart = ftell(pdfp[0]);     // picture starting point
1111          if (dataStart < 0) {
1112                  sprintf(errmsg, "cannot seek on '%s'", pfname);
1113                  error(SYSTEM, errmsg);
1114 <                fclose(pfp);
1114 >                fclose(pdfp[0]);
1115 >                if (pdfp[1]) fclose(pdfp[1]);
1116                  return RDTnone;
1117          }
1118          long    doneScans = 0;
1119          if (bytesPer) {                         // fixed-width records?
1120 <                fseek(pfp, 0, SEEK_END);
1121 <                long    dataEnd = ftell(pfp);
1120 >                fseek(pdfp[0], 0, SEEK_END);
1121 >                long    dataEnd = ftell(pdfp[0]);
1122                  doneScans = (dataEnd - dataStart)/(bytesPer*GetWidth());
1123                  if (dataEnd-dataStart > bytesPer*GetWidth()*doneScans)
1124 <                        fseek(pfp, dataStart + bytesPer*GetWidth()*doneScans, SEEK_SET);
1124 >                        fseek(pdfp[0], dataStart + bytesPer*GetWidth()*doneScans, SEEK_SET);
1125          } else {                                // else get compressed scanlines
1126                  COLR *  scan = (COLR *)tempbuffer(sizeof(COLR)*GetWidth());
1127 <                while (freadcolrs(scan, GetWidth(), pfp) >= 0)
1127 >                while (freadcolrs(scan, GetWidth(), pdfp[0]) >= 0)
1128                          ++doneScans;
1129 <                if (!feof(pfp)) {
1129 >                if (!feof(pdfp[0])) {
1130                          sprintf(errmsg, "error reading compressed scanline from '%s'", pfname);
1131                          error(USER, errmsg);
1132 <                        fclose(pfp);
1132 >                        fclose(pdfp[0]);
1133 >                        if (pdfp[1]) fclose(pdfp[1]);
1134                          return RDTnone;
1135                  }
1136          }
1137          if (doneScans >= GetHeight()) {         // nothing left to do?
1138                  sprintf(errmsg, "output file '%s' is already complete", pfname);
1139                  error(WARNING, errmsg);
1140 <                fclose(pfp);
1140 >                fclose(pdfp[0]);
1141 >                if (pdfp[1]) fclose(pdfp[1]);
1142                  return dt;
1143          }
1144          if (!doneScans) {
1145                  sprintf(errmsg, "restarting empty frame '%s'", pfname);
1146                  error(WARNING, errmsg);
1147          }
1148 <        if (dfname) {                           // append depth file, too?
1149 <                if (dfname[0] == '!') {
1150 <                        error(USER, "depth data cannot be reloaded from command");
1151 <                        fclose(pfp);
1148 >        long    toSkip = 0;
1149 >        switch (RDTdepthT(dt)) {                // append depth file, too?
1150 >        case RDTdfloat:
1151 >                toSkip = sizeof(float)*GetWidth()*doneScans;
1152 >                break;
1153 >        case RDTdshort:
1154 >                if (!fgetsresolu(&res, pdfp[1]) || (res.rt != PIXSTANDARD) |
1155 >                                (res.xr != GetWidth()) | (res.yr != GetHeight())) {
1156 >                        sprintf(errmsg, "missing/bad resolution for '%s'", dfname);
1157 >                        error(USER, errmsg);
1158 >                        fclose(pdfp[0]); fclose(pdfp[0]);
1159                          return RDTnone;
1160                  }
1161 <                dfp = fopen(dfname, "a");
1162 <                if (!dfp) {
1163 <                        sprintf(errmsg, "cannot reopen depth file '%s'", dfname);
1164 <                        error(SYSTEM, errmsg);
1165 <                        fclose(pfp);
1166 <                        return RDTnone;
1167 <                }
1168 <                SET_FILE_BINARY(dfp);
1169 <                const long      dflen = ftell(dfp);
997 <                if (dflen != sizeof(float)*GetWidth()*doneScans) {
998 <                        fclose(dfp);
999 <                        dfp = fopen(dfname, "r+");
1000 <                        if (!dfp) return RDTnone;       // WTH?
1001 <                        SET_FILE_BINARY(dfp);
1002 <                }
1003 <                if (dflen < sizeof(float)*GetWidth()*doneScans) {
1004 <                        HeaderInfo      dinfo;
1005 <                        if (getheader(dfp, head_check, &dinfo) < 0)
1006 <                                sprintf(errmsg, "bad header in encoded depth file '%s'",
1007 <                                                dfname);
1008 <                        else if (strcmp(dinfo.fmt, DEPTH16FMT))
1009 <                                sprintf(errmsg, "wrong format (%s) for depth file '%s'",
1010 <                                                dinfo.fmt, dfname);
1011 <                        else if (!SetReferenceDepth(dinfo.depth_unit))
1012 <                                sprintf(errmsg, "bad/missing reference depth (%s) in '%s'",
1013 <                                                dinfo.depth_unit, dfname);
1014 <                        else if (!fscnresolu(hvdim, hvdim+1, dfp) ||
1015 <                                        (hvdim[0] != GetWidth()) | (hvdim[1] != GetHeight()))
1016 <                                sprintf(errmsg, "bad/mismatched resolution in '%s'",
1017 <                                                dfname);
1018 <                        else
1019 <                                errmsg[0] = '\0';
1020 <
1021 <                        if (errmsg[0]) {
1022 <                                error(USER, errmsg);
1023 <                                fclose(dfp);
1024 <                                fclose(pfp);
1025 <                                return RDTnone;
1026 <                        }
1027 <                        const long      dStart = ftell(dfp);
1028 <                        if (dflen-dStart < 2*GetWidth()*doneScans) {
1029 <                                sprintf(errmsg, "missing %ld depths in '%s'",
1030 <                                        (long)GetWidth()*doneScans - (dflen-dStart)/2,
1031 <                                        dfname);
1032 <                                error(WARNING, errmsg);
1033 <                        }
1034 <                        fseek(dfp, dStart + 2*GetWidth()*doneScans, SEEK_SET);
1035 <                        dt = RDTnewDT(dt, RDTdshort);
1036 <                } else {
1037 <                        if (dflen > sizeof(float)*GetWidth()*doneScans)
1038 <                                fseek(dfp, sizeof(float)*GetWidth()*doneScans, SEEK_SET);
1039 <                        dt = RDTnewDT(dt, RDTdfloat);
1040 <                }
1161 >                toSkip = 2L*GetWidth()*doneScans;
1162 >                break;
1163 >        default:;
1164 >        }                                       // fseek() needed for output
1165 >        if (pdfp[1] && fseek(pdfp[1], toSkip, SEEK_CUR) < 0) {
1166 >                sprintf(errmsg, "cannot seek on depth file '%s'", dfname);
1167 >                error(SYSTEM, errmsg);
1168 >                fclose(pdfp[0]); fclose(pdfp[1]);
1169 >                return RDTnone;
1170          }
1171 <        int     bheight = (psample > 1) ? int(2*psample+.99) : 4;
1171 >        int     bheight = (psample > 1) ? int(8*psample+.99) : 16;
1172          if (bheight > GetHeight()-doneScans)
1173                  bheight = GetHeight()-doneScans;
1174          int     vstep =  bheight >> (psample > 1);
1175          vstep += !vstep;
1176  
1177          NewBar(bheight);                        // render remainder if we can
1178 <        if (!RenderBelow(GetHeight()-doneScans, vstep, pfp, dt, dfp)) {
1179 <                fclose(pfp);
1180 <                if (dfp) fclose(dfp);
1178 >        if (!RenderBelow(GetHeight()-doneScans, vstep, pdfp[0], dt, pdfp[1])) {
1179 >                fclose(pdfp[0]);
1180 >                if (pdfp[1]) fclose(pdfp[1]);
1181                  Cleanup();
1182                  return RDTnone;
1183          }
1184          NewBar();                               // close up and return success
1185 <        fclose(pfp);
1186 <        if (dfp) fclose(dfp);
1185 >        fclose(pdfp[0]);
1186 >        if (pdfp[1]) fclose(pdfp[1]);
1187          return dt;
1188   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines