/** \file volprops.c * \brief MINC 2.0 Volume properties functions * \author Leila Baghdadi * * These functions manipulate "volume properties" objects, which are * used to control several options related to MINC 2.0 volume structure. * These include compression, blocking, multi-resolution, and record s * structure. * * This approach was adopted with the intent that it would make the * default volume creation as simple as possible, while allowing a * lot of control for more advanced applications. This approach to * managing properties is also believed to be more readily extensible than * any obvious alternative. ************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif /*HAVE_CONFIG_H*/ #define _GNU_SOURCE 1 #include #include #include "minc2.h" #include "minc2_private.h" #include "minc_config.h" /** * \defgroup mi2VPrp MINC 2.0 Volume Properties Functions */ /** Maximum number of elements in a filter parameter list. */ #define MI2_MAX_CD_ELEMENTS 100 /** Create a volume property list. The new list will be returned in the * \a props parameter. When the program is finished * using the property list it should call mifree_volume_props() to free the * memory associated with the list. * \param props A pointer to the returned volume properties handle. * \ingroup mi2VPrp */ int minew_volume_props(mivolumeprops_t *props) { mivolumeprops_t handle; handle = (mivolumeprops_t)malloc(sizeof(struct mivolprops)); if (handle == NULL) { return (MI_ERROR); } /* Initialize all the fields. */ handle->enable_flag = FALSE; handle->depth = 0; handle->compression_type = MI_COMPRESS_NONE; handle->zlib_level = 0; handle->edge_count = 0; handle->edge_lengths = NULL; handle->max_lengths = 0; handle->record_length = 0; handle->record_name = NULL; handle->template_flag = 0; handle->checksum = miget_cfg_bool(MICFG_MINC_CHECKSUM); *props = handle; return (MI_NOERROR); } /** Destroy a volume property list. * \param props The volume property list to delete. * \ingroup mi2VPrp */ int mifree_volume_props(mivolumeprops_t props) { if (props == NULL) { return (MI_ERROR); } if (props->edge_lengths != NULL) { free(props->edge_lengths); } if (props->record_name != NULL) { free(props->record_name); } free(props); return (MI_NOERROR); } /*! Get a copy of the volume property list. When the program is finished * using the property list it should call mifree_volume_props() to free the * memory associated with the list. * \param volume A volume handle * \param props A pointer to the returned volume properties handle. * \ingroup mi2VPrp */ int miget_volume_props(mihandle_t volume, mivolumeprops_t *props) { mivolumeprops_t handle; hid_t hdf_vol_dataset; hid_t hdf_plist; int nfilters; unsigned int flags; size_t cd_nelmts; unsigned int cd_values[MI2_MAX_CD_ELEMENTS]; char fname[MI2_CHAR_LENGTH]; int fcode; if (volume->hdf_id < 0) { return (MI_ERROR); } hdf_vol_dataset = midescend_path(volume->hdf_id, "/minc-2.0/image/0/image"); if (hdf_vol_dataset < 0) { return (MI_ERROR); } hdf_plist = H5Dget_create_plist(hdf_vol_dataset); if (hdf_plist < 0) { return (MI_ERROR); } handle = (mivolumeprops_t)malloc(sizeof(struct mivolprops)); if (handle == NULL) { return (MI_ERROR); } /* Get the layout of the raw data for a dataset. */ if (H5Pget_layout(hdf_plist) == H5D_CHUNKED) { hsize_t dims[MI2_MAX_VAR_DIMS]; int i; /* Returns chunk dimensionality */ handle->edge_count = H5Pget_chunk(hdf_plist, MI2_MAX_VAR_DIMS, dims); if (handle->edge_count < 0) { free(handle); return (MI_ERROR); } handle->edge_lengths = (int *)malloc(handle->edge_count*sizeof(int)); if (handle->edge_lengths == NULL) { free(handle); return (MI_ERROR); } for (i = 0; i < handle->edge_count; i++) { handle->edge_lengths[i] = dims[i]; } /* Get the number of filters in the pipeline */ nfilters = H5Pget_nfilters(hdf_plist); if (nfilters == 0) { handle->zlib_level = 0; handle->compression_type = MI_COMPRESS_NONE; handle->checksum = 0; } else { for (i = 0; i < nfilters; i++) { cd_nelmts = MI2_MAX_CD_ELEMENTS; fcode = H5Pget_filter1(hdf_plist, i, &flags, &cd_nelmts, cd_values, sizeof(fname), fname); switch (fcode) { case H5Z_FILTER_DEFLATE: handle->compression_type = MI_COMPRESS_ZLIB; handle->zlib_level = cd_values[0]; break; case H5Z_FILTER_SHUFFLE: break; case H5Z_FILTER_FLETCHER32: handle->checksum=1; break; case H5Z_FILTER_SZIP: break; default: break; } } } } else { handle->edge_count = 0; handle->edge_lengths = NULL; handle->zlib_level = 0; handle->compression_type = MI_COMPRESS_NONE; handle->checksum = 0; } *props = handle; H5Pclose(hdf_plist); H5Dclose(hdf_vol_dataset); return (MI_NOERROR); } /** Set multi-resolution properties. The \a enable_flag determines * whether or not thumbnail images will be calculated at all. The \a * depth parameter determines the lowest-resolution image that will be * available. The full resolution image is considered to be image #0, * the half resolution image is image #1, the quarter-resolution image * is #2, etc. Therefore a \a depth value of 2 implies both the half * and quarter resolution thumbnails will be calculated and stored in * the file. * \param props A volume property list handle * \param enable_flag TRUE if multiresolution support should be enabled in * this file. * \param depth The maximum depth of multiresolution data * to support. * \ingroup mi2VPrp */ int miset_props_multi_resolution(mivolumeprops_t props, miboolean_t enable_flag, int depth) { if (props == NULL || depth > MI2_MAX_RESOLUTION_GROUP || depth <= 0) { return (MI_ERROR); } props->enable_flag = enable_flag; props->depth = depth; return (MI_NOERROR); } /** Get multi-resolution properties. Returns the value of the \a enable_flag * and \a depth parameters. * \param props A volume property list handle * \param enable_flag Pointer to a boolean which will be set to TRUE if * multiresolution has been enabled. * \param depth Pointer to a integer which will contain the maximum resolution * depth enabled if multiresolution is enabled. * \ingroup mi2VPrp */ int miget_props_multi_resolution(mivolumeprops_t props, miboolean_t *enable_flag, int *depth) { if (props == NULL || enable_flag == NULL || depth == NULL) { return (MI_ERROR); } *enable_flag = props->enable_flag; *depth = props->depth; return (MI_NOERROR); } /** Select a different resolution from a multi-resolution image. * \ingroup mi2VPrp */ int miselect_resolution(mihandle_t volume, int depth) { hid_t grp_id; char path[MI2_MAX_PATH]; if ( volume->hdf_id < 0 || depth > MI2_MAX_RESOLUTION_GROUP || depth < 0) { return (MI_ERROR); } grp_id = H5Gopen1(volume->hdf_id, MI_ROOT_PATH "/image"); if (grp_id < 0) { return (MI_ERROR); } /* Check given depth with the available depth in file. Make sure the selected resolution does exist. */ if (depth > volume->create_props->depth) { return (MI_ERROR); } else if (depth != 0) { if (minc_update_thumbnail(volume, grp_id, 0, depth) < 0) { return (MI_ERROR); } } volume->selected_resolution = depth; if (volume->image_id >= 0) { H5Dclose(volume->image_id); } snprintf(path, sizeof(path), "%d/image", depth); volume->image_id = H5Dopen1(grp_id, path); if (volume->volume_class == MI_CLASS_REAL) { if (volume->imax_id >= 0) { H5Dclose(volume->imax_id); } snprintf(path, sizeof(path), "%d/image-max", depth); volume->imax_id = H5Dopen1(grp_id, path); if (volume->imin_id >= 0) { H5Dclose(volume->imin_id); } snprintf(path, sizeof(path), "%d/image-min", depth); volume->imin_id = H5Dopen1(grp_id, path); } return (MI_NOERROR); } /** Compute or recompute all resolution groups. * * \ingroup mi2VPrp */ int miflush_from_resolution(mihandle_t volume, int depth) { if ( volume->hdf_id < 0 || depth > MI2_MAX_RESOLUTION_GROUP || depth <= 0) { return (MI_ERROR); } if (depth > volume->create_props->depth) { return (MI_ERROR); } else { if (minc_update_thumbnails(volume) < 0) { return (MI_ERROR); } volume->is_dirty = FALSE; } return (MI_NOERROR); } /** Set compression type for a volume property list * Note that enabling compression will automatically * enable blocking with default parameters. * \param props A volume properties list * \param compression_type The type of compression to use (MI_COMPRESS_NONE * or MI_COMPRESS_ZLIB) * \ingroup mi2VPrp */ int miset_props_compression_type(mivolumeprops_t props, micompression_t compression_type) { /* int i; int edge_lengths[MI2_MAX_VAR_DIMS]; */ if (props == NULL) { return (MI_ERROR); } switch (compression_type) { case MI_COMPRESS_NONE: props->compression_type = MI_COMPRESS_NONE; break; case MI_COMPRESS_ZLIB: props->compression_type = MI_COMPRESS_ZLIB; props->zlib_level = MI2_DEFAULT_ZLIB_LEVEL; /* * VF: this will be set on volume creation, when dimensions are known! * for (i = 0; i < MI2_MAX_VAR_DIMS; i++) { edge_lengths[i] = MI2_CHUNK_SIZE ; } miset_props_blocking(props, MI2_MAX_VAR_DIMS, edge_lengths); */ break; default: return (MI_ERROR); } return (MI_NOERROR); } /** Get compression type for a volume property list * \param props A volume property list handle * \param compression_type A pointer to a variable to which the current * compression type will be assigned. * \ingroup mi2VPrp */ int miget_props_compression_type(mivolumeprops_t props, micompression_t *compression_type) { if (props == NULL) { return (MI_ERROR); } *compression_type = props->compression_type; return (MI_NOERROR); } /** Set zlib compression properties for a volume list. The \a zlib_level * parameter may range from 1 to 9, where higher numbers request that the * library attempt to use more memory (and possibly processing power) to * achieve the highest possible compression ratio. * * \param props A volume property list handle * \param zlib_level An integer specifying the desired compression level. * \ingroup mi2VPrp */ int miset_props_zlib_compression(mivolumeprops_t props, int zlib_level) { if (props == NULL || zlib_level > MI2_MAX_ZLIB_LEVEL) { return (MI_ERROR); } props->zlib_level = zlib_level; return (MI_NOERROR); } /** Get zlib compression properties from a volume property list. * \param props A volume property list handle * \param zlib_level Pointer to an integer variable that will receive the * current compression level. * \ingroup mi2VPrp */ int miget_props_zlib_compression(mivolumeprops_t props, int *zlib_level) { if (props == NULL) { return (MI_ERROR); } *zlib_level = props->zlib_level; return (MI_NOERROR); } /** Set blocking structure properties for the volume * \param props A volume property list handle * \param edge_count * \param edge_lengths * \ingroup mi2VPrp */ int miset_props_blocking(mivolumeprops_t props, int edge_count, const int *edge_lengths) { int i; if (props == NULL || edge_count > MI2_MAX_VAR_DIMS) { return (MI_ERROR); } if (props->edge_lengths != NULL) { free(props->edge_lengths); props->edge_lengths = NULL; } props->edge_count = edge_count; if (edge_count != 0) { props->edge_lengths = (int *) malloc(edge_count*sizeof(int)); if (props->edge_lengths == NULL) { return (MI_ERROR); } for (i=0; i< edge_count; i++){ props->edge_lengths[i] = edge_lengths[i]; } } return (MI_NOERROR); } /** Get blocking structure properties for the volume * \param props The properties structure from which to get the information * \param edge_count Returns the number of edges (dimensions) in a block * \param edge_lengths The lengths of the edges * \param max_lengths The number of elements of the edge_lengths array * \ingroup mi2VPrp */ int miget_props_blocking(mivolumeprops_t props, int *edge_count, int *edge_lengths, int max_lengths) { int i; if (props == NULL) { return (MI_ERROR); } *edge_count = props->edge_count; /* If max_lengths is greater than the actual edge count, reduce max_lengths * to the edge_count */ if (max_lengths > props->edge_count) { max_lengths = props->edge_count; } /*edge_lengths = (int *) malloc(max_lengths *sizeof(int));*/ for (i=0; i< max_lengths; i++){ edge_lengths[i] = props->edge_lengths[i]; } return (MI_NOERROR); } /** Set properties for uniform/nonuniform record dimension * \ingroup mi2VPrp */ int miset_props_record(mivolumeprops_t props, misize_t record_length, char *record_name) { if (props == NULL) { return (MI_ERROR); } if (record_length > 0) { props->record_length = record_length; } if (props->record_name != NULL) { free(props->record_name); props->record_name = NULL; } props->record_name = strdup(record_name); return (MI_NOERROR); } /** Set the template volume flag * \ingroup mi2VPrp */ int miset_props_template(mivolumeprops_t props, int template_flag) { if (props == NULL) { return (MI_ERROR); } props->template_flag = template_flag; return (MI_NOERROR); } int miset_props_checksum(mivolumeprops_t props, int on) { if (props == NULL) { return (MI_ERROR); } props->checksum=on; return (MI_NOERROR); } int miget_props_checksum(mivolumeprops_t props,int *on) { if (props == NULL) { return (MI_ERROR); } *on=props->checksum; return (MI_NOERROR); } // kate: indent-mode cstyle; indent-width 2; replace-tabs on;