%EXTEND   Extends/pads an image with values
%
% SYNOPSIS:
%  out = extend(in, newsize, type, value, clip)
%
% PARAMETERS:
%  in:      input image
%  newsize: new image size
%  type:    'symmetric',
%           'leftup', 'rightup', 'leftdown', 'rightdown'
%  value:   extension value
%  clip:    clip images if newsize < oldsize ('no','yes')
%
% DEFAULTS:
%  type: 'symmetric'
%  value: 0
%  clip: 'no' (if newsize smaller than input, do nothing)
%
% EXAMPLE:
%  extend(readim,[512 512])
%  extend(readim('chromo3d'),30,'symmetric',1)
%
% SEE ALSO:
%  cut, cropim

% (C) Copyright 2004-2010      Department of Molecular Biology
%     All rights reserved      Max-Planck-Institute for Biophysical Chemistry
%                              Am Fassberg 11, 37077 G"ottingen
%                              Germany
%
% Bernd Rieger, Sep 2004.
% 9 April 2007, Rewrote to use SUBSASGN instead of EVAL. (CL)
% 20 July 2010, Keeping pixel dimensions. (CL)
% 21 July 2010, Keeping image origin in the correct place. (CL)
%               'leftlow' -> 'leftdown'; 'rightlow' -> 'rightdown'. (CL)

function out = extend(varargin)
d = struct('menu','Manipulation',...
   'display','Extend (padding)',...
   'inparams',struct('name',       {'in','bor','typ','value','clp'},...
         'description',{'Input image','New image size',...
            'Placement flavour','Value','Clipping'},...
         'type',       {'image','array','option','array','boolean'},...
         'dim_check',  {0,1,0,0,0},...
'range_check',{[],'N+',{'symmetric','leftup','leftdown','rightup','rightdown'},'R',[]},...
         'required',   {1,1,0,0,0},...
         'default',    {'a','256','symmetric',0,0}...
        ),...
   'outparams',struct('name',{'out'},...
                      'description',{'Output image'},...
                      'type',{'image'}...
                      )...
  );
if nargin == 1
   s = varargin{1};
   if ischar(s) & strcmp(s,'DIP_GetParamList')
      out = d;
      return
   end
end
if nargin>=3 & ischar(varargin{3})
   switch varargin{3}
   case 'leftlow'
      varargin{3} = 'leftdown';
   case 'rightlow'
      varargin{3} = 'rightdown';
   end
end
try
   [in,bor,typ,value,clp] = getparams(d,varargin{:});
catch
   if ~isempty(paramerror)
      error(paramerror)
   else
      error(firsterr)
   end
end
if ~isscalar(in)
   error('Only implemented for scalar (grey-value) images.');
end
in = squeeze(in);
sz = imsize(in);
tmp = sz>bor;
if all(tmp)
   if clp
      out = cut(in,bor);
   else
      out = in; % nothing to do
   end
   return;
end
bortmp = bor;
bor(tmp) = sz(tmp); % all extension to smaller size are put to size;
out = newim(bor,datatype(in));
out.pixelsize = in.pixelsize;
out.pixelunits = in.pixelunits;
if value
   out(:) = value;
end

N = length(sz);
switch typ
   case 'symmetric'
      % Because we're now using this function also in CONVOLVE, we need
      % to make sure that the origin is conserved properly:
      start = (bor-sz)./2;            % start coord
      for ii=find(mod(start,1))
         if mod(sz(ii),2) % odd size input
            start(ii) = ceil(start(ii));
         else             % even size input
            start(ii) = floor(start(ii));
         end
      end
      stop  = start+sz-1;             % end coord
   case 'leftup'
      start = zeros(1,N);
      stop  = sz-1;
   case 'leftdown'
      if N>2
         error('leftdown option only up to 2D');
      end
      start = [0,bor(2)-sz(2)];
      stop  = [sz(1)-1,bor(2)-1];
   case 'rightup'
       if N>2
         error('rightup option only up to 2D');
      end
      start = [bor(1)-sz(1),0];
      stop  = [bor(1)-1,sz(2)-1];
   case 'rightdown'
      start = bor - sz;
      stop  = bor - 1;
   otherwise
      error('Should not happen');
end
s = substruct('()',{});
for ii = 1:N
   s.subs{ii} = start(ii):stop(ii);
end
out = subsasgn(out,s,in);

% if any dimesion is smaller than the old size and clp is yes
if any(tmp) & clp
   sz2 = bor;
   sz2(tmp) = bortmp(tmp);
   out = cut(out,sz2);
end
