Code covered by the BSD License  

Highlights from
3D Slicer

image thumbnail
from 3D Slicer by David Legland
Slicer for exploring 3D images (grayscale, color or vectorial) through planar or 3D slices.

readstack(fname, varargin)
function img = readstack(fname, varargin)
%READSTACK Read either a list of 2D images (slices), or a 3D image
%
%   Syntax
%   IMG = readstack(FNAME)
%   IMG = readstack(FNAME, INDICES)
%   IMG = readstack(FNAME, TYPE, DIM)
%   IMG = readstack(..., 'verbose')
%   IMG = readstack(..., 'quiet')
%
%   Description
%
%   IMG = readstack(FNAME)
%   FNAME is the base name of the image.
%   In the case of a bundle image, this is simply the name of the file.
%   In the case of an image stored as several slices, this is the string
%   common to each file with wildcard '#', '?' or '0' at the position of
%   the slices indices.
%   IMG is a 3-dimensional array of type uint8, size: X*Y*Z;
%    or a 4 dimensional array for color images (X*Y*3*Z).
%
%   IMG = readstack(FNAME, INDICES)
%   forces the number of dimensions of resulting array (slices images)
%   FNAME: base filename of images, without end number (string)
%   INDICES: indices of images to put for result. Ex:  [0:39]
%
%   IMG = readstack(FNAME, DIM, TYPE)
%   forces the size and datatype of resulting array.
%   FNAME: name of the single stack file
%   DIM:   size of final stack. Ex : [256 256 50].
%   TYPE:  matlab type of data ('uint8', 'int16', 'double'...)
%   There is no support for binary raw stacks.
%
%   IMG = readstack(..., 'verbose')
%   gives some information on the files 
%
%   IMG = readstack(..., 'quiet')
%   does not display anything. This is the default mode.
%
%   Examples:
%   IMG = readstack('images???.tif');
%   IMG = readstack('aStack.tif');
%   IMG = readstack('files00.bmp');
%   IMG = readstack('files00.bmp', 5:23);
%   IMG = readstack('files00slices##.tif');
%   IMG = readstack('rawData.raw', [256 256 50], 'uint8');
%
%   See also:
%   savestack, imread
%
%   ---------
%   author: David Legland, david.legland(at)grignon.inra.fr
%   INRA - Cepia Software Platform
%   created the 10/09/2003.
%   http://www.pfl-cepia.inra.fr/index.php?page=slicer
%   Licensed under the terms of the new BSD license, see file license.txt

%   HISTORY 
%   16/02/2004 adapt to read image with name containing several '00'
%       Example: '~/images/avril2003/collees/cm1500.bmp'
%       In this case, consider only the last one.
%   19/02/2004 don't allocate memory prior to load. This allows the
%       function to return an image appropriate with stored type.
%   04/06/2004 automatically detect the number of files to read, and
%       reorganize structure 
%   14/10/2004 correct bug for specifying range in slices images
%   17/10/2004 add support for importing raw single files stacks
%   22/10/2004 add support for verbose or silent modes
%   27/10/2004 correct bug for color images in bundles/stacks
%   18/11/2005 correct bug when specifying range, was keeping first image
%   of stack, not range(1).
%   21/02/2006 adapt to manage windows file format
%   01/02/2006 allow option 'quiet', the same as 'silent'
%   10/08/2006 add support for color images stored as slices
%   14/11/2006 add support for wildcards # and ?, and preallocate memory
%       according to image datatype


% check number of inputs
error(nargchk(1, 5, nargin));

% select 'verbose' or 'silent' option  ----------------

% verbose by default
verbose = 0;

% check each input argument
for i = 1:length(varargin)
    var = varargin{i};
    if ~ischar(var)
        continue;
    end
    
    % check the verbose option, and remove it from input variables
    if strcmp(var, 'verbose')
        verbose = 1;
        t = 1:length(varargin);
        varargin = varargin(t(t~=i));
        break;
    end

    % check the silent option, and remove it from input variables
    if strcmp(var, 'silent') || strcmp(var, 'quiet')
        verbose = 0;
        t = 1:length(varargin);
        varargin = varargin(t(t~=i));
        break;
    end
end


%% Read data in a raw file

