19
19
#endif
20
20
21
21
#include <display.h>
22
+ #include <multidim_x.h>
22
23
23
24
static void set_slice_labels (
24
25
display_struct * display ,
@@ -399,7 +400,44 @@ DEF_MENU_UPDATE(load_label_data )
399
400
return ( get_n_volumes (display ) > 0 );
400
401
}
401
402
402
- /* ARGSUSED */
403
+ /**
404
+ * \brief Scan a volume and set the real and voxel ranges to their
405
+ * true values.
406
+ *
407
+ * Normally the label volume is set to have the a voxel minimum of
408
+ * zero, and a voxel maximum of the currently set largest permitted
409
+ * label value (255 by default). However, when saving the volume, this
410
+ * is awkward or even incorrect because label volumes might have only
411
+ * a few label values set, or in the extreme case of a mask volume,
412
+ * might just have two possible values.
413
+ *
414
+ * To work around this, we save the original settings for the ranges, then
415
+ * scan the volume to determine the "true" minimum and maximum. We then
416
+ * temporarily set the voxel and real ranges to the true scanned values.
417
+ * We will restore it to normal after the save completes.
418
+ *
419
+ * \param label_volume The label volume to scan.
420
+ * \param real_range Will receive the current real range of the volume.
421
+ * \param voxel_range Will receive the current voxel range of the volume.
422
+ */
423
+
424
+ static void
425
+ temporarily_fix_range ( VIO_Volume label_volume ,
426
+ VIO_Real real_range [],
427
+ VIO_Real voxel_range [] )
428
+ {
429
+ VIO_Real voxel_min ;
430
+ VIO_Real voxel_max ;
431
+
432
+ get_volume_real_range ( label_volume , & real_range [0 ], & real_range [1 ] );
433
+ get_volume_voxel_range ( label_volume , & voxel_range [0 ], & voxel_range [1 ] );
434
+
435
+ multidim_scan_range ( & label_volume -> array , & voxel_min , & voxel_max );
436
+
437
+ /* Temporarily reconfigure the volume for saving. */
438
+ set_volume_voxel_range ( label_volume , voxel_min , voxel_max );
439
+ set_volume_real_range ( label_volume , voxel_min , voxel_max );
440
+ }
403
441
404
442
/**
405
443
* Menu command to save labels to a volumetric (e.g. MINC) file.
@@ -410,6 +448,9 @@ DEF_MENU_FUNCTION(save_label_data)
410
448
VIO_STR filename , backup_filename ;
411
449
display_struct * slice_window ;
412
450
VIO_Real crop_threshold ;
451
+ VIO_Real old_real_range [2 ];
452
+ VIO_Real old_voxel_range [2 ];
453
+ VIO_Volume label_volume ;
413
454
414
455
status = VIO_OK ;
415
456
@@ -442,6 +483,10 @@ DEF_MENU_FUNCTION(save_label_data)
442
483
else
443
484
crop_threshold = Crop_label_volumes_threshold ;
444
485
486
+ label_volume = get_label_volume ( slice_window );
487
+
488
+ temporarily_fix_range ( label_volume , old_real_range , old_voxel_range );
489
+
445
490
status = make_backup_file ( filename , & backup_filename );
446
491
if ( status == VIO_OK )
447
492
{
@@ -458,16 +503,25 @@ DEF_MENU_FUNCTION(save_label_data)
458
503
459
504
status = save_label_volume ( filename ,
460
505
backup_filename ,
461
- get_label_volume ( slice_window ) ,
506
+ label_volume ,
462
507
crop_threshold );
463
508
if ( made_backup )
464
509
{
465
510
/* We made a backup, so clean it up now.
466
511
*/
467
512
cleanup_backup_file ( filename , backup_filename , status );
513
+
514
+ delete_string ( backup_filename );
468
515
}
469
516
}
470
517
518
+ /* Restore the original voxel and real ranges.
519
+ */
520
+ set_volume_voxel_range ( label_volume ,
521
+ old_voxel_range [0 ], old_voxel_range [1 ] );
522
+ set_volume_real_range ( label_volume ,
523
+ old_real_range [0 ], old_real_range [1 ] );
524
+
471
525
if ( status == VIO_OK )
472
526
print ( "Label saved to %s\n" , filename );
473
527
else
@@ -908,9 +962,9 @@ typedef struct
908
962
int volume_index ;
909
963
} callback_data ;
910
964
911
- /**
965
+ /**
912
966
* This callback is used to actually set the label voxel during 3D dilation
913
- * and fill operations. It therefore has to have the standard parameter
967
+ * and fill operations. It therefore has to have the standard parameter
914
968
* types.
915
969
* \param volume The label volume to modify.
916
970
* \param x The X voxel coordinate to set.
@@ -948,7 +1002,7 @@ do_fill_connected_3d( display_struct *display, VIO_BOOL is_erase )
948
1002
int label_under_mouse , desired_label , volume_index ;
949
1003
display_struct * slice_window ;
950
1004
callback_data data ;
951
-
1005
+
952
1006
if ( get_slice_window ( display , & slice_window ) &&
953
1007
get_voxel_under_mouse ( slice_window , & volume_index , & view_index , voxel ))
954
1008
{
@@ -970,7 +1024,7 @@ do_fill_connected_3d( display_struct *display, VIO_BOOL is_erase )
970
1024
971
1025
data .slice_window = slice_window ;
972
1026
data .volume_index = volume_index ;
973
-
1027
+
974
1028
fill_connected_voxels_callback ( get_nth_volume (slice_window ,volume_index ),
975
1029
get_nth_label_volume (slice_window ,volume_index ),
976
1030
slice_window -> slice .segmenting .connectivity ,
@@ -1063,10 +1117,10 @@ dilation_or_erosion_command(display_struct *display, VIO_BOOL do_erosion )
1063
1117
min_outside_label = min_user_label ;
1064
1118
max_outside_label = max_user_label ;
1065
1119
}
1066
-
1120
+
1067
1121
data .slice_window = slice_window ;
1068
1122
data .volume_index = volume_index ;
1069
-
1123
+
1070
1124
undo_start ( slice_window , volume_index );
1071
1125
dilate_voxels_callback ( get_volume ( display ),
1072
1126
get_label_volume ( display ),
0 commit comments