| 15 |  | #include "paths.h" | 
| 16 |  | #include "resolu.h" | 
| 17 |  |  | 
| 18 | + | const char      stdin_name[] = "<stdin>"; | 
| 19 | + |  | 
| 20 |  | const char      *cm_fmt_id[] = { | 
| 21 |  | "unknown", COLRFMT, CIEFMT, | 
| 22 |  | "float", "ascii", "double" | 
| 23 |  | }; | 
| 24 |  |  | 
| 25 |  | const int       cm_elem_size[] = { | 
| 26 | < | 0, 0, 4, 4, 3*sizeof(float), 3*sizeof(double) | 
| 26 | > | 0, 4, 4, 3*sizeof(float), 0, 3*sizeof(double) | 
| 27 |  | }; | 
| 28 |  |  | 
| 29 |  | /* Allocate a color coefficient matrix */ | 
| 35 |  | if ((nrows <= 0) | (ncols <= 0)) | 
| 36 |  | error(USER, "attempt to create empty matrix"); | 
| 37 |  | cm = (CMATRIX *)malloc(sizeof(CMATRIX) + | 
| 38 | < | sizeof(COLOR)*(nrows*ncols - 1)); | 
| 38 | > | sizeof(COLOR)*((size_t)nrows*ncols - 1)); | 
| 39 |  | if (!cm) | 
| 40 |  | error(SYSTEM, "out of memory in cm_alloc()"); | 
| 41 |  | cm->nrows = nrows; | 
| 67 |  | cm_free(cm); | 
| 68 |  | return(NULL); | 
| 69 |  | } | 
| 70 | < | old_size = sizeof(CMATRIX) + sizeof(COLOR)*(cm->nrows*cm->ncols - 1); | 
| 70 | > | old_size = sizeof(CMATRIX) + sizeof(COLOR)*((size_t)cm->nrows*cm->ncols - 1); | 
| 71 |  | adjacent_ra_sizes(ra_bounds, old_size); | 
| 72 | < | new_size = sizeof(CMATRIX) + sizeof(COLOR)*(nrows*cm->ncols - 1); | 
| 72 | > | new_size = sizeof(CMATRIX) + sizeof(COLOR)*((size_t)nrows*cm->ncols - 1); | 
| 73 |  | if (nrows < cm->nrows ? new_size <= ra_bounds[0] : | 
| 74 |  | new_size > ra_bounds[1]) { | 
| 75 |  | adjacent_ra_sizes(ra_bounds, new_size); | 
| 183 |  | CMATRIX *cm; | 
| 184 |  | COLORV  *mp; | 
| 185 |  | /* header already loaded */ | 
| 184 | – | if ((nrows <= 0) | (ncols <= 0) && !fscnresolu(&ncols, &nrows, fp)) { | 
| 185 | – | error(USER, "bad picture resolution string"); | 
| 186 | – | return(NULL); | 
| 187 | – | } | 
| 186 |  | cm = cm_alloc(nrows, ncols); | 
| 187 |  | if (!cm) | 
| 188 |  | return(NULL); | 
| 214 |  | cm_load(const char *inspec, int nrows, int ncols, int dtype) | 
| 215 |  | { | 
| 216 |  | const int       ROWINC = 2048; | 
| 219 | – | FILE            *fp = stdin; | 
| 217 |  | int             swap = 0; | 
| 218 | + | FILE            *fp; | 
| 219 |  | COLOR           scale; | 
| 220 |  | CMATRIX         *cm; | 
| 221 |  |  | 
| 222 |  | if (!inspec) | 
| 223 | < | inspec = "<stdin>"; | 
| 224 | < | else if (inspec[0] == '!') { | 
| 223 | > | inspec = stdin_name; | 
| 224 | > | else if (!*inspec) | 
| 225 | > | return(NULL); | 
| 226 | > | if (inspec == stdin_name) {             /* reading from stdin? */ | 
| 227 | > | fp = stdin; | 
| 228 | > | } else if (inspec[0] == '!') { | 
| 229 |  | fp = popen(inspec+1, "r"); | 
| 230 |  | if (!fp) { | 
| 231 |  | sprintf(errmsg, "cannot start command '%s'", inspec); | 
| 240 |  | #endif | 
| 241 |  | if (dtype != DTascii) | 
| 242 |  | SET_FILE_BINARY(fp);            /* doesn't really work */ | 
| 243 | < | if (!dtype | !ncols) {                  /* expecting header? */ | 
| 243 | > | if (!dtype | !nrows | !ncols) {         /* expecting header? */ | 
| 244 |  | char    *err = cm_getheader(&dtype, &nrows, &ncols, &swap, scale, fp); | 
| 245 |  | if (err) | 
| 246 |  | error(USER, err); | 
| 245 | – | if (ncols <= 0) | 
| 246 | – | error(USER, "unspecified number of columns"); | 
| 247 |  | } | 
| 248 | + | if (!nrows | !ncols && !fscnresolu(&ncols, &nrows, fp)) | 
| 249 | + | error(USER, "unspecified matrix size"); | 
| 250 |  | switch (dtype) { | 
| 251 |  | case DTascii: | 
| 252 |  | case DTfloat: | 
| 261 |  | } | 
| 262 |  | if (nrows <= 0) {                       /* don't know length? */ | 
| 263 |  | int     guessrows = 147;        /* usually big enough */ | 
| 264 | < | if ((dtype != DTascii) & (fp != stdin) & (inspec[0] != '!')) { | 
| 264 | > | if (cm_elem_size[dtype] && (fp != stdin) & (inspec[0] != '!')) { | 
| 265 |  | long    startpos = ftell(fp); | 
| 266 |  | if (fseek(fp, 0L, SEEK_END) == 0) { | 
| 267 | + | long    rowsiz = (long)ncols*cm_elem_size[dtype]; | 
| 268 |  | long    endpos = ftell(fp); | 
| 266 | – | long    elemsiz = 3*(dtype==DTfloat ? | 
| 267 | – | sizeof(float) : sizeof(double)); | 
| 269 |  |  | 
| 270 | < | if ((endpos - startpos) % (ncols*elemsiz)) { | 
| 270 | > | if ((endpos - startpos) % rowsiz) { | 
| 271 |  | sprintf(errmsg, | 
| 272 |  | "improper length for binary file '%s'", | 
| 273 |  | inspec); | 
| 274 |  | error(USER, errmsg); | 
| 275 |  | } | 
| 276 | < | guessrows = (endpos - startpos)/(ncols*elemsiz); | 
| 276 | > | guessrows = (endpos - startpos)/rowsiz; | 
| 277 |  | if (fseek(fp, startpos, SEEK_SET) < 0) { | 
| 278 |  | sprintf(errmsg, | 
| 279 |  | "fseek() error on file '%s'", | 
| 315 |  | } | 
| 316 |  | } else {                                        /* read binary file */ | 
| 317 |  | if (sizeof(COLOR) == cm_elem_size[dtype]) { | 
| 318 | < | int     nread = 0; | 
| 318 | > | size_t  nread = 0; | 
| 319 |  | do {                            /* read all we can */ | 
| 320 |  | nread += getbinary(cm->cmem + 3*nread, | 
| 321 |  | sizeof(COLOR), | 
| 322 | < | cm->nrows*cm->ncols - nread, | 
| 322 | > | (size_t)cm->nrows*cm->ncols - nread, | 
| 323 |  | fp); | 
| 324 |  | if (nrows <= 0) {       /* unknown length */ | 
| 325 | < | if (nread == cm->nrows*cm->ncols) | 
| 325 | > | if (nread == (size_t)cm->nrows*cm->ncols) | 
| 326 |  | /* need more space? */ | 
| 327 |  | cm = cm_resize(cm, cm->nrows+ROWINC); | 
| 328 |  | else if (nread && !(nread % cm->ncols)) | 
| 330 |  | cm = cm_resize(cm, nread/cm->ncols); | 
| 331 |  | else            /* ended mid-row */ | 
| 332 |  | goto EOFerror; | 
| 333 | < | } else if (nread < cm->nrows*cm->ncols) | 
| 333 | > | } else if (nread < (size_t)cm->nrows*cm->ncols) | 
| 334 |  | goto EOFerror; | 
| 335 | < | } while (nread < cm->nrows*cm->ncols); | 
| 335 | > | } while (nread < (size_t)cm->nrows*cm->ncols); | 
| 336 |  |  | 
| 337 | + | if (swap) { | 
| 338 | + | if (sizeof(COLORV) == 4) | 
| 339 | + | swap32((char *)cm->cmem, | 
| 340 | + | 3*(size_t)cm->nrows*cm->ncols); | 
| 341 | + | else /* sizeof(COLORV) == 8 */ | 
| 342 | + | swap64((char *)cm->cmem, | 
| 343 | + | 3*(size_t)cm->nrows*cm->ncols); | 
| 344 | + | } | 
| 345 |  | } else if (dtype == DTdouble) { | 
| 346 |  | double  dc[3];                  /* load from double */ | 
| 347 |  | COLORV  *cvp = cm->cmem; | 
| 348 | < | int     n = nrows*ncols; | 
| 348 | > | size_t  n = (size_t)nrows*ncols; | 
| 349 |  |  | 
| 350 |  | if (n <= 0) | 
| 351 |  | goto not_handled; | 
| 352 |  | while (n--) { | 
| 353 |  | if (getbinary(dc, sizeof(double), 3, fp) != 3) | 
| 354 |  | goto EOFerror; | 
| 355 | + | if (swap) swap64((char *)dc, 3); | 
| 356 |  | copycolor(cvp, dc); | 
| 357 |  | cvp += 3; | 
| 358 |  | } | 
| 359 |  | } else /* dtype == DTfloat */ { | 
| 360 |  | float   fc[3];                  /* load from float */ | 
| 361 |  | COLORV  *cvp = cm->cmem; | 
| 362 | < | int     n = nrows*ncols; | 
| 362 | > | size_t  n = (size_t)nrows*ncols; | 
| 363 |  |  | 
| 364 |  | if (n <= 0) | 
| 365 |  | goto not_handled; | 
| 366 |  | while (n--) { | 
| 367 |  | if (getbinary(fc, sizeof(float), 3, fp) != 3) | 
| 368 |  | goto EOFerror; | 
| 369 | + | if (swap) swap32((char *)fc, 3); | 
| 370 |  | copycolor(cvp, fc); | 
| 371 |  | cvp += 3; | 
| 372 |  | } | 
| 378 |  | error(WARNING, errmsg); | 
| 379 |  | } | 
| 380 |  | } | 
| 370 | – | if (swap) { | 
| 371 | – | if (dtype == DTfloat) | 
| 372 | – | swap32((char *)cm->cmem, 3*cm->nrows*cm->ncols); | 
| 373 | – | else if (dtype == DTdouble) | 
| 374 | – | swap64((char *)cm->cmem, 3*cm->nrows*cm->ncols); | 
| 375 | – | } | 
| 381 |  | cleanup: | 
| 382 |  | if (fp != stdin) { | 
| 383 |  | if (inspec[0] != '!') | 
| 489 |  | static const char       tabEOL[2] = {'\t','\n'}; | 
| 490 |  | const COLORV            *mp; | 
| 491 |  | int                     r, c; | 
| 492 | + | size_t                  n, rv; | 
| 493 |  |  | 
| 494 |  | if (!cm) | 
| 495 |  | return(0); | 
| 505 |  | case DTfloat: | 
| 506 |  | case DTdouble: | 
| 507 |  | if (sizeof(COLOR) == cm_elem_size[dtype]) { | 
| 508 | < | r = cm->ncols*cm->nrows; | 
| 509 | < | while (r > 0) { | 
| 510 | < | c = putbinary(mp, sizeof(COLOR), r, fp); | 
| 511 | < | if (c <= 0) | 
| 508 | > | n = (size_t)cm->ncols*cm->nrows; | 
| 509 | > | while (n > 0) { | 
| 510 | > | rv = fwrite(mp, sizeof(COLOR), n, fp); | 
| 511 | > | if (rv <= 0) | 
| 512 |  | return(0); | 
| 513 | < | mp += 3*c; | 
| 514 | < | r -= c; | 
| 513 | > | mp += 3*rv; | 
| 514 | > | n -= rv; | 
| 515 |  | } | 
| 516 |  | } else if (dtype == DTdouble) { | 
| 517 |  | double  dc[3]; | 
| 518 | < | r = cm->ncols*cm->nrows; | 
| 519 | < | while (r--) { | 
| 518 | > | n = (size_t)cm->ncols*cm->nrows; | 
| 519 | > | while (n--) { | 
| 520 |  | copycolor(dc, mp); | 
| 521 |  | if (putbinary(dc, sizeof(double), 3, fp) != 3) | 
| 522 |  | return(0); | 
| 524 |  | } | 
| 525 |  | } else /* dtype == DTfloat */ { | 
| 526 |  | float   fc[3]; | 
| 527 | < | r = cm->ncols*cm->nrows; | 
| 528 | < | while (r--) { | 
| 527 | > | n = (size_t)cm->ncols*cm->nrows; | 
| 528 | > | while (n--) { | 
| 529 |  | copycolor(fc, mp); | 
| 530 |  | if (putbinary(fc, sizeof(float), 3, fp) != 3) | 
| 531 |  | return(0); |