amiraReader.m 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. function data = amiraReader(varargin)
  2. % this m-file skips the header of amira files to give you the straight data
  3. %
  4. % USEAGE: either type in what you want (valuable for scripting or calling from another program)
  5. % > data = amiraReader('C:\Data\Human\Test_foo.am');
  6. % or
  7. % > data = amiraReader; % leave the argument blank and use the file selector
  8. %
  9. % Author: DLB - 3/20/09, help from RTF's geom2am.m @ line 38.
  10. %
  11. %%
  12. warning off all; % you'll get truncation warnings because you read inf in line 24.
  13. switch nargin
  14. case 1
  15. filename = varargin{1};
  16. case 0
  17. [file, pathname] = uigetfile({'*.am'},'Please locate Amira file.','Multiselect','off');
  18. filename = [pathname file];
  19. end
  20. fid = fopen(filename,'r','ieee-be');
  21. datachar = char(fread(fid,inf,'char'))'; % this will be the char data in the header
  22. switch isempty(findstr(datachar,'BINARY-LITTLE-ENDIAN'))
  23. case 1
  24. endianness = 'be';
  25. case 0
  26. endianness = 'le';
  27. end
  28. lattice = findstr(datachar,'define Lattice');
  29. parameter = findstr(datachar,'Parameters');
  30. start_data_position = findstr(datachar,'@1'); % note there will be two @1, so take the second one!
  31. %% Determine if we're dealing with a labelfield or regular data
  32. switch isempty(findstr(datachar,'HxByteRLE'))
  33. case 1 % regular data case
  34. %% blatantly stolen from RTF's geom2am
  35. data_type = char(datachar(findstr(datachar,'Lattice { ')+10:findstr(datachar,'Data } ')-2));
  36. switch data_type
  37. case 'byte'
  38. out_type = 'int8';
  39. case 'short'
  40. out_type = 'int16';
  41. case 'ushort'
  42. out_type = 'uint16';
  43. case 'int32'
  44. out_type = 'int32';
  45. case 'float'
  46. out_type = 'float';
  47. case 'double'
  48. out_type = 'double';
  49. end
  50. %% get the dimensions from the amira header
  51. fseek(fid,lattice+14,'bof');
  52. dimensions = str2num(char(fread(fid,parameter-lattice-15,'char'))');
  53. % get the data from the amira file
  54. fid = fopen(filename,'r',['ieee-' endianness]);
  55. fseek(fid,start_data_position(2)+2,'bof');
  56. data = reshape(fread(fid,dimensions(1)*dimensions(2)*dimensions(3),out_type),dimensions(1),dimensions(2),dimensions(3));
  57. %% THIS SPACE JUST SEPARATES THE LABELFIELDS AND TYPICAL AMIRA FILES
  58. %
  59. % Amira's RLE compression algorithm goes as follows:
  60. %
  61. % 0 to 127 --> Copy the next value n times
  62. % -127 to -1 --> Copy the next n values VERBATIM
  63. %
  64. % The string:
  65. % 00001111111000001010000001000
  66. % Saved in Amira's RLE as:
  67. % 4 0 7 1 5 0 -125 1 0 1 6 0 -127 1 3 0
  68. %
  69. % check label2short.m for more info.
  70. %
  71. %% Thus begins the label2short code. This will give you a matrix from a labelfield
  72. case 0 % labelfield case
  73. lattice = findstr(datachar,'define Lattice');
  74. parameter = findstr(datachar,'Parameters');
  75. boundingbox = findstr(datachar,'BoundingBox');
  76. CoordType = findstr(datachar,'CoordType');
  77. ByteRLE = findstr(datachar,'HxByteRLE,');
  78. start_data_position = findstr(datachar,'@1'); % note there will be two @1, so take the second one!
  79. DataSection = findstr(datachar,'# Data section follows');
  80. %% get the dimensions from the amira header
  81. fseek(fid,lattice+14,'bof');
  82. dimensions = str2num(char(fread(fid,parameter-lattice-15,'char'))');
  83. fseek(fid,ByteRLE+9,'bof');
  84. byte_length = str2num(char(fread(fid,DataSection - ByteRLE-13,'char'))');
  85. fseek(fid,boundingbox-1,'bof');
  86. BB = char(fread(fid,CoordType - boundingbox-5,'char'))';
  87. %% Switch endianess?
  88. switch endianness
  89. case 'le'
  90. fclose(fid);
  91. fid = fopen(filename,'r',['ieee-' endianness]);
  92. fseek(fid,start_data_position(2)+2,'bof');
  93. data = fread(fid,byte_length,'int8');
  94. case 'be'
  95. fseek(fid,start_data_position(2)+2,'bof');
  96. data = fread(fid,byte_length,'int8');
  97. end
  98. %% This decodes Amira's RLE. I figured this out by trial and error
  99. % pre-allocate space for the output.
  100. % we're writing everything to a 1-D variable, then reshaping to 3-D.
  101. % note that we start with a zeros matrix b/c labels contain primarily zeros. we'll avoid writing zeros this way.
  102. out_line = zeros(dimensions(1)*dimensions(2)*dimensions(3),1);
  103. % pre-compute the final offset due to -#'s
  104. final_offset = sum(data(find(data<0))+127);
  105. net_counter = 0; % this sifts through the out_line variable
  106. offset = 0; % this adds an offset to data_counter when writing VERBATIM
  107. % this code will search for 0 values, and avoid explicitly writing them.
  108. for i = 1:floor((byte_length-final_offset)/2) %
  109. data_counter = 2*i+offset; % this will sift through the data variable
  110. if ((data(data_counter) == 0) && (data(data_counter-1) > 0)) % check if the value is 0 AND that we're not writing VERBATIM
  111. net_counter = data(data_counter-1)+net_counter;
  112. else
  113. if data(data_counter-1) < 0 % check if we're writing VERBATIM
  114. for j = 1:128+data(data_counter-1)
  115. out_line(j+net_counter) = data(data_counter+j-1);
  116. % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter+j-1)) ', offset = ' int2str(offset)]);
  117. end
  118. net_counter = 128+data(data_counter-1)+net_counter;
  119. offset = offset + 127+ data(data_counter-1);
  120. else % assume that we're copying value data(data_counter), data(data_counter-1) times.
  121. for j = 1:data(data_counter-1)
  122. out_line(j+net_counter) = data(data_counter);
  123. % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter))]);
  124. end
  125. net_counter = data(data_counter-1)+net_counter;
  126. end
  127. end
  128. end
  129. clear data;
  130. % reshape the 1-D to a 3-D
  131. data = reshape(out_line,dimensions(1),dimensions(2),dimensions(3));
  132. end