/* * Set the volume level for the left and right channels. Their values * range from 0 to 100. */ int gen_set_volume(struct wm_drive *d, int left, int right) { struct ioc_vol vol; if (left < 0) /* don't laugh, I saw this happen once! */ left = 0; if (right < 0) right = 0; left = scale_volume(left, 100); right = scale_volume(right, 100); bzero((char *)&vol, sizeof(vol)); vol.vol[LEFT_PORT] = left; vol.vol[RIGHT_PORT] = right; if (ioctl(d->fd, CDIOCSETVOL, &vol)) return (-1); return (0); } /* gen_set_volume() */
/* * unscale_volume(cd_vol, max) * * Given a value between min_volume and max_volume, return the volume slider * value needed to achieve that value. * * Rather than perform floating-point calculations to reverse the above * formula, we simply do a binary search of scale_volume()'s return values. */ static int unscale_volume(int cd_vol, int max) { int vol = 0, top = max, bot = 0, scaled; while (bot <= top) { vol = (top + bot) / 2; scaled = scale_volume(vol, max); if (cd_vol == scaled) break; if (cd_vol < scaled) top = vol - 1; else bot = vol + 1; } if (vol < 0) vol = 0; else if (vol > max) vol = max; return (vol); } /* unscale_volume() */
int main(int argc, char *argv[]) { char **infiles; int n_infiles; char *out_fn; char *history; VIO_progress_struct progress; VIO_Volume totals, weights; int i, j, k, v; double min, max; double w_min, w_max; long num_missed; double weight, value; double initial_weight; VIO_Real dummy[3]; int sizes[MAX_VAR_DIMS]; double starts[MAX_VAR_DIMS]; double steps[MAX_VAR_DIMS]; long t = 0; /* start the time counter */ current_realtime_seconds(); /* get the history string */ history = time_stamp(argc, argv); /* get args */ if(ParseArgv(&argc, argv, argTable, 0) || (argc < 3)){ fprintf(stderr, "\nUsage: %s [options] <in1.mnc> [<in2.mnc> [...]] <out.mnc>\n", argv[0]); fprintf(stderr, " %s [options] -arb_path pth.conf <infile.raw> <out.mnc>\n", argv[0]); fprintf(stderr, " %s -help\n\n", argv[0]); exit(EXIT_FAILURE); } /* get file names */ n_infiles = argc - 2; infiles = (char **)malloc(sizeof(char *) * n_infiles); for(i = 0; i < n_infiles; i++){ infiles[i] = argv[i + 1]; } out_fn = argv[argc - 1]; /* check for infiles and outfile */ for(i = 0; i < n_infiles; i++){ if(!file_exists(infiles[i])){ fprintf(stderr, "%s: Couldn't find input file %s.\n\n", argv[0], infiles[i]); exit(EXIT_FAILURE); } } if(!clobber && file_exists(out_fn)){ fprintf(stderr, "%s: %s exists, -clobber to overwrite.\n\n", argv[0], out_fn); exit(EXIT_FAILURE); } /* check for weights_fn if required */ if(weights_fn != NULL){ if(!clobber && file_exists(weights_fn)){ fprintf(stderr, "%s: %s exists, -clobber to overwrite.\n\n", argv[0], weights_fn); exit(EXIT_FAILURE); } } /* set up parameters for reconstruction */ if(out_dtype == NC_UNSPECIFIED){ out_dtype = in_dtype; } if(out_is_signed == DEF_BOOL){ out_is_signed = in_is_signed; } /* check vector dimension size */ if(vect_size < 1){ fprintf(stderr, "%s: -vector (%d) must be 1 or greater.\n\n", argv[0], vect_size); exit(EXIT_FAILURE); } /* check sigma */ if(regrid_sigma[0] <= 0 || regrid_sigma[1] <= 0 || regrid_sigma[2] <= 0 ){ fprintf(stderr, "%s: -sigma must be greater than 0\n\n", argv[0]); exit(EXIT_FAILURE); } /* read in the output file config from a file is specified */ if(out_config_fn != NULL){ int ext_args_c; char *ext_args[32]; /* max possible is 32 arguments */ ext_args_c = read_config_file(out_config_fn, ext_args); if(ParseArgv(&ext_args_c, ext_args, argTable, ARGV_DONT_SKIP_FIRST_ARG | ARGV_NO_LEFTOVERS | ARGV_NO_DEFAULTS)){ fprintf(stderr, "\nError in parameters in %s\n", out_config_fn); exit(EXIT_FAILURE); } } if(verbose){ fprintf_vol_def(stdout, &out_inf); } /* transpose the geometry arrays */ /* out_inf.*[] are in world xyz order, perm[] is the permutation array to map world xyz to the right voxel order in the volume */ for(i = 0; i < WORLD_NDIMS; i++){ sizes[i] = out_inf.nelem[perm[i]]; /* sizes, starts, steps are in voxel volume order. */ starts[i] = out_inf.start[perm[i]]; steps[i] = out_inf.step[perm[i]]; } sizes[WORLD_NDIMS] = vect_size; /* create the totals volume */ totals = create_volume((vect_size > 1) ? 4 : 3, (vect_size > 1) ? std_dimorder_v : std_dimorder, out_dtype, out_is_signed, 0.0, 0.0); set_volume_sizes(totals, sizes); set_volume_starts(totals, starts); set_volume_separations(totals, steps); for(i = 0; i < WORLD_NDIMS; i++){ /* out_inf.dircos is in world x,y,z order, we have to use the perm array to map each direction to the right voxel axis. */ set_volume_direction_cosine(totals, i, out_inf.dircos[perm[i]]); } alloc_volume_data(totals); /* create the "weights" volume */ weights = create_volume(3, std_dimorder, out_dtype, out_is_signed, 0.0, 0.0); set_volume_sizes(weights, sizes); set_volume_starts(weights, starts); set_volume_separations(weights, steps); for(i = 0; i < WORLD_NDIMS; i++){ set_volume_direction_cosine(weights, i, out_inf.dircos[perm[i]]); } alloc_volume_data(weights); /* down below in regrid_loop, Andrew makes a nasty direct reference to the voxel_to_world transformation in the volume. This transformation is not necessarily up to date, particularly when non-default direction cosines are used. In volume_io, the direction cosines are set and a FLAG is also set to indicate that the voxel-to-world xform is not up to date. If the stanrd volume_io general transform code is used, it checks internally to see if the matrix is up to date, and if not it is recomputed. So here, we'll (LC + MK) force an update by calling a general transform. */ // convert_world_to_voxel(weights, (Real) 0, (Real) 0, (Real) 0, dummy); // convert_world_to_voxel(totals, (Real) 0, (Real) 0, (Real) 0, dummy); fprintf(stderr, "2Sizes: [%d:%d:%d] \n", sizes[perm[0]], sizes[perm[1]], sizes[perm[2]]); /* initialize weights to be arbitray large value if using NEAREST */ /* volume interpolation else initialize all to zero */ if(regrid_type == NEAREST_FUNC && ap_coord_fn == NULL){ initial_weight = LARGE_INITIAL_WEIGHT; } else{ initial_weight = 0.0; } /* initialize weights and totals */ for(k = sizes[Z_IDX]; k--;){ for(j = sizes[Y_IDX]; j--;){ for(i = sizes[X_IDX]; i--;){ set_volume_real_value(weights, k, j, i, 0, 0, initial_weight); for(v = vect_size; v--;){ set_volume_real_value(totals, k, j, i, v, 0, 0.0); } } } } /* if regridding via an arbitrary path */ if(ap_coord_fn != NULL){ if(n_infiles > 1){ fprintf(stderr, "%s: arb_path only works for one input file (so far).\n\n", argv[0]); exit(EXIT_FAILURE); } /* print some pretty output */ if(verbose){ fprintf(stdout, " | Input data: %s\n", infiles[0]); fprintf(stdout, " | Arb path: %s\n", ap_coord_fn); fprintf(stdout, " | Output range: [%g:%g]\n", out_range[0], out_range[1]); fprintf(stdout, " | Output file: %s\n", out_fn); } regrid_arb_path(ap_coord_fn, infiles[0], max_buffer_size_in_kb, &totals, &weights, vect_size, regrid_range[0], regrid_range[1]); } /* else if regridding via a series of input minc file(s) */ else { for(i = 0; i < n_infiles; i++){ if(verbose){ fprintf(stdout, " | Input file: %s\n", infiles[i]); } regrid_minc(infiles[i], max_buffer_size_in_kb, &totals, &weights, vect_size, regrid_range[0], regrid_range[1]); } } /* initialise min and max counters and divide totals/weights */ num_missed = 0; min = get_volume_real_value(totals, 0, 0, 0, 0, 0); max = get_volume_real_value(totals, 0, 0, 0, 0, 0); w_min = get_volume_real_value(weights, 0, 0, 0, 0, 0); w_max = get_volume_real_value(weights, 0, 0, 0, 0, 0); initialize_progress_report(&progress, FALSE, out_inf.nelem[Z_IDX], "Dividing through"); for(i = sizes[perm[0]]; i--;){ for(j = sizes[perm[1]]; j--;){ for(k = sizes[perm[2]]; k--;){ weight = get_volume_real_value(weights, k, j, i, 0, 0); if(weight < w_min){ w_min = weight; } else if(weight > w_max){ w_max = weight; } if(weight != 0){ for(v = vect_size; v--;){ value = get_volume_real_value(totals, k, j, i, v, 0) / weight; if(value < min){ min = value; } else if(value > max){ max = value; } set_volume_real_value(totals, k, j, i, v, 0, value); } } else { num_missed++; } } } update_progress_report(&progress, k + 1); } terminate_progress_report(&progress); /* set the volumes range */ if(verbose){ fprintf(stdout, " + data range: [%g:%g]\n", min, max); fprintf(stdout, " + weight range: [%g:%g]\n", w_min, w_max); } set_volume_real_range(totals, min, max); set_volume_real_range(weights, w_min, w_max); if(num_missed > 0 && verbose){ int nvox; nvox = out_inf.nelem[X_IDX] * out_inf.nelem[Y_IDX] * out_inf.nelem[Z_IDX]; fprintf(stdout, "\n-regrid_radius possibly too small, no data in %ld/%d[%2.2f%%] voxels\n\n", num_missed, nvox, ((float)num_missed / nvox * 100)); } /* rescale data if required */ if(out_range[0] != -DBL_MAX && out_range[1] != DBL_MAX){ double o_min, o_max; /* get the existing range */ get_volume_real_range(totals, &o_min, &o_max); /* rescale it */ scale_volume(&totals, o_min, o_max, out_range[0], out_range[1]); } /* output the result */ if(verbose){ fprintf(stdout, " | Outputting %s...\n", out_fn); } if(output_volume(out_fn, out_dtype, out_is_signed, 0.0, 0.0, totals, history, NULL) != VIO_OK){ fprintf(stderr, "Problems outputing: %s\n\n", out_fn); } /* output weights volume if required */ if(weights_fn != NULL){ if(verbose){ fprintf(stdout, " | Outputting %s...\n", weights_fn); } if(output_volume(weights_fn, out_dtype, out_is_signed, 0.0, 0.0, weights, history, NULL) != VIO_OK){ fprintf(stderr, "Problems outputting: %s\n\n", weights_fn); } } delete_volume(totals); delete_volume(weights); t = current_realtime_seconds(); printf("Total reconstruction time: %ld hours %ld minutes %ld seconds\n", t/3600, (t/60)%60, t%60); return (EXIT_SUCCESS); }