/* ******** nrrdSave ** ** save a given nrrd to a given filename, with cleverness to guess ** format if not specified by the caller ** ** currently, for NRRD format files, we play the detached header game ** whenever the filename ends in NRRD_EXT_NHDR, and when we play this ** game, the data file is ALWAYS header relative. */ int nrrdSave(const char *filename, const Nrrd *nrrd, NrrdIoState *nio) { char me[]="nrrdSave", err[BIFF_STRLEN]; FILE *file; airArray *mop; if (!(nrrd && filename)) { sprintf(err, "%s: got NULL pointer", me); biffAdd(NRRD, err); return 1; } mop = airMopNew(); if (!nio) { nio = nrrdIoStateNew(); if (!nio) { sprintf(err, "%s: couldn't alloc local NrrdIoState", me); biffAdd(NRRD, err); return 1; } airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways); } if (_nrrdEncodingMaybeSet(nio) || _nrrdFormatMaybeGuess(nrrd, nio, filename)) { sprintf(err, "%s: ", me); biffAdd(NRRD, err); airMopError(mop); return 1; } if (nrrdFormatNRRD == nio->format && airEndsWith(filename, NRRD_EXT_NHDR)) { nio->detachedHeader = AIR_TRUE; _nrrdSplitName(&(nio->path), &(nio->base), filename); /* nix the ".nhdr" suffix */ nio->base[strlen(nio->base) - strlen(NRRD_EXT_NHDR)] = 0; /* nrrdFormatNRRD->write will do the rest */ } else { nio->detachedHeader = AIR_FALSE; } if (!( file = airFopen(filename, stdout, "wb") )) { sprintf(err, "%s: couldn't fopen(\"%s\",\"wb\"): %s", me, filename, strerror(errno)); biffAdd(NRRD, err); airMopError(mop); return 1; } airMopAdd(mop, file, (airMopper)airFclose, airMopAlways); if (nrrdWrite(file, nrrd, nio)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); airMopError(mop); return 1; } airMopOkay(mop); return 0; }
/* ** _nrrdWrite ** ** Write a nrrd to given file or string (allocated by nrrd), using the ** format and and encoding indicated in nio. Cleverness should be ** isolated and collected here: by the time nio->format->write() is ** called, all writing parameters must be given explicitly, and their ** appropriateness is explicitly tested */ int _nrrdWrite(FILE *file, char **stringP, const Nrrd *nrrd, NrrdIoState *_nio) { char me[]="_nrrdWrite", err[BIFF_STRLEN]; NrrdIoState *nio; airArray *mop; if (!((file || stringP) && nrrd)) { sprintf(err, "%s: got NULL pointer", me); biffAdd(NRRD, err); return 1; } if (file && stringP) { sprintf(err, "%s: can't write to both file and string", me); biffAdd(NRRD, err); return 1; } if (nrrdCheck(nrrd)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); return 1; } mop = airMopNew(); if (_nio) { nio = _nio; } else { nio = nrrdIoStateNew(); if (!nio) { sprintf(err, "%s: couldn't alloc local NrrdIoState", me); biffAdd(NRRD, err); airMopError(mop); return 1; } airMopAdd(mop, nio, (airMopper)nrrdIoStateNix, airMopAlways); } if (_nrrdEncodingMaybeSet(nio) || _nrrdFormatMaybeSet(nio)) { sprintf(err, "%s: ", me); biffAdd(NRRD, err); airMopError(mop); return 1; } if (nio->byteSkip || nio->lineSkip) { /* NOTE: unu make bypasses this by calling nrrdFormatNRRD->write() directly */ sprintf(err, "%s: can't generate line or byte skips on data write", me); biffAdd(NRRD, err); airMopError(mop); return 1; } if (stringP) { if (nrrdFormatNRRD != nio->format) { sprintf(err, "%s: sorry, can only write %s files to strings (not %s)", me, nrrdFormatNRRD->name, nio->format->name); biffAdd(NRRD, err); airMopError(mop); return 1; } /* we do this in two passes; first see how much room is needed for the header, then allocate, then write the header */ nio->learningHeaderStrlen = AIR_TRUE; if (nio->format->write(NULL, nrrd, nio)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); airMopError(mop); return 1; } *stringP = (char*)malloc(nio->headerStrlen + 1); if (!*stringP) { sprintf(err, "%s: couldn't allocate header string (%u len )", me, nio->headerStrlen); biffAdd(NRRD, err); airMopError(mop); return 1; } nio->learningHeaderStrlen = AIR_FALSE; nio->headerStringWrite = *stringP; if (nio->format->write(NULL, nrrd, nio)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); airMopError(mop); return 1; } } else { /* call the writer appropriate for the format */ if (nio->format->write(file, nrrd, nio)) { sprintf(err, "%s:", me); biffAdd(NRRD, err); airMopError(mop); return 1; } } airMopOkay(mop); return 0; }