function b = blkproc(a,block,border,P0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10)
%BLKPROC Process an image in blocks.
%	B = BLKPROC(A,[M N],'fun') processes the image A by applying
%	the function 'fun' to each distinct M-by-N block of A.  The
%	results are assembled to create B.  The function 'fun' should
%	operate on an M-by-N block, x, and return a matrix of the
%	same size, y: y = fun(x);
%
%	Up to 10 additional parameters can be passed to the function
%	using B = BLKPROC(A,[M N],'fun',P1,P2,P3,...) in which case
%	'fun' is called using y = fun(x,P1,P2,P3,...).  A is padded,
%	if necessary, so that its size is a multiple of M-by-N.
%
%	B = BLKPROC(A,[M N],[K L],'fun',...) processes the image A
%	in (M+2*K)-by-(N+2*L) blocks that are formed by extending
%	the original M-by-N block from A by K and L in the row and
%	column directions.  This border is padded, if necessary, 
%	at the edges of A.  In this case, the function 'fun' should
%	operate on the (M+2*K)-by-(N+2*L) block and return either an
%	M-by-N result, or a (M+2*K)-by-(N+2*L) result whose M-by-N 
%	center will be incorporated into B.  A border can be used to
%	reduce edge effects.
%
%	At the edges, the blocks are formed by padding with ones
%	if A is an indexed image or with zeros otherwise.
%
%	See also BLK2COL, COL2BLK, HOOD2COL, COLFILT, NLFILTER.

%	Clay M. Thompson 10-6-92
%	Copyright (c) 1992 by The MathWorks, Inc.
%	$Revision: 1.11 $  $Date: 1993/09/30 17:16:34 $

error(nargchk(3,14,nargin));

if nargin==3,
  FUN = border;
  border = [0 0];
  if ~any(FUN<48), fcall = [FUN,'(x)']; else fcall = FUN; end
else
  if isstr(P0), 
    FUN = P0; 
    % Form call string.
    params = [];
    for n=5:nargin
      params = [params,',P',int2str(n-4)];
    end
    if ~any(FUN<48), fcall = [FUN,'(x',params,')']; else fcall = FUN; end
  else
    FUN = border;
    border = [0 0];
    % Form call string and shift parameters
    params = [];
    for n=4:nargin
      params = [params,',P',int2str(n-3)];
      eval(['P',int2str(nargin-n+1),'=P',int2str(nargin-n),';']);
    end
    if ~any(FUN<48), fcall = [FUN,'(x',params,')']; else fcall = FUN; end
  end
end

% Expand A: Add border, pad if size(a) is not divisible by block.
[ma,na] = size(a);
mpad = rem(ma,block(1)); if mpad>0, mpad = block(1)-mpad; end
npad = rem(na,block(2)); if npad>0, npad = block(2)-npad; end
if isind(a),
  aa = ones(ma+mpad+2*border(1),na+npad+2*border(2));
else
  aa = zeros(ma+mpad+2*border(1),na+npad+2*border(2));
end
aa(border(1)+(1:ma),border(2)+(1:na)) = a;

%
% Process each block in turn.
%
m = block(1) + 2*border(1);
n = block(2) + 2*border(2);
mblocks = (ma+mpad)/block(1);
nblocks = (na+npad)/block(2);
b = zeros(ma+mpad,na+npad);
arows = 1:m; acols = 1:n;
brows = 1:block(1); bcols = 1:block(2);
xrows = brows + border(1); xcols = bcols + border(2);
mb = block(1); nb = block(2);
for i=0:mblocks-1,
  for j=0:nblocks-1,
    x = aa(i*mb+arows,j*nb+acols);
    c = eval(fcall);
    if all(size(c)==size(x)),
      b(i*mb+brows,j*nb+bcols) = c(xrows,xcols);
    elseif all(size(c)==size(x)-2*border),
      b(i*mb+brows,j*nb+bcols) = c;
    else
      error('Block returned by FUN is the wrong size.');
    end
  end
end
b = b(1:ma,1:na);
