int unrrdu_cksumDoit(const char *me, char *inS, int endian, int printendian, FILE *fout) { Nrrd *nrrd; airArray *mop; unsigned int crc; char stmp[AIR_STRLEN_SMALL], ends[AIR_STRLEN_SMALL]; size_t nn; mop = airMopNew(); airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways); if (nrrdLoad(nrrd, inS, NULL)) { biffMovef(me, NRRD, "%s: trouble loading \"%s\"", me, inS); airMopError(mop); return 1; } crc = nrrdCRC32(nrrd, endian); nn = nrrdElementNumber(nrrd)*nrrdElementSize(nrrd); sprintf(ends, "(%s)", airEnumStr(airEndian, endian)); fprintf(fout, "%u%s %s%s%s\n", crc, printendian ? ends : "", airSprintSize_t(stmp, nn), strcmp("-", inS) ? " " : "", strcmp("-", inS) ? inS : ""); airMopOkay(mop); return 0; }
int main(int argc, const char **argv) { /* stock variables */ char me[] = BKEY; hestOpt *hopt=NULL; hestParm *hparm; airArray *mop; /* variables specific to this program */ int negskip, progress; Nrrd *nref, *nin; size_t *size, ii, nn, tick, pad[2]; unsigned int axi, refCRC, gotCRC, sizeNum; char *berr, *outS[2], stmp[AIR_STRLEN_SMALL], doneStr[AIR_STRLEN_SMALL]; airRandMTState *rng; unsigned int seed, *rdata, printbytes; unsigned char *dataUC; double time0, time1; FILE *fout; /* start-up */ mop = airMopNew(); hparm = hestParmNew(); airMopAdd(mop, hparm, (airMopper)hestParmFree, airMopAlways); /* learn things from hest */ hestOptAdd(&hopt, "seed", "N", airTypeUInt, 1, 1, &seed, "42", "seed for RNG"); hestOptAdd(&hopt, "s", "sz0", airTypeSize_t, 1, -1, &size, NULL, "sizes of desired output", &sizeNum); hestOptAdd(&hopt, "p", "pb pa", airTypeSize_t, 2, 2, pad, "0 0", "bytes of padding before, and after, the data segment " "in the written data"); hestOptAdd(&hopt, "ns", "bool", airTypeInt, 0, 0, &negskip, NULL, "skipping should be relative to end of file"); hestOptAdd(&hopt, "pb", "print", airTypeUInt, 1, 1, &printbytes, "0", "bytes to print at beginning and end of data, to help " "debug problems"); hestOptAdd(&hopt, "o", "out.data out.nhdr", airTypeString, 2, 2, outS, NULL, "output filenames of data and header"); hestParseOrDie(hopt, argc-1, argv+1, hparm, me, tskipInfo, AIR_TRUE, AIR_TRUE, AIR_TRUE); airMopAdd(mop, hopt, (airMopper)hestOptFree, airMopAlways); airMopAdd(mop, hopt, (airMopper)hestParseFree, airMopAlways); /* generate reference nrrd data */ nref = nrrdNew(); airMopAdd(mop, nref, (airMopper)nrrdNuke, airMopAlways); if (nrrdMaybeAlloc_nva(nref, nrrdTypeUInt, sizeNum, size)) { airMopAdd(mop, berr=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error allocating data: %s\n", me, berr); airMopError(mop); return 1; } rng = airRandMTStateNew(seed); airMopAdd(mop, rng, (airMopper)airRandMTStateNix, airMopAlways); nn = nrrdElementNumber(nref); rdata = AIR_CAST(unsigned int *, nref->data); fprintf(stderr, "generating data: . . . "); fflush(stderr); time0 = airTime(); progress = AIR_FALSE; tick = nn/100; for (ii=0; ii<nn; ii++) { rdata[ii] = airUIrandMT_r(rng); if (ii && tick && !(ii % tick)) { time1 = airTime(); if (time1 - time0 > 1.0) { /* if it took more than a second to do 1% of the thing, would be good to generate some progress indication */ progress = AIR_TRUE; } if (progress) { fprintf(stderr, "%s", airDoneStr(0, ii, nn, doneStr)); fflush(stderr); } } } if (progress) { fprintf(stderr, "%s\n", airDoneStr(0, ii, nn, doneStr)); fflush(stderr); } else { fprintf(stderr, "\n"); } fprintf(stderr, "finding reference (big-endian) CRC: "); fflush(stderr); refCRC = nrrdCRC32(nref, airEndianBig); fprintf(stderr, "%u\n", refCRC); /* write data, with padding */ fprintf(stderr, "saving data . . . "); fflush(stderr); if (!(fout = fopen(outS[0], "wb" COMMIT))) { fprintf(stderr, "\n%s: couldn't open %s for writing: %s\n", me, outS[0], strerror(errno)); airMopError(mop); return 1; } airMopAdd(mop, fout, (airMopper)airFclose, airMopAlways); for (ii=0; ii<pad[0]; ii++) { if (EOF == fputc(1, fout)) { fprintf(stderr, "\n%s: error doing pre-padding\n", me); airMopError(mop); return 1; } } if (nn != fwrite(nref->data, nrrdElementSize(nref), nn, fout)) { fprintf(stderr, "\n%s: error writing data\n", me); airMopError(mop); return 1; } for (ii=0; ii<pad[1]; ii++) { if (EOF == fputc(2, fout)) { fprintf(stderr, "\n%s: error doing post-padding\n", me); airMopError(mop); return 1; } } if (EOF == fflush(fout)) { fprintf(stderr, "\n%s: error fflushing data: %s\n", me, strerror(errno)); } fprintf(stderr, "\n"); if (printbytes) { size_t bi, rpb, nn; char stmp[AIR_STRLEN_SMALL]; nn = nrrdElementSize(nref)*nrrdElementNumber(nref); rpb = AIR_MIN(printbytes, nn); dataUC = AIR_CAST(unsigned char *, nref->data); fprintf(stderr, "CORRECT %s bytes at beginning:\n", airSprintSize_t(stmp, rpb)); for (bi=0; bi<rpb; bi++) { fprintf(stderr, "%x ", dataUC[bi]); } fprintf(stderr, "...\n"); fprintf(stderr, "CORRECT %s bytes at end:\n", airSprintSize_t(stmp, rpb)); fprintf(stderr, "..."); for (bi=nn - rpb; bi<nn; bi++) { fprintf(stderr, " %x", dataUC[bi]); } fprintf(stderr, "\n"); } airMopSingleOkay(mop, fout); airMopSingleOkay(mop, nref); nref = NULL; /* write header; for now just writing the header directly */ fprintf(stderr, "writing header . . . \n"); if (!(fout = fopen(outS[1], "w"))) { fprintf(stderr, "%s: couldn't open %s for writing: %s\n", me, outS[1], strerror(errno)); airMopError(mop); return 1; } airMopAdd(mop, fout, (airMopper)airFclose, airMopAlways); fprintf(fout, "NRRD0005\n"); fprintf(fout, "type: unsigned int\n"); fprintf(fout, "dimension: %u\n", sizeNum); fprintf(fout, "sizes:"); for (axi=0; axi<sizeNum; axi++) { fprintf(fout, " %s", airSprintSize_t(stmp, size[axi])); } fprintf(fout, "\n"); fprintf(fout, "endian: %s\n", airEnumStr(airEndian, airMyEndian())); fprintf(fout, "encoding: %s\n", airEnumStr(nrrdEncodingType, nrrdEncodingTypeRaw)); if (!negskip) { if (pad[0]) { fprintf(fout, "byte skip: %s\n", airSprintSize_t(stmp, pad[0])); } } else { fprintf(fout, "byte skip: -%s\n", airSprintSize_t(stmp, pad[1]+1)); } fprintf(fout, "data file: %s\n", outS[0]); airMopSingleOkay(mop, fout); /* read it in, make sure it checks out */ fprintf(stderr, "reading data . . . \n"); nin = nrrdNew(); airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways); if (nrrdLoad(nin, outS[1], NULL)) { airMopAdd(mop, berr=biffGetDone(NRRD), airFree, airMopAlways); fprintf(stderr, "%s: error reading back in: %s\n", me, berr); airMopError(mop); return 1; } if (printbytes) { size_t bi, rpb, nn; char stmp[AIR_STRLEN_SMALL]; nn = nrrdElementSize(nin)*nrrdElementNumber(nin); rpb = AIR_MIN(printbytes, nn); dataUC = AIR_CAST(unsigned char *, nin->data); fprintf(stderr, "FOUND %s bytes at beginning:\n", airSprintSize_t(stmp, rpb)); for (bi=0; bi<rpb; bi++) { fprintf(stderr, "%x ", dataUC[bi]); } fprintf(stderr, "...\n"); fprintf(stderr, "FOUND %s bytes at end:\n", airSprintSize_t(stmp, rpb)); fprintf(stderr, "..."); for (bi=nn - rpb; bi<nn; bi++) { fprintf(stderr, " %x", dataUC[bi]); } fprintf(stderr, "\n"); } fprintf(stderr, "finding new CRC . . . \n"); gotCRC = nrrdCRC32(nin, airEndianBig); if (refCRC != gotCRC) { fprintf(stderr, "%s: got CRC %u but wanted %u\n", me, gotCRC, refCRC); airMopError(mop); return 1; } fprintf(stderr, "(all ok)\n"); /* HEY: to test gzip reading, we really want to do a system call to gzip compress the data, and write a new header to point to the compressed data, and make sure we can read in that just the same */ airMopOkay(mop); return 0; }