% First argument is image size (Nx-by-Ny-by-Nz-by-Nc), 
% and second argument is image type (usually 'uint8')
if length(varargin) > 1
    % get image size and type
    dim = varargin{1};
    type = varargin{2};
    
    % make compatibility with previous versions
    if ischar(dim)
        tmp = type;
        type = dim;
        dim = tmp;
    end
    
    % auto-detect color image, and permute dimensions if necessary
    colorImage = false;
    if length(dim) > 2 && dim(3) == 3
        colorImage = true;
        dim = dim([3 1 2 4:length(dim)]);
    end
    
    % allocate memory
    img = zeros(dim, type);
    
    % open file and read data, in order C, X, Y and Z
    f = fopen(fname, 'r');
    img(:) = fread(f, prod(dim), ['*' type]);
    fclose(f);
    
    % permute dimension to comply with matlab convention
    if colorImage 
        img = permute(img, [3 2 1 4:length(dim)]);
    else
        img = permute(img, [2 1 3:length(dim)]);
    end
    
    return;
end

% check if image stored in one bundle file or as several stacks
bundle =  sum(ismember('#?', fname)) == 0;
if exist(fname, 'file')
    bundle = length(imfinfo(fname)) > 1;
end


if ~bundle    
    %% images stored in several 2D files ------------------------
    % -> need to know numbers of slices to read.
        
    % Compute the base name of the image, by removing '#', '?' or '0'
    
    % characters to replace with numbers
    chars = '#?0';
    
    index = [];    
    for c = 1:length(chars)
        % identify number of chars in file name
        n = 5;
        while isempty(index) && n > 1
            n = n - 1;
            index = strfind(fname, repmat(chars(c), [1 n]));
        end

        % escape if special characters have been found
        if  ~isempty(index)
            break;
        end
    end
    
    % In the case of several '00' parts, consider only the last one 
    index = index(end);
        
    % create file basename and endname
	basename = fname(1:index-1);
    endname = fname(index+n:end);

    
    % compute indices of slices to read
    
    if ~isempty(varargin)
        % slice indices are given as parameters
        range = varargin{1};
    else            
        % identify slices to read by detecting last index of slices
        i = 0;
        while true
            % check existence of file for given index
            %imgname = sprintf(['%s' sprintf('%%0%dd', n) '%s'], basename, i, endname);
            imgname = [basename sprintf(sprintf('%%0%dd', n), i) endname];
            if ~exist(imgname, 'file')
                break;
            end
            i = i + 1;
        end
        % read slices from the first one to the last existing one
        range = 0:i-1;
    end
    
    if verbose
        msg = sprintf('read slices from %d to %d', range(1), range(end));
        disp(msg);
    end
    
    % Read each slice of the image
    
    % read slice for each range index
    string = [basename sprintf('%%0%dd', n)  endname];
    
    % adapt filename format to windows if needed
    if ispc
        string = strrep(string, '\', '\\');
    end    
    
    % read the first image
    img = imread(sprintf(string, range(1)));
    
    % read each image one after the other
    if length(size(img)) == 2
        % allocate memory
        img(1, 1, length(range)) = 0;
        
        % read each gray scale image successively
        for i = 2:length(range)
            img(:,:,i) = imread(sprintf(string, range(i)));
        end
        
    else
        % pre-allocate memory
        img(1, 1, 1, length(range)) = 0;
        
        % read each color image successively
        for i = 2:length(range)
            img(:,:,:,i) = imread(sprintf(string, range(i)));
        end
    end
    
else
    %% Read Image stored in one bundle file
    
    % get image dimensions
    info = imfinfo(fname);
    
    % If input argument is found, it is used as the number of slices to
    % read. Anyway, read all the slices.
    range = 1:length(info);
    if ~isempty(varargin)
        range = varargin{1};
    end

    if verbose
        msg = sprintf('read %d slices in a stack', length(range)); 
        disp(msg);
    end
    
    % read each slice of the 3D image
    img = imread(fname, range(1));
    
    if ndims(img) == 2             % read gray scale images -----        
        % pre-allocate memory
        img(1, 1, length(range)) = 0;
        
        % add each slice successively
        for i = 2:length(range)
            img(:,:,i) = imread(fname, range(i));
        end
        
    else                            % read color images      -----
        % pre-allocate memory
        img(1, 1, 1, length(range)) = 0;
        
        % add each slice successively
        for i = 2:length(range)
            img(:,:,:,i) = imread(fname, range(i));
        end
    end 
end

Contact us