#! /usr/bin/env perl # # Andrew Janke - rotor@cmr.uq.edu.au # Center for Magnetic Resonance # The University of Queensland # http://www.cmr.uq.edu.au/~rotor # # Copyright Andrew Janke, The University of Queensland. # Permission to use, copy, modify, and distribute this software and its # documentation for any purpose and without fee is hereby granted, # provided that the above copyright notice appear in all copies. The # author and the University of Queensland make no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Script for dumping a miff file from a minc file to STDOUT. # # Thu Jun 1 17:46:19 EST 2000 - major rewrite to speed things # also added transverse/coronal/sagital # Fri Jun 2 19:05:59 EST 2000 - removed pnm code and now use convert # to get "right" size images # Wed Jun 21 20:45:33 EST 2000 - added correct flipping and floping of # output images as per the radiological # convention (-ve z dimension) # Mon Jul 3 12:39:50 EST 2000 - added multiple dimension output # Fri Sep 1 12:46:13 EST 2000 - added -axial option # Tue Nov 21 16:14:07 EST 2000 - added strict and multiple image type output # Thu Feb 22 15:52:27 EST 2001 - changed to mincextract for range stuff # Thu Nov 22 14:05:11 EST 2001 - added -depth 8 to convert args # Tue Dec 3 17:35:05 EST 2002 - added steves -lookup option (minclookup) # - major rewrite of the dimension ordering # the hard bit is done by mincreshape now # Thu Jan 23 17:05:41 EST 2003 - fixed bug with step directions # added -dimsize {z,y,z}space=-1 use strict; use warnings "all"; use Getopt::Tabular; use File::Basename; use File::Temp qw/ tempdir /; my($Help, $Usage, $me, @opt_table, $tmpdir, %opt); my(@args, $args, $infile, $outfile, %ordering, $CODE); # permutation 'matrix' for differing views %ordering = ( 'zspace' => ['yspace', 'xspace'], 'yspace' => ['zspace', 'xspace'], 'xspace' => ['zspace', 'yspace'], ); $me = &basename($0); $CODE = "GRAY"; %opt = ('verbose' => 0, 'clobber' => 0, 'slice' => undef, 'scale' => 2, 'bitdepth' => 8, 'range' => undef, 'image_range' => undef, 'lookup' => undef, 'dirs' => ['zspace'], ); $Help = < 1, CLEANUP => 1 ); # set up file names and do a few checks $infile = $ARGV[0]; $outfile = (defined($ARGV[1])) ? $ARGV[1] : 'MIFF:-'; die "$me: Couldn't find $infile\n\n" if (!-e $infile); if($outfile ne 'MIFF:-' && -e $outfile && !$opt{'clobber'}){ die "$me: $outfile exists, use -clobber to overwrite\n\n"; } if($opt{'bitdepth'} != 16 && $opt{'bitdepth'} != 8) { die "$me: Invalid bitdepth specified - $opt{'bitdepth'} instead of 8 or 16\n\n"; } my ($space, $n_slices, $convert_infile, @extract_args, @convert_args, $pipe_args, $dimorder); my ($img_x, $img_y, $img_step_x, $img_step_y, $img_length_x, $img_length_y, $dim_names); # foreach slicing direction foreach $space (@{$opt{'dirs'}}){ # Get the info we need $args = "mincinfo ". "-dimlength $space ". "-dimlength $ordering{$space}[0] ". "-dimlength $ordering{$space}[1] ". "-attvalue $ordering{$space}[0]:step ". "-attvalue $ordering{$space}[1]:step ". "-dimnames ". $infile; ($n_slices, $img_x, $img_y, $img_step_x, $img_step_y, $dim_names) = split("\n", `$args`); $img_length_x = abs(int($img_step_x * $img_x * $opt{'scale'})); $img_length_y = abs(int($img_step_y * $img_y * $opt{'scale'})); # figure out the slice to get if(!defined($opt{'slice'})){ $opt{'slice'} = int($n_slices/2); } if($opt{'slice'} >= $n_slices || $opt{'slice'} < 0){ die "Slice $opt{'slice'} out of range (0-" . ($n_slices-1) . ")\n\n"; } # check if we have a vector_dimension already if($dim_names =~ m/vector_dimension/){ $CODE = 'RGB'; } # do the reshaping $dimorder = join(',', $space, @{$ordering{$space}}); if($CODE eq 'RGB'){ $dimorder .= ',vector_dimension'; } @args = ('mincreshape', '-clobber', '-quiet', '-normalize', '+direction', '-dimsize', "$space=-1", '-dimsize', "$ordering{$space}[0]=-1", '-dimsize', "$ordering{$space}[1]=-1", '-dimorder', $dimorder, '-dimrange', "$space=$opt{'slice'},1", $infile, "$tmpdir/reshaped.mnc"); if(scalar(@{$opt{'range'}}) != 0){ push(@args, '-valid_range', @{$opt{'range'}}[0], @{$opt{'range'}}[1]); } if(scalar(@{$opt{'image_range'}}) != 0){ push(@args, '-image_range', @{$opt{'image_range'}}[0], @{$opt{'image_range'}}[1]); } &do_cmd(@args); # do the lookup if required $convert_infile = "$tmpdir/reshaped.mnc"; if($opt{'lookup'}){ if($CODE eq 'RGB'){ warn "$me: Input is vector-valued already. No colour lookup done.\n"; } else{ $convert_infile = "$tmpdir/lookup.mnc"; $CODE = 'RGB'; &do_cmd('minclookup', '-quiet', split(' ', $opt{'lookup'}), "$tmpdir/reshaped.mnc", $convert_infile); } } # set up mincextract command @extract_args = ('mincextract', $convert_infile, '-normalize', ($opt{'bitdepth'} == 16) ? ('-short', '-unsigned') : '-byte'); # set up convert arguments # a flip is 'normal' due to the difference between mnc and most image co-ordinates @convert_args = ('convert', '-depth', $opt{'bitdepth'}, '-flip', '-size', $img_y . 'x' . $img_x, '-geometry', $img_length_y . 'x' . $img_length_x . '!', "$CODE:-", $outfile); # check if we are big or little endian for convert's MSB wierdity $pipe_args = '|'; if($opt{'bitdepth'} == 16){ if(unpack("c",substr(pack("s",1),0,1))){ warn "$me: LSB machine, swapping bytes with dd and crossing fingers\n"; $pipe_args .= ' dd conv=swab | '; } } &do_cmd(join(' ', @extract_args, $pipe_args, @convert_args)); } sub do_cmd { print STDERR "@_\n" if $opt{'verbose'}; system(@_) == 0 or die; }