Esempio n. 1
0
/*
******** nrrdSample_nva()
**
** given coordinates within a nrrd, copies the 
** single element into given *val
*/
int
nrrdSample_nva(void *val, const Nrrd *nrrd, const size_t *coord) {
  char me[]="nrrdSample_nva", err[BIFF_STRLEN];
  size_t I, size[NRRD_DIM_MAX], typeSize;
  unsigned int ai;
  
  if (!(nrrd && coord && val)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  /* this shouldn't actually be necessary .. */
  if (!nrrdElementSize(nrrd)) {
    sprintf(err, "%s: nrrd reports zero element size!", me);
    biffAdd(NRRD, err); return 1;
  }
  
  typeSize = nrrdElementSize(nrrd);
  nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSize, size);
  for (ai=0; ai<nrrd->dim; ai++) {
    if (!( coord[ai] < size[ai] )) {
      sprintf(err, "%s: coordinate " _AIR_SIZE_T_CNV 
              " on axis %d out of bounds (0 to " _AIR_SIZE_T_CNV  ")", 
              me, coord[ai], ai, size[ai]-1);
      biffAdd(NRRD, err); return 1;
    }
  }

  NRRD_INDEX_GEN(I, coord, size, nrrd->dim);

  memcpy(val, (char*)(nrrd->data) + I*typeSize, typeSize);
  return 0;
}
Esempio n. 2
0
static int
_nrrdEncodingHex_read(FILE *file, void *_data, size_t elNum,
                      Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingHex_read";
  size_t nibIdx, nibNum;
  unsigned char *data;
  int car=0, nib;

  AIR_UNUSED(nio);
  data = AIR_CAST(unsigned char *, _data);
  nibIdx = 0;
  nibNum = 2*elNum*nrrdElementSize(nrrd);
  if (nibNum/elNum != 2*nrrdElementSize(nrrd)) {
    biffAddf(NRRD, "%s: size_t can't hold 2*(#bytes in array)\n", me);
    return 1;
  }
  while (nibIdx < nibNum) {
    unsigned char nibshift;
    car = fgetc(file);
    if (EOF == car) break;
    nib = _nrrdReadHexTable[car & 127];
    if (-2 == nib) {
      /* not a valid hex character */
      break;
    }
    if (-1 == nib) {
      /* its white space */
      continue;
    }
    /* else it is a valid character, representing a value from 0 to 15 */
    nibshift = AIR_CAST(unsigned char, nib << (4*(1-(nibIdx & 1))));
    /* HEY not sure why the cast is needed with gcc v4.8 -Wconversion */
    *data = AIR_CAST(unsigned char, *data + nibshift);
    data += nibIdx & 1;
    nibIdx++;
  }
  if (nibIdx != nibNum) {
    char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL];
    if (EOF == car) {
      biffAddf(NRRD, "%s: hit EOF getting byte %s of %s", me,
               airSprintSize_t(stmp1, nibIdx/2),
               airSprintSize_t(stmp2, nibNum/2));
    } else {
      biffAddf(NRRD, "%s: hit invalid character ('%c') getting "
               "byte %s of %s", me, car,
               airSprintSize_t(stmp1, nibIdx/2),
               airSprintSize_t(stmp2, nibNum/2));
    }
    return 1;
  }
  return 0;
}
Esempio n. 3
0
int
_nrrdEncodingRaw_write(FILE *file, const void *data, size_t elementNum,
                       const Nrrd *nrrd, NrrdIoState *nio) {
  char me[]="_nrrdEncodingRaw_write", err[BIFF_STRLEN];
  int fd, dio;
  size_t ret, bsize;
  
  bsize = nrrdElementSize(nrrd)*elementNum;
  if (nio->format->usesDIO) {
    fd = fileno(file);
    dio = airDioTest(fd, data, bsize);
  } else {
    fd = -1;
    dio = airNoDio_format;
  }
  if (airNoDio_okay == dio) {
    if (2 <= nrrdStateVerboseIO) {
      fprintf(stderr, "with direct I/O ... ");
    }
    ret = airDioWrite(fd, data, bsize);
    if (ret != bsize) {
      sprintf(err, "%s: airDioWrite wrote only "
              _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " bytes "
              "(%g%% of expected)", me,
              ret, bsize, 100.0*ret/bsize);
      biffAdd(NRRD, err); return 1;
    }
  } else {
    if (2 <= nrrdStateVerboseIO) {
      if (AIR_DIO && nio->format->usesDIO) {
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
      }
    }
    ret = fwrite(data, nrrdElementSize(nrrd), elementNum, file);
    if (ret != elementNum) {
      sprintf(err, "%s: fwrite wrote read only "
              _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not " 
              _AIR_SIZE_T_CNV " (%g%% of expected)", me,
              ret, nrrdElementSize(nrrd), elementNum,
              100.0*ret/elementNum);
      biffAdd(NRRD, err); return 1;
    }
    fflush(file);
    /*
    if (ferror(file)) {
      sprintf(err, "%s: ferror returned non-zero", me);
      biffAdd(NRRD, err); return 1;
    }
    */
  }
  return 0;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
static int
_nrrdEncodingZRL_read(FILE *file, void *data, size_t elementNum,
                      Nrrd *nrrd, NrrdIoState *nio) {

  AIR_UNUSED(nio);
  unsigned char *output_buffer = (unsigned char *) data;
  size_t toread = elementNum*nrrdElementSize(nrrd);
  /*
  static const char me[]="_nrrdEncodingZRL_read";
  printf("!%s: looking for %u values (%u bytes) of type %s\n", me,
         (unsigned int)elementNum, (unsigned int)toread,
         airEnumStr(nrrdType, nrrd->type)); */
  int cc, dd;
  unsigned int j = 0;
  while (j < toread) {
    cc = fgetc(file);
    if (cc == 0) {
      dd = fgetc(file);
      if (dd == 0) {
        dd = fgetc(file);
        j += dd + fgetc(file)*256;
      } else {
        j += (unsigned char)dd;
      }
    } else {
      output_buffer[j] = (unsigned char)cc;
      j++;
    }
  }

  return 0;
}
Esempio n. 6
0
NrrdWrapper::NrrdWrapper(Nrrd* n){
	nin = n;
	element_size = (int)nrrdElementSize(nin);
	size0 = nin->axis[0].size;
	size1 = nin->axis[1].size;
	size2 = nin->axis[2].size;
}
Esempio n. 7
0
unsigned int
nrrdCRC32(const Nrrd *nin, int endian) {
  size_t nn;

  /* NULL nrrd or data */
  if (!nin
      || !(nin->data)
      || !(nn = nrrdElementSize(nin)*nrrdElementNumber(nin))
      || airEnumValCheck(airEndian, endian)) {
    return 0;
  }

  return airCRC32(AIR_CAST(const unsigned char *, nin->data),
                  nn, nrrdElementSize(nin),
                  endian == airMyEndian() ? AIR_FALSE : AIR_TRUE);
}
static int
_nrrdEncodingRaw_read(FILE *file, void *data, size_t elementNum,
                      Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingRaw_read";
  size_t ret, bsize;
  int fd, dio, car;
  long savePos;
  char *data_c;
  size_t elementSize, maxChunkSize, remainderValue, chunkSize;
  size_t retTmp;
  char stmp[3][AIR_STRLEN_SMALL];

  bsize = nrrdElementSize(nrrd)*elementNum;
  if (nio->format->usesDIO) {
    fd = fileno(file);
    dio = airDioTest(fd, data, bsize);
  } else {
    fd = -1;
    dio = airNoDio_format;
  }
  if (airNoDio_okay == dio) {
    if (2 <= nrrdStateVerboseIO) {
      fprintf(stderr, "with direct I/O ... ");
    }
    ret = airDioRead(fd, data, bsize);
    if (ret != bsize) {
      biffAddf(NRRD, "%s: airDioRead got read only %s of %sbytes "
               "(%g%% of expected)", me,
               airSprintSize_t(stmp[0], ret),
               airSprintSize_t(stmp[1], bsize),
               100.0*AIR_CAST(double, ret)/AIR_CAST(double, bsize));
      return 1;
    }
  } else {
Esempio n. 9
0
	void load(TextureLoadingInfo& info, Texture* texture)
	{
		Nrrd* nin = boost::any_cast<Nrrd*>(info.options["nrrd"]);
		//		Nrrd* nout = nrrdNew();
		//		nrrdConvert(nout,nin,nrrdTypeUChar);
		//		nrrdQuantize(nout, nin, 0, 8);

		int width = nin->axis[0].size;
		int height = nin->axis[1].size;
		int elemsize = nrrdElementSize(nin);

		// Copy memory upside-down
		char* tmpdata = (char*) malloc(width * height * elemsize);

		char* src = (char*) nin->data;
		for (int i = 0; i < height; ++i)
		{
			int linesize = width * elemsize;
			memcpy(&tmpdata[(height - i - 1) * linesize], &src[i * linesize],
					linesize);
		}

		GLuint name = texture->getGLName();

		glTexImage2D(info.target, 0, 1, width, height, 0, GL_LUMINANCE,
				convert_type_to_enum(nin->type), tmpdata);

		texture->setDimensions(width, height);

		free(tmpdata);
		//		nrrdNuke(nout);

	}
Esempio n. 10
0
int
_nrrdCopy(Nrrd *nout, const Nrrd *nin, int bitflag) {
  char me[]="_nrrdCopy", err[BIFF_STRLEN];
  size_t size[NRRD_DIM_MAX];

  if (!(nin && nout)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nin) {
    /* its not the case that we have nothing to do- the semantics of
       copying cannot be achieved if the input and output nrrd are
       the same; this is an error */
    sprintf(err, "%s: nout==nin disallowed", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!nrrdElementSize(nin)) {
    sprintf(err, "%s: input nrrd reports zero element size!", me);
    biffAdd(NRRD, err); return 1;
  }
  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, size);
  if (nin->data) {
    if (nrrdMaybeAlloc_nva(nout, nin->type, nin->dim, size)) {
      sprintf(err, "%s: couldn't allocate data", me);
      biffAdd(NRRD, err); return 1;
    }
    memcpy(nout->data, nin->data,
           nrrdElementNumber(nin)*nrrdElementSize(nin));
  } else {
    /* someone is trying to copy structs without data, fine fine fine */
    if (nrrdWrap_nva(nout, NULL, nin->type, nin->dim, size)) {
      sprintf(err, "%s: couldn't allocate data", me);
      biffAdd(NRRD, err); return 1;
    }
  }
  nrrdAxisInfoCopy(nout, nin, NULL, NRRD_AXIS_INFO_SIZE_BIT);
  /* if nin->data non-NULL (second branch above), this will 
     harmlessly unset and set type and dim */
  nrrdBasicInfoInit(nout, NRRD_BASIC_INFO_DATA_BIT | bitflag);
  if (nrrdBasicInfoCopy(nout, nin, NRRD_BASIC_INFO_DATA_BIT | bitflag)) {
    sprintf(err, "%s: trouble copying basic info", me);
    biffAdd(NRRD, err); return 1;
  }

  return 0;
}
Esempio n. 11
0
int
_nrrdEncodingHex_read(FILE *file, void *_data, size_t elNum,
                      Nrrd *nrrd, NrrdIoState *nio) {
  char me[]="_nrrdEncodingHex_read", err[AIR_STRLEN_MED];
  size_t nibIdx, nibNum;
  unsigned char *data;
  int car=0, nib;

  AIR_UNUSED(nio);
  data = (unsigned char *)_data;
  nibIdx = 0;
  nibNum = 2*elNum*nrrdElementSize(nrrd);
  if (nibNum/elNum != 2*nrrdElementSize(nrrd)) {
    sprintf(err, "%s: size_t can't hold 2*(#bytes in array)\n", me);
    biffAdd(NRRD, err); return 1;
  }
  while (nibIdx < nibNum) {
    car = fgetc(file);
    if (EOF == car) break;
    nib = _nrrdReadHexTable[car & 127];
    if (-2 == nib) {
      /* not a valid hex character */
      break;
    }
    if (-1 == nib) {
      /* its white space */
      continue;
    }
    *data += (unsigned char)(nib << (4*(1-(nibIdx & 1))));
    data += nibIdx & 1;
    nibIdx++;
  }
  if (nibIdx != nibNum) {
    if (EOF == car) {
      sprintf(err, "%s: hit EOF getting "
              "byte " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV,
              me, nibIdx/2, nibNum/2);
    } else {
      sprintf(err, "%s: hit invalid character ('%c') getting "
              "byte " _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV,
              me, car, nibIdx/2, nibNum/2);
    }
    biffAdd(NRRD, err); return 1;
  }
  return 0;
}
Esempio n. 12
0
void
demoIO(char *filename)
{
  char me[]="demoIO", newname[]="foo.nrrd", *err, *key, *val;
  int kvn, kvi;
  Nrrd *nin;

  /* create a nrrd; at this point this is just an empty container */
  nin = nrrdNew();

  /* read in the nrrd from file */
  if (nrrdLoad(nin, filename, NULL))
  {
    err = biffGetDone(NRRD);
    fprintf(stderr, "%s: trouble reading \"%s\":\n%s", me, filename, err);
    free(err);
    return;
  }

  /* say something about the array */
  printf("%s: \"%s\" is a %d-dimensional nrrd of type %d (%s)\n",
         me, filename, nin->dim, nin->type,
         airEnumStr(nrrdType, nin->type));
  printf("%s: the array contains %d elements, each %d bytes in size\n",
         me, (int)nrrdElementNumber(nin), (int)nrrdElementSize(nin));

  /* print out the key/value pairs present */
  kvn = nrrdKeyValueSize(nin);
  if (kvn)
  {
    for (kvi=0; kvi<kvn; kvi++)
    {
      nrrdKeyValueIndex(nin, &key, &val, kvi);
      printf("%s: key:value %d = %s:%s\n", me, kvi, key, val);
      free(key);
      free(val);
      key = val = NULL;
    }
  }

  /* modify key/value pairs, and write out the nrrd to a different file */
  nrrdKeyValueClear(nin);
  nrrdKeyValueAdd(nin, "new key", "precious value");
  if (nrrdSave(newname, nin, NULL))
  {
    err = biffGetDone(NRRD);
    fprintf(stderr, "%s: trouble writing \"%s\":\n%s", me, newname, err);
    free(err);
    return;
  }

  /* blow away both the Nrrd struct *and* the memory at nin->data
     (nrrdNix() frees the struct but not the data,
     nrrdEmpty() frees the data but not the struct) */
  nrrdNuke(nin);

  return;
}
Esempio n. 13
0
/*
******** nrrdAlloc_nva()
**
** allocates data array and sets information.  If this is a block type
** nrrd, it is necessary to set nrrd->blockSize PRIOR to calling
** this function.
**
** This function will always allocate more memory (via calloc), but
** it will free() nrrd->data if it is non-NULL when passed in.
**
** This function takes the same "don't mess with peripheral information"
** attitude as nrrdWrap().
**
** Note to Gordon: don't get clever and change ANY axis-specific
** information here.  It may be very convenient to set that before
** nrrdAlloc or nrrdMaybeAlloc
**
** Note: This function DOES use biff
*/
int
nrrdAlloc_nva(Nrrd *nrrd, int type, unsigned int dim, const size_t *size)
{
  char me[]="nrrdAlloc_nva", err[BIFF_STRLEN];
  size_t num;
  int esize;

  if (!(nrrd && size))
  {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err);
    return 1;
  }
  if (airEnumValCheck(nrrdType, type))
  {
    sprintf(err, "%s: type (%d) is invalid", me, type);
    biffAdd(NRRD, err);
    return 1;
  }
  if (nrrdTypeBlock == type)
  {
    if (!(0 < nrrd->blockSize))
    {
      sprintf(err, "%s: given nrrd->blockSize " _AIR_SIZE_T_CNV " invalid",
              me, nrrd->blockSize);
      biffAdd(NRRD, err);
      return 1;
    }
  }
  if (!AIR_IN_CL(1, dim, NRRD_DIM_MAX))
  {
    sprintf(err, "%s: dim (%d) not in valid range [1,%d]",
            me, dim, NRRD_DIM_MAX);
    biffAdd(NRRD, err);
    return 1;
  }

  nrrd->data = airFree(nrrd->data);
  if (nrrdWrap_nva(nrrd, NULL, type, dim, size))
  {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err);
    return 1 ;
  }
  num = nrrdElementNumber(nrrd);
  esize = nrrdElementSize(nrrd);
  nrrd->data = calloc(num, esize);
  if (!(nrrd->data))
  {
    sprintf(err, "%s: calloc(" _AIR_SIZE_T_CNV ",%d) failed",
            me, num, esize);
    biffAdd(NRRD, err);
    return 1 ;
  }

  return 0;
}
Esempio n. 14
0
int
_nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum,
                        Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingAscii_read";
  char numbStr[AIR_STRLEN_HUGE];  /* HEY: fix this */
  char *nstr;
  size_t I;
  char *data;
  int tmp;

  AIR_UNUSED(nio);
  if (nrrdTypeBlock == nrrd->type) {
    biffAddf(NRRD, "%s: can't read nrrd type %s from %s", me,
             airEnumStr(nrrdType, nrrdTypeBlock),
             nrrdEncodingAscii->name);
    return 1;
  }
  data = (char*)_data;
  I = 0;
  while (I < elNum) {
    if (1 != fscanf(file, "%s", numbStr)) {
      biffAddf(NRRD, "%s: couldn't parse element " _AIR_SIZE_T_CNV
               " of " _AIR_SIZE_T_CNV, me, I+1, elNum);
      return 1;
    }
    if (!strcmp(",", numbStr)) {
      /* its an isolated comma, not a value, pass over this */
      continue;
    }
    /* get past any commas prefixing a number (without space) */
    nstr = numbStr + strspn(numbStr, ",");
    if (nrrd->type >= nrrdTypeInt) {
      /* sscanf supports putting value directly into this type */
      if (1 != airSingleSscanf(nstr, nrrdTypePrintfStr[nrrd->type], 
                               (void*)(data + I*nrrdElementSize(nrrd)))) {
        biffAddf(NRRD, "%s: couln't parse %s " _AIR_SIZE_T_CNV
                 " of " _AIR_SIZE_T_CNV " (\"%s\")", me,
                 airEnumStr(nrrdType, nrrd->type),
                 I+1, elNum, nstr);
        return 1;
      }
    } else {
      /* sscanf value into an int first */
      if (1 != airSingleSscanf(nstr, "%d", &tmp)) {
        biffAddf(NRRD, "%s: couln't parse element " _AIR_SIZE_T_CNV
                 " of " _AIR_SIZE_T_CNV " (\"%s\")",
                 me, I+1, elNum, nstr);
        return 1;
      }
      nrrdIInsert[nrrd->type](data, I, tmp);
    }
    I++;
  }
  
  return 0;
}
Esempio n. 15
0
int
_nrrdEncodingAscii_read(FILE *file, void *_data, size_t elNum,
                        Nrrd *nrrd, NrrdIoState *nio) {
  char me[]="_nrrdEncodingAscii_read", err[BIFF_STRLEN],
    numbStr[AIR_STRLEN_HUGE];  /* HEY: fix this */
  size_t I;
  char *data;
  int tmp;

  AIR_UNUSED(nio);
  if (nrrdTypeBlock == nrrd->type) {
    sprintf(err, "%s: can't read nrrd type %s from %s", me,
            airEnumStr(nrrdType, nrrdTypeBlock),
            nrrdEncodingAscii->name);
    biffAdd(NRRD, err); return 1;
  }
  data = (char*)_data;
  for (I=0; I<elNum; I++) {
    if (1 != fscanf(file, "%s", numbStr)) {
      sprintf(err, "%s: couldn't parse element " _AIR_SIZE_T_CNV
              " of " _AIR_SIZE_T_CNV, me, I+1, elNum);
      biffAdd(NRRD, err); return 1;
    }
    if (nrrd->type >= nrrdTypeInt) {
      /* sscanf supports putting value directly into this type */
      if (1 != airSingleSscanf(numbStr, nrrdTypePrintfStr[nrrd->type], 
                               (void*)(data + I*nrrdElementSize(nrrd)))) {
        sprintf(err, "%s: couln't parse %s " _AIR_SIZE_T_CNV
                " of " _AIR_SIZE_T_CNV " (\"%s\")", me,
                airEnumStr(nrrdType, nrrd->type),
                I+1, elNum, numbStr);
        biffAdd(NRRD, err); return 1;
      }
    } else {
      /* sscanf value into an int first */
      if (1 != airSingleSscanf(numbStr, "%d", &tmp)) {
        sprintf(err, "%s: couln't parse element " _AIR_SIZE_T_CNV
                " of " _AIR_SIZE_T_CNV " (\"%s\")",
                me, I+1, elNum, numbStr);
        biffAdd(NRRD, err); return 1;
      }
      nrrdIInsert[nrrd->type](data, I, tmp);
    }
  }
  
  return 0;
}
Esempio n. 16
0
int
_nrrdEncodingAscii_write(FILE *file, const void *_data, size_t elNum,
                         const Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingAscii_write";
  char buff[AIR_STRLEN_MED];
  size_t bufflen, linelen;
  const char *data;
  size_t I;
  
  if (nrrdTypeBlock == nrrd->type) {
    biffAddf(NRRD, "%s: can't write nrrd type %s to %s", me,
             airEnumStr(nrrdType, nrrdTypeBlock),
             nrrdEncodingAscii->name);
    return 1;
  }
  data = (char*)_data;
  linelen = 0;
  for (I=0; I<elNum; I++) {
    nrrdSprint[nrrd->type](buff, data);
    if (1 == nrrd->dim) {
      fprintf(file, "%s\n", buff);
    } else if (nrrd->dim == 2 
               && nrrd->axis[0].size <= nio->valsPerLine) {
      fprintf(file, "%s%c", buff,
              (I+1)%(nrrd->axis[0].size) ? ' ' : '\n');
    } else {
      bufflen = strlen(buff);
      if (linelen+bufflen+1 <= nio->charsPerLine) {
        fprintf(file, "%s%s", I ? " " : "", buff);
        linelen += (I ? 1 : 0) + bufflen;
      } else {
        fprintf(file, "\n%s", buff);
        linelen = bufflen;
      }
    }
    data += nrrdElementSize(nrrd);
  }
  /* just to be sure, we always end with a carraige return */
  fprintf(file, "\n");
  
  return 0;
}
Esempio n. 17
0
int
_nrrdEncodingHex_write(FILE *file, const void *_data, size_t elNum,
                       const Nrrd *nrrd, NrrdIoState *nio) {
  /* char me[]="_nrrdEncodingHex_write", err[AIR_STRLEN_MED]; */
  unsigned char *data;
  size_t byteIdx, byteNum;

  AIR_UNUSED(nio);
  data = (unsigned char*)_data;
  byteNum = elNum*nrrdElementSize(nrrd);
  for (byteIdx=0; byteIdx<byteNum; byteIdx++) {
    fprintf(file, "%c%c",
            _nrrdWriteHexTable[(*data)>>4],
            _nrrdWriteHexTable[(*data)&15]);
    if (34 == byteIdx%35)
      fprintf(file, "\n");
    data++;
  }
  return 0;
}
Esempio n. 18
0
static int
_nrrdEncodingHex_write(FILE *file, const void *_data, size_t elNum,
                       const Nrrd *nrrd, NrrdIoState *nio) {
  /* static const char me[]="_nrrdEncodingHex_write"; */
  const unsigned char *data;
  size_t byteIdx, byteNum;
  unsigned int bytesPerLine;

  bytesPerLine = AIR_MAX(1, nio->charsPerLine/2);
  data = AIR_CAST(const unsigned char*, _data);
  byteNum = elNum*nrrdElementSize(nrrd);
  for (byteIdx=0; byteIdx<byteNum; byteIdx++) {
    fprintf(file, "%c%c",
            _nrrdWriteHexTable[(*data)>>4],
            _nrrdWriteHexTable[(*data)&15]);
    if (bytesPerLine-1 == byteIdx % bytesPerLine) {
      fprintf(file, "\n");
    }
    data++;
  }
  /* just to be sure, we always end with a carraige return */
  fprintf(file, "\n");
  return 0;
}
Esempio n. 19
0
/*
******** nrrdMaybeAlloc_nva
**
** calls nrrdAlloc_nva if the requested space is different than
** what is currently held
**
** also subscribes to the "don't mess with peripheral information" philosophy
*/
int
nrrdMaybeAlloc_nva(Nrrd *nrrd, int type,
                   unsigned int dim, const size_t *size)
{
  char me[]="nrrdMaybeAlloc_nva", err[BIFF_STRLEN];
  size_t sizeWant, sizeHave, numWant, elementSizeWant;
  int need;
  unsigned int ai;

  if (!nrrd)
  {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err);
    return 1;
  }
  if (airEnumValCheck(nrrdType, type))
  {
    sprintf(err, "%s: type (%d) is invalid", me, type);
    biffAdd(NRRD, err);
    return 1;
  }
  if (nrrdTypeBlock == type)
  {
    if (nrrdTypeBlock == nrrd->type)
    {
      sprintf(err, "%s: can't change from one block nrrd to another", me);
      biffAdd(NRRD, err);
      return 1;
    }
    if (!(0 < nrrd->blockSize))
    {
      sprintf(err, "%s: given nrrd->blockSize " _AIR_SIZE_T_CNV " invalid",
              me, nrrd->blockSize);
      biffAdd(NRRD, err);
      return 1;
    }
    elementSizeWant = nrrd->blockSize;
  }
  else
  {
    elementSizeWant = nrrdTypeSize[type];
  }
  if (_nrrdSizeCheck(size, dim, AIR_TRUE))
  {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err);
    return 1;
  }

  if (!(nrrd->data))
  {
    need = 1;
  }
  else
  {
    numWant = 1;
    for (ai=0; ai<dim; ai++)
    {
      numWant *= size[ai];
    }
    if (!nrrdElementSize(nrrd))
    {
      sprintf(err, "%s: nrrd reports zero element size!", me);
      biffAdd(NRRD, err);
      return 1;
    }
    sizeHave = nrrdElementNumber(nrrd) * nrrdElementSize(nrrd);
    /* fprintf(stderr, "##%s: sizeHave = %d * %d = %d\n", me,
            (int)(nrrdElementNumber(nrrd)),
            (int)(nrrdElementSize(nrrd)), (int)sizeHave); */
    sizeWant = numWant * elementSizeWant;
    /* fprintf(stderr, "##%s: sizeWant = %d * %d = %d\n", me,
            (int)(numWant),
            (int)(elementSizeWant), (int)sizeWant); */
    need = sizeHave != sizeWant;
    /* fprintf(stderr, "##%s: need = %d\n", me, need); */
  }
  if (need)
  {
    if (nrrdAlloc_nva(nrrd, type, dim, size))
    {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err);
      return 1;
    }
  }
  else
  {
    if (nrrdWrap_nva(nrrd, nrrd->data, type, dim, size))
    {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err);
      return 1;
    }
    /* but we do have to initialize memory! */
    memset(nrrd->data, 0, nrrdElementNumber(nrrd)*nrrdElementSize(nrrd));
  }

  return 0;
}
Esempio n. 20
0
/*
** _nrrdApply2DLutOrRegMap()
**
** the guts of nrrdApply2DLut and nrrdApply2DRegMap
**
** yikes, does NOT use biff, since we're only supposed to be called
** after copious error checking.  
**
** FOR INSTANCE, this allows nout == nin, which could be a big
** problem if mapAxis == 1.
**
** we don't need a typeOut arg because nout has already been allocated
** as some specific type; we'll look at that.
**
** NOTE: non-existant values get passed through regular maps and luts
** "unchanged".  However, if the output type is integral, the results
** are probaby undefined.  HEY: there is currently no warning message
** or error handling based on nrrdStateDisallowIntegerNonExist, but
** there really should be.
*/
int
_nrrdApply2DLutOrRegMap(Nrrd *nout, const Nrrd *nin,
                        const NrrdRange *range0, const NrrdRange *range1,
                        const Nrrd *nmap, int ramps,
                        int rescale0, int rescale1) {
  char me[]="_nrrdApply2DLutOrRegMap";
  char *inData, *outData, *mapData, *entData;
  size_t N, I;
  double (*inLoad)(const void *v), (*mapLup)(const void *v, size_t I),
    (*outInsert)(void *v, size_t I, double d),
    val0, val1, domMin0, domMax0, domMin1, domMax1;
  unsigned int i, mapAxis, mapLen0, mapLen1, mapIdx0, mapIdx1,
    entSize, entLen, inSize, outSize;

  mapAxis = nmap->dim - 2;             /* axis of nmap containing entries */
  mapData = (char *)nmap->data;        /* map data, as char* */
                                       /* low end of map domain */
  domMin0 = _nrrdApplyDomainMin(nmap, ramps, mapAxis + 0);
  domMin1 = _nrrdApplyDomainMin(nmap, ramps, mapAxis + 1);
                                       /* high end of map domain */
  domMax0 = _nrrdApplyDomainMax(nmap, ramps, mapAxis + 0);
  domMax1 = _nrrdApplyDomainMax(nmap, ramps, mapAxis + 1);
  mapLen0 = nmap->axis[mapAxis+0].size;   /* number of entries in map axis 0 */
  mapLen1 = nmap->axis[mapAxis+1].size;   /* number of entries in map axis 1 */
  mapLup = nrrdDLookup[nmap->type];    /* how to get doubles out of map */
  inData = (char *)nin->data;          /* input data, as char* */
  inLoad = nrrdDLoad[nin->type];       /* how to get doubles out of nin */
  inSize = nrrdElementSize(nin);       /* size of one input value */
  outData = (char *)nout->data;        /* output data, as char* */
  outInsert = nrrdDInsert[nout->type]; /* putting doubles into output */
  entLen = (mapAxis                    /* number of elements in one entry */
            ? nmap->axis[0].size
            : 1);
  outSize = entLen*nrrdElementSize(nout); /* size of entry in output */
  entSize = entLen*nrrdElementSize(nmap); /* size of entry in map */

  /*
  fprintf(stderr, "!%s: entLen = %u, mapLen = %u,%u\n", me,
          entLen, mapLen0, mapLen1);
  */

  N = nrrdElementNumber(nin)/2;       /* number of value pairs to be mapped */
  /* _VV = 1; */
  if (ramps) {
    fprintf(stderr, "%s: PANIC: unimplemented\n", me);
    exit(1);
  } else {
    /* lookup table */
    for (I=0; I<N; I++) {
      val0 = inLoad(inData + 0*inSize);
      val1 = inLoad(inData + 1*inSize);
      if (rescale0) {
        val0 = AIR_AFFINE(range0->min, val0, range0->max, domMin0, domMax0);
      }
      if (rescale1) {
        val1 = AIR_AFFINE(range1->min, val1, range1->max, domMin1, domMax1);
      }
      if (AIR_EXISTS(val0) && AIR_EXISTS(val1)) {
        mapIdx0 = airIndexClamp(domMin0, val0, domMax0, mapLen0);
        mapIdx1 = airIndexClamp(domMin1, val1, domMax1, mapLen1);
        entData = mapData + entSize*(mapIdx0 + mapLen0*mapIdx1);
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, mapLup(entData, i));
        }
      } else {
        /* copy non-existant values from input to output */
        for (i=0; i<entLen; i++) {
          outInsert(outData, i, val0 + val1);  /* HEY this is weird */
        }
      }
      inData += 2*inSize;
      outData += outSize;
    }
  }

  return 0;
}
Esempio n. 21
0
/*
******** nrrdInset()
**
** (opposite of nrrdCrop()) replace some sub-volume inside a nrrd with
** another given nrrd.
**
*/
int
nrrdInset(Nrrd *nout, const Nrrd *nin, const Nrrd *nsub, const size_t *min) {
  char me[]="nrrdInset", func[] = "inset", err[BIFF_STRLEN],
    buff1[NRRD_DIM_MAX*30], buff2[AIR_STRLEN_SMALL];
  unsigned int ai;
  size_t I,
    lineSize,                /* #bytes in one scanline to be copied */
    typeSize,                /* size of data type */
    cIn[NRRD_DIM_MAX],       /* coords for line start, in input */
    cOut[NRRD_DIM_MAX],      /* coords for line start, in output */
    szIn[NRRD_DIM_MAX],
    szOut[NRRD_DIM_MAX],
    idxIn, idxOut,           /* linear indices for input and output */
    numLines;                /* number of scanlines in output nrrd */
  char *dataIn, *dataOut, *subCont;

  /* errors */
  if (!(nout && nin && nsub && min)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nsub) {
    sprintf(err, "%s: nout==nsub disallowed", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdCheck(nin)) {
    sprintf(err, "%s: input not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdCheck(nsub)) {
    sprintf(err, "%s: subvolume not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->dim == nsub->dim )) {
    sprintf(err, "%s: input's dim (%d) != subvolume's dim (%d)",
            me, nin->dim, nsub->dim);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->type == nsub->type )) {
    sprintf(err, "%s: input's type (%s) != subvolume's type (%s)", me,
            airEnumStr(nrrdType, nin->type),
            airEnumStr(nrrdType, nsub->type));
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    if (!( nin->blockSize == nsub->blockSize )) {
      sprintf(err, "%s: input's blockSize (" _AIR_SIZE_T_CNV
              ") != subvolume's blockSize (" _AIR_SIZE_T_CNV ")",
              me, nin->blockSize, nsub->blockSize);
      biffAdd(NRRD, err); return 1;
    }
  }
  for (ai=0; ai<nin->dim; ai++) {
    if (!( min[ai] + nsub->axis[ai].size - 1 <= nin->axis[ai].size - 1)) {
      sprintf(err, "%s: axis %d range of inset indices [" _AIR_SIZE_T_CNV 
              "," _AIR_SIZE_T_CNV  "] not within "
              "input indices [0," _AIR_SIZE_T_CNV "]", me, ai,
              min[ai], min[ai] + nsub->axis[ai].size - 1,
              nin->axis[ai].size - 1);
      biffAdd(NRRD, err); return 1;
    }
  }
  
  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
  } 
  /* else we're going to inset in place */

  /* WARNING: following code copied/modified from nrrdCrop(),
     so the meanings of "in"/"out", "src"/"dest" are all messed up */

  nrrdAxisInfoGet_nva(nin, nrrdAxisInfoSize, szIn);
  nrrdAxisInfoGet_nva(nsub, nrrdAxisInfoSize, szOut);
  numLines = 1;
  for (ai=1; ai<nin->dim; ai++) {
    numLines *= szOut[ai];
  }
  lineSize = szOut[0]*nrrdElementSize(nin);
  
  /* the skinny */
  typeSize = nrrdElementSize(nin);
  dataIn = (char *)nout->data;
  dataOut = (char *)nsub->data;
  for (ai=0; ai<NRRD_DIM_MAX; ai++) {
    cOut[ai] = 0;
  }
  for (I=0; I<numLines; I++) {
    for (ai=0; ai<nin->dim; ai++) {
      cIn[ai] = cOut[ai] + min[ai];
    }
    NRRD_INDEX_GEN(idxOut, cOut, szOut, nin->dim);
    NRRD_INDEX_GEN(idxIn, cIn, szIn, nin->dim);
    memcpy(dataIn + idxIn*typeSize, dataOut + idxOut*typeSize, lineSize);
    /* the lowest coordinate in cOut[] will stay zero, since we are 
       copying one (1-D) scanline at a time */
    NRRD_COORD_INCR(cOut, szOut, nin->dim, 1);
  }

  /* HEY: before Teem version 2.0 figure out nrrdKind stuff here */
  
  strcpy(buff1, "[");
  for (ai=0; ai<nin->dim; ai++) {
    sprintf(buff2, "%s" _AIR_SIZE_T_CNV, (ai ? "," : ""), min[ai]);
    strcat(buff1, buff2);
  }
  strcat(buff1, "]");
  subCont = _nrrdContentGet(nsub);
  if (nrrdContentSet_va(nout, func, nin, "%s,%s", subCont, buff1)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); free(subCont); return 1;
  }
  free(subCont); 
  /* basic info copied by nrrdCopy above */

  return 0;
}
Esempio n. 22
0
int
_nrrdFieldInteresting(const Nrrd *nrrd, NrrdIoState *nio, int field)
{
    int ret;
    unsigned int ai;

    if (!( nrrd
            && AIR_IN_CL(1, nrrd->dim, NRRD_DIM_MAX)
            && nio
            && nio->encoding
            && AIR_IN_OP(nrrdField_unknown, field, nrrdField_last) ))
    {
        return 0;
    }

    ret = 0;
    switch (field)
    {
    case nrrdField_comment:
        /* comments and key/value pairs are always handled differently (by
           being printed explicity), so they are never "interesting" */
        break;
    case nrrdField_content:
        ret = !!(airStrlen(nrrd->content));
        break;
    case nrrdField_number:
        /* "number" is entirely redundant with "sizes", which is a
           required field.  Absolutely nothing is lost in eliding "number"
           from the header, so "number" is NEVER interesting.  Should this
           judgement later be found in error, this is the one place where
           the policy change can be implemented */
        break;
    case nrrdField_type:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_block_size:
        ret = (nrrdTypeBlock == nrrd->type);
        break;
    case nrrdField_dimension:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_space:
        /* its interesting if its known */
        ret = (nrrdSpaceUnknown != nrrd->space);
        break;
    case nrrdField_space_dimension:
        /* its interesting if its non-zero and if space is not known */
        ret = (nrrd->spaceDim > 0 && nrrdSpaceUnknown == nrrd->space);
        break;
    case nrrdField_sizes:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_spacings:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].spacing);
        }
        break;
    case nrrdField_thicknesses:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].thickness);
        }
        break;
    case nrrdField_axis_mins:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].min);
        }
        break;
    case nrrdField_axis_maxs:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= AIR_EXISTS(nrrd->axis[ai].max);
        }
        break;
    case nrrdField_space_directions:
        ret = nrrd->spaceDim > 0;
        break;
    case nrrdField_centers:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= (nrrdCenterUnknown != nrrd->axis[ai].center);
        }
        break;
    case nrrdField_kinds:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= (nrrdKindUnknown != nrrd->axis[ai].kind);
        }
        break;
    case nrrdField_labels:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= !!(airStrlen(nrrd->axis[ai].label));
        }
        break;
    case nrrdField_units:
        for (ai=0; ai<nrrd->dim; ai++)
        {
            ret |= !!(airStrlen(nrrd->axis[ai].units));
        }
        break;
    case nrrdField_min:
    case nrrdField_max:
        /* these no longer exist in the Nrrd struct; we never write them */
        ret = AIR_FALSE;
        break;
    case nrrdField_old_min:
        ret = AIR_EXISTS(nrrd->oldMin);
        break;
    case nrrdField_old_max:
        ret = AIR_EXISTS(nrrd->oldMax);
        break;
    case nrrdField_endian:
        ret = nio->encoding->endianMatters && 1 < nrrdElementSize(nrrd);
        break;
    case nrrdField_encoding:
        /* this is vital */
        ret = 1;
        break;
    case nrrdField_line_skip:
        ret = nio->lineSkip > 0;
        break;
    case nrrdField_byte_skip:
        ret = nio->byteSkip != 0;
        break;
    case nrrdField_keyvalue:
        /* comments and key/value pairs are always handled differently (by
           being printed explicity), so they are never "interesting" */
        break;
    case nrrdField_sample_units:
        ret = airStrlen(nrrd->sampleUnits);
        break;
    case nrrdField_space_units:
        for (ai=0; ai<nrrd->spaceDim; ai++)
        {
            ret |= !!(airStrlen(nrrd->spaceUnits[ai]));
        }
        break;
    case nrrdField_space_origin:
        /* we're trusting other validity checks to ensure that
           all the coeffs exist or not, together */
        ret = (nrrd->spaceDim > 0
               && AIR_EXISTS(nrrd->spaceOrigin[0]));
        break;
    case nrrdField_measurement_frame:
        /* we're trusting other validity checks to ensure that
           all the coeffs exist or not, together */
        ret = (nrrd->spaceDim > 0
               && AIR_EXISTS(nrrd->measurementFrame[0][0]));
        break;
    case nrrdField_data_file:
        /* detached header was either requested or is required */
        ret = (nio->detachedHeader
               || nio->dataFNFormat
               || nio->dataFNArr->len > 1);
        break;
    }

    return ret;
}
Esempio n. 23
0
/*
******** nrrdSlice()
**
** slices a nrrd along a given axis, at a given position.
**
** This is a newer version of the procedure, which is simpler, faster,
** and requires less memory overhead than the first one.  It is based
** on the observation that any slice is a periodic square-wave pattern
** in the original data (viewed as a one- dimensional array).  The
** characteristics of that periodic pattern are how far from the
** beginning it starts (offset), the length of the "on" part (length),
** the period (period), and the number of periods (numper).
*/
int
nrrdSlice(Nrrd *nout, const Nrrd *cnin, unsigned int saxi, size_t pos) {
  static const char me[]="nrrdSlice", func[]="slice";
  size_t
    I,
    rowLen,                  /* length of segment */
    colStep,                 /* distance between start of each segment */
    colLen,                  /* number of periods */
    szOut[NRRD_DIM_MAX];
  unsigned int ai, outdim;
  int map[NRRD_DIM_MAX];
  const char *src;
  char *dest, stmp[2][AIR_STRLEN_SMALL];
  airArray *mop;
  Nrrd *nin;

  if (!(cnin && nout)) {
    biffAddf(NRRD, "%s: got NULL pointer", me);
    return 1;
  }
  if (nout == cnin) {
    biffAddf(NRRD, "%s: nout==nin disallowed", me);
    return 1;
  }
  if (1 == cnin->dim) {
    if (0 != saxi) {
      biffAddf(NRRD, "%s: slice axis must be 0, not %u, for 1-D array",
               me, saxi);
      return 1;
    }
  } else {
    if (!( saxi < cnin->dim )) {
      biffAddf(NRRD, "%s: slice axis %d out of bounds (0 to %d)",
               me, saxi, cnin->dim-1);
      return 1;
    }
  }
  if (!( pos < cnin->axis[saxi].size )) {
    biffAddf(NRRD, "%s: position %s out of bounds (0 to %s)", me,
             airSprintSize_t(stmp[0], pos),
             airSprintSize_t(stmp[1], cnin->axis[saxi].size-1));
    return 1;
  }
  /* this shouldn't actually be necessary .. */
  if (!nrrdElementSize(cnin)) {
    biffAddf(NRRD, "%s: nrrd reports zero element size!", me);
    return 1;
  }

  /* HEY: copy and paste from measure.c/nrrdProject */
  mop = airMopNew();
  if (1 == cnin->dim) {
    /* There are more efficient ways of dealing with this case; this way is
       easy to implement because it leaves most of the established code below
       only superficially changed; uniformly replacing nin with (nin ? nin :
       cnin), even if pointlessly so; this expression that can't be assigned
       to a new variable because of the difference in const. */
    nin = nrrdNew();
    airMopAdd(mop, nin, (airMopper)nrrdNuke, airMopAlways);
    if (nrrdAxesInsert(nin, cnin, 1)) {
      biffAddf(NRRD, "%s: trouble inserting axis on 1-D array", me);
      airMopError(mop); return 1;
    }
  } else {
    nin = NULL;
  }

  /* set up control variables */
  rowLen = colLen = 1;
  for (ai=0; ai<(nin ? nin : cnin)->dim; ai++) {
    if (ai < saxi) {
      rowLen *= (nin ? nin : cnin)->axis[ai].size;
    } else if (ai > saxi) {
      colLen *= (nin ? nin : cnin)->axis[ai].size;
    }
  }
  rowLen *= nrrdElementSize(nin ? nin : cnin);
  colStep = rowLen*(nin ? nin : cnin)->axis[saxi].size;

  outdim = (nin ? nin : cnin)->dim-1;
  for (ai=0; ai<outdim; ai++) {
    map[ai] = AIR_INT(ai) + (ai >= saxi);
    szOut[ai] = (nin ? nin : cnin)->axis[map[ai]].size;
  }
  nout->blockSize = (nin ? nin : cnin)->blockSize;
  if (nrrdMaybeAlloc_nva(nout, (nin ? nin : cnin)->type, outdim, szOut)) {
    biffAddf(NRRD, "%s: failed to create slice", me);
    airMopError(mop); return 1;
  }

  /* the skinny */
  src = AIR_CAST(const char *, (nin ? nin : cnin)->data);
  dest = AIR_CAST(char *, nout->data);
  src += rowLen*pos;
  for (I=0; I<colLen; I++) {
    /* HEY: replace with AIR_MEMCPY() or similar, when applicable */
    memcpy(dest, src, rowLen);
    src += colStep;
    dest += rowLen;
  }

  /* copy the peripheral information */
  if (nrrdAxisInfoCopy(nout, (nin ? nin : cnin), map, NRRD_AXIS_INFO_NONE)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }
  if (nrrdContentSet_va(nout, func, cnin /* hide possible axinsert*/,
                        "%d,%d", saxi, pos)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }
  if (nrrdBasicInfoCopy(nout, (nin ? nin : cnin),
                        NRRD_BASIC_INFO_DATA_BIT
                        | NRRD_BASIC_INFO_TYPE_BIT
                        | NRRD_BASIC_INFO_BLOCKSIZE_BIT
                        | NRRD_BASIC_INFO_DIMENSION_BIT
                        | NRRD_BASIC_INFO_SPACEORIGIN_BIT
                        | NRRD_BASIC_INFO_CONTENT_BIT
                        | NRRD_BASIC_INFO_COMMENTS_BIT
                        | (nrrdStateKeyValuePairsPropagate
                           ? 0
                           : NRRD_BASIC_INFO_KEYVALUEPAIRS_BIT))) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }
  /* translate origin if this was a spatial axis, otherwise copy */
  /* note that if there is no spatial info at all, this is all harmless */
  if (AIR_EXISTS((nin ? nin : cnin)->axis[saxi].spaceDirection[0])) {
    nrrdSpaceVecScaleAdd2(nout->spaceOrigin,
                          1.0, (nin ? nin : cnin)->spaceOrigin,
                          AIR_CAST(double, pos),
                          (nin ? nin : cnin)->axis[saxi].spaceDirection);
  } else {
Esempio n. 24
0
int
_nrrdEncodingRaw_read(FILE *file, void *data, size_t elementNum,
                      Nrrd *nrrd, NrrdIoState *nio) {
  char me[]="_nrrdEncodingRaw_read", err[BIFF_STRLEN];
  size_t ret, bsize;
  int fd, dio, car;
  long savePos;

  bsize = nrrdElementSize(nrrd)*elementNum;
  if (nio->format->usesDIO) {
    fd = fileno(file);
    dio = airDioTest(fd, data, bsize);
  } else {
    fd = -1;
    dio = airNoDio_format;
  }
  if (airNoDio_okay == dio) {
    if (2 <= nrrdStateVerboseIO) {
      fprintf(stderr, "with direct I/O ... ");
    }
    ret = airDioRead(fd, data, bsize);
    if (ret != bsize) {
      sprintf(err, "%s: airDioRead got read only "
              _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " bytes "
              "(%g%% of expected)", me,
              ret, bsize, 100.0*ret/bsize);
      biffAdd(NRRD, err); return 1;
    }
  } else {
    if (2 <= nrrdStateVerboseIO) {
      if (AIR_DIO && nio->format->usesDIO) {
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
      }
    }
    ret = fread(data, nrrdElementSize(nrrd), elementNum, file);
    if (ret != elementNum) {
      sprintf(err, "%s: fread got read only "
              _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not "
              _AIR_SIZE_T_CNV " (%g%% of expected)", me,
              ret, nrrdElementSize(nrrd), elementNum,
              100.0*ret/elementNum);
      biffAdd(NRRD, err); return 1;
    }
    car = fgetc(file);
    if (1 <= nrrdStateVerboseIO && EOF != car) {
      fprintf(stderr, "%s: WARNING: finished reading raw data, "
              "but file not at EOF\n", me);
      ungetc(car, file);
    }
    if (2 <= nrrdStateVerboseIO && nio->byteSkip && stdin != file) {
      savePos = ftell(file);
      if (!fseek(file, 0, SEEK_END)) {
        fprintf(stderr, "(%s: used %g%% of file for nrrd data)\n",
                me, 100.0*bsize/(ftell(file) + 1));
        fseek(file, savePos, SEEK_SET);
      }
    }
  }

  return 0;
}
Esempio n. 25
0
/*
******** nrrdSplice()
**
** (opposite of nrrdSlice): replaces one slice of a nrrd with
** another nrrd.  Will allocate memory for output only if nout != nin.
*/
int
nrrdSplice(Nrrd *nout, const Nrrd *nin, const Nrrd *nslice,
           unsigned int axis, size_t pos) {
  char me[]="nrrdSplice", func[]="splice", err[BIFF_STRLEN];
  size_t 
    I, 
    rowLen,                  /* length of segment */
    colStep,                 /* distance between start of each segment */
    colLen;                  /* number of periods */
  unsigned int ai;
  char *src, *dest, *sliceCont;

  if (!(nin && nout && nslice)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  if (nout == nslice) {
    sprintf(err, "%s: nout==nslice disallowed", me);
    biffAdd(NRRD, err); return 1;
  }

  /* check that desired slice location is legit */
  if (!( axis < nin->dim )) {
    sprintf(err, "%s: slice axis %d out of bounds (0 to %d)", 
            me, axis, nin->dim-1);
    biffAdd(NRRD, err); return 1;
  }
  if (!( pos < nin->axis[axis].size )) {
    sprintf(err, "%s: position " _AIR_SIZE_T_CNV 
            " out of bounds (0 to " _AIR_SIZE_T_CNV ")", 
            me, pos, nin->axis[axis].size-1);
    biffAdd(NRRD, err); return 1;
  }

  /* check that slice will fit in nin */
  if (nrrdCheck(nslice) || nrrdCheck(nin)) {
    sprintf(err, "%s: input or slice not valid nrrd", me);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->dim-1 == nslice->dim )) {
    sprintf(err, "%s: dim of slice (%d) not one less than dim of input (%d)",
            me, nslice->dim, nin->dim);
    biffAdd(NRRD, err); return 1;
  }
  if (!( nin->type == nslice->type )) {
    sprintf(err, "%s: type of slice (%s) != type of input (%s)",
            me, airEnumStr(nrrdType, nslice->type),
            airEnumStr(nrrdType, nin->type));
    biffAdd(NRRD, err); return 1;
  }
  if (nrrdTypeBlock == nin->type) {
    if (!( nin->blockSize == nslice->blockSize )) {
      sprintf(err, "%s: input's blockSize (" _AIR_SIZE_T_CNV 
              ") != subvolume's blockSize (" _AIR_SIZE_T_CNV ")",
              me, nin->blockSize, nslice->blockSize);
      biffAdd(NRRD, err); return 1;
    }
  }
  for (ai=0; ai<nslice->dim; ai++) {
    if (!( nin->axis[ai + (ai >= axis)].size == nslice->axis[ai].size )) {
      sprintf(err, "%s: input's axis %d size (" _AIR_SIZE_T_CNV
              ") != slices axis %d size (" _AIR_SIZE_T_CNV ")",
              me, ai + (ai >= axis),
              nin->axis[ai + (ai >= axis)].size, ai, 
              nslice->axis[ai].size);
      biffAdd(NRRD, err); return 1;
    }
  }

  if (nout != nin) {
    if (nrrdCopy(nout, nin)) {
      sprintf(err, "%s:", me);
      biffAdd(NRRD, err); return 1;
    }
  } 
  /* else we're going to splice in place */

  /* the following was copied from nrrdSlice() */
  /* set up control variables */
  rowLen = colLen = 1;
  for (ai=0; ai<nin->dim; ai++) {
    if (ai < axis) {
      rowLen *= nin->axis[ai].size;
    } else if (ai > axis) {
      colLen *= nin->axis[ai].size;
    }
  }
  rowLen *= nrrdElementSize(nin);
  colStep = rowLen*nin->axis[axis].size;

  /* the skinny */
  src = (char *)nout->data;    /* switched src,dest from nrrdSlice() */
  dest = (char *)nslice->data;
  src += rowLen*pos;
  for (I=0; I<colLen; I++) {
    /* HEY: replace with AIR_MEMCPY() or similar, when applicable */
    memcpy(src, dest, rowLen);  /* switched src,dest from nrrdSlice() */
    src += colStep;
    dest += rowLen;
  }
  
  sliceCont = _nrrdContentGet(nslice);
  if (nrrdContentSet_va(nout, func, nin, "%s,%d," _AIR_SIZE_T_CNV, 
                        sliceCont, axis, pos)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); free(sliceCont); return 1;
  }
  free(sliceCont);
  /* basic info copied by nrrdCopy above */

  return 0;
}
Esempio n. 26
0
int
_nrrdEncodingRaw_write(FILE *file, const void *data, size_t elementNum,
                       const Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingRaw_write";
  int fd, dio;
  size_t ret, bsize;
  char *data_c;
  size_t elementSize, maxChunkSize, remainder, chunkSize;
  size_t retTmp;
  
  bsize = nrrdElementSize(nrrd)*elementNum;
  if (nio->format->usesDIO) {
    fd = fileno(file);
    dio = airDioTest(fd, data, bsize);
  } else {
    fd = -1;
    dio = airNoDio_format;
  }
  if (airNoDio_okay == dio) {
    if (2 <= nrrdStateVerboseIO) {
      fprintf(stderr, "with direct I/O ... ");
    }
    ret = airDioWrite(fd, data, bsize);
    if (ret != bsize) {
      biffAddf(NRRD, "%s: airDioWrite wrote only "
               _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " bytes "
               "(%g%% of expected)", me,
               ret, bsize, 100.0*ret/bsize);
      return 1;
    }
  } else {
    if (2 <= nrrdStateVerboseIO) {
      if (AIR_DIO && nio->format->usesDIO) {
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
      }
    }

    /* HEY: There's a bug in fread/fwrite in gcc 4.2.1 (with SnowLeopard).
            When it reads/writes a >=2GB data array, it pretends to succeed
            (i.e. the return value is the right number) but it hasn't
            actually read/written the data.  The work-around is to loop
            over the data, reading/writing 1GB (or smaller) chunks.         */
    ret = 0;
    data_c = (char *)data;
    elementSize = nrrdElementSize(nrrd);
    maxChunkSize = 1024 * 1024 * 1024 / elementSize;
    while(ret < elementNum) {
      remainder = elementNum-ret;
      if (remainder < maxChunkSize) {
	chunkSize = remainder;
      } else {
	chunkSize = maxChunkSize;
      }
      retTmp = 
	fwrite(&(data_c[ret*elementSize]), elementSize, chunkSize, file);
      ret += retTmp;
      if (retTmp != chunkSize) {
	biffAddf(NRRD, "%s: fwrite wrote only "
                 _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not "
                 _AIR_SIZE_T_CNV " (%g%% of expected)", me,
                 ret, nrrdElementSize(nrrd), elementNum,
                 100.0*ret/elementNum);
	return 1;
      }
    }
    /* HEY: Here's the old version of the above code.
    ret = fwrite(data, nrrdElementSize(nrrd), elementNum, file);
    if (ret != elementNum) {
      biffAddf(NRRD, "%s: fwrite wrote only "
               _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not " 
               _AIR_SIZE_T_CNV " (%g%% of expected)", me,
               ret, nrrdElementSize(nrrd), elementNum,
               100.0*ret/elementNum);
      return 1;
    }
    */

    fflush(file);
    /*
    if (ferror(file)) {
      biffAddf(NRRD, "%s: ferror returned non-zero", me);
      return 1;
    }
    */
  }
  return 0;
}
Esempio n. 27
0
int
_nrrdEncodingRaw_read(FILE *file, void *data, size_t elementNum,
                      Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdEncodingRaw_read";
  size_t ret, bsize;
  int fd, dio, car;
  long savePos;
  char *data_c;
  size_t elementSize, maxChunkSize, remainder, chunkSize;
  size_t retTmp;

  bsize = nrrdElementSize(nrrd)*elementNum;
  if (nio->format->usesDIO) {
    fd = fileno(file);
    dio = airDioTest(fd, data, bsize);
  } else {
    fd = -1;
    dio = airNoDio_format;
  }
  if (airNoDio_okay == dio) {
    if (2 <= nrrdStateVerboseIO) {
      fprintf(stderr, "with direct I/O ... ");
    }
    ret = airDioRead(fd, data, bsize);
    if (ret != bsize) {
      biffAddf(NRRD, "%s: airDioRead got read only "
               _AIR_SIZE_T_CNV " of " _AIR_SIZE_T_CNV " bytes "
               "(%g%% of expected)", me,
               ret, bsize, 100.0*ret/bsize);
      return 1;
    }
  } else {
    if (2 <= nrrdStateVerboseIO) {
      if (AIR_DIO && nio->format->usesDIO) {
        fprintf(stderr, "with fread(), not DIO: %s ...", airNoDioErr(dio));
      }
    }

    /* HEY: There's a bug in fread/fwrite in gcc 4.2.1 (with SnowLeopard).
            When it reads/writes a >=2GB data array, it pretends to succeed
            (i.e. the return value is the right number) but it hasn't
            actually read/written the data.  The work-around is to loop
            over the data, reading/writing 1GB (or smaller) chunks.         */
    ret = 0;
    data_c = (char *)data;
    elementSize = nrrdElementSize(nrrd);
    maxChunkSize = 1024 * 1024 * 1024 / elementSize;
    while(ret < elementNum) {
      remainder = elementNum-ret;
      if (remainder < maxChunkSize) {
	chunkSize = remainder;
      } else {
	chunkSize = maxChunkSize;
      }
      retTmp = 
	fread(&(data_c[ret*elementSize]), elementSize, chunkSize, file);
      ret += retTmp;
      if (retTmp != chunkSize) {
	biffAddf(NRRD, "%s: fread got read only "
                 _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not "
                 _AIR_SIZE_T_CNV " (%g%% of expected)", me,
                 ret, nrrdElementSize(nrrd), elementNum,
                 100.0*ret/elementNum);
	return 1;
      }
    }
    /* HEY: Here's the old version of the above code. 
    ret = fread(data, nrrdElementSize(nrrd), elementNum, file);
    if (ret != elementNum) {
      biffAddf(NRRD, "%s: fread got read only "
               _AIR_SIZE_T_CNV " " _AIR_SIZE_T_CNV "-sized things, not "
               _AIR_SIZE_T_CNV " (%g%% of expected)", me,
               ret, nrrdElementSize(nrrd), elementNum,
               100.0*ret/elementNum);
      return 1;
    }
    */

    car = fgetc(file);
    if (1 <= nrrdStateVerboseIO && EOF != car) {
      fprintf(stderr, "%s: WARNING: finished reading raw data, "
              "but file not at EOF\n", me);
      ungetc(car, file);
    }
    if (2 <= nrrdStateVerboseIO && nio->byteSkip && stdin != file) {
      savePos = ftell(file);
      if (!fseek(file, 0, SEEK_END)) {
        fprintf(stderr, "(%s: used %g%% of file for nrrd data)\n",
                me, 100.0*bsize/(ftell(file) + 1));
        fseek(file, savePos, SEEK_SET);
      }
    }
  }

  return 0;
}
Esempio n. 28
0
/* this strongly assumes that nrrdFitsInFormat() was true */
int
_nrrdFormatVTK_write(FILE *file, const Nrrd *_nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdFormatVTK_write";
  int i, sx, sy, sz, sax;
  double xs, ys, zs, xm, ym, zm;
  char type[AIR_STRLEN_MED], name[AIR_STRLEN_SMALL];
  Nrrd *nrrd;
  airArray *mop;

  /* HEY: should this copy be done more conservatively */
  mop = airMopNew();
  airMopAdd(mop, nrrd=nrrdNew(), (airMopper)nrrdNuke, airMopAlways);
  if (nrrdCopy(nrrd, _nrrd)) {
    biffAddf(NRRD, "%s: couldn't make private copy", me);
    airMopError(mop); return 1;
  }
  if (!( 3 == nrrd->dim ||
         (4 == nrrd->dim && (3 == nrrd->axis[0].size ||
                             9 == nrrd->axis[0].size)) )) {
    biffAddf(NRRD, "%s: doesn't seem to be scalar, vector, or matrix", me);
    airMopError(mop); return 1;
  }
  sax = nrrd->dim - 3;
  xs = nrrd->axis[sax+0].spacing;
  ys = nrrd->axis[sax+1].spacing;
  zs = nrrd->axis[sax+2].spacing;
  if (!( AIR_EXISTS(xs) && AIR_EXISTS(ys) && AIR_EXISTS(zs) )) {
    xs = ys = zs = 1.0;
  }
  xm = nrrd->axis[sax+0].min;
  ym = nrrd->axis[sax+1].min;
  zm = nrrd->axis[sax+2].min;
  if (!( AIR_EXISTS(xm) && AIR_EXISTS(ym) && AIR_EXISTS(zm) )) {
    xm = ym = zm = 0.0;
  }
  sx = AIR_CAST(int, nrrd->axis[sax+0].size);
  sy = AIR_CAST(int, nrrd->axis[sax+1].size);
  sz = AIR_CAST(int, nrrd->axis[sax+2].size);

  switch(nrrd->type) {
  case nrrdTypeUChar:
    strcpy(type, "unsigned_char");
    break;
  case nrrdTypeChar:
    strcpy(type, "char");
    break;
  case nrrdTypeUShort:
    strcpy(type, "unsigned_short");
    break;
  case nrrdTypeShort:
    strcpy(type, "short");
    break;
  case nrrdTypeUInt:
    strcpy(type, "unsigned_int");
    break;
  case nrrdTypeInt:
    strcpy(type, "int");
    break;
  case nrrdTypeFloat:
    strcpy(type, "float");
    break;
  case nrrdTypeDouble:
    strcpy(type, "double");
    break;
  default:
    biffAddf(NRRD, "%s: can't put %s-type nrrd into VTK", me,
             airEnumStr(nrrdType, nrrd->type));
    airMopError(mop); return 1;
  }
  fprintf(file, "%s\n", MAGIC3);
  /* there is a file-format-imposed limit on the length of the "content" */
  if (nrrd->content) {
    /* when the "250" below was previously "255", vtk didn't deal */
    for (i=0; i<=250 && nrrd->content[i]; i++) {
      fputc(nrrd->content[i], file);
    }
    fputc('\n', file);
  } else {
    fprintf(file, NRRD_UNKNOWN "\n");
  }
  if (nrrdEncodingRaw == nio->encoding) {
    fprintf(file, "BINARY\n");
  } else {
    fprintf(file, "ASCII\n");
  }
  fprintf(file, "DATASET STRUCTURED_POINTS\n");
  fprintf(file, "DIMENSIONS %d %d %d\n", sx, sy, sz);
  fprintf(file, "ORIGIN %g %g %g\n", xm, ym, zm);
  fprintf(file, "SPACING %g %g %g\n", xs, ys, zs);
  fprintf(file, "POINT_DATA %d\n", sx*sy*sz);
  airSrandMT(AIR_CAST(unsigned int, airTime()));
  sprintf(name, "nrrd%05d", airRandInt(100000));
  if (3 == nrrd->dim) {
    fprintf(file, "SCALARS %s %s\n", name, type);
    fprintf(file, "LOOKUP_TABLE default\n");
  } else {
    /* 4 == nrrd->dim */
    if (3 == nrrd->axis[0].size) {
      fprintf(file, "VECTORS %s %s\n", name, type);
    } else {
      fprintf(file, "TENSORS %s %s\n", name, type);
    }
  }
  if (1 < nrrdElementSize(nrrd)
      && nio->encoding->endianMatters
      && airMyEndian() != airEndianBig) {
    /* encoding exposes endianness, and we're not big, as req.d by VTK */
    nrrdSwapEndian(nrrd);
  }
  if (nio->encoding->write(file, nrrd->data, nrrdElementNumber(nrrd),
                           nrrd, nio)) {
    biffAddf(NRRD, "%s:", me);
    airMopError(mop); return 1;
  }

  airMopOkay(mop);
  return 0;
}
Esempio n. 29
0
int
_nrrdFormatVTK_read(FILE *file, Nrrd *nrrd, NrrdIoState *nio) {
  static const char me[]="_nrrdReadVTK";
  char *three[3];
  int sx, sy, sz, ret, N;
  double xm=0.0, ym=0.0, zm=0.0, xs=1.0, ys=1.0, zs=1.0;
  airArray *mop;
  unsigned int llen;

  if (!_nrrdFormatVTK_contentStartsLike(nio)) {
    biffAddf(NRRD, "%s: this doesn't look like a %s file", me,
             nrrdFormatVTK->name);
    return 1;
  }

#define GETLINE(what)                                        \
  do {                                                       \
    ret = _nrrdOneLine(&llen, nio, file);                    \
  } while (!ret && (1 == llen));                             \
  if (ret || !llen) {                                        \
    biffAddf(NRRD, "%s: couldn't get " #what " line", me);   \
    return 1;                                                \
  }

  /* read in content */
  GETLINE(content);
  if (strcmp(NRRD_UNKNOWN, nio->line)) {
    if (!(nrrd->content = airStrdup(nio->line))) {
      biffAddf(NRRD, "%s: couldn't read or copy content string", me);
      return 1;
    }
  }
  GETLINE(encoding); airToUpper(nio->line);
  if (!strcmp("ASCII", nio->line)) {
    nio->encoding = nrrdEncodingAscii;
  } else if (!strcmp("BINARY", nio->line)) {
    nio->encoding = nrrdEncodingRaw;
  } else {
    biffAddf(NRRD, "%s: encoding \"%s\" wasn't \"ASCII\" or \"BINARY\"",
             me, nio->line);
    return 1;
  }
  GETLINE(DATASET); airToUpper(nio->line);
  if (!strstr(nio->line, "STRUCTURED_POINTS")) {
    biffAddf(NRRD,
             "%s: sorry, only STRUCTURED_POINTS data is nrrd-ready", me);
    return 1;
  }
  GETLINE(DIMENSIONS); airToUpper(nio->line);
  if (!strstr(nio->line, "DIMENSIONS")
      || 3 != sscanf(nio->line, "DIMENSIONS %d %d %d", &sx, &sy, &sz)) {
    biffAddf(NRRD, "%s: couldn't parse DIMENSIONS line (\"%s\")",
             me, nio->line);
    return 1;
  }
  GETLINE(next); airToUpper(nio->line);
  while (!strstr(nio->line, "POINT_DATA")) {
    if (strstr(nio->line, "ORIGIN")) {
      if (3 != sscanf(nio->line, "ORIGIN %lf %lf %lf", &xm, &ym, &zm)) {
        biffAddf(NRRD, "%s: couldn't parse ORIGIN line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    } else if (strstr(nio->line, "SPACING")) {
      if (3 != sscanf(nio->line, "SPACING %lf %lf %lf",
                      &xs, &ys, &zs)) {
        biffAddf(NRRD, "%s: couldn't parse SPACING line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    } else if (strstr(nio->line, "ASPECT_RATIO")) {
      if (3 != sscanf(nio->line, "ASPECT_RATIO %lf %lf %lf",
                      &xs, &ys, &zs)) {
        biffAddf(NRRD, "%s: couldn't parse ASPECT_RATIO line (\"%s\")",
                 me, nio->line);
        return 1;
      }
    }
    GETLINE(next); airToUpper(nio->line);
  }
  if (1 != sscanf(nio->line, "POINT_DATA %d", &N)) {
    biffAddf(NRRD, "%s: couldn't parse POINT_DATA line (\"%s\")",
             me, nio->line);
    return 1;
  }
  if (N != sx*sy*sz) {
    biffAddf(NRRD,
             "%s: product of sizes (%d*%d*%d == %d) != # elements (%d)",
             me, sx, sy, sz, sx*sy*sz, N);
    return 1;
  }
  GETLINE(attribute declaration);
  mop = airMopNew();
  if (3 != airParseStrS(three, nio->line, AIR_WHITESPACE, 3, AIR_FALSE)) {
    biffAddf(NRRD,
             "%s: didn't see three words in attribute declaration \"%s\"",
             me, nio->line);
    return 1;
  }
  airMopAdd(mop, three[0], airFree, airMopAlways);
  airMopAdd(mop, three[1], airFree, airMopAlways);
  airMopAdd(mop, three[2], airFree, airMopAlways);
  airToLower(three[2]);
  if (!strcmp(three[2], "bit")) {
    if (nrrdEncodingAscii == nio->encoding) {
      fprintf(stderr, "%s: WARNING: \"bit\"-type data will be read in as "
              "unsigned char\n", me);
      nrrd->type = nrrdTypeUChar;
    } else {
      biffAddf(NRRD, "%s: can't read in \"bit\"-type data as BINARY", me);
      return 1;
    }
  } else if (!strcmp(three[2], "unsigned_char")) {
    nrrd->type = nrrdTypeUChar;
  } else if (!strcmp(three[2], "char")) {
    nrrd->type = nrrdTypeChar;
  } else if (!strcmp(three[2], "unsigned_short")) {
    nrrd->type = nrrdTypeUShort;
  } else if (!strcmp(three[2], "short")) {
    nrrd->type = nrrdTypeShort;
  } else if (!strcmp(three[2], "unsigned_int")) {
    nrrd->type = nrrdTypeUInt;
  } else if (!strcmp(three[2], "int")) {
    nrrd->type = nrrdTypeInt;
  } else if (!strcmp(three[2], "float")) {
    nrrd->type = nrrdTypeFloat;
  } else if (!strcmp(three[2], "double")) {
    nrrd->type = nrrdTypeDouble;
  } else {
    /* "unsigned_long" and "long" fall in here- I don't know what
       the VTK people mean by these types, since always mean different
       things on 32-bit versus 64-bit architectures */
    biffAddf(NRRD, "%s: type \"%s\" not recognized", me, three[2]);
    airMopError(mop); return 1;
  }
  airToUpper(three[0]);
  if (!strncmp("SCALARS", three[0], strlen("SCALARS"))) {
    GETLINE(LOOKUP_TABLE); airToUpper(nio->line);
    if (strcmp(nio->line, "LOOKUP_TABLE DEFAULT")) {
      biffAddf(NRRD,
               "%s: sorry, can only deal with default LOOKUP_TABLE", me);
      airMopError(mop); return 1;
    }
    nrrd->dim = 3;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, xm, ym, zm);
  } else if (!strncmp("VECTORS", three[0], strlen("VECTORS"))) {
    nrrd->dim = 4;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, 3),
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm);
    nrrd->axis[0].kind = nrrdKind3Vector;
  } else if (!strncmp("TENSORS", three[0], strlen("TENSORS"))) {
    nrrd->dim = 4;
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSize,
                       AIR_CAST(size_t, 9),
                       AIR_CAST(size_t, sx),
                       AIR_CAST(size_t, sy),
                       AIR_CAST(size_t, sz));
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpacing, AIR_NAN, xs, ys, zs);
    nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoMin, AIR_NAN, xm, ym, zm);
    nrrd->axis[0].kind = nrrdKind3DMatrix;
  } else {
    biffAddf(NRRD,
             "%s: sorry, can only deal with SCALARS, VECTORS, and TENSORS "
             "currently, so couldn't parse attribute declaration \"%s\"",
             me, nio->line);
    airMopError(mop); return 1;
  }
  if (!nio->skipData) {
    if (_nrrdCalloc(nrrd, nio, file)) {
      biffAddf(NRRD, "%s: couldn't allocate memory for data", me);
      return 1;
    }
    if (nio->encoding->read(file, nrrd->data, nrrdElementNumber(nrrd),
                            nrrd, nio)) {
      biffAddf(NRRD, "%s:", me);
      return 1;
    }
    if (1 < nrrdElementSize(nrrd)
        && nio->encoding->endianMatters
        && airMyEndian() != airEndianBig) {
      /* encoding exposes endianness, and its big, but we aren't */
      nrrdSwapEndian(nrrd);
    }
  } else {
    nrrd->data = NULL;
  }

  airMopOkay(mop);
  return 0;
}
/*
******** nrrdApply1DIrregMap()
**
** Linear interpolation between irregularly spaced control points.
** Obviously, the location of the control point has to be given
** explicitly.  The map nrrd must have dimension 2, and each 
** control point is represented by a scanline along axis 0.  The
** first value is the position of the control point, and the remaining
** value(s) are linearly weighted according to the position of the
** input value among the control point locations.
**
** To allow "coloring" of non-existant values -inf, NaN, and +inf, if
** the very first value of the map (the location of the first control
** point) is non-existant, then the first three control point locations
** must be -inf, NaN, and +inf, in that order, and the information
** about these points will be used for corresponding input values.
** Doing this makes everything slower, however, because airFPClass_f()
** is called on every single value.
**
** This assumes that nrrd1DIrregMapCheck has been called on "nmap",
** and that nrrd1DIrregAclCheck has been called on "nacl" (if it is
** non-NULL).
*/
int
nrrdApply1DIrregMap(Nrrd *nout, const Nrrd *nin, const NrrdRange *_range,
                    const Nrrd *nmap, const Nrrd *nacl,
                    int typeOut, int rescale) {
  char me[]="nrrdApply1DIrregMap", err[BIFF_STRLEN];
  size_t N, I;
  int i, *acl, entLen, posLen, aclLen, mapIdx, aclIdx,
    entSize, colSize, inSize, lo, hi, baseI;
  double val, *pos, domMin, domMax, mapIdxFrac,
    (*mapLup)(const void *v, size_t I),
    (*inLoad)(const void *v), (*outInsert)(void *v, size_t I, double d);
  char *inData, *outData, *entData0, *entData1;
  NrrdRange *range;
  airArray *mop;

  if (!(nout && nmap && nin)) {
    sprintf(err, "%s: got NULL pointer", me);
    biffAdd(NRRD, err); return 1;
  }
  mop = airMopNew();
  if (_range) {
    range = nrrdRangeCopy(_range);
    nrrdRangeSafeSet(range, nin, nrrdBlind8BitRangeState);
  } else {
    range = nrrdRangeNewSet(nin, nrrdBlind8BitRangeState);
  }
  airMopAdd(mop, range, (airMopper)nrrdRangeNix, airMopAlways);
  if (_nrrdApply1DSetUp(nout, nin, range, nmap,
                        kindImap, typeOut, rescale, AIR_FALSE)) {
    sprintf(err, "%s:", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  if (nacl && nrrd1DIrregAclCheck(nacl)) {
    sprintf(err, "%s: given acl isn't valid", me);
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  
  if (nacl) {
    acl = (int *)nacl->data;
    aclLen = nacl->axis[1].size;
  } else {
    acl = NULL;
    aclLen = 0;
  }
  pos = _nrrd1DIrregMapDomain(&posLen, &baseI, nmap);
  if (!pos) {
    sprintf(err, "%s: couldn't determine domain", me); 
    biffAdd(NRRD, err); airMopError(mop); return 1;
  }
  airMopAdd(mop, pos, airFree, airMopAlways);
  mapLup = nrrdDLookup[nmap->type];
  
  inData = (char *)nin->data;
  inLoad = nrrdDLoad[nin->type];
  inSize = nrrdElementSize(nin);
  mapLup = nrrdDLookup[nmap->type];
  entLen = nmap->axis[0].size;    /* entLen is really 1 + entry length */
  entSize = entLen*nrrdElementSize(nmap);
  colSize = (entLen-1)*nrrdTypeSize[typeOut];
  outData = (char *)nout->data;
  outInsert = nrrdDInsert[nout->type];
  domMin = pos[0];
  domMax = pos[posLen-1];
  
  N = nrrdElementNumber(nin);
  for (I=0;
       I<N;
       I++, inData += inSize, outData += colSize) {
    val = inLoad(inData);
    /* _VV = ( (AIR_EXISTS(val) && (21 == (int)(-val))) 
       || 22400 < I ); */
    /* if (_VV)
       fprintf(stderr, "##%s: (%d) val = % 31.15f\n", me, (int)I, val); */
    if (!AIR_EXISTS(val)) {
      /* got a non-existant value */
      if (baseI) {
        /* and we know how to deal with them */
        switch (airFPClass_d(val)) {
        case airFP_NEG_INF:
          mapIdx = 0;
          break;
        case airFP_SNAN:
        case airFP_QNAN:
          mapIdx = 1;
          break;
        case airFP_POS_INF:
          mapIdx = 2;
          break;
        default:
          mapIdx = 0;
          fprintf(stderr, "%s: PANIC: non-existant value/class %g/%d "
                  "not handled\n",
                  me, val, airFPClass_d(val));
          exit(1);
        }
        entData0 = (char*)(nmap->data) + mapIdx*entSize;
        for (i=1; i<entLen; i++) {
          outInsert(outData, i-1, mapLup(entData0, i));
        }
        continue;  /* we're done! (with this value) */
      } else {
        /* we don't know how to properly deal with this non-existant value:
           we use the first entry, and then fall through to code below */
        mapIdx = 0;
        mapIdxFrac = 0.0;
      }
    } else {
      /* we have an existant value */
      if (rescale) {
        val = AIR_AFFINE(range->min, val, range->max, domMin, domMax);
        /* if (_VV) fprintf(stderr, "   rescaled --> % 31.15f\n", val); */
      }
      val = AIR_CLAMP(domMin, val, domMax);
      if (acl) {
        aclIdx = airIndex(domMin, val, domMax, aclLen);
        lo = acl[0 + 2*aclIdx];
        hi = acl[1 + 2*aclIdx];
      } else {
        lo = 0;
        hi = posLen-2;
      }
      if (lo < hi) {
        mapIdx = _nrrd1DIrregFindInterval(pos, val, lo, hi);
      } else {
        /* acl did its job ==> lo == hi */
        mapIdx = lo;
      }
    }
    mapIdxFrac = AIR_AFFINE(pos[mapIdx], val, pos[mapIdx+1], 0.0, 1.0);
    /* if (_VV) fprintf(stderr, "##%s: val=\n% 31.15f --> "
                     "mapIdx,frac = %d,\n% 31.15f\n",
                     me, val, mapIdx, mapIdxFrac); */
    entData0 = (char*)(nmap->data) + (baseI+mapIdx)*entSize;
    entData1 = (char*)(nmap->data) + (baseI+mapIdx+1)*entSize;
    /* if (_VV) fprintf(stderr, "##%s: 2; %d/\n% 31.15f --> entLen=%d "
                     "baseI=%d -->\n",
                     me, mapIdx, mapIdxFrac, entLen, baseI); */
    for (i=1; i<entLen; i++) {
      val = ((1-mapIdxFrac)*mapLup(entData0, i) +
             mapIdxFrac*mapLup(entData1, i));
      /* if (_VV) fprintf(stderr, "% 31.15f\n", val); */
      outInsert(outData, i-1, val);
    }
    /* if (_VV) fprintf(stderr, "##%s: 3\n", me); */
  }
  airMopOkay(mop);
  return 0;
}