File: volprops.c

package info (click to toggle)
minc 2.1.10-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 8,160 kB
  • sloc: ansic: 82,507; sh: 10,666; yacc: 1,187; perl: 612; makefile: 586; lex: 319
file content (501 lines) | stat: -rw-r--r-- 13,433 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
/** \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.
 ************************************************************************/
#define _GNU_SOURCE 1
#include <stdlib.h>
#include <hdf5.h>
#include "minc2.h"
#include "minc2_private.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;

  *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) {
	return (MI_ERROR);
      }
      handle->edge_lengths = (int *)malloc(handle->edge_count*sizeof(int));
      if (handle->edge_lengths == NULL) {
	  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;
      }
      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:
	    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;
  }
  
  *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, "/minc-2.0/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);
  }
  sprintf(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);
      }
      sprintf(path, "%d/image-max", depth);
      volume->imax_id = H5Dopen1(grp_id, path);

      if (volume->imin_id >= 0) {
          H5Dclose(volume->imin_id);
      }
      sprintf(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;
   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, long 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);
}