/* ** Sat Jan 29 16:44:50 EST 2005: this used to "open the seperate ** datafile, and set the FILE* in nio->dataFile, which otherwise will ** stay NULL", but now we support multiple detached data files. So. ** ** The job of this function is to map the "data file" specification to ** one or more filenames that can be passed direction to fopen for ** reading in the data. This involves parsing the various formats for ** identifying multiple data files, and possibly prefixing them with ** nio->path. */ int _nrrdReadNrrdParse_data_file (FILE *ffile, Nrrd *nrrd, NrrdIoState *nio, int useBiff) { char me[]="_nrrdReadNrrdParse_data_file", err[BIFF_STRLEN]; char *info, *nums; unsigned int linelen; int tmp; airArray *mop; mop = airMopNew(); info = airStrdup(nio->line + nio->pos); if (!info) { sprintf(err, "%s: couldn't copy line!", me); biffMaybeAdd(NRRD, err, useBiff); return 1; } airMopAdd(mop, info, airFree, airMopAlways); if (_nrrdContainsPercentDAndMore(info)) { /* ---------------------------------------------------------- */ /* --------- format.%d <min> <max> <step> [<dim>] ----------- */ /* ---------------------------------------------------------- */ nums = info + strcspn(info, _nrrdFieldSep); tmp = strspn(nums, _nrrdFieldSep); nums[0] = 0; /* terminate so that format is now in info */ nums += tmp; if (!( 3 == sscanf(nums, "%d %d %d",&(nio->dataFNMin), &(nio->dataFNMax), &(nio->dataFNStep)) )) { sprintf(err, "%s: couldn't parse three ints (min, max, step) after " "data filename template", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } if ( 4 == sscanf(nums, "%d %d %d %u", &(nio->dataFNMin), &(nio->dataFNMax), &(nio->dataFNStep), &(nio->dataFileDim)) ) { if (!( nio->dataFileDim >= 1 && nio->dataFileDim <= nrrd->dim )) { sprintf(err, "%s: datafile dimension %d outside valid range [1,%d]", me, nio->dataFileDim, nrrd->dim); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } } else { nio->dataFileDim = nrrd->dim-1; } if (0 == nio->dataFNStep) { sprintf(err, "%s: file number step must be non-zero", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } if ((nio->dataFNMax - nio->dataFNMin)*(nio->dataFNStep) < 0) { sprintf(err, "%s: file number max %d not approached from min %d " "by step %d", me, nio->dataFNMax, nio->dataFNMin, nio->dataFNStep); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } if (!( nio->dataFNFormat = airStrdup(info) )) { sprintf(err, "%s: couldn't copy data filename format", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } } else if (!strncmp(info, NRRD_LIST_FLAG, strlen(NRRD_LIST_FLAG))) { /* ---------------------------------------------------------- */ /* ------------------------- LIST --------------------------- */ /* ---------------------------------------------------------- */ if (_nrrdHeaderCheck(nrrd, nio, AIR_TRUE)) { sprintf(err, "%s: NRRD header is incomplete. \"" NRRD_LIST_FLAG "\" data file specification must be contiguous with " "end of header!", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } info += strlen(NRRD_LIST_FLAG); if (info[0]) { if (1 == sscanf(info, "%u", &(nio->dataFileDim))) { if (!( nio->dataFileDim >= 1 && nio->dataFileDim <= nrrd->dim )) { sprintf(err, "%s: datafile dimension %d outside valid range [1,%d]", me, nio->dataFileDim, nrrd->dim); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } } else { sprintf(err, "%s: couldn't parse info after \"" NRRD_LIST_FLAG "\" as an int", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } } else { /* nothing after NRRD_LIST_FLAG, so dataFileDim is implicit */ nio->dataFileDim = nrrd->dim-1; } /* read in all the datafile names */ do { /* yes, nio->line is re-used/over-written here, but I don't think that's a problem */ if (_nrrdOneLine(&linelen, nio, ffile)) { sprintf(err, "%s: trouble getting file name line", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } if (linelen > 0) { tmp = airArrayLenIncr(nio->dataFNArr, 1); nio->dataFN[tmp] = airStrdup(nio->line); } } while (linelen > 0); } else { /* ---------------------------------------------------------- */ /* -------------------- (single filename) ------------------- */ /* ---------------------------------------------------------- */ /* there is apparently only a single detached data file */ tmp = airArrayLenIncr(nio->dataFNArr, 1); nio->dataFN[tmp] = airStrdup(info); nio->dataFileDim = nrrd->dim; } if (_nrrdDataFNCheck(nio, nrrd, useBiff)) { sprintf(err, "%s: trouble with number of datafiles", me); biffMaybeAdd(NRRD, err, useBiff); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
int unrrdu_diceMain(int argc, char **argv, char *me, hestParm *hparm) { hestOpt *opt = NULL; char *base, *err, fnout[AIR_STRLEN_MED], /* file name out */ fffname[AIR_STRLEN_MED], /* format for filename */ *ftmpl; /* format template */ Nrrd *nin, *nout; int top, pret, start, fit; unsigned int axis; size_t pos; airArray *mop; OPT_ADD_AXIS(axis, "axis to slice along"); OPT_ADD_NIN(nin, "input nrrd"); hestOptAdd(&opt, "s,start", "start", airTypeInt, 1, 1, &start, "0", "integer value to start numbering with"); hestOptAdd(&opt, "ff,format", "form", airTypeString, 1, 1, &ftmpl, "", "a printf-style format to use for generating all " "filenames. Use this to override the number of characters " "used to represent the slice position, or the file format " "of the output, e.g. \"-ff %03.ppm\" for 000.ppm, " "001.ppm, etc. By default (not using this option), slices " "are saved in NRRD format (or PNM or PNG where possible) " "with shortest possible filenames."); hestOptAdd(&opt, "o,output", "prefix", airTypeString, 1, 1, &base, NULL, "output filename prefix (excluding info set via \"-ff\"), " "basically to set path of output files (so be sure to end " "with \"/\"."); mop = airMopNew(); airMopAdd(mop, opt, (airMopper)hestOptFree, airMopAlways); USAGE(_unrrdu_diceInfoL); PARSE(); airMopAdd(mop, opt, (airMopper)hestParseFree, airMopAlways); if (start < 0) { fprintf(stderr, "%s: given start index (%d) less than zero\n", me, start); airMopError(mop); return 1; } if (!( axis < nin->dim )) { fprintf(stderr, "%s: given axis (%u) outside range [0,%u]\n", me, axis, nin->dim-1); airMopError(mop); return 1; } if (airStrlen(ftmpl)) { if (!_nrrdContainsPercentDAndMore(ftmpl)) { fprintf(stderr, "%s: given filename format \"%s\" doesn't seem to " "have the format sequence to print an integer\n", me, ftmpl); airMopError(mop); return 1; } sprintf(fffname, "%%s%s", ftmpl); } else { top = start + nin->axis[axis].size-1; if (top > 9999999) { sprintf(fffname, "%%s%%08d.nrrd"); } else if (top > 999999) { sprintf(fffname, "%%s%%07d.nrrd"); } else if (top > 99999) { sprintf(fffname, "%%s%%06d.nrrd"); } else if (top > 9999) { sprintf(fffname, "%%s%%05d.nrrd"); } else if (top > 999) { sprintf(fffname, "%%s%%04d.nrrd"); } else if (top > 99) { sprintf(fffname, "%%s%%03d.nrrd"); } else if (top > 9) { sprintf(fffname, "%%s%%02d.nrrd"); } else { sprintf(fffname, "%%s%%01d.nrrd"); } } nout = nrrdNew(); airMopAdd(mop, nout, (airMopper)nrrdNuke, airMopAlways); for (pos=0; pos<nin->axis[axis].size; pos++) { if (nrrdSlice(nout, nin, axis, pos)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error slicing nrrd:%s\n", me, err); airMopError(mop); return 1; } if (0 == pos && !airStrlen(ftmpl)) { /* See if these slices would be better saved as PNG or PNM images. Altering the file name will tell nrrdSave() to use a different file format. */ if (nrrdFormatPNG->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE)) { strcpy(fffname + strlen(fffname) - 4, "png"); } else { fit = nrrdFormatPNM->fitsInto(nout, nrrdEncodingRaw, AIR_FALSE); if (2 == fit) { strcpy(fffname + strlen(fffname) - 4, "pgm"); } else if (3 == fit) { strcpy(fffname + strlen(fffname) - 4, "ppm"); } } } sprintf(fnout, fffname, base, pos+start); fprintf(stderr, "%s: %s ...\n", me, fnout); if (nrrdSave(fnout, nout, NULL)) { airMopAdd(mop, err = biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error writing nrrd to \"%s\":%s\n", me, fnout, err); airMopError(mop); return 1; } } airMopOkay(mop); return 0; }