label2short.m 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. function out_data = label2short(varargin)
  2. %%%%%%%%%
  3. %
  4. % The more non-zero elements your labelfield has, the longer this
  5. % function will take to run!!!
  6. %
  7. % USAGE: (1) >> data = label2short; <Enter>
  8. % (2) >> label2short('C:\Data\SU00x\Foo_label-field.am'); <Enter>
  9. %
  10. % Uncomment the last lines of text if you want to write new files!
  11. % Creates an additional file called xxx_short.am
  12. %
  13. % Multi-file select works!!
  14. %
  15. % This m-file decodes Amira's Run-Length Encoding that they use to save
  16. % space in their LabelFields. As per usual, no documentation on their
  17. % compression algorithm, so I figured it out on my own.
  18. %
  19. % 0 to 127 --> Copy the next value n times
  20. % -127 to -1 --> Copy the next n values VERBATIM
  21. %
  22. % The string:
  23. % 00001111111000001010000001000
  24. % Saved in Amira's RLE as:
  25. % 4 0 7 1 5 0 -125 1 0 1 6 0 -127 1 3 0
  26. %
  27. % I never knew about RLE, this guy's site was fairly useful. His name is
  28. % dipperstein, I mean, come on!
  29. % http://michael.dipperstein.com/rle/index.html
  30. % last updated June 8, 2008 - viewed 3/18/09
  31. %
  32. % DLB 3/18/09
  33. %
  34. %% multi file selector
  35. switch nargin
  36. case 1
  37. filename = varargin{1};
  38. leng = 1;
  39. case 0
  40. [file, pathname] = uigetfile({'*.am'},'Please locate Amira LabelField(s).','Multiselect','on');
  41. if isequal(file,0)
  42. disp('User selected Cancel');
  43. fclose all;
  44. return
  45. else
  46. if isa(file,'cell')
  47. for k = 1:length(file)
  48. filename{k} = fullfile(pathname,file{k});
  49. disp(['User selected ' filename{k}]);
  50. end
  51. leng = length(file);
  52. else
  53. filename = [pathname file];
  54. disp(['User selected ', fullfile(pathname, filename)]);
  55. leng = 1;
  56. end
  57. end
  58. end
  59. for n = 1:leng
  60. if isa(filename,'cell')
  61. fil = filename{n};
  62. else
  63. fil = filename;
  64. end
  65. fid = fopen(fil,'r','ieee-be');
  66. datachar = char(fread(fid,inf,'char'))';
  67. switch isempty(findstr(datachar,'BINARY-LITTLE-ENDIAN'))
  68. case 1
  69. endianness = 'be';
  70. case 0
  71. endianness = 'le';
  72. end
  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(fil,'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, not
  99. % sure what algorithm they use.
  100. % pre-allocate space for the output
  101. out_line = zeros(dimensions(1)*dimensions(2)*dimensions(3),1);
  102. % pre-compute the final offset due to -#'s
  103. final_offset = sum(data(find(data<0))+127);
  104. net_counter = 0;
  105. offset = 0;
  106. for i = 1:floor((byte_length-final_offset)/2) %
  107. % disp(int2str(i));
  108. data_counter = 2*i+offset;
  109. if ((data(data_counter) == 0) && (data(data_counter-1) > 0))
  110. net_counter = data(data_counter-1)+net_counter;
  111. else
  112. if data(data_counter-1) < 0
  113. for j = 1:128+data(data_counter-1)
  114. out_line(j+net_counter) = data(data_counter+j-1);
  115. % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter+j-1)) ', offset = ' int2str(offset)]);
  116. end
  117. net_counter = 128+data(data_counter-1)+net_counter;
  118. offset = offset + 127+ data(data_counter-1);
  119. else
  120. for j = 1:data(data_counter-1)
  121. out_line(j+net_counter) = data(data_counter);
  122. % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter))]);
  123. end
  124. net_counter = data(data_counter-1)+net_counter;
  125. end
  126. end
  127. end
  128. out_data = reshape(out_line,dimensions(1),dimensions(2),dimensions(3));
  129. %% this is from my amiraCTWriter.m
  130. % fid = fopen(strrep(fil,'.am','_short.am'),'w');
  131. % switch endianness
  132. % case 'be'
  133. % fprintf(fid,'# AmiraMesh 3D BINARY 2.0\n\n');
  134. % fprintf(fid,['# CreationDate: ' datestr(now,'ddd mmm') datestr(now,' dd HH:MM:SS yyyy') '\n\n']);
  135. % case 'le'
  136. % fprintf(fid,'# AmiraMesh BINARY-LITTLE-ENDIAN 2.1\n\n');
  137. % end
  138. % fprintf(fid,'define Lattice %g %g %g\n\n',dimensions(1),dimensions(2),dimensions(3));
  139. % fprintf(fid,'Parameters {\n');
  140. % fprintf(fid,' Content "%gx%gx%g %s, uniform coordinates",\n',dimensions(1),dimensions(2),dimensions(3),'short');
  141. % fprintf(fid,' %s\n',BB);
  142. % fprintf(fid,' CoordType "uniform"\n');
  143. % fprintf(fid,'}\n\n');
  144. % fprintf(fid,'Lattice { %s Data } @1\n\n','short');
  145. % fprintf(fid,'# Data section follows\n');
  146. % fprintf(fid,'@1\n');
  147. % fclose(fid); % close the text part of the file
  148. % fid = fopen(strrep(fil,'.am','_short.am'),'ab',['ieee-' endianness]);
  149. % fwrite(fid,out_data(:,:,:),'short');
  150. % fclose(fid);
  151. end