예제 #1
0
int
main(int argc, char **argv)
{
    /* NIFTI stuff */
    nifti_image *nii_ptr;
    nifti_image nii_rec;
    int nii_dimids[MAX_NII_DIMS];
    int nii_dir[MAX_NII_DIMS];
    int nii_map[MAX_NII_DIMS];
    unsigned long nii_lens[MAX_NII_DIMS];
    int nii_ndims;
    static int nifti_filetype;
    static int nifti_datatype;
    static int nifti_signed = 1;

    /* MINC stuff */
    int mnc_fd;                 /* MINC file descriptor */
    nc_type mnc_type;           /* MINC data type as read */
    int mnc_ndims;              /* MINC image dimension count */
    int mnc_dimids[MAX_VAR_DIMS]; /* MINC image dimension identifiers */
    long mnc_dlen;              /* MINC dimension length value */
    double mnc_dstep;           /* MINC dimension step value */
    int mnc_icv;                /* MINC image conversion variable */
    int mnc_vid;                /* MINC Image variable ID */
    long mnc_start[MAX_VAR_DIMS]; /* MINC data starts */
    long mnc_count[MAX_VAR_DIMS]; /* MINC data counts */
    int mnc_signed;             /* MINC if output voxels are signed */
    double real_range[2];       /* MINC real range (min, max) */
    double input_valid_range[2]; /* MINC valid range (min, max) */
    double output_valid_range[2]; /* Valid range of output data. */
    double nifti_slope;         /* Slope to be applied to output voxels. */
    double nifti_inter;         /* Intercept to be applied to output voxels. */
    double total_valid_range;   /* Overall valid range (max - min). */
    double total_real_range;    /* Overall real range (max - min). */

    /* Other stuff */
    char out_str[1024];         /* Big string for filename */
    char att_str[1024];         /* Big string for attribute values */
    int i;                      /* Generic loop counter the first */
    int j;                      /* Generic loop counter the second */
    char *str_ptr;              /* Generic ASCIZ string pointer */
    int r;                      /* Result code. */
    static int vflag = 0;       /* Verbose flag (default is quiet) */

    static ArgvInfo argTable[] = {
        {NULL, ARGV_HELP, NULL, NULL,
         "Output voxel data type specification"},
        {"-byte", ARGV_CONSTANT, (char *)DT_INT8, (char *)&nifti_datatype,
         "Write voxel data in 8-bit signed integer format."},
        {"-short", ARGV_CONSTANT, (char *)DT_INT16, (char *)&nifti_datatype,
         "Write voxel data in 16-bit signed integer format."},
        {"-int", ARGV_CONSTANT, (char *)DT_INT32, (char *)&nifti_datatype,
         "Write voxel data in 32-bit signed integer format."},
        {"-float", ARGV_CONSTANT, (char *)DT_FLOAT32, (char *)&nifti_datatype,
         "Write voxel data in 32-bit floating point format."},
        {"-double", ARGV_CONSTANT, (char *)DT_FLOAT64, (char *)&nifti_datatype,
         "Write voxel data in 64-bit floating point format."},
        {"-signed", ARGV_CONSTANT, (char *)1, (char *)&nifti_signed,
         "Write integer voxel data in signed format."},
        {"-unsigned", ARGV_CONSTANT, (char *)0, (char *)&nifti_signed,
         "Write integer voxel data in unsigned format."},
        {NULL, ARGV_HELP, NULL, NULL,
         "Output file format specification"},
        {"-dual", ARGV_CONSTANT, (char *)FT_NIFTI_DUAL, 
         (char *)&nifti_filetype,
         "Write NIfTI-1 two-file format (.img and .hdr)"},
        {"-ASCII", ARGV_CONSTANT, (char *)FT_NIFTI_ASCII, 
         (char *)&nifti_filetype,
         "Write NIfTI-1 ASCII header format (.nia)"},
        {"-nii", ARGV_CONSTANT, (char *)FT_NIFTI_SINGLE, 
         (char *)&nifti_filetype,
         "Write NIfTI-1 one-file format (.nii)"},
        {"-analyze", ARGV_CONSTANT, (char *)FT_ANALYZE, 
         (char *)&nifti_filetype,
         "Write an Analyze two-file format file (.img and .hdr)"},
        {NULL, ARGV_HELP, NULL, NULL,
         "Other options"},
        {"-quiet", ARGV_CONSTANT, (char *)0, 
         (char *)&vflag,
         "Quiet operation"},
        {"-verbose", ARGV_CONSTANT, (char *)1, 
         (char *)&vflag,
         "Quiet operation"},
        {NULL, ARGV_END, NULL, NULL, NULL}
    };

    ncopts = 0;                 /* Clear global netCDF error reporting flag */

    /* Default NIfTI file type is "NII", single binary file
     */
    nifti_filetype = FT_UNSPECIFIED;
    nifti_datatype = DT_UNKNOWN;

    if (ParseArgv(&argc, argv, argTable, 0) || (argc < 2)) {
        fprintf(stderr, "Too few arguments\n");
        return usage();
    }

    if (!nifti_signed) {
        switch (nifti_datatype) {
        case DT_INT8:
            nifti_datatype = DT_UINT8;
            break;
        case DT_INT16:
            nifti_datatype = DT_UINT16;
            break;
        case DT_INT32:
            nifti_datatype = DT_UINT32;
            break;
        }
    }
    switch (nifti_datatype){
    case DT_INT8:
    case DT_UINT8:
        mnc_type = NC_BYTE;
        break;
    case DT_INT16:
    case DT_UINT16:
        mnc_type = NC_SHORT;
        break;
    case DT_INT32:
    case DT_UINT32:
        mnc_type = NC_INT;
        break;
    case DT_FLOAT32:
        mnc_type = NC_FLOAT;
        break;
    case DT_FLOAT64:
        mnc_type = NC_DOUBLE;
        break;
    }

    if (argc == 2) {
        strcpy(out_str, argv[1]);
        str_ptr = strrchr(out_str, '.');
        if (str_ptr != NULL && !strcmp(str_ptr, ".mnc")) {
            *str_ptr = '\0';
        }
    }
    else if (argc == 3) {
        strcpy(out_str, argv[2]);
        str_ptr = strrchr(out_str, '.');
        if (str_ptr != NULL) {
            /* See if a recognized file extension was specified.  If so,
             * we trim it off and set the output file type if none was
             * specified.  If the extension is not recognized, assume
             * that we will form the filename by just adding the right
             * extension for the selected output format.
             */
            if (!strcmp(str_ptr, ".nii")) {
                if (nifti_filetype == FT_UNSPECIFIED) {
                    nifti_filetype = FT_NIFTI_SINGLE;
                }
                *str_ptr = '\0';
            }
            else if (!strcmp(str_ptr, ".img") || 
                     !strcmp(str_ptr, ".hdr")) {
                if (nifti_filetype == FT_UNSPECIFIED) {
                    nifti_filetype = FT_NIFTI_DUAL;
                }
                *str_ptr = '\0';
            }
            else if (!strcmp(str_ptr, ".nia")) {
                if (nifti_filetype == FT_UNSPECIFIED) {
                    nifti_filetype = FT_NIFTI_ASCII;
                }
                *str_ptr = '\0';
            }
        }
    }
    else {
        fprintf(stderr, "Filename argument required\n");
        return usage();
    }

    /* Open the MINC file.  It needs to exist.
     */
    mnc_fd = miopen(argv[1], NC_NOWRITE);
    if (mnc_fd < 0) {
        fprintf(stderr, "Can't find input file '%s'\n", argv[1]);
        return (-1);
    }

    /* Find the MINC image variable.  If we can't find it, there is no
     * further processing possible...
     */
    mnc_vid = ncvarid(mnc_fd, MIimage);
    if (mnc_vid < 0) {
        fprintf(stderr, "Can't locate the image variable (mnc_vid=%d)\n", mnc_vid);
        return (-1);
    }

    /* Find out about the MINC image variable - specifically, how many
     * dimensions, and which dimensions.
     */
    r = ncvarinq(mnc_fd, mnc_vid, NULL, NULL, &mnc_ndims, mnc_dimids, NULL);
    if (r < 0) {
        fprintf(stderr, "Can't read information from image variable\n");
        return (-1);
    }
    if (mnc_ndims > MAX_NII_DIMS) {
        fprintf(stderr, "NIfTI-1 files may contain at most %d dimensions\n", 
                MAX_NII_DIMS);
        return (-1);
    }

    /* Initialize the NIfTI structure 
     */
    nii_ptr = &nii_rec;

    init_nifti_header(nii_ptr);

    /* For now we just use the mnc2nii command line as the description
     * field.  Probably we should use something better, perhaps a
     * combination of some other standard MINC fields that might
     * provide more information.
     */
    str_ptr = nii_ptr->descrip;
    for (i = 0; i < argc; i++) {
        char *arg_ptr = argv[i];

        if ((str_ptr - nii_ptr->descrip) >= MAX_NII_DESCRIP) {
            break;
        }

        if (i != 0) {
            *str_ptr++ = ' ';
        }

        while (*arg_ptr != '\0' && 
               (str_ptr - nii_ptr->descrip) < MAX_NII_DESCRIP) {
            *str_ptr++ = *arg_ptr++;
        }
        *str_ptr = '\0';
    }

    nii_ptr->fname = malloc(strlen(out_str) + 4 + 1);
    nii_ptr->iname = malloc(strlen(out_str) + 4 + 1);
    strcpy(nii_ptr->fname, out_str);
    strcpy(nii_ptr->iname, out_str);

    switch (nifti_filetype) {
    case FT_ANALYZE:
        strcat(nii_ptr->fname, ".hdr");
        strcat(nii_ptr->iname, ".img");
        break;
    case FT_NIFTI_SINGLE:
        strcat(nii_ptr->fname, ".nii");
        strcat(nii_ptr->iname, ".nii");
        break;
    case FT_NIFTI_DUAL:
        strcat(nii_ptr->fname, ".hdr");
        strcat(nii_ptr->iname, ".img");
        break;
    case FT_NIFTI_ASCII:
        strcat(nii_ptr->fname, ".nia");
        strcat(nii_ptr->iname, ".nia");
        break;
    default:
        fprintf(stderr, "Unknown output file type %d\n", nifti_filetype);
        return (-1);
    }

    /* Get real voxel range for the input file.
     */
    miget_image_range(mnc_fd, real_range);

    /* Get the actual valid voxel value range.
     */
    miget_valid_range(mnc_fd, mnc_vid, input_valid_range);

    /* Find the default range for the output type. Our output file
     * will use the full legal range of the output type if it is
     * an integer.
     */

    if (nifti_datatype == DT_UNKNOWN) {
        nii_ptr->datatype = DT_FLOAT32; /* Default */
        mnc_type = NC_FLOAT;
        mnc_signed = 1;
    }
    else {
        nii_ptr->datatype = nifti_datatype;
        mnc_signed = nifti_signed;
    }

    if (vflag) {
        fprintf(stderr, "MINC type %d signed %d\n", mnc_type, mnc_signed);
    }

    miget_default_range(mnc_type, mnc_signed, output_valid_range);

    total_valid_range = input_valid_range[1] - input_valid_range[0];
    total_real_range = real_range[1] - real_range[0];

    if ((output_valid_range[1] - output_valid_range[0]) > total_valid_range) {
        /* Empirically, forcing the valid range to be the nearest power
         * of two greater than the existing valid range seems to improve
         * the behavior of the conversion. This is at least in part because
         * of the limited precision of the NIfTI-1 voxel scaling fields.
         */
        double new_range = nearest_power_of_two(total_valid_range);
        if (new_range - 1.0 >= total_valid_range) {
            new_range -= 1.0;
        }

        if (output_valid_range[1] > total_valid_range) {
            output_valid_range[0] = 0;
            output_valid_range[1] = new_range;
        }
        else {
            output_valid_range[1] = output_valid_range[0] + new_range;
        }
    }
    else {
        /* The new range can't fully represent the input range. Use the 
         * full available range, and warn the user that they may have a
         * problem.
         */
        printf("WARNING: Range of input exceeds range of output format.\n");
    }

    if (vflag) {
        printf("Real range: %f %f Input valid range: %f %f Output valid range: %f %f\n",
               real_range[0], real_range[1],
               input_valid_range[0], input_valid_range[1],
               output_valid_range[0], output_valid_range[1]);
    }

    /* If the output type is not floating point, we may need to scale the
     * voxel values.
     */

    if (mnc_type != NC_FLOAT && mnc_type != NC_DOUBLE) {

        /* Figure out how to map pixel values into the range of the 
         * output datatype.
         */
        nifti_slope = ((real_range[1] - real_range[0]) / 
                       (output_valid_range[1] - output_valid_range[0]));

        if (nifti_slope == 0.0) {
            nifti_slope = 1.0;
        }
        nifti_inter = real_range[0] - (output_valid_range[0] * nifti_slope);

        /* One problem with NIfTI-1 is the limited precision of the 
         * scl_slope and scl_inter fields (they are just 32-bits). So
         * we look for possible issues and warn about that here.
         */
        if (nifti_inter != (float) nifti_inter || 
            nifti_slope != (float) nifti_slope) {
            double epsilon_i = nifti_inter - (float) nifti_inter;
            double epsilon_s = nifti_slope - (float) nifti_slope;

            /* If the loss in precision is more than one part per thousand
             * of the real range, flag this as a problem!
             */
            if ((epsilon_i > total_real_range / 1.0e3) ||
                (epsilon_s > total_real_range / 1.0e3)) {
                fprintf(stderr, "ERROR: Slope and intercept cannot be represented in the NIfTI-1 header.\n");
                fprintf(stderr, "      slope %f (%f), intercept %f (%f)\n", 
                        nifti_slope, (float) nifti_slope,
                        nifti_inter, (float) nifti_inter);
                return (-1);
            }
        }
    }
    else {
        nifti_slope = 0.0;
    }

    nii_ptr->scl_slope = nifti_slope;
    nii_ptr->scl_inter = nifti_inter;

    nii_ptr->nvox = 1;          /* Initial value for voxel count */

    /* Find all of the dimensions of the MINC file, in the order they 
     * will be listed in the NIfTI-1/Analyze file.  We use this to build
     * a map for restructuring the data according to the normal rules
     * of NIfTI-1.
     */
    nii_ndims = 0;
    for (i = 0; i < MAX_NII_DIMS; i++) {
        if (dimnames[i] == NULL) {
            nii_dimids[nii_ndims] = -1;
            continue;
        }

        nii_dimids[nii_ndims] = ncdimid(mnc_fd, dimnames[i]);
        if (nii_dimids[nii_ndims] == -1) {
            continue;
        }

        /* Make sure the dimension is actually used to define the image.
         */
        for (j = 0; j < mnc_ndims; j++) {
            if (nii_dimids[nii_ndims] == mnc_dimids[j]) {
                nii_map[nii_ndims] = j;
                break;
            }
        }

        if (j < mnc_ndims) {
            mnc_dlen = 1;
            mnc_dstep = 0;

            ncdiminq(mnc_fd, nii_dimids[nii_ndims], NULL, &mnc_dlen);
            ncattget(mnc_fd, ncvarid(mnc_fd, dimnames[i]), MIstep, &mnc_dstep);

            if (mnc_dstep < 0) {
                nii_dir[nii_ndims] = -1;
                mnc_dstep = -mnc_dstep;
            }
            else {
                nii_dir[nii_ndims] = 1;
            }

            nii_lens[nii_ndims] = mnc_dlen;
            nii_ndims++;
        }

        nii_ptr->dim[dimmap[i]] = (int) mnc_dlen;
        nii_ptr->nvox *= mnc_dlen;

        nii_ptr->pixdim[dimmap[i]] = (float) mnc_dstep;
    }

    /* Here we do some "post-processing" of the results. Make certain that
     * the nt value is never zero, and make certain that ndim is set to
     * 4 if there is a time dimension and 5 if there is a vector dimension
     */

    if (nii_ptr->dim[3] > 1 && nii_ndims < 4) {
        nii_ndims = 4;
    }

    if (nii_ptr->dim[4] > 1) {
        nii_ptr->intent_code = NIFTI_INTENT_VECTOR;
        nii_ndims = 5;
    }

    nii_ptr->ndim = nii_ndims; /* Total number of dimensions in file */
    nii_ptr->nx = nii_ptr->dim[0];
    nii_ptr->ny = nii_ptr->dim[1];
    nii_ptr->nz = nii_ptr->dim[2];
    nii_ptr->nt = nii_ptr->dim[3];
    nii_ptr->nu = nii_ptr->dim[4];

    nii_ptr->dx = nii_ptr->pixdim[0];
    nii_ptr->dy = nii_ptr->pixdim[1];
    nii_ptr->dz = nii_ptr->pixdim[2];
    nii_ptr->dt = nii_ptr->pixdim[3];
    nii_ptr->du = 1; /* MINC files don't define a sample size for a vector_dimension */

    nii_ptr->nifti_type = nifti_filetype;

    /* Load the direction_cosines and start values into the NIfTI-1 
     * sform structure.
     *
     */
    for (i = 0; i < MAX_SPACE_DIMS; i++) {
        int id = ncvarid(mnc_fd, mnc_spatial_names[i]);
        double start;
        double step;
        double dircos[MAX_SPACE_DIMS];
        int tmp;

        if (id < 0) {
            continue;
        }

        /* Set default values */
        start = 0.0;
        step = 1.0;
        dircos[DIM_X] = dircos[DIM_Y] = dircos[DIM_Z] = 0.0;
        dircos[i] = 1.0;

        miattget(mnc_fd, id, MIstart, NC_DOUBLE, 1, &start, &tmp);
        miattget(mnc_fd, id, MIstep, NC_DOUBLE, 1, &step, &tmp);
        miattget(mnc_fd, id, MIdirection_cosines, NC_DOUBLE, MAX_SPACE_DIMS, 
                 dircos, &tmp);
        ncdiminq(mnc_fd, ncdimid(mnc_fd, mnc_spatial_names[i]), NULL, 
                 &mnc_dlen);

        if (step < 0) {
            step = -step;
            start = start - step * (mnc_dlen - 1);
        }

        nii_ptr->sto_xyz.m[0][i] = step * dircos[0];
        nii_ptr->sto_xyz.m[1][i] = step * dircos[1];
        nii_ptr->sto_xyz.m[2][i] = step * dircos[2];

        nii_ptr->sto_xyz.m[0][3] += start * dircos[0];
        nii_ptr->sto_xyz.m[1][3] += start * dircos[1];
        nii_ptr->sto_xyz.m[2][3] += start * dircos[2];

        miattgetstr(mnc_fd, id, MIspacetype, sizeof(att_str), att_str);

        /* Try to set the S-transform code correctly.
         */
        if (!strcmp(att_str, MI_TALAIRACH)) {
            nii_ptr->sform_code = NIFTI_XFORM_TALAIRACH;
        }
        else if (!strcmp(att_str, MI_CALLOSAL)) {
            /* TODO: Not clear what do do here... */
            nii_ptr->sform_code = NIFTI_XFORM_SCANNER_ANAT;
        }
        else {                  /* MI_NATIVE or unknown */
            nii_ptr->sform_code = NIFTI_XFORM_SCANNER_ANAT;
        }
    }

    /* So the last row is right... */
    nii_ptr->sto_xyz.m[3][0] = 0.0;
    nii_ptr->sto_xyz.m[3][1] = 0.0;
    nii_ptr->sto_xyz.m[3][2] = 0.0;
    nii_ptr->sto_xyz.m[3][3] = 1.0;

    nii_ptr->sto_ijk = nifti_mat44_inverse(nii_ptr->sto_xyz);

    nifti_datatype_sizes(nii_ptr->datatype, 
                         &nii_ptr->nbyper, &nii_ptr->swapsize);


    if (vflag) {
        nifti_image_infodump(nii_ptr);
    }

    /* Now load the actual MINC data. */

    nii_ptr->data = malloc(nii_ptr->nbyper * nii_ptr->nvox);
    if (nii_ptr->data == NULL) {
        fprintf(stderr, "Out of memory.\n");
        return (-1);
    }

    mnc_icv = miicv_create();
    miicv_setint(mnc_icv, MI_ICV_TYPE, mnc_type);
    miicv_setstr(mnc_icv, MI_ICV_SIGN, (mnc_signed) ? MI_SIGNED : MI_UNSIGNED);
    miicv_setdbl(mnc_icv, MI_ICV_VALID_MAX, output_valid_range[1]);
    miicv_setdbl(mnc_icv, MI_ICV_VALID_MIN, output_valid_range[0]);
    miicv_setdbl(mnc_icv, MI_ICV_IMAGE_MAX, real_range[1]);
    miicv_setdbl(mnc_icv, MI_ICV_IMAGE_MIN, real_range[0]);
    miicv_setdbl(mnc_icv, MI_ICV_DO_NORM, TRUE);
    miicv_setdbl(mnc_icv, MI_ICV_USER_NORM, TRUE);

    miicv_attach(mnc_icv, mnc_fd, mnc_vid);

    /* Read in the entire hyperslab from the file.
     */
    for (i = 0; i < mnc_ndims; i++) {
        ncdiminq(mnc_fd, mnc_dimids[i], NULL, &mnc_count[i]);
        mnc_start[i] = 0;
    }

    r = miicv_get(mnc_icv, mnc_start, mnc_count, nii_ptr->data);
    if (r < 0) {
        fprintf(stderr, "Read error\n");
        return (-1);
    }

    /* Shut down the MINC stuff now that it has done its work. 
     */
    miicv_detach(mnc_icv);
    miicv_free(mnc_icv);
    miclose(mnc_fd);

    if (vflag) {
        /* Debugging stuff - just to check the contents of these arrays.
         */
        for (i = 0; i < nii_ndims; i++) {
            printf("%d: %ld %d %d\n", 
                   i, nii_lens[i], nii_map[i], nii_dir[i]);
        }
        printf("bytes per voxel %d\n", nii_ptr->nbyper);
        printf("# of voxels %ld\n", nii_ptr->nvox);
    }

    /* Rearrange the data to correspond to the NIfTI dimension ordering.
     */
    restructure_array(nii_ndims,
                      nii_ptr->data,
                      nii_lens,
                      nii_ptr->nbyper,
                      nii_map,
                      nii_dir);

    if (vflag) {
        /* More debugging stuff - check coordinate transform.
         */
        test_xform(nii_ptr->sto_xyz, 0, 0, 0);
        test_xform(nii_ptr->sto_xyz, 10, 0, 0);
        test_xform(nii_ptr->sto_xyz, 0, 10, 0);
        test_xform(nii_ptr->sto_xyz, 0, 0, 10);
        test_xform(nii_ptr->sto_xyz, 10, 10, 10);
    }

    if (vflag) {
        fprintf(stdout, "Writing NIfTI-1 file...");
    }
    nifti_image_write(nii_ptr);
    if (vflag) {
        fprintf(stdout, "done.\n");
    }

    return (0);
}
예제 #2
0
MNCAPI int
minc_load_data(char *path, void *dataptr, int datatype,
               long *ct, long *cz, long *cy, long *cx,
               double *dt, double *dz, double *dy, double *dx,
               void **infoptr)
{
    int fd;                     /* MINC file descriptor */
    nc_type nctype;             /* netCDF type */
    char *signstr;              /* MI_SIGNED or MI_UNSIGNED */
    int length;
    int dim_id[MI_S_NDIMS];
    long dim_len[MI_S_NDIMS];
    int i, j;                   /* Generic loop counters */
    int var_id;
    int var_ndims;
    int var_dims[MAX_NC_DIMS];
    int icv;                    /* MINC image conversion variable */
    long start[MI_S_NDIMS];
    long count[MI_S_NDIMS];
    size_t ucount[MI_S_NDIMS];
    int dir[MI_S_NDIMS];        /* Dimension "directions" */
    int map[MI_S_NDIMS];        /* Dimension mapping */
    int old_ncopts;             /* For storing the old state of ncopts */
    double *p_dtmp;
    long *p_ltmp;
    struct file_info *p_file;
    struct att_info *p_att;
    int r;                      /* Generic return code */
    
    *infoptr = NULL;

    fd = miopen(path, NC_NOWRITE);
    if (fd < 0) {
        return (MINC_STATUS_ERROR);
    }

    old_ncopts =get_ncopts();
    set_ncopts(0);

    for (i = 0; i < MI_S_NDIMS; i++) {
        dim_id[i] = ncdimid(fd, minc_dimnames[i]);
        if (dim_id[i] >= 0) {
            ncdiminq(fd, dim_id[i], NULL, &dim_len[i]);
            var_id = ncvarid(fd, minc_dimnames[i]);
            ncattinq(fd, var_id, MIstep, &nctype, &length);

            switch (i) {
            case MI_S_T:
                p_ltmp = ct;
                p_dtmp = dt;
                break;
            case MI_S_X:
                p_ltmp = cx;
                p_dtmp = dx;
                break;
            case MI_S_Y:
                p_ltmp = cy;
                p_dtmp = dy;
                break;
            case MI_S_Z:
                p_ltmp = cz;
                p_dtmp = dz;
                break;
            default:
                return (MINC_STATUS_ERROR);
            }
                
            if (nctype == NC_DOUBLE && length == 1) {
                ncattget(fd, var_id, MIstep, p_dtmp);
            }
            else {
                *p_dtmp = 0;    /* Unknown/not set */
            }
            *p_ltmp = dim_len[i];
        }
        else {
            dim_len[i] = 0;
        }
    }

    set_ncopts(old_ncopts);

    var_id = ncvarid(fd, MIimage);

    ncvarinq(fd, var_id, NULL, &nctype, &var_ndims, var_dims, NULL);

    if (var_ndims != 3 && var_ndims != 4) {
        return (MINC_STATUS_ERROR);
    }

    /* We want the data to wind up in t, x, y, z order. */

    for (i = 0; i < MI_S_NDIMS; i++) {
        map[i] = -1;
    }

    for (i = 0; i < var_ndims; i++) {
        if (var_dims[i] == dim_id[MI_S_T]) {
            map[MI_S_T] = i;
        }
        else if (var_dims[i] == dim_id[MI_S_X]) {
            map[MI_S_X] = i;
        }
        else if (var_dims[i] == dim_id[MI_S_Y]) {
            map[MI_S_Y] = i;
        }
        else if (var_dims[i] == dim_id[MI_S_Z]) {
            map[MI_S_Z] = i;
        }
    }

    icv = miicv_create();

    minc_simple_to_nc_type(datatype, &nctype, &signstr);
    miicv_setint(icv, MI_ICV_TYPE, nctype);
    miicv_setstr(icv, MI_ICV_SIGN, signstr);
    miicv_attach(icv, fd, var_id);

    for (i = 0; i < var_ndims; i++) {
        start[i] = 0;
    }

    for (i = 0; i < MI_S_NDIMS; i++) {
        if (map[i] >= 0) {
            count[map[i]] = dim_len[i];
        }
    }

    r = miicv_get(icv, start, count, dataptr);
    if (r < 0) {
        return (MINC_STATUS_ERROR);
    }

    if (map[MI_S_T] >= 0) {
        if (*dt < 0) {
            dir[MI_S_T] = -1;
            *dt = -*dt;
        }
        else {
            dir[MI_S_T] = 1;
        }
    }

    if (map[MI_S_X] >= 0) {
        if (*dx < 0) {
            dir[MI_S_X] = -1;
            *dx = -*dx;
        }
        else {
            dir[MI_S_X] = 1;
        }
    }

    if (map[MI_S_Y] >= 0) {
        if (*dy < 0) {
            dir[MI_S_Y] = -1;
            *dy = -*dy;
        }
        else {
            dir[MI_S_Y] = 1;
        }
    }

    if (map[MI_S_Z] >= 0) {
        if (*dz < 0) {
            dir[MI_S_Z] = -1;
            *dz = -*dz;
        }
        else {
            dir[MI_S_Z] = 1;
        }
    }

    if (var_ndims == 3) {
        for (i = 1; i < MI_S_NDIMS; i++) {
            map[i-1] = map[i];
            dir[i-1] = dir[i];
        }
    }

    j = 0;
    for (i = 0; i < MI_S_NDIMS; i++) {
        if (dim_len[i] > 0) {
            ucount[j++] = dim_len[i];
        }
    }

    restructure_array(var_ndims, dataptr, ucount, nctypelen(nctype),
                      map, dir);

    miicv_detach(icv);
    miicv_free(icv);

    old_ncopts =get_ncopts();
    set_ncopts(0);

    /* Generate the complete infoptr array.
     * This is essentially an in-memory copy of the variables and attributes
     * in the file.
     */

    p_file = (struct file_info *) malloc(sizeof (struct file_info));

    ncinquire(fd, &p_file->file_ndims, &p_file->file_nvars,
              &p_file->file_natts, NULL);

    p_file->file_atts = (struct att_info *) malloc(sizeof (struct att_info) * 
                                                   p_file->file_natts);

    p_file->file_vars = (struct var_info *) malloc(sizeof (struct var_info) *
                                                   p_file->file_nvars);

    for (i = 0; i < p_file->file_natts; i++) {
        p_att = &p_file->file_atts[i];

        ncattname(fd, NC_GLOBAL, i, p_att->att_name);
        ncattinq(fd, NC_GLOBAL, 
                 p_att->att_name, 
                 &p_att->att_type, 
                 &p_att->att_len);

        p_att->att_val = malloc(p_att->att_len * nctypelen(p_att->att_type));

        ncattget(fd, NC_GLOBAL, p_att->att_name, p_att->att_val);
    }

    for (i = 0; i < p_file->file_nvars; i++) {
        struct var_info *p_var = &p_file->file_vars[i];

        ncvarinq(fd, i, 
                 p_var->var_name, 
                 &p_var->var_type, 
                 &p_var->var_ndims, 
                 p_var->var_dims,
                 &p_var->var_natts);

        p_var->var_atts = malloc(p_var->var_natts *
                                 sizeof (struct att_info));

        if (ncdimid(fd, p_var->var_name) >= 0) {
            /* It's a dimension variable, have to treat it specially... */
        }

        for (j = 0; j < p_var->var_natts; j++) {
            p_att = &p_var->var_atts[j];

            ncattname(fd, i, j, p_att->att_name);
            ncattinq(fd, i, 
                     p_att->att_name, 
                     &p_att->att_type, 
                     &p_att->att_len);

            p_att->att_val = malloc(p_att->att_len * nctypelen(p_att->att_type));
            ncattget(fd, i, p_att->att_name, p_att->att_val);
        }
    }

    *infoptr = p_file;

    set_ncopts(old_ncopts);

    miclose(fd);

    return (MINC_STATUS_OK);
}
예제 #3
0
파일: hyper.c 프로젝트: happyyang/ITK
/** Read/write a hyperslab of data, performing dimension remapping
 * and data rescaling as needed.
 */
