changeset 74:3fd199825b13

uintlut and padarray functions added
author jmones
date Sun, 08 Aug 2004 21:20:25 +0000
parents 2a7e0fbc7124
children 13fee9301f12
files INDEX padarray.m uintlut.m
diffstat 3 files changed, 357 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/INDEX
+++ b/INDEX
@@ -15,7 +15,8 @@
  imrotate
  imtranslate
  imshear
- impad 
+ impad
+ padarray 
  rotate_scale
 Statistics
  corr2 
@@ -29,6 +30,7 @@
  imnoise 
  medfilt2 
  ordfilt2 cordflt2 
+ uintlut
 Black and white image functions
  bwarea 
  bweuler 
new file mode 100644
--- /dev/null
+++ b/padarray.m
@@ -0,0 +1,300 @@
+## Copyright (C) 2004 Josep Mones i Teixidor
+##
+## 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} {@var{B} = } padarray (@var{A},@var{padsize})
+## @deftypefnx {Function File} {@var{B} = } padarray (@var{A},@var{padsize},@var{padval})
+## @deftypefnx {Function File} {@var{B} = } padarray (@var{A},@var{padsize},@var{padval},@var{direction})
+## Pads an array in a configurable way.
+##
+## B = padarray(A,padsize) pads an array @var{A} with zeros, where
+## @var{padsize} defines the amount of padding to add in each dimension
+## (it must be a vector of positive integers). 
+##
+## Each component of @var{padsize} defines the number of elements of
+## padding that will be added in the corresponding dimension. For
+## instance, [4,5] adds 4 elements of padding in first dimension (vertical)
+## and 5 in second dimension (horizontal).
+##
+## B = padarray(A,padsize,padval) pads @var{A} using the value specified
+## by @var{padval}. @var{padval} can be a scalar or a string. Possible
+## values are:
+## @table @code
+## @item 0
+## Pads with 0 as described above. This is the default behaviour.
+## @item scalar
+## Pads using @var{padval} as a padding value.
+## @item 'circular'
+## Pads with a circular repetition of elements in @var{A} (similar to
+## tiling @var{A}).
+## @item 'replicate'
+## Pads 'replicating' values of @var{A} which are at the border of the
+## array.
+## @item 'symmetric'
+## Pads with a mirror reflection of @var{A}.
+## @end table
+##
+## B = padarray(A,padsize,padval,direction) pads @var{A} defining the
+## direction of the pad. Possible values are:
+## @table @code
+## @item 'both'
+## For each dimension it pads before the first element the number
+## of elements defined by @var{padsize} and the same number again after
+## the last element. This is the default value.
+## @item 'pre'
+## For each dimension it pads before the first element the number of
+## elements defined by @var{padsize}.
+## @item 'post'
+## For each dimension it pads after the last element the number of
+## elements defined by @var{padsize}.
+## @end table
+## @end deftypefn
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function B = padarray(A, padsize, padval, direction)
+  # Check parameters
+  if (nargin<2 || nargin>4)
+    usage ("B = padarray(A, padsize [, padval] [, direction])");
+  endif
+  if (nargin<3)
+    padval=0;
+  endif
+  if (nargin<4)
+    direction='both';
+  endif
+
+  if (!isvector(padsize) || any(padsize<0))
+    error("padarray: padsize must be a vector of positive integers.");
+  endif
+
+  # Check direction
+  pre=false;
+  post=false;
+  switch(direction)
+    case('pre')
+      pre=true;
+    case('post')
+      post=true;
+    case('both')
+      post=true;
+      pre=true;
+    otherwise
+      error ("padarray: direction possible values are: 'pre', 'post' and 'both'");
+  endswitch
+  
+  
+  B=A;
+  dim=1;
+  for s=padsize
+    if (s>0)
+      # padding in this dimension was requested
+      ds=size(B);
+      ds=[ds, ones(1,dim-length(ds))]; # data size
+      ps=ds;
+      ps(dim)=s;		       # padding size
+
+      if (isstr(padval))
+	# Init a "index all" cell array. All cases need it.
+	idx=cell();
+	for i=1:length(ds)
+	  idx{i}=1:ds(i);
+	endfor
+
+	switch(padval)
+	  case('circular')
+	    complete=0;
+	    D=B;
+	    if (ps(dim)>ds(dim))
+	      complete=floor(ps(dim)/ds(dim));
+	      ps(dim)=rem(ps(dim),ds(dim));
+	    endif
+	    if (pre)
+	      for i=1:complete
+		B=cat(dim,D,B);
+	      endfor
+	      idxt=idx;
+	      idxt{dim}=ds(dim)-ps(dim)+1:ds(dim);
+	      B=cat(dim,D(idxt{:}),B);
+	    endif
+	    if (post)
+	      for i=1:complete
+		B=cat(dim,B,D);
+	      endfor
+	      idxt=idx;
+	      idxt{dim}=1:ps(dim);
+	      B=cat(dim,B,D(idxt{:}));
+	    endif
+	    # end circular case
+
+	  case('replicate')
+	    if (pre)
+	      idxt=idx;
+	      idxt{dim}=1;
+	      pad=B(idxt{:});
+	      # can we do this without the loop?	
+	      for i=1:s
+		B=cat(dim,pad,B);
+	      endfor
+	    endif
+	    if (post)
+	      idxt=idx;
+	      idxt{dim}=size(B,dim);
+	      pad=B(idxt{:});
+	      for i=1:s
+		B=cat(dim,B,pad);
+	      endfor
+	    endif
+	    # end replicate case
+	
+	  case('symmetric')
+	    if (ps(dim)>ds(dim))
+	      error("padarray: padding is longer than data using symmetric padding");
+	    endif
+	    if (pre)
+	      idxt=idx;
+	      idxt{dim}=ps(dim):-1:1;
+	      B=cat(dim,B(idxt{:}),B);
+	    endif
+	    if (post)
+	      idxt=idx;
+	      sbd=size(B,dim);
+	      idxt{dim}=sbd:-1:sbd-ps(dim)+1;
+	      B=cat(dim,B,B(idxt{:}));
+	    endif
+	    # end symmetric case
+
+	  otherwise
+	    error("padarray: invalid string in padval parameter.");
+
+	endswitch
+	# end cases where padval is a string
+
+      elseif (isscalar(padval))
+	# Handle fixed value padding
+	if (padval==0)
+	  pad=zeros(ps);
+	else
+	  pad=padval*ones(ps);
+	endif
+	if(pre&&post)
+	  # check if this is not quicker than just 2 calls (one for each)
+	  B=cat(dim,pad,B,pad);
+	elseif(pre)
+	  B=cat(dim,pad,B);
+	elseif(post)
+	  B=cat(dim,B,pad);
+	endif
+      else
+	error ("padarray: padval can only be a scalar or a string.");
+      endif
+    endif
+    dim+=1;
+  endfor
+endfunction
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1])
+%! % pads [1,2,3;4,5,6] with a whole border of 2 rows and 1 columns of 0
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1],5)
+%! % pads [1,2,3;4,5,6] with a whole border of 2 rows and 1 columns of 5
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1],0,'pre')
+%! % pads [1,2,3;4,5,6] with a left and top border of 2 rows and 1 columns of 0
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1],'circular')
+%! % pads [1,2,3;4,5,6] with a whole 'circular' border of 2 rows and 1 columns
+%! % border 'repeats' data as if we tiled blocks of data
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1],'replicate')
+%! % pads [1,2,3;4,5,6] with a whole border of 2 rows and 1 columns which
+%! % 'replicates' edge data
+
+%!demo
+%! padarray([1,2,3;4,5,6],[2,1],'symmetric')
+%! % pads [1,2,3;4,5,6] with a whole border of 2 rows and 1 columns which
+%! % is symmetric to the data on the edge 
+
+% Test default padval and direction
+%!assert(padarray([1;2],[1]), [0;1;2;0]);
+%!assert(padarray([3,4],[0,2]), [0,0,3,4,0,0]);
+%!assert(padarray([1,2,3;4,5,6],[1,2]), \
+%!      [zeros(1,7);0,0,1,2,3,0,0;0,0,4,5,6,0,0;zeros(1,7)]);
+
+% This segfaults because of cat (uncomment when
+% cat(3,eye(2),eye(2)) works)
+%! %assert(padarray([1,2,3;4,5,6],[3,2,1]), cat(3, 			\
+%! %	zeros(7,7),							\
+%! %	[zeros(3,7); [zeros(2,2), [1,2,3;4,5,6], zeros(2,2)]; zeros(3,7)], \
+%! %	zeros(7,7))); 
+
+% Test if default param are ok
+%!assert(padarray([1,2],[4,5])==padarray([1,2],[4,5],0));
+%!assert(padarray([1,2],[4,5])==padarray([1,2],[4,5],0,'both'));
+
+% Test literal padval
+%!assert(padarray([1;2],[1],i), [i;1;2;i]);
+
+% Test directions (horizontal)
+%!assert(padarray([1;2],[1],i,'pre'), [i;1;2]);
+%!assert(padarray([1;2],[1],i,'post'), [1;2;i]);
+%!assert(padarray([1;2],[1],i,'both'), [i;1;2;i]);
+
+% Test directions (vertical)
+%!assert(padarray([1,2],[0,1],i,'pre'), [i,1,2]);
+%!assert(padarray([1,2],[0,1],i,'post'), [1,2,i]);
+%!assert(padarray([1,2],[0,1],i,'both'), [i,1,2,i]);
+
+% Test circular padding
+%!test
+%! A=[1,2,3;4,5,6];
+%! B=repmat(A,7,9);
+%! assert(padarray(A,[1,2],'circular','pre'), B(2:4,2:6));
+%! assert(padarray(A,[1,2],'circular','post'), B(3:5,4:8));
+%! assert(padarray(A,[1,2],'circular','both'), B(2:5,2:8));
+%! % This tests when padding is bigger than data
+%! assert(padarray(A,[5,10],'circular','both'), B(2:13,3:25));
+
+% Test replicate padding
+%!test
+%! A=[1,2;3,4];
+%! B=kron(A,ones(10,5));
+%! assert(padarray(A,[9,4],'replicate','pre'), B(1:11,1:6));
+%! assert(padarray(A,[9,4],'replicate','post'), B(10:20,5:10));
+%! assert(padarray(A,[9,4],'replicate','both'), B);
+
+% Test symmetric padding
+%!test
+%! A=[1:3;4:6];
+%! HA=[3:-1:1;6:-1:4];
+%! VA=[4:6;1:3];
+%! VHA=[6:-1:4;3:-1:1];
+%! B=[VHA,VA,VHA; HA,A,HA; VHA,VA,VHA];
+%! assert(padarray(A,[1,2],'symmetric','pre'), B(2:4,2:6));
+%! assert(padarray(A,[1,2],'symmetric','post'), B(3:5,4:8));
+%! assert(padarray(A,[1,2],'symmetric','both'), B(2:5,2:8));
+
+%
+% $Log$
+% Revision 1.1  2004/08/08 21:20:25  jmones
+% uintlut and padarray functions added
+%
+%
new file mode 100644
--- /dev/null
+++ b/uintlut.m
@@ -0,0 +1,54 @@
+## Copyright (C) 2004 Josep Mones i Teixidor
+##
+## 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} {@var{B} = } uintlut (@var{A},@var{LUT})
+## Computes matrix B by using A as an index to lookup table LUT.
+##
+## B = uintlut(A, LUT) calculates a matrix B by using @var{LUT} as a
+## lookup table indexed by values in @var{A}.
+## 
+## B class is the same as @var{LUT}. 
+## @end deftypefn
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function B = uintlut(A, LUT)
+  if (nargin != 2)
+    usage("B = uintlut(A, LUT)");
+  endif
+
+  ## We convert indexing array A to double since even CVS version of
+  ## Octave is unable to use non-double arrays as indexing types. This
+  ## won't be needed in the future eventually.
+  B=LUT(double(A));
+endfunction
+
+%!demo
+%! uintlut(uint8([1,2,3,4]),uint8([255:-1:0]));
+%! % Returns a uint8 array [255,254,253,252]
+
+%!assert(uintlut(uint8([1,2,3,4]),uint8([255:-1:0])), uint8([255:-1:252]));
+%!assert(uintlut(uint16([1,2,3,4]),uint16([255:-1:0])), uint16([255:-1:252]));
+%!assert(uintlut(uint32([1,2,3,4]),uint32([255:-1:0])), uint32([255:-1:252]));
+%!assert(uintlut(uint64([1,2,3,4]),uint64([255:-1:0])), uint64([255:-1:252]));
+
+%
+% $Log$
+% Revision 1.1  2004/08/08 21:20:25  jmones
+% uintlut and padarray functions added
+%
+%