/* ----------------------------- MNI Header ----------------------------------- @NAME : save_volume_slice @INPUT : icvid - id of icv to write volume_info - volume information (minimum and maximum are ignored) slice_num - number of slice to write image - image to write slice_min - minimum real value for slice slice_max - maximum real value for slice @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to write out a slice. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void save_volume_slice(int icvid, Volume_Info *volume_info, int slice_num, unsigned char *image, double slice_min, double slice_max) { int mincid; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; /* Get the minc file id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); /* Set up the start and count variables for writinging the volume */ (void) miset_coords(3, 0, start); start[0] = slice_num; count[0] = 1; count[1] = volume_info->nrows; count[2] = volume_info->ncolumns; /* Write out the slice min and max */ (void) mivarput1(mincid, ncvarid(mincid, MIimagemin), start, NC_DOUBLE, NULL, &slice_min); (void) mivarput1(mincid, ncvarid(mincid, MIimagemax), start, NC_DOUBLE, NULL, &slice_max); /* Write out the volume */ (void) miicv_put(icvid, start, count, image); }
/* ----------------------------- MNI Header ----------------------------------- @NAME : save_volume_slice @INPUT : icvid - id of icv to write volume_info - volume information (minimum and maximum are ignored) slice_num - number of slice to write image - image to write slice_min - minimum real value for slice slice_max - maximum real value for slice @OUTPUT : (nothing) @RETURNS : (nothing) @DESCRIPTION: Routine to write out a slice. @METHOD : @GLOBALS : @CALLS : @CREATED : August 26, 1993 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ void save_volume_slice(int icvid, Volume_Info *volume_info, int slice_num[], unsigned char *image, double slice_min, double slice_max) { int mincid; long start[MAX_VAR_DIMS], count[MAX_VAR_DIMS]; int idim, ndims; /* Get the minc file id */ (void) miicv_inqint(icvid, MI_ICV_CDFID, &mincid); ndims = volume_info->number_of_dimensions; /* Set up the start and count variables for writing the volume */ (void) miset_coords(MAX_VAR_DIMS, 0, start); for(idim=0; idim<ndims-2; idim++){ start[idim] = slice_num[idim]; count[idim] = 1; } count[ndims-2] = volume_info->length[ndims-2]; count[ndims-1] = volume_info->length[ndims-1]; /* Write out the slice min and max */ (void) mivarput1(mincid, ncvarid(mincid, MIimagemin), start, NC_DOUBLE, NULL, &slice_min); (void) mivarput1(mincid, ncvarid(mincid, MIimagemax), start, NC_DOUBLE, NULL, &slice_max); /* Write out the volume */ (void) miicv_put(icvid, start, count, image); }
int test2(struct testinfo *ip, struct dimdef *dims, int ndims) { int i, j, k; int stat; long coords[3]; float flt; stat = miattputdbl(ip->fd, ip->imgid, MIvalid_max, (XSIZE * 10000.0)); if (stat < 0) { FUNC_ERROR("miattputdbl"); } stat = miattputdbl(ip->fd, ip->imgid, MIvalid_min, -(XSIZE * 10000.0)); if (stat < 0) { FUNC_ERROR("miattputdbl"); } ncendef(ip->fd); /* End definition mode. */ coords[0] = 0; flt = -(XSIZE * 100000.0); stat = mivarput1(ip->fd, ip->minid, coords, NC_FLOAT, MI_SIGNED, &flt); if (stat < 0) { FUNC_ERROR("mivarput1"); } flt = XSIZE * 100000.0; stat = mivarput1(ip->fd, ip->maxid, coords, NC_FLOAT, MI_SIGNED, &flt); if (stat < 0) { FUNC_ERROR("mivarput1"); } for (i = 0; i < dims[TST_X].length; i++) { for (j = 0; j < dims[TST_Y].length; j++) { for (k = 0; k < dims[TST_Z].length; k++) { int tmp = (i * 10000) + (j * 100) + k; coords[TST_X] = i; coords[TST_Y] = j; coords[TST_Z] = k; stat = mivarput1(ip->fd, ip->imgid, coords, NC_INT, MI_SIGNED, &tmp); if (stat < 0) { fprintf(stderr, "At (%d,%d,%d), status %d: ", i,j,k,stat); FUNC_ERROR("mivarput1"); } } } } return (0); }
/* ----------------------------- MNI Header ----------------------------------- @NAME : handle_normalization @INPUT : reshape_info - information for reshaping volume block_start - start of current block block_count - count for current block minmax_buffer - buffer space for getting min and max values @OUTPUT : fillvalue - pixel fill value to use for this block @RETURNS : (none) @DESCRIPTION: Sets up icv for normalization to ensure that block is internally normalized. Output image-max and min are set. The appropriate pixel fill value is calculated for this min and max (applies to the whole block). @METHOD : @GLOBALS : @CALLS : @CREATED : October 25, 1994 (Peter Neelin) @MODIFIED : ---------------------------------------------------------------------------- */ static void handle_normalization(Reshape_info *reshape_info, long *block_start, long *block_count, double *minmax_buffer, double *fillvalue) { int iloop; int inmincid, inimgid, varid, icvid; long minmax_start[MAX_VAR_DIMS]; double minimum, maximum, *extreme, valid_min, valid_max, denom; char *varname; /* Get input minc id, image id and icv id*/ inmincid = reshape_info->inmincid; inimgid = ncvarid(inmincid, MIimage); icvid = reshape_info->icvid; /* Get input min and max for block */ get_block_min_and_max(reshape_info, block_start, block_count, minmax_buffer, &minimum, &maximum); /* Modify the icv if necessary */ if (reshape_info->do_block_normalization) { (void) miicv_detach(icvid); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MIN, minimum); (void) miicv_setdbl(icvid, MI_ICV_IMAGE_MAX, maximum); (void) miicv_setint(icvid, MI_ICV_USER_NORM, TRUE); (void) miicv_setint(icvid, MI_ICV_DO_NORM, TRUE); (void) miicv_attach(icvid, inmincid, inimgid); } /* Save the image max and min for the block */ for (iloop=0; iloop < 2; iloop++) { /* Get varid and pointer to min or max value */ switch (iloop) { case 0: varname = MIimagemin; extreme = &minimum; break; case 1: varname = MIimagemax; extreme = &maximum; break; } /* Save the value */ ncopts = 0; varid = ncvarid(reshape_info->outmincid, varname); ncopts = NCOPTS_DEFAULT; if (varid != MI_ERROR) { (void) mitranslate_coords(reshape_info->outmincid, reshape_info->outimgid, block_start, varid, minmax_start); (void) mivarput1(reshape_info->outmincid, varid, minmax_start, NC_DOUBLE, NULL, extreme); } } /* Calculate the pixel fill value */ *fillvalue = ((reshape_info->fillvalue == NOFILL) ? 0.0 : reshape_info->fillvalue); if ((reshape_info->output_datatype != NC_FLOAT) && (reshape_info->output_datatype != NC_DOUBLE) && (*fillvalue != FILL)) { (void) miicv_inqdbl(icvid, MI_ICV_VALID_MIN, &valid_min); (void) miicv_inqdbl(icvid, MI_ICV_VALID_MAX, &valid_max); denom = maximum - minimum; if (denom == 0.0) { *fillvalue = valid_min; } else { *fillvalue = (*fillvalue - minimum) * (valid_max - valid_min) / denom + valid_min; } } }
/* ----------------------------- MNI Header ----------------------------------- @NAME : PutMaxMin @INPUT : ImInfo - pointer to struct describing the image variable ImVals - pointer to array of doubles containing the image data SliceNum, FrameNum - needed to correctly place the max and min values into the MIimagemax and MIimagemin variables DoFrames - whether or not there is a time dimension in this file @OUTPUT : (none) @RETURNS : (void) @DESCRIPTION: Finds the max and min values of an image, and puts them into the MIimagemax and MIimagemin variables associated with the specified image variable. Note: the caller must make sure that MIimagemax and MIimagemin exist in the file, and ensure that ImInfo->MaxID and ImInfo->MinID contain their variable ID's. @METHOD : @GLOBALS : @CALLS : @CREATED : 93-6-3, Greg Ward @MODIFIED : ---------------------------------------------------------------------------- */ void PutMaxMin (ImageInfoRec *ImInfo, double *ImVals, long SliceNum, long FrameNum, Boolean DoSlices, Boolean DoFrames) { int i; double Max, Min; long Coord [2]; /* might use 0, 1 or 2 elements */ int old_ncopts; int ret; nc_type range_type; int range_len; int update_vr; double valid_range[2]; double vr_max; #ifdef DEBUG int NumDims; /* number of dimensions in imagemax/imagemin */ int Dims [4]; /* dimension ID's of imagemax/imagemin */ printf ("Slice dimension is %d\n", ImInfo->SliceDim); printf ("Frame dimension is %d\n", ImInfo->FrameDim); ncvarinq (ImInfo->CDF, ImInfo->MaxID, NULL, NULL, &NumDims, Dims, NULL); printf ("MIimagemax has %d dimensions: ", NumDims); for (i = 0; i < NumDims; i++) { printf ("%5d", Dims [i]); } putchar ('\n'); ncvarinq (ImInfo->CDF, ImInfo->MinID, NULL, NULL, &NumDims, Dims, NULL); printf ("MIimagemin has %d dimensions: ", NumDims); for (i = 0; i < NumDims; i++) { printf ("%5d", Dims [i]); } putchar ('\n'); #endif Max = - DBL_MAX; Min = DBL_MAX; /* * Find the actual max and min values in the buffer */ for (i = 0; i < ImInfo->ImageSize; i++) { if (ImVals [i] > Max) { Max = ImVals [i]; } if (ImVals [i] < Min) { Min = ImVals [i]; } } /* for i */ /* * Now figure out the Coord vector (where to put the max and min * within the MIimagemax and MIimagemin variables), and put 'em there */ if (DoFrames) /* i.e. some frame was specified */ { Coord [ImInfo->FrameDim] = FrameNum; } if (DoSlices) { Coord [ImInfo->SliceDim] = SliceNum; } #ifdef DEBUG printf ("Slice %ld, frame %ld: max is %lg, min is %lg\n", (DoSlices) ? (SliceNum) : -1, (DoFrames) ? (FrameNum) : -1, Max, Min); if (DoSlices && DoFrames) printf ("Coord vector is: %ld %ld\n", Coord [0], Coord [1]); #endif mivarput1 (ImInfo->CDF, ImInfo->MaxID, Coord, NC_DOUBLE, MI_SIGNED, &Max); mivarput1 (ImInfo->CDF, ImInfo->MinID, Coord, NC_DOUBLE, MI_SIGNED, &Min); /* * Update the image valid_range attribute for floating-point volumes */ if ((ImInfo->DataType == NC_FLOAT) || (ImInfo->DataType == NC_DOUBLE)) { /* Get type and length of valid_range attribute */ old_ncopts = ncopts; ncopts = 0; ret = ncattinq(ImInfo->CDF, ImInfo->ID, MIvalid_range, &range_type, &range_len); ncopts = old_ncopts; /* If type and length are okay, then read in old value and update */ if ((ret != MI_ERROR) && (range_type == NC_DOUBLE) && (range_len == 2)) { (void) ncattget(ImInfo->CDF, ImInfo->ID, MIvalid_range, valid_range); /* Test for first write of valid range */ vr_max = (ImInfo->DataType == NC_DOUBLE ? 1.79769313e+308 : 3.402e+38); update_vr = ((valid_range[0] < -vr_max) && (valid_range[1] > vr_max)); /* Check the range */ if ((Min < valid_range[0]) || update_vr) valid_range[0] = Min; if ((Max > valid_range[1]) || update_vr) valid_range[1] = Max; /* Check for whether float rounding is needed */ if (ImInfo->DataType == NC_FLOAT) { valid_range[0] = (float) valid_range[0]; valid_range[1] = (float) valid_range[1]; } /* Write it out */ (void) ncattput(ImInfo->CDF, ImInfo->ID, MIvalid_range, NC_DOUBLE, 2, valid_range); } } /* if DataType is floating-point */ } /* PutMaxMin */
MNCAPI int minc_save_data(int fd, void *dataptr, int datatype, long st, long sz, long sy, long sx, long ct, long cz, long cy, long cx) { nc_type nctype; char *signstr; int i; int var_id; int var_ndims; int var_dims[MAX_NC_DIMS]; int icv; long start[MI_S_NDIMS]; long count[MI_S_NDIMS]; int old_ncopts; int r; double min, max; long slice_size; long index; int dtbytes; /* Length of datatype in bytes */ old_ncopts =get_ncopts(); set_ncopts(0); var_id = ncvarid(fd, MIimage); ncvarinq(fd, var_id, NULL, NULL, &var_ndims, var_dims, NULL); set_ncopts(old_ncopts); if (var_ndims < 2 || var_ndims > 4) { return (MINC_STATUS_ERROR); } r = minc_simple_to_nc_type(datatype, &nctype, &signstr); if (r == MINC_STATUS_ERROR) { return (MINC_STATUS_ERROR); } dtbytes = nctypelen(nctype); /* Update the image-min and image-max values */ if (ct > 0) { slice_size = cz * cy * cx; index = st; for (i = 0; i < ct; i++) { find_minmax((char *) dataptr + (dtbytes * slice_size * i), slice_size, datatype, &min, &max); mivarput1(fd, ncvarid(fd, MIimagemin), &index, NC_DOUBLE, MI_SIGNED, &min); mivarput1(fd, ncvarid(fd, MIimagemax), &index, NC_DOUBLE, MI_SIGNED, &max); index++; } } else { slice_size = cy * cx; index = sz; for (i = 0; i < cz; i++) { find_minmax((char *) dataptr + (dtbytes * slice_size * i), slice_size, datatype, &min, &max); mivarput1(fd, ncvarid(fd, MIimagemin), &index, NC_DOUBLE, MI_SIGNED, &min); mivarput1(fd, ncvarid(fd, MIimagemax), &index, NC_DOUBLE, MI_SIGNED, &max); index++; } } /* We want the data to wind up in t, x, y, z order. */ icv = miicv_create(); if (icv < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_TYPE, nctype); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setstr(icv, MI_ICV_SIGN, signstr); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_DO_NORM, 1); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_setint(icv, MI_ICV_DO_FILLVALUE, 1); if (r < 0) { return (MINC_STATUS_ERROR); } r = miicv_attach(icv, fd, var_id); if (r < 0) { return (MINC_STATUS_ERROR); } i = 0; switch (var_ndims) { case 4: count[i] = ct; start[i] = st; i++; /* fall through */ case 3: count[i] = cz; start[i] = sz; i++; /* fall through */ case 2: count[i] = cy; start[i] = sy; i++; count[i] = cx; start[i] = sx; i++; break; } r = miicv_put(icv, start, count, dataptr); if (r < 0) { return (MINC_STATUS_ERROR); } miicv_detach(icv); miicv_free(icv); return (MINC_STATUS_OK); }