+% ## Copyright (C) 2000 Teemu Ikonen
+% ##
+% ## This program is free software; you can redistribute it and/or
+% ## modify it under the terms of the GNU General Public License
+% ## as published by the Free Software Foundation; either version 2
+% ## of the License, or (at your option) any later version.
+% ##
+% ## This program is distributed in the hope that it will be useful, but
+% ## WITHOUT ANY WARRANTY; without even the implied warranty of
+% ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+% ## General Public License for more details.
+% ##
+% ## You should have received a copy of the GNU General Public License
+% ## along with this program; if not, write to the Free Software
+% ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+%
+
+% ## -*- texinfo -*-
+% ## @deftypefn {Function File} {} im_pad(@var{A}, @var{xpad}, @var{ypad}, [@var{padding}, [@var{const}]])
+% ## Pad (augment) a matrix for application of image processing algorithms.
+% ##
+% ## Pads the input image @var{A} with @var{xpad}(1) elements from left,
+% ## @var{xpad}(2), elements from right, @var{ypad}(1) elements from above
+% ## and @var{ypad}(2) elements from below.
+% ## Values of padding elements are determined from the optional arguments
+% ## @var{padding} and @var{const}. @var{padding} is one of
+% ##
+% ## @table @samp
+% ## @item "zeros"
+% ## pad with zeros (default)
+% ##
+% ## @item "ones"
+% ## pad with ones
+% ##
+% ## @item "constant"
+% ## pad with a value obtained from the optional fifth argument const
+% ##
+% ## @item "symmetric"
+% ## pad with values obtained from @var{A} so that the padded image mirrors
+% ## @var{A} starting from edges of @var{A}
+% ##
+% ## @item "reflect"
+% ## same as symmetric, but the edge rows and columns are not used in the padding
+% ##
+% ## @item "replicate"
+% ## pad with values obtained from A so that the padded image
+% ## repeates itself in two dimensions
+% ##
+% ## @end table
+% ## @end deftypefn
+%
+% ## Author: Teemu Ikonen <tpikonen@pcu.helsinki.fi>
+% ## Created: 5.5.2000
+% ## Keywords: padding image processing
+% ## 2006-11-28 P. Cloetens <cloetens@esrf.fr>
+% ## * add padding possibility 'extend'
+% ## * rename to im_pad
+% ## 2006-12-03 PC
+% ## * extend with average of last value over extend_avg rows/columns
+%
+% ## A nice test matrix for padding:
+% ## A = 10*[1:5]' * ones(1,5) + ones(5,1)*[1:5]
+
+function retval = im_pad(A, xpad, ypad, padding, const)
+
+try empty_list_elements_ok_save = empty_list_elements_ok;
+catch empty_list_elements_ok_save = 0;
+end
+try warn_empty_list_elements_save = warn_empty_list_elements;
+catch warn_empty_list_elements_save = 0;
+end
+unwind_protect
+
+if nargin < 4
+ padding = 'zeros';
+end
+if nargin < 5
+ const = 1;
+end
+
+extend_avg = const; %# we use the same fifth argument
+
+origx = size(A,2);
+origy = size(A,1);
+
+if isscalar(xpad)
+ retx = xpad;
+ xpad(1) = ceil((retx-origx)/2);
+ xpad(2) = retx-origx-xpad(1);
+else
+ retx = origx + xpad(1) + xpad(2);
+end
+
+if isscalar(ypad)
+ rety = ypad;
+ ypad(1) = ceil((rety-origy)/2);
+ ypad(2) = rety-origy-ypad(1);
+else
+ rety = origy + ypad(1) + ypad(2);
+end
+
+empty_list_elements_ok = 1;
+warn_empty_list_elements = 0;
+
+if(strcmp(padding, 'zeros'))
+ retval = zeros(rety,retx);
+ retval(ypad(1)+1 : ypad(1)+origy, xpad(1)+1 : xpad(1)+origx) = A;
+ elseif(strcmp(padding,'ones'))
+ retval = ones(rety,retx);
+ retval(ypad(1)+1 : ypad(1)+origy, xpad(1)+1 : xpad(1)+origx) = A;
+ elseif(strcmp(padding,'constant'))
+ retval = const.*ones(rety,retx);
+ retval(ypad(1)+1 : ypad(1)+origy, xpad(1)+1 : xpad(1)+origx) = A;
+ elseif(strcmp(padding,'replicate'))
+ y1 = origy-ypad(1)+1;
+ x1 = origx-xpad(1)+1;
+ if(y1 < 1 || x1 < 1 || ypad(2) > origy || xpad(2) > origx)
+ error('Too large padding for this padding type');
+ else
+ yrange1 = y1 : origy;
+ yrange2 = 1 : ypad(2);
+ xrange1 = x1 : origx;
+ xrange2 = 1 : xpad(2);
+ retval = [ A(yrange1, xrange1), A(yrange1, :), A(yrange1, xrange2);
+ A(:, xrange1), A, A(:, xrange2);
+ A(yrange2, xrange1), A(yrange2, :), A(yrange2, xrange2) ];
+ end
+ elseif(strcmp(padding,'symmetric'))
+ y2 = origy-ypad(2)+1;
+ x2 = origx-xpad(2)+1;
+ if(ypad(1) > origy || xpad(1) > origx || y2 < 1 || x2 < 1)
+ error('Too large padding for this padding type');
+ else
+ yrange1 = 1 : ypad(1);
+ yrange2 = y2 : origy;
+ xrange1 = 1 : xpad(1);
+ xrange2 = x2 : origx;
+ retval = [ fliplr(flipud(A(yrange1, xrange1))), flipud(A(yrange1, :)), fliplr(flipud(A(yrange1, xrange2)));
+ fliplr(A(:, xrange1)), A, fliplr(A(:, xrange2));
+ fliplr(flipud(A(yrange2, xrange1))), flipud(A(yrange2, :)), fliplr(flipud(A(yrange2, xrange2))) ];
+ end
+ elseif(strcmp(padding,'reflect'))
+ y2 = origy-ypad(2);
+ x2 = origx-xpad(2);
+ if(ypad(1)+1 > origy || xpad(1)+1 > origx || y2 < 1 || x2 < 1)
+ error('Too large padding for this padding type');
+ else
+ yrange1 = 2 : ypad(1)+1;
+ yrange2 = y2 : origy-1;
+ xrange1 = 2 : xpad(1)+1;
+ xrange2 = x2 : origx-1;
+ retval = [ fliplr(flipud(A(yrange1, xrange1))), flipud(A(yrange1, :)), fliplr(flipud(A(yrange1, xrange2)));
+ fliplr(A(:, xrange1)), A, fliplr(A(:, xrange2));
+ fliplr(flipud(A(yrange2, xrange1))), flipud(A(yrange2, :)), fliplr(flipud(A(yrange2, xrange2))) ];
+ end
+ elseif(strcmp(padding,'extend'))
+ if (extend_avg > 1)
+ retval = [ repmat(mean2(A(1:extend_avg,1:extend_avg)),ypad(1),xpad(1)) , repmat(mean(A(1:extend_avg,:),1),ypad(1),1) , repmat(mean2(A(1:extend_avg,end-extend_avg+1:end)),ypad(1),xpad(2)) ;
+ repmat(mean(A(:,1:extend_avg),2),1,xpad(1)) , A , repmat(mean(A(:,end-extend_avg+1:end),2),1,xpad(2)) ;
+ repmat(mean2(A(end-extend_avg+1:end,1:extend_avg)),ypad(2),xpad(1)) , repmat(mean(A(end-extend_avg+1:end,:),1),ypad(2),1) , repmat(mean2(A(end-extend_avg+1:end,end-extend_avg+1:end)),ypad(2),xpad(2)) ];
+ else
+ retval = [ repmat(A(1,1),ypad(1),xpad(1)) , repmat(A(1,:),ypad(1),1) , repmat(A(1,end),ypad(1),xpad(2)) ;
+ repmat(A(:,1),1,xpad(1)) , A , repmat(A(:,end),1,xpad(2)) ;
+ repmat(A(end,1),ypad(2),xpad(1)) , repmat(A(end,:),ypad(2),1) , repmat(A(end,end),ypad(2),xpad(2)) ];
+ end
+ else
+ error('Unknown padding type');
+ end
+
+unwind_protect_cleanup
+ empty_list_elements_ok = empty_list_elements_ok_save;
+ warn_empty_list_elements = warn_empty_list_elements_save;
+end_unwind_protect
+
+ end
\ No newline at end of file