function out_data = label2short(varargin) %%%%%%%%% % % The more non-zero elements your labelfield has, the longer this % function will take to run!!! % % USAGE: (1) >> data = label2short; % (2) >> label2short('C:\Data\SU00x\Foo_label-field.am'); % % Uncomment the last lines of text if you want to write new files! % Creates an additional file called xxx_short.am % % Multi-file select works!! % % This m-file decodes Amira's Run-Length Encoding that they use to save % space in their LabelFields. As per usual, no documentation on their % compression algorithm, so I figured it out on my own. % % 0 to 127 --> Copy the next value n times % -127 to -1 --> Copy the next n values VERBATIM % % The string: % 00001111111000001010000001000 % Saved in Amira's RLE as: % 4 0 7 1 5 0 -125 1 0 1 6 0 -127 1 3 0 % % I never knew about RLE, this guy's site was fairly useful. His name is % dipperstein, I mean, come on! % http://michael.dipperstein.com/rle/index.html % last updated June 8, 2008 - viewed 3/18/09 % % DLB 3/18/09 % %% multi file selector switch nargin case 1 filename = varargin{1}; leng = 1; case 0 [file, pathname] = uigetfile({'*.am'},'Please locate Amira LabelField(s).','Multiselect','on'); if isequal(file,0) disp('User selected Cancel'); fclose all; return else if isa(file,'cell') for k = 1:length(file) filename{k} = fullfile(pathname,file{k}); disp(['User selected ' filename{k}]); end leng = length(file); else filename = [pathname file]; disp(['User selected ', fullfile(pathname, filename)]); leng = 1; end end end for n = 1:leng if isa(filename,'cell') fil = filename{n}; else fil = filename; end fid = fopen(fil,'r','ieee-be'); datachar = char(fread(fid,inf,'char'))'; switch isempty(findstr(datachar,'BINARY-LITTLE-ENDIAN')) case 1 endianness = 'be'; case 0 endianness = 'le'; end lattice = findstr(datachar,'define Lattice'); parameter = findstr(datachar,'Parameters'); boundingbox = findstr(datachar,'BoundingBox'); CoordType = findstr(datachar,'CoordType'); ByteRLE = findstr(datachar,'HxByteRLE,'); start_data_position = findstr(datachar,'@1'); % note there will be two @1, so take the second one! DataSection = findstr(datachar,'# Data section follows'); %% get the dimensions from the amira header fseek(fid,lattice+14,'bof'); dimensions = str2num(char(fread(fid,parameter-lattice-15,'char'))'); fseek(fid,ByteRLE+9,'bof'); byte_length = str2num(char(fread(fid,DataSection - ByteRLE-13,'char'))'); fseek(fid,boundingbox-1,'bof'); BB = char(fread(fid,CoordType - boundingbox-5,'char'))'; %% Switch endianess? switch endianness case 'le' fclose(fid); fid = fopen(fil,'r',['ieee-' endianness]); fseek(fid,start_data_position(2)+2,'bof'); data = fread(fid,byte_length,'int8'); case 'be' fseek(fid,start_data_position(2)+2,'bof'); data = fread(fid,byte_length,'int8'); end %% This decodes Amira's RLE. I figured this out by trial and error, not % sure what algorithm they use. % pre-allocate space for the output out_line = zeros(dimensions(1)*dimensions(2)*dimensions(3),1); % pre-compute the final offset due to -#'s final_offset = sum(data(find(data<0))+127); net_counter = 0; offset = 0; for i = 1:floor((byte_length-final_offset)/2) % % disp(int2str(i)); data_counter = 2*i+offset; if ((data(data_counter) == 0) && (data(data_counter-1) > 0)) net_counter = data(data_counter-1)+net_counter; else if data(data_counter-1) < 0 for j = 1:128+data(data_counter-1) out_line(j+net_counter) = data(data_counter+j-1); % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter+j-1)) ', offset = ' int2str(offset)]); end net_counter = 128+data(data_counter-1)+net_counter; offset = offset + 127+ data(data_counter-1); else for j = 1:data(data_counter-1) out_line(j+net_counter) = data(data_counter); % disp(['i = ' int2str(i) ', length = ' int2str(data(data_counter-1)) ', written value = ' int2str(data(data_counter))]); end net_counter = data(data_counter-1)+net_counter; end end end out_data = reshape(out_line,dimensions(1),dimensions(2),dimensions(3)); %% this is from my amiraCTWriter.m % fid = fopen(strrep(fil,'.am','_short.am'),'w'); % switch endianness % case 'be' % fprintf(fid,'# AmiraMesh 3D BINARY 2.0\n\n'); % fprintf(fid,['# CreationDate: ' datestr(now,'ddd mmm') datestr(now,' dd HH:MM:SS yyyy') '\n\n']); % case 'le' % fprintf(fid,'# AmiraMesh BINARY-LITTLE-ENDIAN 2.1\n\n'); % end % fprintf(fid,'define Lattice %g %g %g\n\n',dimensions(1),dimensions(2),dimensions(3)); % fprintf(fid,'Parameters {\n'); % fprintf(fid,' Content "%gx%gx%g %s, uniform coordinates",\n',dimensions(1),dimensions(2),dimensions(3),'short'); % fprintf(fid,' %s\n',BB); % fprintf(fid,' CoordType "uniform"\n'); % fprintf(fid,'}\n\n'); % fprintf(fid,'Lattice { %s Data } @1\n\n','short'); % fprintf(fid,'# Data section follows\n'); % fprintf(fid,'@1\n'); % fclose(fid); % close the text part of the file % fid = fopen(strrep(fil,'.am','_short.am'),'ab',['ieee-' endianness]); % fwrite(fid,out_data(:,:,:),'short'); % fclose(fid); end