static int mirw_hyperslab_icv(int opcode,
                              mihandle_t volume,
                              mitype_t buffer_data_type,
                              const misize_t start[],
                              const misize_t count[],
                              void *buffer)
{
  hid_t dset_id = -1;
  hid_t mspc_id = -1;
  hid_t fspc_id = -1;
  hid_t buffer_type_id = -1;
  int result = MI_ERROR;
  hsize_t hdf_start[MI2_MAX_VAR_DIMS];
  hsize_t hdf_count[MI2_MAX_VAR_DIMS];
  int dir[MI2_MAX_VAR_DIMS];  /* Direction vector in file order */
  hsize_t ndims;
  int slice_ndims;
  int n_different = 0;
  double volume_valid_min, volume_valid_max;
  misize_t buffer_size;
  void *temp_buffer=NULL;
  size_t icount[MI2_MAX_VAR_DIMS];
  int idir[MI2_MAX_VAR_DIMS];
  int imap[MI2_MAX_VAR_DIMS];
  double *image_slice_max_buffer=NULL;
  double *image_slice_min_buffer=NULL;
  int scaling_needed=0;
  char path[MI2_MAX_PATH];
  
  hsize_t image_slice_start[MI2_MAX_VAR_DIMS];
  hsize_t image_slice_count[MI2_MAX_VAR_DIMS];
  hsize_t image_slice_length=0;
  hsize_t total_number_of_slices=0;
  hsize_t i;
  int j;


  /* Disallow write operations to anything but the highest resolution.
   */
  if (opcode == MIRW_OP_WRITE && volume->selected_resolution != 0) {
    return MI_LOG_ERROR(MI2_MSG_GENERIC,"Trying to write to a volume thumbnail");
  }
  
  sprintf(path, MI_ROOT_PATH "/image/%d/image", volume->selected_resolution);
  /*printf("Using:%s\n",path);*/
  
  /* Open the dataset with the specified path
  */
  MI_CHECK_HDF_CALL(dset_id = H5Dopen1(volume->hdf_id, path),"H5Dopen1");
  if (dset_id < 0) {
    return (MI_ERROR);
  }

  MI_CHECK_HDF_CALL(fspc_id = H5Dget_space(dset_id),"H5Dget_space");
  if (fspc_id < 0) {
    goto cleanup;
  }

 
  buffer_type_id = mitype_to_hdftype(buffer_data_type, TRUE);
  if(buffer_type_id<0)
  {
    goto cleanup;
  }
  
  ndims = volume->number_of_dims;
  
  if (ndims == 0) {
    /* A scalar volume is possible but extremely unlikely, not to
     * mention useless!
     */
    mspc_id = H5Screate(H5S_SCALAR);
    hdf_count[0]=1; 
  } else {

    n_different = mitranslate_hyperslab_origin(volume, start, count, hdf_start, hdf_count, dir);

    mspc_id = H5Screate_simple(ndims, hdf_count, NULL);
    
    if (mspc_id < 0) {
      fprintf(stderr,"H5Screate_simple: Fail %s:%d\n",__FILE__,__LINE__);
      goto cleanup;
    }
  }
  
  miget_hyperslab_size_hdf(buffer_type_id, ndims, hdf_count, &buffer_size);

  MI_CHECK_HDF_CALL(result = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, hdf_start, NULL,
                               hdf_count, NULL),"H5Sselect_hyperslab");
  if (result < 0) {
    goto cleanup;
  }

  if((result=miget_volume_valid_range( volume, &volume_valid_max, &volume_valid_min))<0)
  {
    goto cleanup;
  }

