ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/cmatrix.c
(Generate patch)

Comparing ray/src/util/cmatrix.c (file contents):
Revision 2.27 by greg, Thu Mar 26 16:56:10 2020 UTC vs.
Revision 2.41 by greg, Sat Apr 19 17:12:59 2025 UTC

# Line 15 | Line 15 | static const char RCSid[] = "$Id$";
15   #include "paths.h"
16   #include "resolu.h"
17  
18 const char      *cm_fmt_id[] = {
19                        "unknown", COLRFMT, CIEFMT,
20                        "float", "ascii", "double"
21                };
22
23 const int       cm_elem_size[] = {
24                        0, 4, 4, 3*sizeof(float), 0, 3*sizeof(double)
25                };
26
18   /* Allocate a color coefficient matrix */
19   CMATRIX *
20   cm_alloc(int nrows, int ncols)
# Line 33 | Line 24 | cm_alloc(int nrows, int ncols)
24          if ((nrows <= 0) | (ncols <= 0))
25                  error(USER, "attempt to create empty matrix");
26          cm = (CMATRIX *)malloc(sizeof(CMATRIX) +
27 <                                sizeof(COLOR)*(nrows*ncols - 1));
27 >                                sizeof(COLOR)*((size_t)nrows*ncols - 1));
28          if (!cm)
29                  error(SYSTEM, "out of memory in cm_alloc()");
30          cm->nrows = nrows;
# Line 65 | Line 56 | cm_resize(CMATRIX *cm, int nrows)
56                  cm_free(cm);
57                  return(NULL);
58          }
59 <        old_size = sizeof(CMATRIX) + sizeof(COLOR)*(cm->nrows*cm->ncols - 1);
59 >        old_size = sizeof(CMATRIX) + sizeof(COLOR)*((size_t)cm->nrows*cm->ncols - 1);
60          adjacent_ra_sizes(ra_bounds, old_size);
61 <        new_size = sizeof(CMATRIX) + sizeof(COLOR)*(nrows*cm->ncols - 1);
61 >        new_size = sizeof(CMATRIX) + sizeof(COLOR)*((size_t)nrows*cm->ncols - 1);
62          if (nrows < cm->nrows ? new_size <= ra_bounds[0] :
63                                  new_size > ra_bounds[1]) {
64                  adjacent_ra_sizes(ra_bounds, new_size);
# Line 94 | Line 85 | get_cminfo(char *s, void *p)
85          char    fmt[MAXFMTLEN];
86          int     i;
87  
88 <        if (!strncmp(s, "NCOMP=", 6) && atoi(s+6) != 3) {
88 >        if (isncomp(s) && ncompval(s) != 3) {
89                  ip->err = "unexpected # components (must be 3)";
90                  return(-1);
91          }
# Line 175 | Line 166 | cm_getheader(int *dt, int *nr, int *nc, int *swp, COLO
166  
167   /* Allocate and load image data into matrix */
168   static CMATRIX *
169 < cm_load_rgbe(FILE *fp, int nrows, int ncols, COLOR scale)
169 > cm_load_rgbe(FILE *fp, int nrows, int ncols)
170   {
180        int     doscale;
171          CMATRIX *cm;
172          COLORV  *mp;
173                                                  /* header already loaded */
184        if ((nrows <= 0) | (ncols <= 0) && !fscnresolu(&ncols, &nrows, fp)) {
185                error(USER, "bad picture resolution string");
186                return(NULL);
187        }
174          cm = cm_alloc(nrows, ncols);
175          if (!cm)
176                  return(NULL);
191        doscale = (scale[0] < .99) | (scale[0] > 1.01) |
192                        (scale[1] < .99) | (scale[1] > 1.01) |
193                        (scale[2] < .99) | (scale[2] > 1.01) ;
177          mp = cm->cmem;
178          while (nrows--) {
179                  if (freadscan((COLOR *)mp, ncols, fp) < 0) {
# Line 198 | Line 181 | cm_load_rgbe(FILE *fp, int nrows, int ncols, COLOR sca
181                          cm_free(cm);
182                          return(NULL);
183                  }
184 <                if (doscale) {
202 <                        int     i = ncols;
203 <                        while (i--) {
204 <                                *mp++ *= scale[0];
205 <                                *mp++ *= scale[1];
206 <                                *mp++ *= scale[2];
207 <                        }
208 <                } else
209 <                        mp += 3*ncols;
184 >                mp += 3*ncols;
185          }                                       /* caller closes stream */
186          return(cm);
187   }
# Line 216 | Line 191 | CMATRIX *
191   cm_load(const char *inspec, int nrows, int ncols, int dtype)
192   {
193          const int       ROWINC = 2048;
194 <        FILE            *fp = stdin;
194 >        int             dimsOK = (dtype == DTascii) | (nrows > 0) && ncols;
195          int             swap = 0;
196 +        FILE            *fp;
197          COLOR           scale;
198          CMATRIX         *cm;
199  
200          if (!inspec)
201 <                inspec = "<stdin>";
202 <        else if (inspec[0] == '!') {
201 >                inspec = stdin_name;
202 >        else if (!*inspec)
203 >                return(NULL);
204 >        if (inspec == stdin_name) {             /* reading from stdin? */
205 >                fp = stdin;
206 >        } else if (inspec[0] == '!') {
207                  fp = popen(inspec+1, "r");
208                  if (!fp) {
209                          sprintf(errmsg, "cannot start command '%s'", inspec);
# Line 238 | Line 218 | cm_load(const char *inspec, int nrows, int ncols, int
218   #endif
219          if (dtype != DTascii)
220                  SET_FILE_BINARY(fp);            /* doesn't really work */
221 <        if (!dtype | !ncols) {                  /* expecting header? */
221 >        if (!dtype | !dimsOK) {                 /* expecting header? */
222                  char    *err = cm_getheader(&dtype, &nrows, &ncols, &swap, scale, fp);
223                  if (err)
224                          error(USER, err);
225 <                if (ncols <= 0)
226 <                        error(USER, "unspecified number of columns");
225 >                dimsOK = ncols > 0 && ( nrows > 0 ||
226 >                                (dtype != DTrgbe) & (dtype != DTxyze) );
227          }
228 +        if (!dimsOK && !fscnresolu(&ncols, &nrows, fp))
229 +                error(USER, "unspecified matrix size");
230          switch (dtype) {
231          case DTascii:
232          case DTfloat:
# Line 252 | Line 234 | cm_load(const char *inspec, int nrows, int ncols, int
234                  break;
235          case DTrgbe:
236          case DTxyze:
237 <                cm = cm_load_rgbe(fp, nrows, ncols, scale);
237 >                cm = cm_load_rgbe(fp, nrows, ncols);
238                  goto cleanup;
239          default:
240                  error(USER, "unexpected data type in cm_load()");
# Line 313 | Line 295 | cm_load(const char *inspec, int nrows, int ncols, int
295                          }
296          } else {                                        /* read binary file */
297                  if (sizeof(COLOR) == cm_elem_size[dtype]) {
298 <                        int     nread = 0;
298 >                        size_t  nread = 0;
299                          do {                            /* read all we can */
300                                  nread += getbinary(cm->cmem + 3*nread,
301                                                  sizeof(COLOR),
302 <                                                cm->nrows*cm->ncols - nread,
302 >                                                (size_t)cm->nrows*cm->ncols - nread,
303                                                  fp);
304                                  if (nrows <= 0) {       /* unknown length */
305 <                                        if (nread == cm->nrows*cm->ncols)
305 >                                        if (nread == (size_t)cm->nrows*cm->ncols)
306                                                          /* need more space? */
307                                                  cm = cm_resize(cm, cm->nrows+ROWINC);
308                                          else if (nread && !(nread % cm->ncols))
# Line 328 | Line 310 | cm_load(const char *inspec, int nrows, int ncols, int
310                                                  cm = cm_resize(cm, nread/cm->ncols);
311                                          else            /* ended mid-row */
312                                                  goto EOFerror;
313 <                                } else if (nread < cm->nrows*cm->ncols)
313 >                                } else if (nread < (size_t)cm->nrows*cm->ncols)
314                                          goto EOFerror;
315 <                        } while (nread < cm->nrows*cm->ncols);
315 >                        } while (nread < (size_t)cm->nrows*cm->ncols);
316  
317                          if (swap) {
318                                  if (sizeof(COLORV) == 4)
319                                          swap32((char *)cm->cmem,
320 <                                                        3*cm->nrows*cm->ncols);
320 >                                                        3*(size_t)cm->nrows*cm->ncols);
321                                  else /* sizeof(COLORV) == 8 */
322                                          swap64((char *)cm->cmem,
323 <                                                        3*cm->nrows*cm->ncols);
323 >                                                        3*(size_t)cm->nrows*cm->ncols);
324                          }
325                  } else if (dtype == DTdouble) {
326                          double  dc[3];                  /* load from double */
327                          COLORV  *cvp = cm->cmem;
328 <                        int     n = nrows*ncols;
328 >                        size_t  n = (size_t)nrows*ncols;
329  
330                          if (n <= 0)
331                                  goto not_handled;
# Line 357 | Line 339 | cm_load(const char *inspec, int nrows, int ncols, int
339                  } else /* dtype == DTfloat */ {
340                          float   fc[3];                  /* load from float */
341                          COLORV  *cvp = cm->cmem;
342 <                        int     n = nrows*ncols;
342 >                        size_t  n = (size_t)nrows*ncols;
343  
344                          if (n <= 0)
345                                  goto not_handled;
# Line 389 | Line 371 | cleanup:
371          else
372                  funlockfile(fp);
373   #endif
374 +        if ((scale[0] < .99) | (scale[0] > 1.01) |
375 +                        (scale[1] < .99) | (scale[1] > 1.01) |
376 +                        (scale[2] < .99) | (scale[2] > 1.01)) {
377 +                size_t  n = (size_t)ncols*nrows;
378 +                COLORV  *mp = cm->cmem;
379 +                while (n--) {           /* apply exposure scaling */
380 +                        *mp++ *= scale[0];
381 +                        *mp++ *= scale[1];
382 +                        *mp++ *= scale[2];
383 +                }
384 +        }
385          return(cm);
386   EOFerror:
387          sprintf(errmsg, "unexpected EOF reading %s", inspec);
# Line 487 | Line 480 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
480          static const char       tabEOL[2] = {'\t','\n'};
481          const COLORV            *mp;
482          int                     r, c;
483 +        size_t                  n, rv;
484  
485          if (!cm)
486                  return(0);
487 + #ifdef getc_unlocked
488 +        flockfile(fp);
489 + #endif
490          mp = cm->cmem;
491          switch (dtype) {
492          case DTascii:
# Line 502 | Line 499 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
499          case DTfloat:
500          case DTdouble:
501                  if (sizeof(COLOR) == cm_elem_size[dtype]) {
502 <                        r = cm->ncols*cm->nrows;
503 <                        while (r > 0) {
504 <                                c = putbinary(mp, sizeof(COLOR), r, fp);
505 <                                if (c <= 0)
502 >                        n = (size_t)cm->ncols*cm->nrows;
503 >                        while (n > 0) {
504 >                                rv = fwrite(mp, sizeof(COLOR), n, fp);
505 >                                if (rv <= 0)
506                                          return(0);
507 <                                mp += 3*c;
508 <                                r -= c;
507 >                                mp += 3*rv;
508 >                                n -= rv;
509                          }
510                  } else if (dtype == DTdouble) {
511                          double  dc[3];
512 <                        r = cm->ncols*cm->nrows;
513 <                        while (r--) {
512 >                        n = (size_t)cm->ncols*cm->nrows;
513 >                        while (n--) {
514                                  copycolor(dc, mp);
515                                  if (putbinary(dc, sizeof(double), 3, fp) != 3)
516                                          return(0);
# Line 521 | Line 518 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
518                          }
519                  } else /* dtype == DTfloat */ {
520                          float   fc[3];
521 <                        r = cm->ncols*cm->nrows;
522 <                        while (r--) {
521 >                        n = (size_t)cm->ncols*cm->nrows;
522 >                        while (n--) {
523                                  copycolor(fc, mp);
524                                  if (putbinary(fc, sizeof(float), 3, fp) != 3)
525                                          return(0);
# Line 541 | Line 538 | cm_write(const CMATRIX *cm, int dtype, FILE *fp)
538                  fputs("Unsupported data type in cm_write()!\n", stderr);
539                  return(0);
540          }
541 + #ifdef getc_unlocked
542 +        funlockfile(fp);
543 + #endif
544          return(fflush(fp) == 0);
545   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines