%CAT   Concatenate (append, join) images.
%   CAT(DIM,A,B) concatenates the images A and B along
%   the dimension DIM.
%   CAT(1,A,B) is the same as [A,B].
%   CAT(2,A,B) is the same as [A;B].
%
%   CAT(DIM,A1,A2,A3,A4,...) concatenates the input images
%   A1, A2, etc. along the dimension DIM.
%
%   If any of the inputs is a dip_image_array, its images are
%   concatenated horizontally. CAT always produces a single
%   dip_image.
%
%   CAT(DIM,A) concatenates the images in the dip_image_array
%   A along the dimension DIM.

% (C) Copyright 1999-2008               Pattern Recognition Group
%     All rights reserved               Faculty of Applied Physics
%                                       Delft University of Technology
%                                       Lorentzweg 1
%                                       2628 CJ Delft
%                                       The Netherlands
%
% Cris Luengo, July 2000.
% 15 November 2002: Fixed binary images to work in MATLAB 6.5 (R13)
% 26 July 2007: Reorganized to remove repeated code.
% February 2008: Adding pixel dimensions and units to dip_image. (BR)
% 5 March 2008: Bug fix. (CL)
% 24 July 2008: Using default pixel size & units from DI_DEFAULTPHYSDIMS. (CL)
% 5 November 2008: Fixed to work with images of different dimensionality. (CL)

function out = cat(dim,varargin)
if nargin < 2, error('Erroneus input.'); end
if di_isdipimobj(dim), error('Erroneus input.'); end
% Collect all images in cell array
n = nargin-1;
if n > 1
   in = cell(1,n);
   in_type = cell(1,n);
   in_phys = cell(1,n);
   for ii=1:n
      img = varargin{ii};
      if ~di_isdipimobj(img)
         img = dip_image(img);
      end
      if ~isscalar(img)
         img = cat(1,img);  % concatenate dip_image_array into single image
      end
      in{ii} = img.data;
      in_type{ii} = img.dip_type;
      in_phys{ii} = img.physDims;
   end
else
   img = varargin{1};
   n = prod(imarsize(img));
   in = cell(1,n);
   in_type = cell(1,n);
   in_phys = cell(1,n);
   for ii=1:n
      in{ii} = img(ii).data;
      in_type{ii} = img(ii).dip_type;
      in_phys{ii} = img(ii).physDims;
   end
end
% Find the correct output datatype
dpd = di_defaultphysdims(1);
out_type = in_type{1};
out_phys = in_phys{1};
if length(out_phys.PixelSize) < dim
   out_phys.PixelSize(end+1:dim) = dpd.PixelSize;
   out_phys.PixelUnits(end+1:dim) = dpd.PixelUnits;
end
for ii=2:length(in)
   out_type = di_findtypex(out_type,in_type{ii});
   if length(in_phys{ii}.PixelSize) < dim
      in_phys{ii}.PixelSize(end+1:dim) = dpd.PixelSize;
      in_phys{ii}.PixelUnits(end+1:dim) = dpd.PixelUnits;
   end
   out_phys = di_findphysdims(out_phys,in_phys{ii});
end
pd = di_defaultphysdims(1);
out_phys.PixelSize(end+1:dim) = pd.PixelSize;
out_phys.PixelUnits(end+1:dim) = pd.PixelUnits;
% Convert images to the output type
for ii=1:length(in)
   if ~strcmp(in_type{ii},out_type)
      in{ii} = di_convert(in{ii},di_mattype(out_type));
   end
end
% Call CAT
if dim == 1
   dim = 2;
elseif dim == 2
   dim = 1;
end
try
   out = dip_image(cat(dim,in{:}),out_type);
   out.physDims = out_phys;
catch
   error(di_firsterr)
end