#ifdef _DEBUG
  printf("mirw_hyperslab_icv:Volume:%lx valid_max:%f valid_min:%f scaling:%d n_different:%d\n",(long int)(volume),volume_valid_max,volume_valid_min,volume->has_slice_scaling,n_different);
#endif  
  
  if(volume->has_slice_scaling)
  {
    hid_t image_max_fspc_id;
    hid_t image_min_fspc_id;
    hid_t scaling_mspc_id;
    total_number_of_slices=1;
    image_slice_length=1;
    scaling_needed=1;

    image_max_fspc_id=H5Dget_space(volume->imax_id);
    image_min_fspc_id=H5Dget_space(volume->imin_id);

    if ( image_max_fspc_id < 0 ) {
      /*Report error that image-max is not found!*/
      return ( MI_ERROR );
    }

    slice_ndims = H5Sget_simple_extent_ndims ( image_max_fspc_id );
    if(slice_ndims<0)
    {
      /*TODO: report read error somehow*/
      fprintf(stderr,"H5Sget_simple_extent_ndims: Fail %s:%d\n",__FILE__,__LINE__);
      goto cleanup;
    }

    if ( (hsize_t)slice_ndims > ndims ) { /*Can this really happen?*/
      slice_ndims = ndims;
    }

    for ( j = 0; j < slice_ndims; j++ ) {
      image_slice_count[j] = hdf_count[j];
      image_slice_start[j] = hdf_start[j];
      
      if(hdf_count[j]>1) /*avoid zero sized dimensions?*/
        total_number_of_slices*=hdf_count[j];
    }
    
    for (i = slice_ndims; i < ndims; i++ ) {
      if(hdf_count[i]>1) /*avoid zero sized dimensions?*/
        image_slice_length*=hdf_count[i];
      
      image_slice_count[i] = 0;
      image_slice_start[i] = 0;
    }
    
    image_slice_max_buffer=malloc(total_number_of_slices*sizeof(double));
    if(!image_slice_max_buffer)
    {
      result=MI_ERROR;
      MI_LOG_ERROR(MI2_MSG_OUTOFMEM,total_number_of_slices*sizeof(double));
      goto cleanup;
    }
    
    image_slice_min_buffer=malloc(total_number_of_slices*sizeof(double));
    
    if(!image_slice_min_buffer)
    {
      result=MI_ERROR;
      MI_LOG_ERROR(MI2_MSG_OUTOFMEM,total_number_of_slices*sizeof(double));
      goto cleanup;
    }
    
    scaling_mspc_id = H5Screate_simple(slice_ndims, image_slice_count, NULL);
    
    if( (result=H5Sselect_hyperslab(image_max_fspc_id, H5S_SELECT_SET, image_slice_start, NULL, image_slice_count, NULL))>=0 )
    {
      if((result=H5Dread(volume->imax_id, H5T_NATIVE_DOUBLE, scaling_mspc_id, image_max_fspc_id, H5P_DEFAULT,image_slice_max_buffer))<0)
      {
        MI_LOG_ERROR(MI2_MSG_HDF5,"H5Dread");
        goto cleanup;
      }
    } else {
      MI_LOG_ERROR(MI2_MSG_HDF5,"H5Sselect_hyperslab");
      goto cleanup;
    }
    
    if((result=H5Sselect_hyperslab(image_min_fspc_id, H5S_SELECT_SET, image_slice_start, NULL, image_slice_count, NULL))>=0 )
    {
      if((result=H5Dread(volume->imin_id, H5T_NATIVE_DOUBLE, scaling_mspc_id, image_min_fspc_id, H5P_DEFAULT,image_slice_min_buffer))<0)
      {
        MI_LOG_ERROR(MI2_MSG_HDF5,"H5Dread");
        goto cleanup;
      }
    } else {
      /*TODO: report read error somehow*/
      MI_LOG_ERROR(MI2_MSG_HDF5,"H5Sselect_hyperslab");
      goto cleanup;
    }
    H5Sclose(scaling_mspc_id);
    H5Sclose(image_max_fspc_id);
  } else {
    slice_ndims=0;
    total_number_of_slices=1;
    image_slice_max_buffer=malloc(sizeof(double));
    image_slice_min_buffer=malloc(sizeof(double));
    miget_volume_range(volume,image_slice_max_buffer,image_slice_min_buffer);
    image_slice_length=1;
    /*it produces unity scaling*/
    scaling_needed=(*image_slice_max_buffer!=volume_valid_max) || (*image_slice_min_buffer!=volume_valid_min);
    for (i = 0; i < ndims; i++) {
      image_slice_length *= hdf_count[i];
    }
#ifdef _DEBUG    
    printf("mirw_hyperslab_icv:Real max:%f min:%f\n",*image_slice_max_buffer,*image_slice_min_buffer);
#endif    
  }
  
  //A hack to disable interslice scaling when it is not needed according to MINC1 specs
  if( volume->volume_type==MI_TYPE_FLOAT    || volume->volume_type==MI_TYPE_DOUBLE || 
      volume->volume_type==MI_TYPE_FCOMPLEX || volume->volume_type==MI_TYPE_DCOMPLEX )
  {
    scaling_needed=0;
  } 
#ifdef _DEBUG  
  printf("mirw_hyperslab_icv:Slice_ndim:%d total_number_of_slices:%d image_slice_length:%d scaling_needed:%d\n",slice_ndims,total_number_of_slices,image_slice_length,scaling_needed);
#endif

  if (opcode == MIRW_OP_READ) 
  {
    MI_CHECK_HDF_CALL(result = H5Dread(dset_id, buffer_type_id, mspc_id, fspc_id, H5P_DEFAULT, buffer),"H5Dread");
    if(result<0)
    {
      goto cleanup;
    }
    
    if(scaling_needed)
    {
      switch(buffer_data_type)
      {
        case MI_TYPE_FLOAT:
#ifdef _DEBUG  
          printf("Descaling  float\n");
#endif
          APPLY_DESCALING(float,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_DOUBLE:
#ifdef _DEBUG  
          printf("Descaling  double\n");
#endif
          APPLY_DESCALING(double,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_INT:
#ifdef _DEBUG  
          printf("Descaling  int\n");
#endif
          APPLY_DESCALING(int,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_UINT:
#ifdef _DEBUG  
          printf("Descaling  uint\n");
#endif
          APPLY_DESCALING(unsigned int,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_SHORT:
#ifdef _DEBUG  
          printf("Descaling  short\n");
#endif
          APPLY_DESCALING(short,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_USHORT:
#ifdef _DEBUG  
          printf("Descaling  ushort\n");
#endif
          APPLY_DESCALING(unsigned short,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_BYTE:
#ifdef _DEBUG  
          printf("Descaling  byte\n");
#endif
          APPLY_DESCALING(char,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        case MI_TYPE_UBYTE:
#ifdef _DEBUG  
          printf("Descaling  ubyte\n");
#endif
          APPLY_DESCALING(unsigned char,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
          break;
        default:
          /*TODO: report unsupported conversion*/
          result=MI_ERROR;
          goto cleanup;
      } 
    } else {
#ifdef _DEBUG  
      printf("Descaling  not needed!\n");
#endif
    }
    
    if (n_different != 0 ) {
      for (i = 0; i < ndims; i++) {
        icount[i] = count[i];
      }
      restructure_array(ndims, buffer, icount, H5Tget_size(buffer_type_id),volume->dim_indices, dir);
      /*TODO: check if we managed to restructure the array*/
      result=0;
    }
  } else { /*opcode != MIRW_OP_READ*/

    volume->is_dirty = TRUE; /* Mark as modified. */
    
    if (n_different != 0 ) {
      /* Invert before calling */
      for (i = 0; i < ndims; i++) {
        icount[volume->dim_indices[i]] = count[i];
        idir[volume->dim_indices[i]] = dir[i];
        /* this one was correct the original way*/
        imap[volume->dim_indices[i]] = i;

      }
    }
    if(scaling_needed || n_different != 0) 
    {
      /*create temporary copy, to be destroyed*/
      temp_buffer=malloc(buffer_size);
      if(!temp_buffer)
      {
        MI_LOG_ERROR(MI2_MSG_OUTOFMEM,buffer_size);
        result=MI_ERROR; /*TODO: error code?*/
        goto cleanup;
      }
      memcpy(temp_buffer,buffer,buffer_size);

      if (n_different != 0 )
        restructure_array(ndims, temp_buffer, icount, H5Tget_size(buffer_type_id), imap, idir);

      if(scaling_needed)
      {
        switch(buffer_data_type)
        {
          case MI_TYPE_FLOAT:
#ifdef _DEBUG  
            printf("scaling  float\n");
#endif
            APPLY_SCALING(float,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_DOUBLE:
#ifdef _DEBUG  
            printf("scaling  double\n");
#endif
            APPLY_SCALING(double,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_INT:
#ifdef _DEBUG  
            printf("scaling  int\n");
#endif
            APPLY_SCALING(int,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_UINT:
#ifdef _DEBUG  
            printf("scaling  unsigned int\n");
#endif
            APPLY_SCALING(unsigned int,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_SHORT:
#ifdef _DEBUG  
            printf("scaling  short\n");
#endif
            APPLY_SCALING(short,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_USHORT:
#ifdef _DEBUG  
            printf("scaling  unsigned short\n");
#endif
            APPLY_SCALING(unsigned short,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_BYTE:
#ifdef _DEBUG
            printf("scaling  char\n");
#endif
            APPLY_SCALING(char,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          case MI_TYPE_UBYTE:
#ifdef _DEBUG
            printf("scaling  unsigned char\n");
#endif
            APPLY_SCALING(unsigned char,temp_buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max);
            break;
          default:
            /*TODO: report unsupported conversion*/
            result=MI_ERROR;
            goto cleanup;
        }
      }
      MI_CHECK_HDF_CALL(result = H5Dwrite(dset_id, buffer_type_id, mspc_id, fspc_id, H5P_DEFAULT, temp_buffer),"H5Dwrite");
    } else {
      MI_CHECK_HDF_CALL(result = H5Dwrite(dset_id, buffer_type_id, mspc_id, fspc_id, H5P_DEFAULT, buffer),"H5Dwrite");
    }
    
    if(result<0)
    {
      goto cleanup;
    }
  }
      
cleanup:

  if (buffer_type_id >= 0) {
    H5Tclose(buffer_type_id);
  }
  if (mspc_id >= 0) {
    H5Sclose(mspc_id);
  }
  if (fspc_id >= 0) {
    H5Sclose(fspc_id);
  }
  if ( dset_id >=0 ) {
    H5Dclose(dset_id);
  }
  
  if(temp_buffer!=NULL)
  {
    free(temp_buffer);
  }
  if(image_slice_min_buffer!=NULL)
  {
    free(image_slice_min_buffer);
  }
  if(image_slice_max_buffer!=NULL)
  {
    free(image_slice_max_buffer);
  }
  return (result);
}
예제 #4
0
파일: hyper.c 프로젝트: happyyang/ITK
/** Read/write a hyperslab of data, performing dimension remapping
 * and data rescaling as needed. Data in the range (min-max) will map to the appropriate full range of buffer_data_type
 */
static int mirw_hyperslab_normalized(int opcode,
                              mihandle_t volume,
                              mitype_t buffer_data_type,
                              const misize_t start[],
                              const misize_t count[],
                              double data_min,
                              double data_max,
                              void *buffer)
{
  hid_t dset_id = -1;
  hid_t mspc_id = -1;
  hid_t fspc_id = -1;
  hid_t volume_type_id = -1;
  hid_t buffer_type_id = -1;
  int result = MI_ERROR;
  hsize_t hdf_start[MI2_MAX_VAR_DIMS];
  hsize_t hdf_count[MI2_MAX_VAR_DIMS];
  int dir[MI2_MAX_VAR_DIMS];  /* Direction vector in file order */
  hsize_t ndims;
  int slice_ndims;
  int n_different = 0;
  double volume_valid_min, volume_valid_max;
  misize_t buffer_size;
  misize_t input_buffer_size;
  double *temp_buffer=NULL;
  size_t icount[MI2_MAX_VAR_DIMS];
  int idir[MI2_MAX_VAR_DIMS];
  int imap[MI2_MAX_VAR_DIMS];
  double *image_slice_max_buffer=NULL;
  double *image_slice_min_buffer=NULL;

  char path[MI2_MAX_PATH];
  
  hsize_t image_slice_start[MI2_MAX_VAR_DIMS];
  hsize_t image_slice_count[MI2_MAX_VAR_DIMS];
  hsize_t image_slice_length=0;
  hsize_t total_number_of_slices=0;
  hsize_t i;
  int j;


  /* Disallow write operations to anything but the highest resolution.
   */
  if (opcode == MIRW_OP_WRITE && volume->selected_resolution != 0) {
    /*TODO: report error that we are not dealing with the rihgt image here*/
    return (MI_ERROR);
  }
  
  sprintf(path, MI_ROOT_PATH "/image/%d/image", volume->selected_resolution);

  /* Open the dataset with the specified path
  */
  MI_CHECK_HDF_CALL(dset_id = H5Dopen1(volume->hdf_id, path),"H5Dopen1");
  if (dset_id < 0) {
    return (MI_ERROR);
  }

  MI_CHECK_HDF_CALL(fspc_id = H5Dget_space(dset_id),"H5Dget_space");
  if (fspc_id < 0) {
    /*TODO: report can't get dataset*/
    goto cleanup;
  }
  buffer_type_id = mitype_to_hdftype(buffer_data_type,TRUE);
  if(buffer_type_id<0)
  {
    goto cleanup;
  }
  
  MI_CHECK_HDF_CALL(volume_type_id = H5Tcopy ( H5T_NATIVE_DOUBLE ),"H5Tcopy");
  if(volume_type_id<0)
  {
    fprintf(stderr,"H5Tcopy: Fail %s:%d\n",__FILE__,__LINE__);
    goto cleanup;
  }
  
  ndims = volume->number_of_dims;
  
  if (ndims == 0) {
    /* A scalar volume is possible but extremely unlikely, not to
     * mention useless!
     */
    mspc_id = H5Screate(H5S_SCALAR);
  } else {

    n_different = mitranslate_hyperslab_origin(volume,start,count, hdf_start,hdf_count,dir);

    MI_CHECK_HDF_CALL(mspc_id = H5Screate_simple(ndims, hdf_count, NULL),"H5Screate_simple");
    
    if (mspc_id < 0) {
      goto cleanup;
    }
  }
  
  miget_hyperslab_size_hdf(volume_type_id,ndims,hdf_count,&buffer_size);
  miget_hyperslab_size_hdf(buffer_type_id,ndims,hdf_count,&input_buffer_size);

  MI_CHECK_HDF_CALL(result = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, hdf_start, NULL,
                               hdf_count, NULL),"H5Sselect_hyperslab");
  if (result < 0) {
    goto cleanup;
  }

  miget_volume_valid_range( volume, &volume_valid_max, &volume_valid_min);

#ifdef _DEBUG
  printf("mirw_hyperslab_normalized:Volume:%x valid_max:%f valid_min:%f scaling:%d\n",volume,volume_valid_max,volume_valid_min,volume->has_slice_scaling);
#endif  
  
  if(volume->has_slice_scaling && 
    !(volume->volume_type==MI_TYPE_FLOAT    || volume->volume_type==MI_TYPE_DOUBLE || 
      volume->volume_type==MI_TYPE_FCOMPLEX || volume->volume_type==MI_TYPE_DCOMPLEX) )
  {
    hid_t image_max_fspc_id;
    hid_t image_min_fspc_id;
    hid_t scaling_mspc_id;
    total_number_of_slices=1;
    image_slice_length=1;

    MI_CHECK_HDF_CALL(image_max_fspc_id=H5Dget_space(volume->imax_id),"H5Dget_space");
    MI_CHECK_HDF_CALL(image_min_fspc_id=H5Dget_space(volume->imin_id),"H5Dget_space");

    if ( image_max_fspc_id < 0 || image_min_fspc_id<0 ) {
      result=MI_ERROR;
      goto cleanup;
    }

    MI_CHECK_HDF_CALL(slice_ndims = H5Sget_simple_extent_ndims ( image_max_fspc_id ),"H5Sget_simple_extent_ndims");
    if(slice_ndims<0)
    {
      goto cleanup;
    }

    if ( (hsize_t)slice_ndims > ndims ) { /*Can this really happen?*/
      slice_ndims = ndims;
    }

    for ( j = 0; j < slice_ndims; j++ ) {
      image_slice_count[j] = hdf_count[j];
      image_slice_start[j] = hdf_start[j];
      
      if(hdf_count[j]>1) /*avoid zero sized dimensions?*/
        total_number_of_slices*=hdf_count[j];
    }
    
    for (i = slice_ndims; i < ndims; i++ ) {
      if(hdf_count[i]>1) /*avoid zero sized dimensions?*/
        image_slice_length*=hdf_count[i];
      
      image_slice_count[i] = 0;
      image_slice_start[i] = 0;
    }
    
    image_slice_max_buffer=malloc(total_number_of_slices*sizeof(double));
    image_slice_min_buffer=malloc(total_number_of_slices*sizeof(double));
    /*TODO check for allocation failure ?*/
    
    MI_CHECK_HDF_CALL(scaling_mspc_id = H5Screate_simple(slice_ndims, image_slice_count, NULL),"H5Screate_simple");
    
    if( (result=H5Sselect_hyperslab(image_max_fspc_id, H5S_SELECT_SET, image_slice_start, NULL, image_slice_count, NULL))>=0 )
    {
      if( ( result=H5Dread(volume->imax_id, H5T_NATIVE_DOUBLE, scaling_mspc_id, image_max_fspc_id, H5P_DEFAULT,image_slice_max_buffer))<0)
      {
        MI_LOG_ERROR(MI2_MSG_HDF5,"H5Dread");
        goto cleanup;
      }
    } else {
      MI_LOG_ERROR(MI2_MSG_HDF5,"H5Sselect_hyperslab");
      goto cleanup;
    }
    
    if( (result=H5Sselect_hyperslab(image_min_fspc_id, H5S_SELECT_SET, image_slice_start, NULL, image_slice_count, NULL))>=0 )
    {
      if( (result=H5Dread(volume->imin_id, H5T_NATIVE_DOUBLE, scaling_mspc_id, image_min_fspc_id, H5P_DEFAULT,image_slice_min_buffer))<0)
      {
        MI_LOG_ERROR(MI2_MSG_HDF5,"H5Dread");
        goto cleanup;
      }
    } else {
      MI_LOG_ERROR(MI2_MSG_HDF5,"H5Sselect_hyperslab");
      goto cleanup;
    }
    H5Sclose(scaling_mspc_id);
    H5Sclose(image_max_fspc_id);
    
  } else {
    slice_ndims=0;
    total_number_of_slices=1;
    image_slice_max_buffer=malloc(sizeof(double));
    image_slice_min_buffer=malloc(sizeof(double));
    miget_volume_range( volume,image_slice_max_buffer,image_slice_min_buffer );
    image_slice_length=1;
    for (i = 0; i < ndims; i++) {
      image_slice_length *= hdf_count[i];
    }
#ifdef _DEBUG
    printf("mirw_hyperslab_normalized:Real max:%f min:%f\n",*image_slice_max_buffer,*image_slice_min_buffer);
#endif
  }

#ifdef _DEBUG  
  printf("mirw_hyperslab_normalized:Slice_ndim:%d total_number_of_slices:%d image_slice_length:%d\n",slice_ndims,total_number_of_slices,image_slice_length);
  printf("mirw_hyperslab_normalized:data min:%f data max:%f buffer_data_type:%d\n",data_min,data_max,buffer_data_type);
#endif

  /*Allocate temporary Buffer*/
  temp_buffer=(double*)malloc(buffer_size);
  if(!temp_buffer)
  {
    MI_LOG_ERROR(MI2_MSG_OUTOFMEM,buffer_size);
    result=MI_ERROR;
    goto cleanup;
  }
  
  if (opcode == MIRW_OP_READ) 
  {
    MI_CHECK_HDF_CALL(result = H5Dread(dset_id, volume_type_id, mspc_id, fspc_id, H5P_DEFAULT, temp_buffer),"H5Dread");
    if(result<0)
    {
      goto cleanup;
    }
    
    /*WARNING: floating point types will be normalized between 0.0 and 1.0*/
    switch(buffer_data_type)
    {
      case MI_TYPE_FLOAT:
        APPLY_DESCALING_NORM(float,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,0.0f,1.0f);
        break;
      case MI_TYPE_DOUBLE:
        APPLY_DESCALING_NORM(double,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,0.0,1.0);
        break;
      case MI_TYPE_INT:
        APPLY_DESCALING_NORM(int,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,INT_MIN,INT_MAX);
        break;
      case MI_TYPE_UINT:
        APPLY_DESCALING_NORM(unsigned int,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,0,UINT_MAX);
        break;
      case MI_TYPE_SHORT:
        APPLY_DESCALING_NORM(short,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,SHRT_MIN,SHRT_MAX);
        break;
      case MI_TYPE_USHORT:
        APPLY_DESCALING_NORM(unsigned short,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,0,USHRT_MAX);
        break;
      case MI_TYPE_BYTE:
        APPLY_DESCALING_NORM(char,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,SCHAR_MIN,SCHAR_MAX);
        break;
      case MI_TYPE_UBYTE:
        APPLY_DESCALING_NORM(unsigned char,temp_buffer,buffer,image_slice_length,total_number_of_slices,image_slice_min_buffer,image_slice_max_buffer,volume_valid_min,volume_valid_max,data_min,data_max,0,UCHAR_MAX);
        break;
      default:
        /*TODO: report unsupported conversion*/
        result=MI_ERROR;
        goto cleanup;
    }
    
    if (n_different != 0 ) {
      for (i = 0; i < ndims; i++) {
         icount[i] = count[i];
      }
      restructure_array(ndims, buffer, icount, H5Tget_size(buffer_type_id),volume->dim_indices, dir);
      /*TODO: check if we managed to restructure the array*/
      result=0;
    }
  } else { /*opcode != MIRW_OP_READ*/
예제 #5
0
파일: hyper.c 프로젝트: happyyang/ITK
/** Read/write a hyperslab of data.  This is the simplified function
 * which performs no value conversion.  It is much more efficient than
 * mirw_hyperslab_icv()
 */
static int mirw_hyperslab_raw(int opcode,
                              mihandle_t volume,
                              mitype_t midatatype,
                              const misize_t start[],
                              const misize_t count[],
                              void *buffer)
{
  hid_t dset_id = -1;
  hid_t mspc_id = -1;
  hid_t fspc_id = -1;
  hid_t type_id = -1;
  int result = MI_ERROR;
  hsize_t hdf_start[MI2_MAX_VAR_DIMS];
  hsize_t hdf_count[MI2_MAX_VAR_DIMS];
  int dir[MI2_MAX_VAR_DIMS];  /* Direction vector in file order */
  int ndims;
  int n_different = 0;
  misize_t buffer_size;
  void *temp_buffer=NULL;
  char path[MI2_MAX_PATH];
  size_t icount[MI2_MAX_VAR_DIMS];

  /* Disallow write operations to anything but the highest resolution.
   */
  if (opcode == MIRW_OP_WRITE && volume->selected_resolution != 0) {
    return MI_LOG_ERROR(MI2_MSG_GENERIC,"Trying to write to a volume thumbnail");
  }

  sprintf(path, MI_ROOT_PATH "/image/%d/image", volume->selected_resolution);
  /*printf("Using:%s\n",path);*/
  
  /* Open the dataset with the specified path
  */
  MI_CHECK_HDF_CALL(dset_id = H5Dopen1(volume->hdf_id, path),"H5Dopen1");
  if (dset_id < 0) {
    return (MI_ERROR);
  }

  MI_CHECK_HDF_CALL(fspc_id = H5Dget_space(dset_id),"H5Dget_space");
  if (fspc_id < 0) {
    /*TODO: report can't get dataset*/
    goto cleanup;
  }

  MI_CHECK_HDF_CALL(fspc_id = H5Dget_space(dset_id),"H5Dget_space");
  if (fspc_id < 0) {
    goto cleanup;
  }

  if (midatatype == MI_TYPE_UNKNOWN) {
    type_id = H5Tcopy(volume->mtype_id);
  } else {
    type_id = mitype_to_hdftype(midatatype, TRUE);
  }

  ndims = volume->number_of_dims;

  if (ndims == 0) {
    /* A scalar volume is possible but extremely unlikely, not to
     * mention useless!
     */
    mspc_id = H5Screate(H5S_SCALAR);
  } else {

    n_different = mitranslate_hyperslab_origin(volume, start, count, hdf_start, hdf_count, dir);

    MI_CHECK_HDF_CALL(mspc_id = H5Screate_simple(ndims, hdf_count, NULL),"H5Screate_simple");
    if (mspc_id < 0) {
      goto cleanup;
    }
  }

  MI_CHECK_HDF_CALL(result = H5Sselect_hyperslab(fspc_id, H5S_SELECT_SET, hdf_start, NULL,
                               hdf_count, NULL),"H5Sselect_hyperslab");
  if (result < 0) {
    goto cleanup;
  }

  miget_hyperslab_size_hdf(type_id,ndims,hdf_count,&buffer_size);
  
  
  if (opcode == MIRW_OP_READ) {
    MI_CHECK_HDF_CALL(result = H5Dread(dset_id, type_id, mspc_id, fspc_id, H5P_DEFAULT,buffer),"H5Dread");
    
    /* Restructure the array after reading the data in file orientation.
     */
    if (n_different != 0) {
      int i;

      for (i = 0; i < ndims; i++) {
        icount[i] = count[i];
      }
      restructure_array(ndims, buffer, icount, H5Tget_size(type_id),
                        volume->dim_indices, dir);
    }
  } else {

    volume->is_dirty = TRUE; /* Mark as modified. */

    /* Restructure array before writing to file.
     * TODO: use temporary buffer for that!
     */

    if (n_different != 0) {
      int idir[MI2_MAX_VAR_DIMS];
      int imap[MI2_MAX_VAR_DIMS];
      int i;

      /* Invert before calling */
      for (i = 0; i < ndims; i++) {
        icount[volume->dim_indices[i]] = count[i];

        idir[volume->dim_indices[i]] = dir[i];

        // this one was correct the original way
        imap[volume->dim_indices[i]] = i;

      }

      /*Use temporary array to preserve input data*/
      temp_buffer=malloc(buffer_size);
      if(temp_buffer==NULL)
      {
        /*TODO: report memory error*/
        result=MI_ERROR;
        goto cleanup;
      }
      
      memcpy(temp_buffer,buffer,buffer_size);
      
      restructure_array(ndims, temp_buffer, icount, H5Tget_size(type_id),
                        imap, idir);
      MI_CHECK_HDF_CALL(result = H5Dwrite(dset_id, type_id, mspc_id, fspc_id, H5P_DEFAULT,
                      temp_buffer),"H5Dwrite");
    } else {
      MI_CHECK_HDF_CALL(result = H5Dwrite(dset_id, type_id, mspc_id, fspc_id, H5P_DEFAULT,
                        buffer),"H5Dwrite");
    }

  }

cleanup:

  if (type_id >= 0) {
    H5Tclose(type_id);
  }
  if (mspc_id >= 0) {
    H5Sclose(mspc_id);
  }
  if (fspc_id >= 0) {
    H5Sclose(fspc_id);
  }
  if ( dset_id >=0 ) {
    H5Dclose(dset_id);
  }
  if ( temp_buffer!= NULL) {
    free( temp_buffer );
  }
  return (result);
}