changeset 186:13c6a9bdec24

Changed the structure to match the package system
author hauberg
date Sun, 20 Aug 2006 12:59:37 +0000
parents a3a15d67c85f
children 243cc4891c69
files COPYING DESCRIPTION MakeShears.m Makeconf.add Makefile __imagemagick__.cc applylut.m autumn.m bestblk.m blkproc.m bmpwrite.m bone.m brighten.m bwarea.m bwborder.m bweuler.m bwfill.cc bwlabel.cc bwlabel.m bwmorph.m bwselect.m cmpermute.m cmunique.m col2im.m colfilt.m colorgradient.m configure.add conndef.m cool.m copper.m cordflt2.cc corr2.m dilate.m edge.m erode.m fftconv2.m flag.m graycomatrix.cc grayslice.m histeq.m hot.m houghtf.cc hsv.m im2bw.m im2col.m imadjust.m imginfo.m imhist.m imnoise.m impad.m imread.m imresize.m imrotate.m imrotate_Fourier.m imshear.m imtranslate.m imwrite.m inst/MakeShears.m inst/applylut.m inst/autumn.m inst/bestblk.m inst/blkproc.m inst/bmpwrite.m inst/bone.m inst/brighten.m inst/bwarea.m inst/bwborder.m inst/bweuler.m inst/bwlabel.m inst/bwmorph.m inst/bwselect.m inst/cmpermute.m inst/cmunique.m inst/col2im.m inst/colfilt.m inst/colorgradient.m inst/conndef.m inst/cool.m inst/copper.m inst/corr2.m inst/dilate.m inst/edge.m inst/erode.m inst/fftconv2.m inst/flag.m inst/grayslice.m inst/histeq.m inst/hot.m inst/hsv.m inst/im2bw.m inst/im2col.m inst/imadjust.m inst/imginfo.m inst/imhist.m inst/imnoise.m inst/impad.m inst/imread.m inst/imresize.m inst/imrotate.m inst/imrotate_Fourier.m inst/imshear.m inst/imtranslate.m inst/imwrite.m inst/isbw.m inst/isgray.m inst/isind.m inst/isrgb.m inst/jet.m inst/makelut.m inst/mat2gray.m inst/mean2.m inst/medfilt2.m inst/nlfilter.m inst/ordfilt2.m inst/padarray.m inst/pink.m inst/poly2mask.m inst/prism.m inst/qtdecomp.m inst/qtgetblk.m inst/qtsetblk.m inst/rainbow.m inst/rgb2gray.m inst/roicolor.m inst/spring.m inst/std2.m inst/stretchlim.m inst/summer.m inst/testimio.m inst/uintlut.m inst/white.m inst/winter.m isbw.m isgray.m isind.m isrgb.m jet.m jpgread.cc jpgwrite.cc makelut.m mat2gray.m mean2.m medfilt2.m nlfilter.m ordfilt2.m padarray.m pink.m pngcanvas.h pngread.cc pngwrite.cc poly2mask.m prism.m qtdecomp.m qtgetblk.m qtsetblk.m rainbow.m rgb2gray.m roicolor.m rotate_scale.cc spring.m src/Makeconf.add src/Makeconf.base src/Makeconf.in src/Makefile src/__imagemagick__.cc src/admin/CONTENTS src/admin/OctRe.pm src/admin/change_va_arg.pm src/admin/find_changes src/admin/get_authors src/admin/get_contents src/admin/make_index src/admin/mkdoc src/admin/mkpkgadd src/admin/mktests.sh src/admin/mktexi src/admin/no_vr_val.pm src/admin/octlink.sh src/admin/run_forge src/admin/template.ndev src/admin/template.readme src/autogen.sh src/bwfill.cc src/bwlabel.cc src/configure.add src/configure.base src/cordflt2.cc src/graycomatrix.cc src/houghtf.cc src/install-sh src/jpgread.cc src/jpgwrite.cc src/octinst.sh.in src/pngcanvas.h src/pngread.cc src/pngwrite.cc src/rotate_scale.cc std2.m stretchlim.m summer.m testimio.m uintlut.m white.m winter.m
diffstat 204 files changed, 15563 insertions(+), 10849 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
new file mode 100644
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,10 @@
+Name: Image
+Version: 1.0.0
+Date: 2006-08-05
+Author: Various Authors
+Maintainer: The Octave Community
+Title: Image Processing.
+Description: Add a description to this package!
+Depends: octave (>= 2.9.7)
+License: GPL version 2 or later
+Url: http://octave.sf.net
deleted file mode 100644
--- a/MakeShears.m
+++ /dev/null
@@ -1,7 +0,0 @@
-function [S1, S2] = MakeShears(theta)
-
-S1 = eye(2);
-S2 = eye(2);
-
-S1(1,2) = -tan(theta/2);
-S2(2,1) = sin(theta);
deleted file mode 100644
--- a/Makeconf.add
+++ /dev/null
@@ -1,3 +0,0 @@
-@DEFHAVE_JPEG@
-@DEFHAVE_PNG@
-@DEFHAVE_MAGICKXX@
deleted file mode 100644
--- a/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-sinclude ../../Makeconf
-
-ifdef HAVE_JPEG
-	JPEG=jpgwrite.oct jpgread.oct
-endif
-
-ifdef HAVE_PNG
-	PNG=pngread.oct pngwrite.oct
-endif
-
-ifdef HAVE_MAGICKXX
-	IMAGEMAGICK=__imagemagick__.oct __magick_read__$(OCTLINK)
-endif
-
-all: cordflt2.oct bwlabel.oct bwfill.oct rotate_scale.oct \
-	houghtf.oct graycomatrix.oct \
-	$(JPEG) $(PNG) $(IMAGEMAGICK)
-
-jpgread.oct: jpgread.cc
-	$(MKOCTFILE) $< -ljpeg
-
-jpgwrite.oct: jpgwrite.cc
-	$(MKOCTFILE) $< -ljpeg
-
-pngread.oct: pngread.cc
-	$(MKOCTFILE) $< -lpng
-
-pngwrite.oct: pngwrite.cc
-	$(MKOCTFILE) $< -lpng
-
-__imagemagick__.oct: __imagemagick__.cc
-	$(MKOCTFILE) $< -lMagick++ -lMagick
-
-__magick_read__$(OCTLINK): __imagemagick__.oct
-	$(MKOCTLINK) __imagemagick__.oct $@
-
-clean: ; -$(RM) *.o octave-core core *.oct *~
deleted file mode 100644
--- a/__imagemagick__.cc
+++ /dev/null
@@ -1,310 +0,0 @@
-#include <octave/oct.h>
-#include <Magick++.h>
-#include <iostream>
-using namespace std;
-using namespace Magick;
-
-octave_value_list read_indexed_images(vector<Image> imvec, Array<int> frameidx, bool wantalpha)
-{
-    octave_value_list output;
-    int rows = imvec[0].baseRows();
-    int columns = imvec[0].baseColumns();
-    int nframes = frameidx.length();
-    ImageType type = imvec[0].type();
-    
-    unsigned int mapsize = imvec[0].colorMapSize();
-    int i = mapsize;
-    unsigned int depth = 0;
-    while(i >>= 1) depth++;
-    i = 0;
-    depth--;
-    while(depth >>= 1) i++;
-    depth = 1 << i;
-
-    int x, y, frame;
-    const IndexPacket *pix;
-    switch(depth) {
-	case 1:
-	case 2:
-	case 4:
-	case 8:
-	{
-	    uint8NDArray im = uint8NDArray(dim_vector(rows, columns, nframes));
-	    for(frame=0; frame < nframes; frame++) {
-		imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-		pix = imvec[frameidx(frame)].getConstIndexes();
-		i = 0;      
-		for(y=0; y < rows; y++) {
-		    for(x=0; x < columns; x++) {        
-			im(y, x, frame) = static_cast<octave_uint8>(pix[i++]);
-		    }
-		}
-	    }
-	    im.chop_trailing_singletons();
-	    output(0) = octave_value(im);
-	}
-	    break;
-	case 16:
-	{
-	    uint16NDArray im = uint16NDArray(dim_vector(rows, columns, nframes));
-	    for(frame=0; frame < nframes; frame++) {
-		imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-		pix = imvec[frameidx(frame)].getConstIndexes();		
-		i = 0;      
-		for(y=0; y < rows; y++) {
-		    for(x=0; x < columns; x++) {
-			im(y, x, frame) = static_cast<octave_uint16>(pix[i++]);
-		    }
-		}
-	    }
-	    im.chop_trailing_singletons();
-	    output(0) = octave_value(im);
-	}
-	    break;
-	default:
-	    error("Index depths bigger than 16-bit not supported");
-	    return octave_value_list();
-    }
-
-    ColorRGB c;
-    Matrix map = Matrix(mapsize, 3);
-    Matrix alpha;
-    switch(type) {
-	case PaletteMatteType:
-/*	    warning("palettematte");
-	    map = Matrix(mapsize, 3);
-	    alpha = Matrix(mapsize, 1);
-	    for(i = 0; i < mapsize; i++) {
-		warning("%d", i);
-		c = imvec[0].colorMap(i);
-		map(i, 0) = c.red();
-		map(i, 1) = c.green();
-		map(i, 2) = c.blue();
-		alpha(i, 1) = c.alpha();				
-	    }
-	    break;	    */
-    	case PaletteType:
-	    alpha = Matrix(0,0);
-	    for(i = 0; i < mapsize; i++) {
-		c = imvec[0].colorMap(i);
-		map(i, 0) = c.red();
-		map(i, 1) = c.green();
-		map(i, 2) = c.blue();		
-	    }
-	    break;	    
-	default:
-	    error("Unsupported indexed image type");
-	    return octave_value_list();
-    }
-
-    output(1) = octave_value(map);
-    if(wantalpha) {
-	output(2) = octave_value(alpha);
-    }     
-    return output;
-}
-
-template <class T>
-octave_value_list read_images(vector<Image> imvec, Array<int> frameidx)
-{
-  int i;
-  T im;  
-  int rows = imvec[0].baseRows();
-  int columns = imvec[0].baseColumns();
-  int nframes = frameidx.length();
-  ImageType type = imvec[0].type();
-  
-  int x, y, frame;
-  const PixelPacket *pix;
-  dim_vector idim = dim_vector();
-  idim.resize(4);
-  idim(0) = rows;
-  idim(1) = columns;
-  idim(2) = 1;
-  idim(3) = nframes;
-  Array<int> idx(dim_vector(4));
-  switch(type) {
-      case BilevelType:
-    //    break;
-      case GrayscaleType:
-	  im = T(dim_vector(rows, columns, nframes));
-	  for(frame=0; frame < nframes; frame++) {
-	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-	      i = 0;      
-	      for(y=0; y < rows; y++) {
-		  for(x=0; x < columns; x++) {        
-		      im(y, x, frame) = pix[i++].red;
-		  }
-	      }
-	  }
-	  break;
-      case GrayscaleMatteType:
-	  idim(2) = 2;
-	  im = T(idim);
-	  for(frame=0; frame < nframes; frame++) {
-	      idx(3) = frame;
-	      i = 0;
-	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-	      for(y=0; y < rows; y++) {
-		  idx(0) = y;
-		  for(x=0; x < columns; x++) {
-		      idx(1) = x;
-		      idx(2) = 0;
-		      im(idx) = pix[i].red;
-		      idx(2) = 1;
-		      im(idx) = pix[i].opacity;
-		      i++;
-		  }
-	      }
-	  }    
-	  break;
-      case PaletteType:
-      case TrueColorType:
-	  idim(2) = 3;
-	  im = T(idim);      
-	  for(frame=0; frame < nframes; frame++) {
-	      idx(3) = frame;
-	      i = 0;
-	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-	      for(y=0; y < rows; y++) {
-		  idx(0) = y;
-		  for(x=0; x < columns; x++) {
-		      idx(1) = x;
-		      idx(2) = 0;
-		      im(idx) = pix[i].red;
-		      idx(2) = 1;
-		      im(idx) = pix[i].green;
-		      idx(2) = 2;
-		      im(idx) = pix[i].blue;
-		      i++;
-		  }
-	      }
-	  }      
-	  break;
-      case PaletteMatteType:
-      case TrueColorMatteType:
-      case ColorSeparationType:
-	  idim(2) = 4;
-	  im = T(idim);      	  
-	  for(frame=0; frame < nframes; frame++) {
-	      idx(3) = frame;
-	      i = 0;
-	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
-	      for(y=0; y < rows; y++) {
-		  idx(0) = y;
-		  for(x=0; x < columns; x++) {
-		      idx(1) = x;
-		      idx(2) = 0;
-		      im(idx) = pix[i].red;
-		      idx(2) = 1;
-		      im(idx) = pix[i].green;
-		      idx(2) = 2;
-		      im(idx) = pix[i].blue;
-		      idx(2) = 3;
-		      im(idx) = pix[i].opacity;
-		      i++;
-		  }
-	      }
-	  }      
-	  break;
-      default:
-	  error("Undefined Imagemagick image type");
-	  return octave_value_list();
-  }
-
-  im.chop_trailing_singletons();
-  return octave_value_list(octave_value(im));
-}
-
-// instantiate templates
-template octave_value_list read_images<boolNDArray>(vector<Image>, Array<int>);
-template octave_value_list read_images<uint8NDArray>(vector<Image>, Array<int>);
-template octave_value_list read_images<uint16NDArray>(vector<Image>, Array<int>);
-
-DEFUN_DLD(__magick_read__, args, nargout,
-"function m = __imagemagick_read__(fname[, index])\n\
-function [m, colormap] = __imagemagick_read__(fname[, index])\n\
-function [m, colormap, alpha] = __imagemagick_read__(fname[, index])\n\
-\n\
-Read images with ImageMagick++. User interface in imread.m.\n\
-\n\
-")
-{
-    octave_value_list output;
-    int i;    
-    if(args.length() > 2 || args.length() < 1 || !args(0).is_string() \
-       || nargout > 3) {
-      print_usage ();
-      return octave_value_list();
-    }
-    Array<int> frameidx;
-    if(args.length() == 2 && args(1).is_real_type()) {
-	frameidx = args(1).int_vector_value();
-    } else {
-	frameidx = Array<int>(1);
-	frameidx(0) = 1;
-    }
-
-    vector<Image> imvec;
-    try {
-	// Read a file into vector of image objects
-	readImages(&imvec, args(0).string_value());
-    }
-    catch( Warning &warning_ ) {
-        warning("Magick++ warning: %s", warning_.what());
-    }
-    catch( ErrorCoder &error_) {
-	warning("Magick++ coder error: %s", error_.what());
-    }
-    catch( Exception &error_ ) {
-	error("Magick++ exception: %s", error_.what());
-	imvec.clear();
-	return octave_value_list();	
-    }
-
-    int nframes = imvec.size();
-    for(i = 0; i < frameidx.length(); i++) {
-	frameidx(i) = frameidx(i) - 1;
-	if(frameidx(i) >= nframes || frameidx(i) < 0) {
-	    error("Invalid index vector");
-	    imvec.clear();
-	    return output;
-	}
-    }
-    
-    ClassType klass = imvec[0].classType();
-    if(klass == PseudoClass && nargout > 1) {
-	output = read_indexed_images(imvec, frameidx, (nargout == 3));
-    } else {
-	int depth = imvec[0].modulusDepth();
-	i = 0;
-	while(depth >>= 1) i++;
-	depth = 1 << i;
-	
-	switch(depth) {
-	    case 1:
-		output = read_images<boolNDArray>(imvec, frameidx);
-	    break;
-	    case 2:
-	    case 4:
-	    case 8:
-		output = read_images<uint8NDArray>(imvec, frameidx);		
-	    break;
-	    case 16:
-		output = read_images<uint16NDArray>(imvec, frameidx);		
-	    break;
-	    case 32:
-	    case 64:
-	    default:
-		error("Image depths bigger than 16-bit not supported");
-	}
-	if(nargout > 1) {
-	    output(1) = Matrix(0,0);
-	    if(nargout > 2)
-		output(2) = Matrix(0,0);
-	}
-    }
-    imvec.clear();
-
-    return output;
-}
deleted file mode 100644
--- a/applylut.m
+++ /dev/null
@@ -1,62 +0,0 @@
-## 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{A} = } applylut (@var{BW},@var{LUT})
-## Uses lookup tables to perform a neighbour operation on binary images.
-##
-## A = applylut(BW,LUT) returns the result of a neighbour operation
-## using the lookup table @var{LUT} which can be created by makelut.
-##
-## It first computes a matrix with the index of each element in the
-## lookup table. To do this, it convolves the original matrix with a
-## matrix which assigns each of the neighbours a bit in the resulting
-## index. Then @var{LUT} is accessed to compute the result.
-##
-## @end deftypefn
-## @seealso{makelut}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function A = applylut(BW, LUT)
-  if (nargin != 2)
-    usage ("A = applylut(BW, LUT)");
-  endif
-
-  nq=log2(length(LUT));
-  n=sqrt(nq);
-  if (floor(n)!=n)
-    error ("applylut: LUT length is not as expected. Use makelut to create it.");
-  endif
-  w=reshape(2.^[nq-1:-1:0],n,n);
-  A=LUT(filter2(w,BW)+1);
-endfunction
-
-%!demo
-%! lut=makelut(inline('sum(x(:))>=3','x'), 3);
-%! applylut(eye(5),lut)
-%! % everything should be 0 despite a diagonal which
-%! % doesn't reach borders.
-
-
-%!assert(prod(applylut(eye(3),makelut(inline('x(1,1)==1','x'),2))==eye(3))==1); % 2-by-2 test
-%!assert(prod(applylut(eye(3),makelut(inline('x(2,2)==1','x'),3))==eye(3))==1); % 3-by-3 test
-%!assert(prod(applylut(eye(3),makelut(inline('x(3,3)==1','x'),3))== \
-%!	      applylut(eye(3),makelut(inline('x(2,2)==1','x'),2)))==1);
-
-
-
-
deleted file mode 100644
--- a/autumn.m
+++ /dev/null
@@ -1,51 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} autumn (@var{n})
-## Create color colormap. 
-## (red through orange to yellow)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = autumn (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("autumn: argument must be a scalar");
-    endif
-  else
-    usage ("autumn (number)");
-  endif
-
-  if (number == 1)
-    map = [1, 0, 0];  
-  elseif (number > 1)
-    r = ones (number, 1);
-    g = (0:number - 1)' ./ (number - 1);
-    b = zeros (number, 1);
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/bestblk.m
+++ /dev/null
@@ -1,110 +0,0 @@
-## 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{siz} = } bestblk ([@var{m} @var{n}], @var{k})
-## @deftypefnx {Function File} {[@var{mb} @var{nb}] = } bestblk ([@var{m} @var{n}], @var{k})
-## Calculates the best size of block for block processing.
-##
-## @code{siz=bestblk([m,n],k)} calculates the optimal block size for block
-## processing for a @var{m}-by-@var{n} image. @var{k} is the maximum
-## side dimension of the block. Its default value is 100. @var{siz} is a
-## row vector which contains row and column dimensions for the block.
-##
-## @code{[mb,nb]=bestblk([m,n],k)} behaves as described above but
-## returns block dimensions to @var{mb} and @var{nb}.
-##
-## @strong{Algorithm:}
-##
-## For each dimension (@var{m} and @var{n}), it follows this algorithm:
-##
-## 1.- If dimension is less or equal than @var{k}, it returns the
-## dimension value.
-##
-## 2.- If not then returns the value between
-## @code{round(min(dimension/10,k/2))} which minimizes padding.
-##
-##
-## @end deftypefn
-## @seealso{blkproc}
-
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function [varargout] = bestblk(ims,k)
-  if(nargin<1 || nargin>2)
-    usage("siz=bestblk([m,n],k), [mb,nb]=bestblk([m,n],k)");
-  endif
-  if(nargout>2)
-    usage("siz=bestblk([m,n],k), [mb,nb]=bestblk([m,n],k)");
-  endif
-  if(nargin<2)
-    k=100;
-  endif
-  if(!isvector(ims))
-    error("bestblk: first parameter is not a vector.");
-  endif
-  ims=ims(:);
-  if(length(ims)!=2)
-    error("bestblk: length of first parameter is not 2.");
-  endif
-
-  mb=mi=ims(1);
-  p=mi;
-  if(mi>k)
-    for i=round(min(mi/10,k/2)):k
-      pt=rem(mi,i);
-      if(pt<p)
-	p=pt;
-	mb=i;
-      endif
-    endfor
-  endif
-
-  nb=ni=ims(2);
-  p=ni;
-  if(ni>k)
-    for i=round(min(ni/10,k/2)):k
-      pt=rem(ni,i);
-      if(pt<p)
-	p=pt;
-	nb=i;
-      endif
-    endfor
-  endif
-
-  if(nargout<=1)
-    varargout{1}=[mb;nb];
-  else
-    varargout{1}=mb;
-    varargout{2}=nb;
-  endif
-
-endfunction
-
-%!demo
-%! siz=bestblk([200;10],50)
-%! # Best block is [20,10]
-
-%!assert(bestblk([300;100],150),[30;100]);
-%!assert(bestblk([256,128],17),[16;16]);
-
-% $Log$
-% Revision 1.2  2005/07/03 01:10:19  pkienzle
-% Try to correct for missing newline at the end of the file
-%
-% Revision 1.1  2004/08/15 19:01:05  jmones
-% bestblk added: Calculates best block size for block processing
deleted file mode 100644
--- a/blkproc.m
+++ /dev/null
@@ -1,190 +0,0 @@
-## 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} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun})
-## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun}, ...)
-## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], [@var{mborder},@var{nborder}], @var{fun}, @var{...})
-## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, 'indexed', ...)
-## Processes image in blocks using user-supplied function
-##
-## @code{B=blkproc(A,[m,n],fun)} divides image @var{A} in
-## @var{m}-by-@var{n} blocks, and passes them to user-supplied function
-## @var{fun}, which result is concatenated to build returning matrix
-## @var{B}. If padding is needed to build @var{m}-by-@var{n}, it is added
-## at the bottom and right borders of the image.  0 is used as a padding
-## value.
-##
-## @code{B=blkproc(A,[m,n],fun,...)} behaves as described above but
-## passes extra parameters to function @var{fun}.
-##
-## @code{B=blkproc(A,[m,n],[mborder,nborder],fun,...)} behaves as
-## described but uses blocks which overlap with neighbour blocks.
-## Overlapping dimensions are @var{mborder} vertically and @var{nborder}
-## horizontally. This doesn't change the number of blocks in an image
-## (which depends only on size(@var{A}) and [@var{m},@var{n}]). Adding a
-## border requires extra padding on all edges of the image. 0 is used as
-## a padding value.
-##
-## @code{B=blkproc(A,'indexed',...)} assumes that @var{A} is an indexed
-## image, so it pads the image using proper value: 0 for uint8 and
-## uint16 images and 1 for double images. Keep in mind that if 'indexed'
-## is not specified padding is always done using 0.
-##
-## @end deftypefn
-## @seealso{colfilt,inline,bestblk}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function B = blkproc(A, varargin)
-  if(nargin<3)
-    error("blkproc: invalid number of parameters.");
-  endif
-  
-  ## check 'indexed' presence
-  indexed=false;
-  p=1;
-  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
-    indexed=true;
-    p+=1;
-    if(isa(A,"uint8") || isa(A,"uint16"))
-	padval=0;
-    else
-      padval=1; 
-    endif
-  else
-    padval=0;
-  endif
-
-  ## check [m,n]
-  if(!isvector(varargin{p}))
-    error("blkproc: expected [m,n] but param is not a vector.");
-  endif
-  if(length(varargin{p})!=2)
-    error("blkproc: expected [m,n] but param has wrong length.");
-  endif
-  sblk=varargin{p}(:);
-  p+=1;
-
-  ## check [mborder,nborder]
-  if(nargin<p)
-    error("blkproc: required parameters haven't been supplied.");
-  endif
-
-  if(isvector(varargin{p}))
-    if(length(varargin{p})!=2)
-      error("blkproc: expected [mborder,nborder] but param has wrong length.");
-    endif
-    sborder=varargin{p}(:);
-    p+=1;
-  else
-    sborder=[0;0];
-  endif
-
-  ## check fun
-  ## TODO: add proper checks for this one
-  if(nargin<p)
-    error("blkproc: required parameters haven't been supplied.");
-  endif
-
-  fun=varargin{p};
-  if(!isa(fun,"function handle") &&
-     !isa(fun,"inline function") &&
-     !ischar(fun))
-    error("blkproc: invalid fun parameter.");
-  endif
-  
-  ## remaining params are params to fun
-  ## extra params are p+1:nargin-1
-
-  ## First of all we calc needed padding which will be applied on bottom
-  ## and right borders
-  ## The "-" makes the function output needed elements to fill another
-  ## block directly
-  sp=mod(-size(A)',sblk);
-
-  if(any(sp))
-    A=padarray(A,sp,padval,'post');
-  endif
-
-  ## we store A size without border padding to iterate later
-  soa=size(A);
-  
-  ## If we have borders then we need more padding
-  if(any(sborder))
-    A=padarray(A,sborder,padval);
-  endif
-
-  ## calculate end of block
-  eblk=sblk+sborder*2-1;
-
-  ## now we can process by blocks
-  ## we try to preserve fun return type by concatenating everything
-  for i=1:sblk(1):soa(1)
-    ## This assures r has the same class as returned by fun
-    r=feval(fun,A(i:i+eblk(1),1:1+eblk(2)),varargin{p+1:nargin-1});
-    for j=1+sblk(2):sblk(2):soa(2)
-      r=horzcat(r,feval(fun,A(i:i+eblk(1),j:j+eblk(2)),varargin{p+1:nargin-1}));
-    endfor
-    if(i==1) ## this assures B has the same class as A
-      B=r;
-    else
-      B=vertcat(B,r);
-    endif
-  endfor
-endfunction
-
-%!demo
-%! blkproc(eye(6),[2,2],inline("any(x(:))","x"))
-%! # Returns a 3-by-3 diagonal
-
-
-%!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],@sum));
-%!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],inline("sum(x)","x")));
-%!assert(blkproc(eye(6),[1,2],@sum),kron(eye(3),[1;1]));
-%!assert(blkproc(eye(6),[2,2],inline("any(x(:))","x")),eye(3)!=0);
-%!assert(blkproc(eye(6),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
-%!assert(blkproc(eye(6),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[8,5,6;6,2,3;5,3,4;4,3,5;3,2,6;6,5,8]);
-%!assert(blkproc(eye(6),[2,3],[4,3],inline("sum(x(:))","x")),ones(3,2)*6);
-
-% Some int* and uint* tests
-%!assert(blkproc(eye(6),[2,2],inline("int8(sum(x(:)))","x")),eye(3,"int8")*2);
-
-% Padding is 0 even for indexed
-%!assert(blkproc(uint8(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
-%!assert(blkproc(uint8(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
-%!assert(blkproc(uint16(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
-%!assert(blkproc(uint16(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
-
-
-%
-% $Log$
-% Revision 1.5  2005/09/08 02:00:17  pkienzle
-% [for Bill Denney] isstr -> ischar
-%
-% Revision 1.4  2004/11/15 16:04:20  pkienzle
-% Fix tests for functions which return boolean matrices
-%
-% Revision 1.3  2004/09/03 17:49:37  jmones
-% Improved uint8 and uint16 padding expections
-%
-% Revision 1.2  2004/09/03 13:40:13  jmones
-% Check result has same class as function result, and improved fun param checking
-%
-% Revision 1.1  2004/08/15 19:27:46  jmones
-% blkproc: block process an image using user-supplied function
-%
-%
deleted file mode 100644
--- a/bmpwrite.m
+++ /dev/null
@@ -1,88 +0,0 @@
-## bmpwrite(X,map,file)
-##   Write the bitmap X into file (8-bit indexed uncompressed).
-##   The values in X are indices into the given RGB colour map.
-## bmpwrite(X,file)
-##   Write the bitmap X into file (24-bit truecolor uncompressed).
-##   X is an m x n x 3 array of R,G,B values.
-
-## This code is in the public domain.
-## Author: Paul Kienzle <pkienzle@users.sf.net>
-
-function bmpwrite(x,map,file)
-  if nargin==2
-     bmpwrite_truecolor(x,map);
-  else
-     bmpwrite_indexed(x,map,file);
-  endif
-endfunction
-
-function bmpwrite_truecolor(x,file)
-    h = rows(x); w = columns(x);
-    padw = ceil(3*w/4)*4-3*w;
-    header = 14+40;
-    filesize = header+h*(3*w+padw);
-    arch = "ieee-le";
-    file = fopen(file, "wb");
-    fwrite(file,toascii("BM"),"uchar",0,arch); # file tag
-    fwrite(file,filesize,"long",0,arch);    # length of file
-    fwrite(file,0,"long",0,arch);           # reserved
-    fwrite(file,header,"long",0,arch);      # offset of raster data in file
-
-    fwrite(file,40,"long",0,arch);          # header size
-    fwrite(file,w,"long",0,arch);           # image width
-    fwrite(file,h,"long",0,arch);           # image height
-    fwrite(file,1,"short",0,arch);          # number of planes
-    fwrite(file,24,"short",0,arch);         # pixels per plane
-    fwrite(file,0,"long",0,arch);           # compression (none)
-    fwrite(file,0,"long",0,arch);           # compressed size of image
-    resolution = 72/2.54*100;               # 72 dpi / 2.54 cm/in * 100 cm/m
-    fwrite(file,resolution,"long",0,arch);  # horizontal resolution
-    fwrite(file,resolution,"long",0,arch);  # vertical resolution
-    fwrite(file,0,"long",0,arch);           # number of colours used
-    fwrite(file,0,"long",0,arch);           # number of "important" colors
-
-    ## raster image, lines written bottom to top.
-    R = x(end:-1:1,:,1)';
-    G = x(end:-1:1,:,2)';
-    B = x(end:-1:1,:,3)';
-    RGB=[B(:),G(:),R(:)]';  # Now [[B;G;R],[B;G;R],...,[B;G;R]]
-    RGB=reshape(RGB,3*w,h); # Now [[B;G;R;...;B;G;R],...,[B;G;R;...;B;G;R]]
-    fwrite(file,[RGB;zeros(padw,h)],"uchar",0,arch);
-    fclose(file);
-endfunction
-
-function bmpwrite_indexed(x,map,file)
-    [h,w] = size(x);
-    padw = ceil(w/4)*4-w;
-    header = 14+40+4*rows(map);
-    filesize = header+(w+padw)*h;
-    arch = "ieee-le";
-    file = fopen(file, "wb");
-    fwrite(file,toascii("BM"),"uchar",0,arch); # file tag
-    fwrite(file,filesize,"long",0,arch);    # length of file
-    fwrite(file,0,"long",0,arch);           # reserved
-    fwrite(file,header,"long",0,arch);      # offset of raster data in file
-
-    fwrite(file,40,"long",0,arch);          # header size
-    fwrite(file,w,"long",0,arch);           # image width
-    fwrite(file,h,"long",0,arch);           # image height
-    fwrite(file,1,"short",0,arch);          # number of planes
-    fwrite(file,8,"short",0,arch);          # pixels per plane
-    fwrite(file,0,"long",0,arch);           # compression (none)
-    fwrite(file,0,"long",0,arch);           # compressed size of image
-    resolution = 72/2.54*100;               # 72 dpi / 2.54 cm/in * 100 cm/m
-    fwrite(file,resolution,"long",0,arch);  # horizontal resolution
-    fwrite(file,resolution,"long",0,arch);  # vertical resolution
-    fwrite(file,rows(map),"long",0,arch);   # number of colours used
-    fwrite(file,0,"long",0,arch);           # number of "important" colors
-
-    ## colormap BGR0BGR0BGR0BGR0...
-    map=[round(map*255), zeros(rows(map),1)];
-    map=map(:,[3,2,1,4]);
-    fwrite(file,map',"uchar",0,arch);
-
-    ## raster image, each line on a 32-bit boundary, padded with zeros
-    ## lines written bottom to top.
-    fwrite(file,[flipud(x-1)';zeros(padw,h)],"uchar",0,arch);
-    fclose(file);
-endfunction
deleted file mode 100644
--- a/bone.m
+++ /dev/null
@@ -1,54 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} bone (@var{n})
-## Create color colormap. 
-## (a gray colormap with a light blue tone)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = bone (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("bone: argument must be a scalar");
-    endif
-  else
-    usage ("bone (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 0];  
-  elseif (number > 1)
-    x = linspace (0, 1, number)';
-
-    r = (x < 3/4) .* (7/8 * x) + (x >= 3/4) .* (11/8 * x - 3/8);
-    g = (x < 3/8) .* (7/8 * x)\
-      + (x >= 3/8 & x < 3/4) .* (29/24 * x - 1/8)\
-      + (x >= 3/4) .* (7/8 * x + 1/8);
-    b = (x < 3/8) .* (29/24 * x) + (x >= 3/8) .* (7/8 * x + 1/8);
-    map=[r, g, b];
-  else
-    map = [];
-  endif
-endfunction
deleted file mode 100644
--- a/brighten.m
+++ /dev/null
@@ -1,65 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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{map_out}= brighten (@var{map},@var{beta})
-## @deftypefnx {Function File} @var{map_out}= brighten (@var{beta})
-## darkens or brightens the given colormap.
-## If the @var{map} argument is omitted, the function is applied to the
-## current colormap.
-## Should the resulting colormap @var{map_out} not be assigned, it will be
-## written to the current colormap.
-## The argument @var{beta} should be a scalar between -1 and 1,
-## where a negative value darkens and a positive value brightens
-## the colormap.
-##
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	05. March 2000
-
-function [Rmap] = brighten (m, beta)
-
-  if (nargin == 1)
-    beta = m;
-    m = colormap;
-
-  elseif (nargin == 2)
-    if ( (!is_matrix (m)) || (size (m, 2) != 3) )
-      error ("brighten(map,beta) map must be a matrix of size nx3.");
-    endif
-
-  else
-    usage ("brighten(...) number of arguments must be 1 or 2.");
-  endif
-
-  if ( (!is_scalar (beta)) || (beta <= -1) || (beta >= 1) )
-    error ("brighten(...,beta) beta must be a scalar in the range (-1,1).");
-  endif
-
-  if (beta > 0)
-    gamma = 1 - beta;
-  else
-    gamma = 1 / (1 + beta);
-  endif
-
-  if (nargout == 0)
-    colormap (m .^ gamma);
-  else
-    Rmap = m .^ gamma;
-  endif
-
-endfunction
deleted file mode 100644
--- a/bwarea.m
+++ /dev/null
@@ -1,57 +0,0 @@
-## Copyright (C) 2005 Søren Hauberg
-## 
-## 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{total}= bwarea(@var{bw})
-## Estimates the area of the "on" pixels of @var{bw}.
-## If @var{bw} is a binary image "on" pixels are defined as pixels
-## valued 1. If @var{bw} is a grayscale image "on" pixels is defined
-## as pixels with values larger than zero.
-## This algorithm is not the same as counting the number of "on"
-## pixels as it tries to estimate the area of the original object
-## and not the image object.
-## @end deftypefn
-
-## Author: Søren Hauberg <hauberg at gmail dot com>
-## 
-## 2005-06-05 Søren Hauberg <hauberg at gmail dot com>
-## * Initial revision
-
-
-function total = bwarea(bw)
-  if (isgray(bw))
-    bw = (bw > 0);
-  endif
-
-  if (!isbw(bw))
-    error("input image muste be either binary or gray scale.\n");
-  endif
-  
-  four = ones(2);
-  two  = diag([1 1]);
-
-  fours = conv2(bw, four);
-  twos  = conv2(bw, two);
-
-  nQ1 = sum(fours(:) == 1);
-  nQ3 = sum(fours(:) == 3);
-  nQ4 = sum(fours(:) == 4);
-  nQD = sum(fours(:) == 2 & twos(:) != 1);
-  nQ2 = sum(fours(:) == 2 & twos(:) == 1);
-
-  total = 0.25*nQ1 + 0.5*nQ2 + 0.875*nQ3 + nQ4 + 0.75*nQD;
-  
-endfunction
deleted file mode 100644
--- a/bwborder.m
+++ /dev/null
@@ -1,35 +0,0 @@
-## Copyright (C) 2000  Etienne Grossmann
-##
-## 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
-
-##       b = bwborder(im)
-##
-## b is the borders in the 0-1 matrix im. 4-neighborhood is considered.
-## 
-## A pixel is on the border if it is set in im, and it has at least one
-## neighbor that is not set.
-
-## Author:        Etienne Grossmann <etienne@cs.uky.edu>
-## Last modified: January 2000
-
-function b = bwborder(im)
-
-[R,C]=size(im);
-
-b = im & ...
-    !([im(2:R,:) ;  zeros(1,C) ] & ...
-      [zeros(1,C); im(1:R-1,:) ] & ...
-      [im(:,2:C) ,  zeros(R,1) ] & ...
-      [zeros(R,1),  im(:,1:C-1)] ) ;
deleted file mode 100644
--- a/bweuler.m
+++ /dev/null
@@ -1,99 +0,0 @@
-## 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{eul} = } bweuler (@var{BW},@var{n})
-## Calculates the Euler number of a binary image
-##
-## eul=bweuler(BW,n) calculates the Euler number @var{eul} of a binary
-## image @var{BW}, which is a scalar whose value is the total number of
-## objects in an image minus the number of holes.
-##
-## @var{n} can have the values:
-## @table @code
-## @item 4
-## bweuler will use 4-connected neighbourhood definition.
-## @item 8
-## bweuler will use 8-connected neighbourhood definition. This is the
-## default value.
-## @end table
-##
-## This function uses Bit Quads as described in "Digital Image
-## Processing" to calculate euler number.
-##
-## References:
-## W. K. Pratt, "Digital Image Processing", 3rd Edition, pp 593-595
-##
-## @end deftypefn
-## @seealso qtgetblk
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function eul = bweuler(BW, n)
-  if(nargin<1 || nargin>2)
-    usage("eul=bweuler(BW,n)");
-  endif
-  if(nargin<2)
-    n=8;
-  endif
-
-  ## q1lut=makelut(inline("sum(x(:))==1","x"),2);
-  ## q3lut=makelut(inline("sum(x(:))==3","x"),2);
-  ## qdlut=makelut(inline("all((x==eye(2))(:))||all((x==fliplr(eye(2)))(:))","x"),2);
-  ## lut_4=(q1lut-q3lut+2*qdlut)/4;  # everything in one lut will be quicker
-  ## lut_8=(q1lut-q3lut-2*qdlut)/4;
-  ## we precalculate this...
-  if(n==8)
-    lut=[0;.25;.25;0;.25;0;-.5;-.25;.25;-.5;0;-.25;0;-.25;-.25;0];
-  elseif(n==4)
-    lut=[0;.25;.25;0;.25;0;.5;-.25;.25;.5;0;-.25;0;-.25;-.25;0];
-  else
-    error("bweuler: n can only be 4 or 8.");
-  endif
-  
-  eul=sum(applylut(BW,lut)(:));
-endfunction
-
-%!demo
-%! A=zeros(9,10);
-%! A([2,5,8],2:9)=1;
-%! A(2:8,[2,9])=1
-%! bweuler(A)
-%! # Euler number (objects minus holes) is 1-2=-1 in an 8-like object
-
-%!test
-%! A=zeros(10,10);
-%! A(2:9,3:8)=1;
-%! A(4,4)=0;
-%! A(8,8)=0; # not a hole
-%! A(6,6)=0;
-%! assert(bweuler(A),-1);
-
-%!# This will test if n=4 and n=8 behave differently
-%!test
-%! A=zeros(10,10);
-%! A(2:4,2:4)=1;
-%! A(5:8,5:8)=1;
-%! assert(bweuler(A,4),2);
-%! assert(bweuler(A,8),1);
-%! assert(bweuler(A),1);
-
-% $Log$
-% Revision 1.2  2005/07/03 01:10:19  pkienzle
-% Try to correct for missing newline at the end of the file
-%
-% Revision 1.1  2004/08/15 19:33:20  jmones
-% bweuler: Calculates the Euler number of a binary image
deleted file mode 100644
--- a/bwfill.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * BWFILL: fill a bw image starting at points
- * imo= block(im, xregs, yregs);
- *
- * Copyright (C) 1999 Andy Adler
- * This code has no warrany whatsoever.
- * Do what you like with this code as long as you
- *     leave this copyright in place.
- *
- * $Id$
- */
-
-#include <octave/oct.h>
-
-#ifndef OCTAVE_LOCAL_BUFFER
-#include <vector>
-#define OCTAVE_LOCAL_BUFFER(T, buf, size) \
-  std::vector<T> buf ## _vector (size); \
-  T *buf = &(buf ## _vector[0])
-#endif
-
-#define   ptUP     (-1)
-#define   ptDN     (+1)
-#define   ptRT     (+ioM)
-#define   ptLF     (-ioM)
-
-/*
- * check if the point needs to be filled, if so
- * fill it and change the appropriate variables
- */
-void checkpoint( int pt,
-      unsigned char* imo,
-               int * ptstack,
-               int * npoints ) {
-// printf("filling %d np=%d fill=%d\n",pt,*npoints, *(imo+pt)==0 );
-   if( *(imo+pt) != 0 ) return;
-
-   *(imo+pt) = 2;
-   *(ptstack + (*npoints))= pt;
-   (*npoints)++;
-}
-
-DEFUN_DLD (bwfill, args, ,
-  "[...] = bwfill (...)\n\
-   [BW2,IDX] = BWFILL(BW1,Y,X,N) performs a flood-fill on BW1\n\
-\n\
-       (X(k), Y(k)) are rows and columns of seed points\n\
-\n\
-   [BW2,IDX] = BWFILL(BW1,'holes',N) fills interior holes in BW1\n\
-\n\
-       N = 4 or 8(default) for neighborhood connectedness\n\
-\n\
-       IDX is the indices of the filled pixels")
-{
-   octave_value_list retval;
-   octave_value tmp;
-   ColumnVector xseed, yseed ;
-   int nargin = args.length ();
-
-   if (nargin < 2 ) {
-      print_usage ();
-      return retval;
-   }
-
-   Matrix       im=    args(0).matrix_value();
-   int          imM=   im.rows();
-   int          imN=   im.columns();
-
-   int          nb=    8;
-   int          npoints= 0;
-   bool         fillmode= false;
-   if (args(1).is_string() && args(1).string_value() == "holes" ) {
-      fillmode= true;
-
-      npoints= 2*( imM + imN - 4 ); // don't start fill from corners
-
-      xseed= ColumnVector( npoints );
-      yseed= ColumnVector( npoints );
-      int idx= 0;
-      for (int j=2; j<= imN-1; j++) {
-         xseed( idx )= j;   yseed( idx++)= 1;   
-         xseed( idx )= j;   yseed( idx++)= imM;   
-      }
-
-      for (int i=2; i<= imM-1; i++) {
-         yseed( idx )= i;   xseed( idx++)= 1;   
-         yseed( idx )= i;   xseed( idx++)= imN;   
-      }
-
-      if (nargin >= 4 ) 
-         nb= (int) args(2).double_value();
-   } // holes mode? 
-   else {
-      {
-         ColumnVector tmp( args(2).vector_value() );
-         xseed= tmp;
-      }
-      {
-         ColumnVector tmp( args(1).vector_value() );
-         yseed= tmp;
-      }
-      npoints= xseed.length();
-      if (nargin >= 4 ) 
-         nb= (int) args(3).double_value();
-   } // holes mode? 
-
-/*
- * put a one pixel thick boundary around the image
- *  so that we can be more efficient in the main loop
- */
-   int           ioM=   imM+2;
-   OCTAVE_LOCAL_BUFFER(unsigned char, imo, (imM+2) * (imN+2));
-
-   for (int i=0; i<imM; i++) 
-      for (int j=0; j<imN; j++)
-         imo[(i+1) + ioM*(j+1)]= ( im(i,j) > 0 ) ;
-
-   for (int i=0; i<ioM; i++) 
-      imo[i]= imo[i + ioM*(imN+1)] = 3;
-
-   for (int j=1; j<imN+1; j++)
-      imo[ioM*j]= imo[imM+1 + ioM*j] = 3;
-
-// This is obviously big enough for the point stack, but I'm
-// sure it can be smaller. 
-   OCTAVE_LOCAL_BUFFER(int, ptstack, ioM*imN );
-
-   int seedidx= npoints; 
-   npoints= 0;
-   while ( (--seedidx) >= 0 ) {
-// no need to add 1 to convert indexing style because we're adding a boundary
-      int pt= (int) xseed( seedidx )*ioM + (int) yseed( seedidx ); 
-      checkpoint( pt , imo, ptstack, &npoints );
-   }
-
-   while ( npoints > 0 ) {
-      npoints--;
-      int pt= ptstack[ npoints ];
-      
-      checkpoint( pt + ptLF, imo, ptstack, &npoints );
-      checkpoint( pt + ptRT, imo, ptstack, &npoints );
-      checkpoint( pt + ptUP, imo, ptstack, &npoints );
-      checkpoint( pt + ptDN, imo, ptstack, &npoints );
-      
-      if (nb==8) {
-         checkpoint( pt + ptLF + ptUP, imo, ptstack, &npoints );
-         checkpoint( pt + ptRT + ptUP, imo, ptstack, &npoints );
-         checkpoint( pt + ptLF + ptDN, imo, ptstack, &npoints );
-         checkpoint( pt + ptRT + ptDN, imo, ptstack, &npoints );
-      }
-   } // while ( npoints
-
-   Matrix       imout( imM, imN );
-   ColumnVector idxout (imM*imN );
-   int idx=0;
-
-   int notvalidpt= 0;
-   int idxpoint=   2;
-   if ( fillmode ) {
-      notvalidpt= 2;
-      idxpoint=   0;
-   }
-
-   for (int i=0; i<imM; i++) 
-      for (int j=0; j<imN; j++) {
-         imout(i,j) =    (double) ( imo[(i+1) + ioM*(j+1)] != notvalidpt );
-         if ( imo[(i+1) + ioM*(j+1)] == idxpoint )
-            idxout(idx++) = (double) (i + j*imM + 1);
-      }
-
-   /*
-   Matrix imout( imM+2, imN+2 );
-   for (int i=0; i<imM+2; i++) 
-      for (int j=0; j<imN+2; j++)
-         imout(i,j) = (double) imo[i + ioM*j];
-    */
-
-   retval(0)= imout;
-// we need to do this to be able to return a proper empty vector
-   if (idx > 0) 
-      retval(1)= idxout.extract(0, idx-1);
-   else
-      retval(1)= ColumnVector ( 0 );
-   return retval;
-}
-
-
-/*
- * $Log$
- * Revision 1.7  2006/05/19 06:58:50  jwe
- * *** empty log message ***
- *
- * Revision 1.5  2003/05/15 21:25:40  pkienzle
- * OCTAVE_LOCAL_BUFFER now requires #include <memory>
- *
- * Revision 1.4  2003/03/05 15:31:52  pkienzle
- * Backport to octave-2.1.36
- *
- * Revision 1.3  2003/02/20 23:03:57  pkienzle
- * Use of "T x[n]" where n is not constant is a g++ extension so replace it with
- * OCTAVE_LOCAL_BUFFER(T,x,n), and other things to keep the picky MipsPRO CC
- * compiler happy.
- *
- * Revision 1.2  2002/11/02 10:39:36  pkienzle
- * gcc 3.2 wants \n\ for multi-line strings.
- *
- * Revision 1.1  2002/03/17 02:38:51  aadler
- * fill and edge detection operators
- *
- * Revision 1.9  2000/06/16 20:22:47  aadler
- * mods for 2.1/2.0 compat
- *
- * Revision 1.8  2000/06/13 17:27:24  aadler
- * mods for 2.1.30
- *
- * Revision 1.7  1999/06/10 19:42:12  aadler
- * minor verbose fix
- *
- * Revision 1.6  1999/06/08 16:30:30  aadler
- * bug fix. reversed r,c input arguments
- *
- * Revision 1.5  1999/06/08 15:41:02  aadler
- * now fills in holes
- *
- * Revision 1.4  1999/06/08 15:21:02  aadler
- * fixed bug that so specified points are only used if they can fill
- *
- * Revision 1.3  1999/06/08 15:05:08  aadler
- * now returns 1 and gives index output
- *
- * Revision 1.2  1999/06/04 21:58:57  aadler
- * fixed 8 vs 4 neighborhood
- *
- * Revision 1.1  1999/06/04 21:43:20  aadler
- * Initial revision
- *
- *
- */
deleted file mode 100644
--- a/bwlabel.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-/* ---------------------------------------------------------------------
-
-    bwimage.cc - octave module to label componenets of a binary image
-
-    copyright 2002 Jeffrey E. Boyd
-
-    - uses 4, 6, or 8 connectedness
-    - See BKP Horn, Robot Vision, MIT Press, 1986, p 66 - 71 
-
-    labeling scheme
-
-        +-+-+-+
-        |D|C|E|
-        +-+-+-+
-        |B|A| |
-        +-+-+-+
-        | | | |
-        +-+-+-+
-                
-    A is the center pixel of a neighborhood.  In the 3 versions of
-    connectedness:
-    
-    4:  A connects to B and C
-    6:  A connects to B, C, and D
-    8:  A connects to B, C, D, and E
-    
-    
---------------------------------------------------------------------- */
-
-
-
-#include <oct.h>
-#ifndef OCTAVE_LOCAL_BUFFER
-#include <vector>
-#define OCTAVE_LOCAL_BUFFER(T, buf, size) \
-  std::vector<T> buf ## _vector (size); \
-  T *buf = &(buf ## _vector[0])
-#endif
-
-
-
-#define     NO_OBJECT       0
-#define     MIN(x, y)       (((x) < (y)) ? (x) : (y))
-
-
-
-static int find( int *, int );
-
-static bool any_bad_argument( const octave_value_list& );
-
-
-/*
-%!assert(bwlabel([0 1 0; 0 0 0; 1 0 1]),[0 1 0; 0 0 0; 2 0 3]);
-*/
-DEFUN_DLD(bwlabel, args, ,
-"\n\
-[l,num] = bwlabel( bw, n ) - label foreground components of boolean image\n\
-\n\
-    bw  -   boolean image array\n\
-    n   -   neighborhood connectedness (4, 6,or 8)\n\
-\n\
-    l   -   label image array\n\
-    num -   number of components labeled\n\
-\n\
-    The algorithm is derived from  BKP Horn, Robot Vision, MIT Press,\n\
-    1986, p 65 - 89 \n" )
-{
-    if ( any_bad_argument(args) )
-        return octave_value_list();
-    
-    // input arguments
-    Matrix BW = args(0).matrix_value();     // the input binary image
-    int n;
-    if ( args.length() < 2 ) n = 6;         // n-hood connectivity
-    else n = args(1).int_value(); 
-    int nr = args(0).rows();
-    int nc = args(0).columns();
-    
-    // results
-    Matrix L( nr, nc );     // the label image
-    int nobj;                               // number of objects found in image
-    
-    // other variables
-    int ntable;                             // number of elements in the component table/tree
-    
-    OCTAVE_LOCAL_BUFFER(int, lset, nr * nc);   // label table/tree
-    ntable = 0;
-    lset[0] = 0;
-    
-    for( int r = 0; r < nr; r++ ) {
-        for( int c = 0; c < nc; c++ ) {            
-            if ( BW.elem(r,c) ) {               // if A is an object
-                // get the neighboring pixels B, C, D, and E
-                int B, C, D, E;
-                if ( c == 0 ) B = 0; else B = find( lset, (int)L.elem(r,c-1) );
-                if ( r == 0 ) C = 0; else C = find( lset, (int)L.elem(r-1,c) );
-                if ( r == 0 || c == 0 ) D = 0; else D = find( lset, (int)L.elem(r-1,c-1) );
-                if ( r == 0 || c == nc - 1 ) E = 0;
-                    else E = find( lset, (int)L.elem(r-1,c+1) );
-                    
-                if ( n == 4 ) {
-                    // apply 4 connectedness
-                    if ( B && C ) {        // B and C are labeled
-                        if ( B == C )
-                            L.elem(r,c) = B;
-                        else {
-                            lset[C] = B;
-                            L.elem(r,c) = B;
-                        }
-                    } else if ( B )             // B is object but C is not
-                        L.elem(r,c) = B;
-                    else if ( C )               // C is object but B is not
-                        L.elem(r,c) = C;
-                    else {                      // B, C, D not object - new object
-                        //   label and put into table
-                        ntable++;
-                        L.elem(r,c) = lset[ ntable ] = ntable;
-                    }
-                } else if ( n == 6 ) {
-                    // apply 6 connected ness
-                    if ( D )                    // D object, copy label and move on
-                        L.elem(r,c) = D;
-                    else if ( B && C ) {        // B and C are labeled
-                        if ( B == C )
-                            L.elem(r,c) = B;
-                        else {
-                            int tlabel = MIN(B,C);
-                            lset[B] = tlabel;
-                            lset[C] = tlabel;
-                            L.elem(r,c) = tlabel;
-                        }
-                    } else if ( B )             // B is object but C is not
-                        L.elem(r,c) = B;
-                    else if ( C )               // C is object but B is not
-                        L.elem(r,c) = C;
-                    else {                      // B, C, D not object - new object
-                        //   label and put into table
-                        ntable++;
-                        L.elem(r,c) = lset[ ntable ] = ntable;
-                    }
-                } else if ( n == 8 ) {
-                    // apply 8 connectedness
-                    if ( B || C || D || E ) {
-                        int tlabel = B;
-                        if ( B ) tlabel = B;
-                        else if ( C ) tlabel = C;
-                        else if ( D ) tlabel = D;
-                        else if ( E ) tlabel = E;
-                        L.elem(r,c) = tlabel;
-                        if ( B && B != tlabel ) lset[B] = tlabel;
-                        if ( C && C != tlabel ) lset[C] = tlabel;
-                        if ( D && D != tlabel ) lset[D] = tlabel;
-                        if ( E && E != tlabel ) lset[E] = tlabel;
-                    } else {
-                        //   label and put into table
-                        ntable++;
-                        L.elem(r,c) = lset[ ntable ] = ntable;
-                    }
-                }
-            } else {
-                L.elem(r,c) = NO_OBJECT;      // A is not an object so leave it
-            }
-        }
-    }
-    
-    // consolidate component table
-    for( int i = 0; i <= ntable; i++ )
-        lset[i] = find( lset, i );
-
-    // run image through the look-up table
-    for( int r = 0; r < nr; r++ )
-        for( int c = 0; c < nc; c++ )
-            L.elem(r,c) = lset[ (int)L.elem(r,c) ];
-    
-    // count up the objects in the image
-    for( int i = 0; i <= ntable; i++ )
-        lset[i] = 0;
-
-    for( int r = 0; r < nr; r++ )
-        for( int c = 0; c < nc; c++ )
-            lset[ (int)L.elem(r,c) ]++;
-
-    // number the objects from 1 through n objects
-    nobj = 0;
-    lset[0] = 0;
-    for( int i = 1; i <= ntable; i++ )
-        if ( lset[i] > 0 )
-            lset[i] = ++nobj;
-
-    // run through the look-up table again
-    for( int r = 0; r < nr; r++ )
-        for( int c = 0; c < nc; c++ )
-            L.elem(r,c) = lset[ (int)L.elem(r,c) ];
-
-    octave_value_list rval;
-    rval(0) = L;
-    rval(1) = (double)nobj;
-    return rval;
-}
-
-
-static bool any_bad_argument( const octave_value_list& args )
-{
-    if ( args.length() < 1 || args.length() > 2 ) {
-        error( "bwlabel: number of arguments - expecting bwlabel(bw) or bwlabel(bw,n)" );
-        return true;
-    }
-    
-    if ( !args(0).is_matrix_type() ) {
-        error( "bwlabel: matrix expected for first argument" );
-        return true;
-    }
-    
-    if ( args.length() == 2 ) {
-        if ( !args(1).is_real_scalar() ) {
-            error( "bwlabel: expecting real scalar for second argument" );
-            return true;
-        }
-        int n = args(1).int_value();
-        if ( n != 4 && n != 6 && n != 8 ) {
-            error( "bwlabel: in bwlabel(BW,n) n must be in {4,6,8}" );
-            return true;
-        }
-    }
-    
-    return false;
-    
-}
-
-
-static int find( int set[], int x )
-{
-    int r = x;
-    while ( set[r] != r )
-        r = set[r];
-    return r;
-}
-
deleted file mode 100644
--- a/bwlabel.m
+++ /dev/null
@@ -1,231 +0,0 @@
-## Copyright (C) 2000  Etienne Grossmann
-##
-## 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
-
-##       [im2,npix,bb] = bwlabel(im, mins, maxs, verbose)
-##
-## Find the connected regions of an image.
-##  
-## im  : RxC 0-1 matrix
-##
-## im2 : RxC int matrix in which the connected regions of im have been
-##       numbered. 4-neighborhoods are considered.
-##
-## npix : 1xQ int number of pixel in each region
-##
-## bb   : 4xQ int bounding boxes of the regions. Rows are minrow,
-##        maxrow, mincol, maxcol.
-##
-## Options :
-##
-## mins     : Minimum size of the regions (set to zero for no minimum)
-## maxs     : Maximum size of the regions (set to zero for no maximum)
-## verbose  : Level of output comments in range 0 to 2.
-##
-
-## Author:        Etienne Grossmann <etienne@cs.uky.edu>
-## Last modified: July 2002
-##
-
-## Modified by David Fletcher <david@megapico.co.uk> to avoid artificially
-## separate regions which actually touch (as indicated when "prudent" is set)
-## through addition of lrow update within loop over touching regions. Also
-## removed "sayif" function references, and call to read_options. Enabled
-## options, setting of output verbosity. "Prudent" is left in place, but
-## should no longer find any errors.
-
-function [im2,npix,bb] = bwlabel(im, mins, maxs, verbose)
-
-  if (nargin == 1)
-    mins = 0;
-    maxs = 0;
-    prudent = 1;
-    verbose = 0;
-  elseif (nargin == 2)
-    maxs = 0;
-    prudent = 1;
-    verbose = 0;
-  elseif (nargin == 3)
-    prudent = 1;
-    verbose = 0;
-  elseif ((nargin == 4) && (verbose >= 0) && (verbose <= 2))
-    prudent = 1;
-  else
-    usage ("bwlabel2(im, mins, maxs, verbose)");
-  endif
-
-if any(im(:)&im(:)!=1),
-  printf("bwlabel : im is not binary\n");
-  return
-end
-
-
-[R,C]=size(im);
-tr = 0 ;
-				# Loop as little as possible
-if R<C, tr = 1; im = im' ; [R,C]=size(im); end
-
-gsize = 100 ;			# Predicted number of slices
-
-im2 = zeros(R,C);
-				# find horizontal up/down going edges
-imup =  max(im2, diff([zeros(1,C);im])) ;
-imdo = -min(im2, diff([im;zeros(1,C)])) ;
-
-im2 = ones(R,C);
-######################################################################
-## Find connected regions ############################################
-
-rc = 1 ;			# Counter of region slices 
-
-rnum = ones(1,gsize);		# List of labels of each slice
-npix = zeros(1,gsize);		# Sizes of regions (actual size is in
-				# region's first slice)
-bb = zeros(4,gsize);		# Bounding boxes
-
-if (verbose >= 1) printf("bwlabel : There will be %i loops ... \n%5i ",C,0) ; endif;
-
-lrow = zeros(R,1);		# Last treated image column
- 
-for i=1:C,
-  t1 = find(imup(:,i)) ;
-  t2 = find(imdo(:,i)) ;
-  
-  nrow = zeros(R,1);		# Next row
-
-  for j = 1:rows(t1(:)) ,	# Loop over slices of i'th column
-
-    rc++ ;			# rc = number of current slice.
-    im2(t1(j):t2(j),i) = rc ;
-				# Slices from previous column that touch
-				# this slice.
-    rr = create_set(lrow(t1(j):t2(j))) ;
-    if !isempty(rr) && !rr(1), rr = rr(2:length(rr)) ; end
-
-    if rc>size(rnum,2),		# Get more space (uncertain effect on
-				# speed; avoids resizing rnum and npix)
-      tmp = 2*(ceil(C*rc/i)-rc+1+rows(t1(:))-j) ;
-      if (verbose == 2) printf("bwlabel : (i=%i) Foreseeing %i more regions\n",i,tmp); endif;
-      rnum = [ rnum, ones(1,tmp) ] ;
-      npix = [ npix,zeros(1,tmp) ] ;
-      bb = [ bb,zeros(4,tmp) ] ;
-    end
-
-    if isempty(rr),			# New region 
-      if (verbose == 2) printf("bwlabel : creating region %i\n",rc); endif;
-
-      r0 = rc ;			# r0 = number of the region
-
-      bb(1,r0) = t1(j) ;
-      bb(2,r0) = t2(j) ;
-      bb(3:4,r0) = i ;
-
-    else			# Add to already existing region #####
-
-      r0 = rnum(rr(1)) ;
-      [i, j, r0];
-
-      bb(1,r0) = min(bb(1,r0),t1(j)) ;
-      bb(2,r0) = max(bb(2,r0),t2(j)) ;
-      bb(4,r0) = i ;
-
-				# Touches region r0
-      if (verbose == 2) printf("bwlabel : adding to region %i\n",r0); endif;
-
-				# Touches other regions too
-      for k = rr(find(rr!=r0)),	# Loop over other touching regions, that
-				# should be merged to the first.
-	if (verbose == 2) printf("bwlabel : merging regions %i and %i\n",k,r0); endif;
-	rnum(find(rnum==k)) = r0 ;
-	lrow(find(lrow==k)) = r0 ; ##Update lrow for next comparsion loop
-	npix(r0) = npix(r0) + npix(k) ;
-	bb([1,3],r0) = min(bb([1,3],r0)',bb([1,3],k)')' ;
-	bb([2,4],r0) = max(bb([2,4],r0)',bb([2,4],k)')' ;
-      end
-      
-    end				# End of add to already existing region
-    ## if r0==259 && i==39,"r0==259",keyboard;end
-    rnum(rc) = r0 ;
-
-    npix(r0) = npix(r0) + 1+t2(j)-t1(j) ;
-
-    nrow(t1(j):t2(j)) = r0 ;
-  end				# End of looping over slices
-  lrow = nrow ;
-  if (verbose >= 1)
-    printf(".");
-    if (!rem(i,70) && i<C) printf("\n%5i ",i); end
-  end
-end				# End of looping over columns
-
-if (verbose >= 1) printf("\n"); endif;
-
-keep = ones(1,rc) ; 
-
-if mins, keep = keep & (npix(rnum(1:rc))>=mins) ; end
-if maxs, keep = keep & (npix(rnum(1:rc))<=maxs) ; end
-keep(1) = 1 ;
-keep = find(keep) ;		# Indices of slices to be kept
-
-foo = create_set(rnum(keep)) ;	# Indices of regions to be kept
-nr = prod(size(foo)) ;		# Number of regions (including bg)
-## lrow = zeros(1,nr) ;
-tmp = zeros(1,rc) ;
-tmp(foo) = 0:nr-1 ;
-
-bar = zeros(1,rc) ;
-bar(keep) = tmp(rnum(keep)) ;
-
-## keyboard
-
-im2 = reshape(bar(im2),R,C) ;
-
-npix = npix(foo(2:nr));
-bb = bb(:,foo(2:nr));
-
-if 0,				# Draw bb on the image (will ruin
-				# coherence)
-  for i=1:nr-1,
-    im2([bb(1,i),bb(2,i)] ,bb(3,i):bb(4,i) ) = i ;
-    im2( bb(1,i):bb(2,i) ,[bb(3,i),bb(4,i)]) = i ;
-  end
-end
-
-## keyboard
-if prudent,
-
-  if (verbose >= 1) printf("bwlabel : Checking coherence\n"); endif;
-
-  hcontact = im2 & im2!=[im2(:,2:C),zeros(R,1)] & [im2(:,2:C),zeros(R,1)] ;
-  vcontact = im2 & im2!=[im2(2:R,:);zeros(1,C)] & [im2(2:R,:);zeros(1,C)] ;
-  ok = 1 ;
-  if (any(hcontact(:)))
-    if (verbose == 2) [x,y] = find(hcontact) endif; 
-    ok = 0 ;
-    printf("bwlabel: Whoa! Found horizontally connected separated regions\n");
-  end
-  if (any(vcontact(:)))
-    if (verbose == 2)[x,y] = find(vcontact) endif; 
-    ok = 0 ;
-    printf("bwlabel: Whoa! Found vertically connected separated regions\n");
-  end
-  if !ok, keyboard ; end
-end
-
-## Eventually transpose result
-if tr, 
-  im2 = im2' ; 
-  bb = bb([3,4,1,2],:);
-end
deleted file mode 100644
--- a/bwmorph.m
+++ /dev/null
@@ -1,611 +0,0 @@
-## 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{BW2} = } bwmorph (@var{BW},@var{operation})
-## @deftypefnx {Function File} {@var{BW2} = } bwmorph (@var{BW},@var{operation},@var{n})
-## Perform a morphological operation on a binary image
-##
-## BW2=bwmorph(BW,operation) performs a morphological operation
-## specified by @var{operation} on binary image @var{BW}. All possible
-## operations and their meaning are specified in a table below.
-##
-## BW2=bwmorph(BW,operation,n) performs a morphological operation
-## @var{n} times. Keep in mind that it has no sense to apply some
-## operations more than once, since some of them return the same result
-## regardless how many iterations we request. Those return a warning if
-## are called with n>1 and they compute the result for n=1.
-##
-## @var{n}>1 is actually used for the following operations: diag,
-## dilate, erode, majority, shrink, skel, spur, thicken and thin.
-##
-## @table @code
-## @item 'bothat'
-## Performs a bottom hat operation, a closing operation (which is a
-## dilation followed by an erosion) and finally substracts the original
-## image.
-##
-## @item 'bridge'
-## Performs a bridge operation. Sets a pixel to 1 if it has two nonzero
-## neighbours which are not connected, so it "bridges" them. There are
-## 119 3-by-3 patterns which trigger setting a pixel to 1.
-##
-## @item 'clean'
-## Performs an isolated pixel remove operation. Sets a pixel to 0 if all
-## of its eight-connected neighbours are 0.
-##
-## @item 'close'
-## Performs closing operation, which is a dilation followed by erosion.
-## It uses a ones(3) matrix as structuring element for both operations.
-##
-## @item 'diag'
-## Performs a diagonal fill operation. Sets a pixel to 1 if that
-## eliminates eight-connectivity of the background.
-##
-## @item 'dilate'
-## Performs a dilation operation. It uses ones(3) as structuring element.
-##
-## @item 'erode'
-## Performs an erosion operation. It uses ones(3) as structuring element.
-##
-## @item 'fill'
-## Performs a interior fill operation. Sets a pixel to 1 if all
-## four-connected pixels are 1.
-##
-## @item 'hbreak'
-## Performs a H-break operation. Breaks (sets to 0) pixels that are
-## H-connected.
-##
-## @item 'majority'
-## Performs a majority black operation. Sets a pixel to 1 if five
-## or more pixels in a 3-by-3 window are 1. If not it is set to 0.
-##
-## @item 'open'
-## Performs an opening operation, which is an erosion followed by a
-## dilation. It uses ones(3) as structuring element.
-##
-## @item 'remove'
-## Performs a iterior pixel remove operation. Sets a pixel to 0 if 
-## all of its four-connected neighbours are 1.
-##
-## @item 'shrink'
-## Performs a shrink operation. Sets pixels to 0 such that an object
-## without holes erodes to a single pixel (set to 1) at or near its
-## center of mass. An object with holes erodes to a connected ring lying
-## midway between each hole and its nearest outer boundary. It preserves
-## Euler number.
-##
-## @item 'skel'
-## Performs a skeletonization operation. It calculates a "median axis
-## skeleton" so that points of this skeleton are at the same distance of
-## its nearby borders. It preserver Euler number. Please read
-## compatibility notes for more info.
-##
-## It uses the same algorithm as skel-pratt but this could change for
-## compatibility in the future.
-##
-## @item 'skel-lantuejol'
-## Performs a skeletonization operation as described in Gonzalez & Woods
-## "Digital Image Processing" pp 538-540. The text references Lantuejoul
-## as authour of this algorithm.
-##
-## It has the beauty of being a clean and simple approach, but skeletons
-## are thicker than they need to and, in addition, not guaranteed to be
-## connected.
-##
-## This algorithm is iterative. It will be applied the minimum value of
-## @var{n} times or number of iterations specified in algorithm
-## description. It's most useful to run this algorithm with @code{n=Inf}.
-##
-## @item 'skel-pratt'
-## Performs a skeletonization operation as described by William K. Pratt
-## in "Digital Image Processing".
-##
-## @item 'spur'
-## Performs a remove spur operation. It sets pixel to 0 if it has only
-## one eight-connected pixel in its neighbourhood.
-##
-## @item 'thicken'
-## Performs a thickening operation. This operation "thickens" objects
-## avoiding their fusion. Its implemented as a thinning of the
-## background. That is, thinning on negated image. Finally a diagonal
-## fill operation is performed to avoid "eight-connecting" objects.
-##
-## @item 'thin'
-## Performs a thinning operation. When n=Inf, thinning sets pixels to 0
-## such that an object without holes is converted to a stroke
-## equidistant from its nearest outer boundaries. If the object has
-## holes it creates a ring midway between each hole and its near outer
-## boundary. This differ from shrink in that shrink converts objects
-## without holes to a single pixels and thin to a stroke. It preserves
-## Euler number.
-##
-## @item 'tophat'
-## Performs a top hat operation, a opening operation (which is an
-## erosion followed by a dilation) and finally substracts the original
-## image.
-## @end table
-##
-## Some useful concepts to understant operators:
-##
-## Operations are defined on 3-by-3 blocks of data, where the pixel in
-## the center of the block. Those pixels are numerated as follows:
-##
-## @multitable @columnfractions 0.05 0.05 0.05
-## @item X3 @tab X2 @tab X1
-## @item X4 @tab  X @tab X0
-## @item X5 @tab X6 @tab X7
-## @end multitable
-##
-## @strong{Neighbourhood definitions used in operation descriptions:}
-## @table @code
-## @item 'four-connected'
-## It refers to pixels which are connected horizontally or vertically to
-## X: X1, X3, X5 and X7.
-## @item 'eight-connected'
-## It refers to all pixels which are connected to X: X0, X1, X2, X3, X4,
-## X5, X6 and X7.
-## @end table
-## 
-## @strong{Compatibility notes:}
-## @table @code
-## @item 'fill'
-## Checking MATLAB behaviour is needed because its documentation doesn't
-## make clear if it creates a black pixel if all eight-connected pixels
-## are black or if four-connected suffice (as we do currently following
-## Pratt's book).
-## @item 'skel'
-## Algorithm used here is described in Pratt's book. When applying it to
-## the "circles" image in MATLAB documentation, results are not the
-## same. Perhaps MATLAB uses Blum's algoritm (for further info please
-## read comments in code).
-## @item 'skel-pratt'
-## This option is not available in MATLAB.
-## @item 'skel-lantuejoul'
-## This option is not available in MATLAB.
-## @item 'thicken'
-## This implementation also thickens image borders. This can easily be
-## avoided i necessary. MATLAB documentation doesn't state how it behaves.
-## @end table
-##
-## References:
-## W. K. Pratt, "Digital Image Processing"
-## Gonzalez and Woods, "Digital Image Processing"
-##
-## @end deftypefn
-## @seealso dilate erode makelut applylut
-
-
-## TODO: As soon as Octave doesn't segfault when assigning values to a
-## TODO: bool matrix, remove all conversions from lut to logical and
-## TODO: just create it as a logical from the beginning.
-
-## TODO: n behaviour should be tested in all cases for compatibility.
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function BW2 = bwmorph(BW, operation, n)
-  if(nargin<2 || nargin>3)
-    usage("BW2=bwmorph(BW, operation [,n])");
-  endif
-  if(nargin<3)
-    n=1;
-  endif
-  if(n<0)
-    error("bwmorph: n should be > 0");
-  elseif(n==0) ## we'll just return the same matrix (check this!)
-    BW2=BW;
-  endif
-
-  ## post processing command
-  postcmd="";
-    
-  switch(operation)
-    case('bothat')
-      se=ones(3);
-      BW2=erode(dilate(BW, se), se)-BW;
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok. Should I just ignore it
-	## TODO: without a warning?
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('bridge')
-      ## see __bridge_lut_fun__ for rules
-      ## lut=makelut("__bridge_lut_fun__",3);
-      lut=logical([0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   1;1;1;1;1;1;1;1;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   1;1;1;1;1;1;1;1;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      BW2=applylut(BW, lut);
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('clean')
-      ## BW(j,k)=X&&(X0||X1||...||X7)
-      ## lut=makelut(inline("x(2,2)&&any((x.*[1,1,1;1,0,1;1,1,1])(:))","x"),3);
-      ## which is the same as...
-      lut=repmat([zeros(16,1);ones(16,1)],16,1);  ## identity
-      lut(17)=0;                                  ## isolated to 0
-      ## I'd prefer to create lut directly as a logical, but assigning a
-      ## value to a logical segfaults 2.1.57. We'll change it as soon as
-      ## it works.
-      BW2=applylut(BW, logical(lut));
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('close')
-      se=ones(3);
-      BW2=erode(dilate(BW, se), se);
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('diag')
-      ## see __diagonal_fill_lut_fun__ for rules
-      ## lut=makelut("__diagonal_fill_lut_fun__",3);
-      lut=logical([0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      cmd="BW2=applylut(BW, lut);";
-      
-
-    case('dilate')
-      cmd="BW2=dilate(BW, ones(3));";
-
-    case('erode')
-      cmd="BW2=erode(BW, ones(3));";
-      
-    case('fill')
-      ## lut=makelut(inline("x(2,2)||(sum((x&[0,1,0;1,0,1;0,1,0])(:))==4)","x"),3);
-      ## which is the same as...
-      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
-      ## 16 exceptions
-      lut([171,172,175,176,235,236,239,240,427,428,431,432,491,492,495,496])=1;
-      BW2=applylut(BW, logical(lut));
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-
-    case('hbreak')
-      ## lut=makelut(inline("x(2,2)&&!(all(x==[1,1,1;0,1,0;1,1,1])||all(x==[1,0,1;1,1,1;1,0,1]))","x"),3);
-      ## which is the same as
-      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
-      lut([382,472])=0;                          ## the 2 exceptions
-      BW2=applylut(BW, logical(lut));
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('majority')
-      ## lut=makelut(inline("sum((x&ones(3,3))(:))>=5"),3);
-      lut=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
-		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		   0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      cmd="BW2=applylut(BW, lut);";
-
-    case('open')
-      se=ones(3);
-      BW2=dilate(erode(BW, se), se);
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-    case('remove')
-      ## lut=makelut(inline("x(2,2)&&!(sum((x&[0,1,0;1,1,1;0,1,0])(:))==5)","x"),3);
-      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
-      ## 16 qualifying patterns
-      lut([187,188,191,192,251,252,255,256,443,444,447,448,507,508,511,512])=0;
-      BW2=applylut(BW, logical(lut));
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-      
-    case('shrink')
-      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"S");
-      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;0;1;1;1;1;0;1;0;0;1;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;1;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;0;1;1;0;0]);
-      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'S')","m"),3);
-      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;0;0;1;0;0;0;0;0;1;0;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;0;0;0;0;0;0;1;1;0;0;1;0;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;0;0;0;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;1;0;1;0;0;1;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;1;1;0;1;0;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;0;0;1;0;1;0;0;1;0;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;0;0;1;0;1;0;0;1;0;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
-
-    case({'skel','skel-pratt'})
-      ## WARNING: Result doesn't look as MATLAB's sample. It has been
-      ## WARNING: coded following Pratt's guidelines for what he calls
-      ## WARNING: is a "reasonably close approximation". I couldn't find
-      ## WARNING: any bug.
-      ## WARNING: Perhaps MATLAB uses Blum's algorithm (which Pratt
-      ## WARNING: refers to) in: H. Blum, "A Transformation for
-      ## WARNING: Extracting New Descriptors of Shape", Symposium Models
-      ## WARNING: for Perception of Speech and Visual Form, W.
-      ## WARNING: Whaten-Dunn, Ed. MIT Press, Cambridge, MA, 1967.
-
-      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"K");
-      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;1;1;1;1;0]);
-
-      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'K')","m"),3);
-      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;0;1;0;0;0;1;0;1;1;0;0;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;0;0;1;1;0;0;1;1;0;0;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;0;0;0;1;0;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;1;1;0;1;1;1;0;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;0;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
-      postcmd="BW2=bwmorph(BW2,'bridge');";
-
-    case('skel-lantuejoul')
-      ## init values
-      se=ones(3,3);              ## structuring element used everywhere
-      BW2=zeros(size(BW));       ## skeleton result
-      eBW=BW;                    ## eBW will hold k-times eroded BW
-      i=1;
-      while i<=n
-	if(!any(eBW))            ## if erosion result is 0-matrix then
-	  break;                 ## we are over
-	endif
-	BW2|=eBW-dilate(erode(eBW, se), se); ## eBW - opening operation on eBW
-                                  	     ## contributes to skeleton
-	eBW=erode(eBW,se);        
-	i++;
-      endwhile
-      return;                    ## no general loop in this case
-
-    case('spur')
-      ## lut=makelut(inline("xor(x(2,2),(sum((x&[0,1,0;1,0,1;0,1,0])(:))==0)&&(sum((x&[1,0,1;0,0,0;1,0,1])(:))==1)&&x(2,2))","x"),3);
-      ## which is the same as
-      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
-      lut([18,21,81,273])=0; ## 4 qualifying patterns
-      lut=logical(lut);
-      cmd="BW2=applylut(BW, lut);";
-
-    case('thicken')
-      ## This implementation also "thickens" the border. To avoid this,
-      ## a simple solution could be to add a border of 1 to the reversed
-      ## image.
-      BW2=bwmorph(!BW,'thin',n);
-      BW2=bwmorph(BW2,'diag');
-      return;
-
-    case('thin')
-      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"T");
-      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;0;1;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;0;0;0;0;0;0;0;0;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
-		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;0;1;1;0;0]);
-      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'T')","m"),3);
-      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;1;1;0;1;0;1;1;0;0;0;0;1;0;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;0;0;0;0;0;1;1;0;0;1;0;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;1;0;0;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;0;1;0;0;1;0;1;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;1;1;0;1;0;1;0;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;0;1;0;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;0;1;0;0;1;0;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
-		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
-      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
-
-
-    case('tophat')
-      se=ones(3);
-      BW2=BW-dilate(erode(BW, se), se);
-      if(n>1)
-	## TODO: check if ignoring n>1 is ok.
-	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
-      endif
-      return;
-
-
-    otherwise
-      error("bwmorph: unknown operation type requested.");
-  endswitch
-
-  ## we use this assignment because of the swap operation inside the
-  ## while.
-  BW2=BW;
-
-  ## if it doesn't change we don't need to process it further
-  i=1;
-  while(i<=n) ## for wouldn't work because n can be Inf
-    [BW,BW2]=swap(BW,BW2);
-    eval(cmd);
-    if(all((BW2==BW)(:)))
-      break
-    endif
-    i+=1;
-  endwhile
-
-  ## process post processing commands if needed
-  if(postcmd!="")
-    eval(postcmd);
-  endif
-
-endfunction
-
-
-%!demo
-%! bwmorph(ones(11),'shrink', Inf)
-%! # Should return 0 matrix with 1 pixel set to 1 at (6,6)
-
-## TODO: code tests 
-
-
-## Test skel-lantuejoul using Gozalez&Woods example (fig 8.39)
-%!shared slBW, rslBW
-%! uint8(0); # fail for 2.1.57 or less instead of crashing later
-%! slBW=logical(zeros(12,7));
-%! slBW(2,2)=true;
-%! slBW(3:4,3:4)=true;
-%! rslBW=slBW;
-%! slBW(5:6,3:5)=true;
-%! slBW(7:11,2:6)=true;
-%! rslBW([6,7,9],4)=true;
-
-%!assert(bwmorph(slBW,'skel-lantuejoul',1),[rslBW(1:5,:);logical(zeros(7,7))]);
-%!assert(bwmorph(slBW,'skel-lantuejoul',2),[rslBW(1:8,:);logical(zeros(4,7))]);
-%!assert(bwmorph(slBW,'skel-lantuejoul',3),rslBW);
-%!assert(bwmorph(slBW,'skel-lantuejoul',Inf),rslBW);
-
-
-%
-% $Log$
-% Revision 1.6  2004/09/16 02:14:40  pkienzle
-% Use frivolous uint8() call to block tests for version 2.1.57 and earlier
-%
-% Revision 1.5  2004/09/15 20:36:57  jmones
-% logical(1) => true
-%
-% Revision 1.4  2004/09/15 20:00:00  jmones
-% Updated tests to match Gonzalez&Woods example
-%
-% Revision 1.3  2004/09/15 13:51:10  pkienzle
-% Use logical in tests; reduce number of shared variables in tests.
-%
-% Revision 1.2  2004/09/01 22:35:47  jmones
-% Added Lantuejoul skeletonizing algorithm from Gonzalez&Woods
-%
-% Revision 1.1  2004/08/15 19:47:04  jmones
-% bwmorph added: Perform a morphological operation on a binary image
-%
-%
deleted file mode 100644
--- a/bwselect.m
+++ /dev/null
@@ -1,37 +0,0 @@
-function [imout, idx] = bwselect( im, cols, rows, connect )
-# BWSELECT: select connected regions in a binary image
-# [imout, idx] = bwselect( im, cols, rows, connect )
-#
-#   im          -> binary input image
-#   [cols,rows] -> vectors of starting points (x,y)
-#   connect     -> connectedness 4 or 8. default is 8
-#   imout       -> the image of all objects in image im that overlap
-#                  pixels in (cols,rows)
-#   idx         -> index of pixels in imout
-
-# Copyright (C) 1999 Andy Adler
-# This code has no warrany whatsoever.
-# Do what you like with this code as long as you
-#     leave this copyright in place.
-#
-# $Id$
-
-if nargin<4
-   connect= 8;
-end
-
-[jnk,idx]= bwfill( ~im, cols,rows, connect );
-
-imout= zeros( size(jnk) );
-imout( idx ) = 1;
-
-# 
-# $Log$
-# Revision 1.1  2002/03/17 02:38:52  aadler
-# fill and edge detection operators
-#
-# Revision 1.1  1999/06/08 17:06:01  aadler
-# Initial revision
-#
-#
-
deleted file mode 100644
--- a/cmpermute.m
+++ /dev/null
@@ -1,124 +0,0 @@
-## 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{Y}, @var{newmap}] = } cmpermute (@var{X},@var{map})
-## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmpermute (@var{X},@var{map},@var{index})
-## Reorders colors in a colormap
-##
-## @code{[Y,newmap]=cmpermute(X,map)} rearranges colormap @var{map}
-## randomly returning colormap @var{newmap} and generates indexed image
-## @var{Y} so that it mantains correspondence between indices and the
-## colormap from original indexed image @var{X} (both image and colormap
-## pairs produce the same result).
-##
-## @code{[Y,newmap]=cmpermute(X,map,index)} behaves as described above
-## but instead of sorting colors randomly, it uses @var{index} to define
-## the order of the colors in the new colormap.
-##
-## @strong{Note:} @code{index} shouldn't have repeated elements, this
-## function won't explicitly check this, but it will fail if it has.
-##
-## @end deftypefn
-
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function [Y, newmap] = cmpermute(X, map, index)
-  switch(nargin)
-    case(2)
-      index=randperm(rows(map));
-    case(3)
-      if(!isvector(index) || length(index)!=rows(map))
-	error("cmpermute: invalid parameter index.");
-      endif
-    otherwise
-      usage("[Y, newmap] = cmpermute(X, map [, index])");
-  endswitch
-
-  ## new colormap
-  newmap=map(index,:);
-
-  ## build reverse index
-  rindex = zeros(size(index));
-  rindex(index) = 1:length(index);
- 
-  ## readapt indices
-  if(isa(X,"uint8"))
-    rindex=uint8(rindex-1);
-    ## 0-based indices
-    Y=rindex(double(X)+1);
-  else
-    Y=rindex(X);
-  endif
-endfunction
-
-
-%!demo
-%! [Y,newmap]=cmpermute([1:4],hot(4),4:-1:1)
-%! # colormap will be arranged in reverse order (so will image)
-
-%!shared X,map
-%! X=magic(16);
-%! [X,map]=cmunique(X);
-
-%!test # random permutation, 0-based index
-%! [Y,newmap]=cmpermute(X,map);
-%! # test we didn't lose colors
-%! assert(sort(map),sortrows(newmap)); 
-%! # test if images are equal
-%! assert(map(double(X)+1),newmap(double(Y)+1));
-
-%!test # reverse map, 0-based index
-%! [Y,newmap]=cmpermute(X,map,rows(map):-1:1);
-%! # we expect a reversed colormap
-%! assert(newmap(rows(newmap):-1:1,:),map);
-%! # we expect reversed indices in image
-%! assert(X,max(Y(:))-Y);
-
-%!shared X,map
-%! X=magic(20);
-%! [X,map]=cmunique(X);
-
-%!test # random permutation, 1-based index
-%! [Y,newmap]=cmpermute(X,map);
-%! # test we didn't lose colors
-%! assert(sort(map),sortrows(newmap)); 
-%! # test if images are equal
-%! assert(map(X),newmap(Y));
-
-%!test # reverse map, 1-based index
-%! [Y,newmap]=cmpermute(X,map,rows(map):-1:1);
-%! # we expect a reversed colormap
-%! assert(newmap(rows(newmap):-1:1,:),map);
-%! # we expect reversed indices in image
-%! assert(X,max(Y(:))+1-Y);
-
-%
-% $Log$
-% Revision 1.4  2004/09/08 15:01:28  pkienzle
-% Redo tests: reduce # of shared variables; force full range of uint8
-%
-% Revision 1.3  2004/09/08 14:13:08  jmones
-% Synchronized with cmunique. uint8 support added. Tests working for 2.1.58
-%
-% Revision 1.2  2004/08/18 14:57:42  jmones
-% speed improvement suggested by Paul Kienzle
-%
-% Revision 1.1  2004/08/17 19:18:42  jmones
-% cmpermute added: Reorders colors in a colormap
-%
-%
deleted file mode 100644
--- a/cmunique.m
+++ /dev/null
@@ -1,203 +0,0 @@
-## 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{Y}, @var{newmap}] = } cmunique (@var{X},@var{map})
-## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{RGB})
-## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{I})
-## Finds colormap with unique colors and corresponding image
-##
-## @code{[Y,newmap]=cmunique(X,map)} returns an indexed image @var{y}
-## along with its associated colormap @var{newmap} equivalent (which
-## produce the same image) to supplied @var{X} and its colormap
-## @var{map}; but eliminating any repeated rows in colormap colors and
-## adjusting indices in the image matrix as needed.
-##
-## @code{[Y,newmap]=cmunique(RGB)} returns an indexed image @var{y}
-## along with its associated colormap @var{newmap} computed from a
-## true-color image @var{RGB} (a m-by-n-by-3 array), where @var{newmap}
-## is the smallest colormap possible (alhough it could be as long as
-## number of pixels in image).
-##
-## @code{[Y,newmap]=cmunique(I)} returns an indexed image @var{y}
-## along with its associated colormap @var{newmap} computed from a
-## intensity image @var{I}, where @var{newmap} is the smallest
-## colormap possible (alhough it could be as long as number of pixels
-## in image).
-##
-## @strong{Notes:}
-##
-## @var{newmap} is always a @var{m}-by-3 matrix, even if input image is
-## a intensity grey-scale image @var{I} (all three RGB planes are
-## assigned the same value).
-##
-## @var{newmap} is always of class double. If we use a RGB or intensity
-## image of class uint8 or uint16, the colors in the colormap will be of
-## class double in the range [0,1] (they are divided by intmax("uint8")
-## and intmax("uint16") respectively.
-##
-## @end deftypefn
-
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function [Y, newmap] = cmunique(P1, P2)
-  if (nargin<1 || nargin>2)
-    usage("[Y, newmap] = cmunique(X, map), [Y, newmap] = cmunique(RGB), [Y, newmap] = cmunique(I)");
-  endif
-  
-
-  if(nargin==2)
-    ## (X, map) case
-    [newmap,i,j]=unique(P2,'rows');                 ## calculate unique colormap
-    if(isa(P1,"double"))
-      Y=j(P1);                                      ## find new indices
-    else
-      Y=j(double(P1)+1);                            ## find new indices
-    endif
-  else
-    switch(size(P1,3))
-      case(1)
-	## I case
-	[newmap,i,j]=unique(P1);                        ## calculate unique colormap
-	newmap=repmat(newmap,1,3);                      ## get a RGB colormap
-	Y=reshape(j,rows(P1),columns(P1));              ## Y is j reshaped
-      case(3)
-	## RGB case
-	map=[P1(:,:,1)(:), P1(:,:,2)(:), P1(:,:,3)(:)]; ## build a map with all values
-	[newmap,i,j]=unique(map, 'rows');               ## calculate unique colormap
-	Y=reshape(j,rows(P1),columns(P1));              ## Y is j reshaped
-      otherwise
-	error("cmunique: first parameter is invalid.");
-    endswitch
-    
-    ## if image was uint8 or uint16 we have to convert newmap to [0,1] range
-    if(!isa(P1,"double"))
-      newmap=double(newmap)/double(intmax(class(P1)));
-    endif
-  endif
-
-  if(rows(newmap)<=256)
-    ## convert Y to uint8 (0-based indices then)
-    Y=uint8(Y-1);
-  endif
-
-  
-endfunction
-
-
-%!demo
-%! [Y,newmap]=cmunique([1:4;5:8],[hot(4);hot(4)])
-%! # Both rows are equal since map maps colors to the same value
-%! # cmunique will give the same indices to both
-
-
-%!# This triggers invalid first parameter
-%!error(cmunique(zeros(3,3,2)));
-
-%!# Check that output is uint8 in short colormaps
-%!test
-%! [Y,newmap]=cmunique([1:4;5:8], [hot(4);hot(4)]);
-%! assert(Y,uint8([0:3;0:3]));
-%! assert(newmap,hot(4));
-
-%!# Check that output is double in bigger
-%!test
-%! [Y,newmap]=cmunique([1:300;301:600], [hot(300);hot(300)]);
-%! assert(Y,[1:300;1:300]);
-%! assert(newmap,hot(300));
-
-%!# Check boundary case 256
-%!test
-%! [Y,newmap]=cmunique([1:256;257:512], [hot(256);hot(256)]);
-%! assert(Y,uint8([0:255;0:255]));
-%! assert(newmap,hot(256));
-
-%!# Check boundary case 257
-%!test
-%! [Y,newmap]=cmunique([1:257;258:514], [hot(257);hot(257)]);
-%! assert(Y,[1:257;1:257]);
-%! assert(newmap,hot(257));
-
-%!# Random RGB image
-%!test
-%! RGB=rand(10,10,3);
-%! [Y,newmap]=cmunique(RGB);
-%! assert(RGB(:,:,1),newmap(:,1)(Y+1));
-%! assert(RGB(:,:,2),newmap(:,2)(Y+1));
-%! assert(RGB(:,:,3),newmap(:,3)(Y+1));
-
-%!# Random uint8 RGB image
-%!test
-%! RGB=uint8(rand(10,10,3)*255);
-%! RGBd=double(RGB)/255;
-%! [Y,newmap]=cmunique(RGB);
-%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
-%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
-%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
-
-%!# Random uint16 RGB image
-%!test
-%! RGB=uint16(rand(10,10,3)*65535);
-%! RGBd=double(RGB)/65535;
-%! [Y,newmap]=cmunique(RGB);
-%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
-%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
-%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
-
-%!# Random I image
-%!test
-%! I=rand(10,10);
-%! [Y,newmap]=cmunique(I);
-%! assert(I,newmap(:,1)(Y+1));
-%! assert(I,newmap(:,2)(Y+1));
-%! assert(I,newmap(:,3)(Y+1));
-
-%!# Random uint8 I image
-%!test
-%! I=uint8(rand(10,10)*256);
-%! Id=double(I)/255;
-%! [Y,newmap]=cmunique(I);
-%! assert(Id,newmap(:,1)(Y+1));
-%! assert(Id,newmap(:,2)(Y+1));
-%! assert(Id,newmap(:,3)(Y+1));
-
-%!# Random uint16 I image
-%!test
-%! I=uint16(rand(10,10)*65535);
-%! Id=double(I)/65535;
-%! [Y,newmap]=cmunique(I);
-%! assert(Id,newmap(:,1)(Y+1));
-%! assert(Id,newmap(:,2)(Y+1));
-%! assert(Id,newmap(:,3)(Y+1));
-
-%
-% $Log$
-% Revision 1.4  2004/09/08 16:06:31  jmones
-% Solved problem with uint8 indexing and reduced tests on types (suggested by P. Kienzle)
-%
-% Revision 1.3  2004/09/03 17:07:26  jmones
-% Support for uint8 and uint16 types added.
-%
-% Revision 1.2  2004/08/17 15:48:03  jmones
-% Clarified expected data for RGB images in doc
-%
-% Revision 1.1  2004/08/17 15:45:40  jmones
-% cmunique: Finds colormap with unique colors and corresponding image
-%
-%
-	
-
deleted file mode 100644
--- a/col2im.m
+++ /dev/null
@@ -1,169 +0,0 @@
-## 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{A} = } col2im (@var{B}, [@var{m},@var{n}], [@var{mm},@var{nn}], @var{block_type})
-## @deftypefnx {Function File} {@var{A} = } col2im (@var{B}, [@var{m},@var{n}], [@var{mm},@var{nn}])
-## Rearranges matrix columns into blocks
-##
-## @code{A=col2im(B,[m,n],[mm,nn],block_type)} rearranges columns of
-## matrix @var{B} intro blocks in a way controlled by @var{block_type}
-## param, which can take the following values:
-##
-## @table @code
-## @item distinct
-## It uses @var{m}-by-@var{n} distinct blocks (which are not
-## overlapped), and are rearranged to form a @var{mm}-by-@var{nn} matrix
-## @var{A}. @var{B}'s height must be @var{m}*@var{n} and @code{col2im}
-## rearranges each column to a @var{m}-by-@var{n} block and uses them to
-## fill the whole matrix in left-to-right and then up-to-down order.
-## @item sliding
-## Is uses @var{m}-by-@var{n} sliding blocks. It rearranges row vector
-## @var{B} to a (@var{mm}-@var{m}+1)-by-(@var{nn}-@var{n}+1) matrix
-## @var{A}. @var{B} must be a
-## 1-by-(@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1).
-## @end table
-##
-## @code{A=col2im(B,[m,n],[mm,nn])} takes @code{distinct} as a default
-## value for @var{block_type}.
-##
-## @end deftypefn
-## @seealso{im2col}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function A = col2im(B, sblock, sb, block_type)
-  if(nargin<3 || nargin>4)
-    usage("A=col2im(B, [m,n], [mm,nn] [, block_type])");
-  endif
-  
-  if(nargin!=4)
-    block_type='sliding';
-  endif
-
-  ## common checks
-  if(!ismatrix(B))
-    error("col2im: B should be a matrix (or vector).");
-  endif
-  if(!isvector(sblock) || length(sblock)!=2)
-    error("col2im: expected [m,n] as second parameter.");
-  endif
-  if(!isvector(sb) || length(sb)!=2)
-    error("col2im: expected [mm,nn] as third parameter.");
-  endif
-
-  m=sblock(1);
-  n=sblock(2);
-  mm=sb(1);
-  nn=sb(2);
-
-  switch(block_type)
-    case('distinct')
-      if(rows(B)!=m*n)
-	error("col2im: B height must be m*n for 'distinct' block_type.");
-      endif
-      if(rem(mm,m)!=0)
-	error("col2im: mm should be multiple of m");
-      endif
-      if(rem(nn,n)!=0)
-	error("col2im: nn should be multiple of n");
-      endif
-      mt=mm/m;
-      nt=nn/n;
-      if(columns(B)<mt*nt)
-	error("col2im: B's width is too small (should be mm*nn/(m*m)).");
-      endif
-      c=1;
-      for i=1:mt
-	## TODO: check if we can horzcat([],uint8([10;11])) in a
-	## future Octave version > 2.1.58 in order to deuglify this!
-	r=reshape(B(:,c),m,n);
-	c+=1;
-	for j=2:nt
-	  r=horzcat(r, reshape(B(:,c),m,n));
-	  c+=1;
-	endfor
-	if(i==1) ## this workarrounds a bug in ver<=2.1.57 cat implementation
-	  A=r;
-	else
-	  A=vertcat(A,r);
-	endif
-      endfor
-	
-    case('sliding')
-      if(!all(size(B)==[1,(mm-m+1)*(nn-n+1)]))
-	error("col2im: wrong B size. Should be 1-by-(mm-m+1)*(nn-n+1).");
-      endif
-      A=reshape(B, mm-m+1, nn-n+1);
-      
-    otherwise
-      error("col2im: invalid block_type.");
-  endswitch
-
-endfunction
-
-%!demo
-%! A=[1:10;11:20;21:30;31:40]
-%! B=im2col(A,[2,5],'distinct')
-%! C=col2im(B,[2,5],[4,10],'distinct')
-%! # Divide A using distinct blocks and reverse operation
-
-
-%!shared B, Ad
-%! v=[1:10]';
-%! r=reshape(v,2,5);
-%! B=[v, v+10, v+20, v+30, v+40, v+50];
-%! Ad=[r, r+10; r+20, r+30; r+40, r+50];
-
-%!# bad m
-%!error(col2im(B,[3,5],[6,10],'distinct'));
-
-%!# bad n
-%!error(col2im(B,[2,3],[6,10],'distinct'));
-
-%!# bad mm
-%!error(col2im(B,[2,5],[7,10],'distinct'));
-
-%!# bad nn
-%!error(col2im(B,[2,5],[6,11],'distinct'));
-
-%!# bad block_type
-%!error(col2im(B,[2,5],[6,10],'wrong_block_type'));
-
-%!# this should be ok
-%!assert(col2im(B,[2,5],[6,10],'distinct'), Ad);
-
-%!# now sliding
-%!assert(col2im(ones(1,(10-2+1)*(7-3+1)),[2,3],[10,7]), ones((10-2+1),(7-3+1)));
-%!assert(col2im(ones(1,(10-2+1)*(7-3+1)),[2,3],[10,7],'sliding'), ones((10-2+1),(7-3+1)));
-
-
-%!# disctint on uint8
-%!assert(col2im(uint8(B),[2,5],[6,10],'distinct'), uint8(Ad));
-
-%!# now sliding on uint8
-%!assert(col2im(ones(1,(10-2+1)*(7-3+1),"uint8"),[2,3],[10,7]), ones((10-2+1),(7-3+1),"uint8"));
-
-
-%
-% $Log$
-% Revision 1.2  2004/09/03 17:57:42  jmones
-% Added support for int* and uint* types
-%
-% Revision 1.1  2004/08/18 14:39:07  jmones
-% im2col and col2im added
-%
-%
deleted file mode 100644
--- a/colfilt.m
+++ /dev/null
@@ -1,94 +0,0 @@
-## COLFILT Apply filter to matrix blocks
-## colfilt(A,[r c],[m n],'sliding',f,...)
-##   For each r x c overlapping subblock of A, add a column in matrix C
-##   f(C,...) should return a row vector which is then reshaped into a
-##   a matrix of size A and returned.  A is processed in chunks of size m x n.
-## colfilt(A,[r c],[m n],'distinct',f,...)
-##   For each r x c non-overlapping subblock of A, add a column in matrix C
-##   f(C,...) should return a matrix of size C each column of which is
-##   placed back into the subblock from whence it came.  A is processed
-##   in chunks of size m x n.
-##
-## The present version requires [m n], but for compatibility it should
-## be optional.  Use colfilt(A,[r c],size(A),...)
-##
-## The present version requires that [m n] divide size(A), but for
-## compatibility it should work even if [m n] does not divide A. Use
-## the following instead:
-##    [r c] = size(A);
-##    padA = zeros (m*ceil(r/m),n*ceil(c/n));
-##    padA(1:r,1:c) = A;
-##    B = colfilt(padA,...);
-##    B = B(1:r,1:c);
-##
-## The present version does not handle 'distinct'
-
-## This software is granted to the public domain
-## Author: Paul Kienzle <pkienzle@users.sf.net>
-
-function B = colfilt(A,filtsize,blksize,blktype,f,varargin)
-
-   [m,n]=size(A);
-   r = filtsize(1);
-   c = filtsize(2);
-   mblock = blksize(1);
-   nblock = blksize(2);
-
-   switch blktype
-   case 'sliding'
-     # pad with zeros
-     padm = (m+r-1);
-     padn = (n+c-1);
-     padA = zeros(padm, padn);
-     padA([1:m]+floor((r-1)/2),[1:n]+floor((c-1)/2)) = A;
-     padA = padA(:);
-
-     # throw away old A to save memory.
-     B=A; clear A;  
-
-     # build the index vector
-     colidx = [0:r-1]'*ones(1,c) + padm*ones(r,1)*[0:c-1];
-     offset = [1:mblock]'*ones(1,nblock) + padm*ones(mblock,1)*[0:nblock-1];
-     idx = colidx(:)*ones(1,mblock*nblock) + ones(r*c,1)*offset(:)';
-     clear colidx offset;
-
-     # process the matrix, one block at a time
-     idxA = zeros(r*c,mblock*nblock);
-     tmp = zeros(mblock,nblock);
-     for i = 0:m/mblock-1
-       for j = 0:n/nblock-1
-         idxA(:) = padA(idx + (i*mblock + padm*j*nblock));
-         tmp(:) = feval(f,idxA,varargin{:});
-         B(1+i*mblock:(i+1)*mblock, 1+j*nblock:(j+1)*nblock) = tmp;
-       end
-     end
-
-   case 'old-sliding'  # processes the whole matrix at a time
-     padA = zeros(m+r-1,n+c-1);
-     padA([1:m]+floor(r/2),[1:n]+floor(c/2)) = A;
-     [padm,padn] = size(padA);
-     colidx = [0:r-1]'*ones(1,c) + padm*ones(r,1)*[0:c-1];
-     offset = [1:m]'*ones(1,n) + padm*ones(m,1)*[0:n-1];
-     idx = colidx(:)*ones(1,m*n) + ones(r*c,1)*offset(:)';
-     idxA = zeros(r*c,m*n);
-     idxA(:) = padA(:)(idx);
-     B = zeros(size(A));
-     B(:) = feval(f,idxA,varargin{:});
-   case 'old-distinct' # processes the whole matrix at a time
-     if (r*floor(m/r) != m || c*floor(n/c) != n)
-        error("colfilt expected blocks to exactly fill A");
-     endif
-     colidx = [0:r-1]'*ones(1,c) + m*ones(r,1)*[0:c-1];
-     offset = [1:r:m]'*ones(1,n/c) + m*ones(m/r,1)*[0:c:n-1];
-     idx =colidx(:)*ones(1,m*n/r/c) + ones(r*c,1)*offset(:)';
-     idxA = zeros(r*c,m*n/r/c);
-     idxA(:) = A(:)(idx);
-     B = zeros(prod(size(A)),1);
-     B(idx) = feval(f,idxA,varargin{:});
-     B = reshape(B,size(A));
-   endswitch
-endfunction
-
-%!test
-%! A = reshape(1:36,6,6);
-%! assert(colfilt(A,[2,2],[3,3],'sliding','sum'), conv2(A,ones(2),'same'));
deleted file mode 100644
--- a/colorgradient.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## M = colorgradient(C,w,n)
-## Define a colour map which smoothly traverses the given colors.
-## C contains the colours, one row per r,g,b value.
-## w(i) is the relative length of the transition from colour i to colour i+1
-## in the entire gradient.  The default is ones(rows(C)-1,1).
-## n is the length of the colour map.  The default is rows(colormap).
-##
-## E.g., 
-##    colorgradient([0,0,1; 1,1,0; 1,0,0])  # blue -> yellow -> red
-##    x = linspace(0,1,200);
-##    imagesc(x(:,ones(30,1)))';
-
-## This program is granted to the public domain.
-## Author: Paul Kienzle <pkienzle@users.sf.net>
-
-function ret = colorgradient(C,w,n)
-  if nargin < 1 || nargin > 3
-    usage("M = colorgradient(C,w,n)")
-  endif
-
-  if nargin == 1
-    n = rows(colormap);
-    w = ones(length(C)-1,1);
-  elseif nargin == 2
-    if (length(w) == 1)
-      n = w;
-      w = ones(rows(C)-1,1);
-    else
-      n = rows(colormap);
-    endif
-  endif
-
-  if (length(w)+1 != rows(C))
-    error("must have one weight for each color interval");
-  endif
-
-  w = 1+round((n-1)*cumsum([0;w(:)])/sum(w));
-  map = zeros(n,3);
-  for i=1:length(w)-1
-    if (w(i) != w(i+1))
-      map(w(i):w(i+1),1) = linspace(C(i,1),C(i+1,1),w(i+1)-w(i)+1)';
-      map(w(i):w(i+1),2) = linspace(C(i,2),C(i+1,2),w(i+1)-w(i)+1)';
-      map(w(i):w(i+1),3) = linspace(C(i,3),C(i+1,3),w(i+1)-w(i)+1)';
-    endif
-  endfor
-
-  if nargout == 0
-    colormap(map);
-  else
-    ret = map;
-  endif
-endfunction
deleted file mode 100644
--- a/configure.add
+++ /dev/null
@@ -1,56 +0,0 @@
-
-if test -e main/image/NOINSTALL ; then
-
-	dnl Not installing so don't test for libjpeg/libpng/libMagick++.
-	STATUS=none
-
-else
-
-	AC_DEFINE(have_jpeg)
-	AC_CHECK_HEADER(jpeglib.h, have_jpeg=yes, have_jpeg=no)
-	if test $have_jpeg = yes ; then
-	    OF_CHECK_LIB(jpeg, jpeg_std_error, have_jpeg=yes, have_jpeg=no)
-	    if test $have_jpeg = no ; then
-		STATUS="libjpeg not found"
-	    else
-		STATUS="jpeg"
-		AC_SUBST(DEFHAVE_JPEG)
-		DEFHAVE_JPEG="HAVE_JPEG=1"
-	    fi
-	else
-	    STATUS="jpeglib.h not found"
-	fi
-
-	AC_DEFINE(have_png)
-	AC_CHECK_HEADER(png.h, have_png=yes, have_png=no)
-	if test $have_png = yes ; then
-	    OF_CHECK_LIB(png, png_set_sig_bytes, have_png=yes, have_png=no)
-	    if test $have_png = no ; then
-		STATUS="$STATUS, libpng not found"
-	    else
-		STATUS="$STATUS, png"
-		AC_SUBST(DEFHAVE_PNG)
-		DEFHAVE_PNG="HAVE_PNG=1"
-	    fi
-	else
-	    STATUS="$STATUS, png.h not found"
-	fi
-
-	AC_CHECK_PROG(HAVE_MAGICKXX, Magick++-config, yes)
-	if test $HAVE_MAGICKXX ; then
-		STATUS="$STATUS, ImageMagick++"
-		AC_SUBST(DEFHAVE_MAGICKXX)		
-		DEFHAVE_MAGICKXX="HAVE_MAGICKXX=1"	
-	else
-	    STATUS="$STATUS, ImageMagick++ not found"
-	fi
-
-
-fi
-
-dnl Append the status message to the global status message.  This will
-dnl be displayed at the end of configuration so that the user doesn't
-dnl have to scan the list for critical details.
-
-STATUS_MSG="$STATUS_MSG
-   read/write image formats: $STATUS"
deleted file mode 100644
--- a/conndef.m
+++ /dev/null
@@ -1,106 +0,0 @@
-## 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{conn} = } conndef (@var{num_dims}, @var{type})
-## Creates a connectivity array
-##
-## @code{conn=conndef(num_dims,type)} creates a connectivity array
-## (@var{CONN}) of @var{num_dims} dimensions and which type is defined
-## by @var{type} as follows:
-## @table @code
-## @item minimal
-## Neighbours touch the central element on a (@var{num_dims}-1)-dimensional
-## surface.
-## @item maximal
-## Neighbours touch the central element in any way. Equivalent to
-## @code{ones(repmat(3,1,@var{num_dims}))}.
-## @end table
-##
-## @end deftypefn
-
-
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function conn = conndef(num_dims,conntype)
-  if(nargin!=2)
-    usage("conn=conndef(num_dims, type)");
-  endif
-  if(num_dims<=0)
-    error("conndef: num_dims must be > 0");
-  endif
-    
-  if(strcmp(conntype,"minimal"))
-    if(num_dims==1)
-      conn=[1;1;1];
-    elseif(num_dims==2)
-      conn=[0,1,0;1,1,1;0,1,0];
-    else
-      conn=zeros(repmat(3,1,num_dims));
-      idx={};
-      idx{1}=1:3;
-      for i=2:num_dims
-	idx{i}=2;
-      endfor
-      conn(idx{:})=1;
-      for i=2:num_dims
-	idx{i-1}=2;
-	idx{i}=1:3;
-	conn(idx{:})=1;
-      endfor
-    endif
-    
-  elseif(strcmp(conntype,"maximal"))
-    if(num_dims==1)
-      conn=[1;1;1];
-    else
-      conn=ones(repmat(3,1,num_dims));
-    endif
-  else
-    error("conndef: invalid type parameter.");
-  endif
-  
-endfunction
-
-%!demo
-%! conndef(2,'minimal')
-%! % Create a 2-D minimal connectivity array
-
-%!assert(conndef(1,'minimal'), [1;1;1]);
-
-%!assert(conndef(2,'minimal'), [0,1,0;1,1,1;0,1,0]);
-
-%!test
-%! C=zeros(3,3);
-%! C(2,2,1)=1;
-%! C(2,2,3)=1;
-%! C(:,:,2)=[0,1,0;1,1,1;0,1,0];
-%! assert(conndef(3,'minimal'), C);
-
-%!assert(conndef(1,'maximal'), ones(3,1));
-%!assert(conndef(2,'maximal'), ones(3,3));
-%!assert(conndef(3,'maximal'), ones(3,3,3));
-%!assert(conndef(4,'maximal'), ones(3,3,3,3));
-
-
-
-% $Log$
-% Revision 1.2  2005/07/03 01:10:19  pkienzle
-% Try to correct for missing newline at the end of the file
-%
-% Revision 1.1  2004/08/15 19:38:44  jmones
-% conndef added: Creates a connectivity array
deleted file mode 100644
--- a/cool.m
+++ /dev/null
@@ -1,51 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} cool (@var{n})
-## Create color colormap. 
-## (cyan to magenta)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = cool (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("cool: argument must be a scalar");
-    endif
-  else
-    usage ("cool (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 1, 1];  
-  elseif (number > 1)
-    r = (0:number - 1)' ./ (number - 1);
-    g = 1 - r;
-    b = ones (number, 1);
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/copper.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} copper (@var{n})
-## Create color colormap. 
-## (black to a light copper tone)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = copper (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("copper: argument must be a scalar");
-    endif
-  else
-    usage ("copper (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 0];  
-  elseif (number > 1)
-    x = linspace (0, 1, number)';
-    r = (x < 4/5) .* (5/4 * x) + (x >= 4/5);
-    g = 4/5 * x;
-    b = 1/2 * x;
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/cordflt2.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-// 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.
-
-#include <octave/oct.h>
-
-#ifdef HAVE_OCTAVE_20
-typedef Matrix boolMatrix;
-#define bool_matrix_value matrix_value
-#endif
-
-#define SWAP(a, b) { SWAP_temp = (a); (a)=(b); (b) = SWAP_temp; }
-
-// Template function for comparison
-// ET is the type of the matrix element
-template <class ET>
-inline bool compare(const ET a, const ET b)
-{
-    if(a > b)
-      return 1;
-    else
-      return 0;
-}
-
-// Explicit template function for complex compare
-template <> inline bool compare<Complex>(const Complex a, const Complex b)
-{
-    double anorm2 = a.real() * a.real() + a.imag() * a.imag();
-    double bnorm2 = b.real() * b.real() + b.imag() * b.imag();
-        
-    if( anorm2 > bnorm2 ) {
-      return 1;
-    } else {
-      return 0;
-    }
-}
-
-// select nth largest member from the array values
-// Partitioning algorithm, see Numerical recipes chap. 8.5
-template <class ET>
-ET selnth(ET *vals, int len, int nth)
-{
-    ET SWAP_temp;
-    ET hinge;
-    int l, r, mid, i, j;
-
-    l = 0;
-    r = len - 1;
-    for(;;) {
-	// if partition size is 1 or two, then sort and return
-	if(r <= l+1) {
-	    if(r == l+1 && compare<ET>(vals[l], vals[r])) {
-		SWAP(vals[l], vals[r]);
-	    }
-	    return vals[nth];
-	} else {
-	    mid = (l+r) >> 1;
-	    SWAP(vals[mid], vals[l+1]);
-	    // choose median of l, mid, r to be the hinge element
-	    // and set up sentinels in the borders (order l, l+1 and r)
-	    if(compare<ET>(vals[l], vals[r])) {
-		SWAP(vals[l], vals[r]);
-	    }
-	    if(compare<ET>(vals[l+1], vals[r])) {
-		SWAP(vals[l+1], vals[r]);
-	    }
-	    if(compare<ET>(vals[l], vals[l+1])) {
-		SWAP(vals[l], vals[l+1]);
-	    }
-	    i = l+1;
-	    j = r;
-	    hinge = vals[l+1];
-	    for(;;) {
-		do i++; while(compare<ET>(hinge, vals[i]));
-		do j--; while(compare<ET>(vals[j], hinge));
-		if(i > j) 
-		    break;
-		SWAP(vals[i], vals[j]);
-	    }
-	    vals[l+1] = vals[j];
-	    vals[j] = hinge;
-	    if(j >= nth)
-		r = j - 1;
-	    if(j <= nth)
-		l = i;
-	}
-    }
-}
-
-// Template function for doing the actual filtering
-// MT is the type of the matrix to be filtered (Matrix or ComplexMatrix)
-// ET is the type of the element of the matrix (double or Complex)
-template <class MT, class ET> 
-octave_value_list do_filtering(MT A, int nth, boolMatrix dom, MT S)
-{
-    int i, j, c, d;
-    
-    int len = 0;
-    for(j = 0; j < dom.columns(); j++) {
-	for(i = 0; i < dom.rows(); i++) {
-	    if(dom.elem(i,j)) 
-	      len++;
-	}
-    }
-    if(nth > len - 1) {
-	warning("nth should be less than number of non-zero values in domain");
-	warning("setting nth to largest possible value\n");
-	nth = len - 1;
-    }
-    if(nth < 0) {
-	warning("nth should be non-negative, setting to 1\n");
-	nth = 0; // nth is a c-index
-    }
-                
-    int rowoffset = (dom.columns() + 1)/2 - 1;
-    int coloffset = (dom.rows() + 1)/2 - 1;
-
-    //outputs
-    octave_value_list out;
-    const int origx = A.columns() - dom.columns()+1;
-    const int origy = A.rows() - dom.rows()+1;
-    MT retval = MT(origy, origx);
-
-    int *offsets = new int[len];
-    ET *values = new ET[len];
-    ET *adds = new ET[len];
-    
-    c = 0;
-    d = A.rows();
-    for(j = 0; j < dom.columns(); j++) {
-	for(i = 0; i < dom.rows(); i++) {
-	    if(dom.elem(i,j)) {
-		offsets[c] = (i - coloffset) + (j - rowoffset)*d;
-		adds[c] = S.elem(i,j);
-		c++;
-	    }
-	}
-    }
-    
-    ET *data = A.fortran_vec();
-    int base = coloffset + A.rows()*rowoffset;
-    for(j = 0; j < retval.columns(); j++) {
-	for(i = 0; i < retval.rows(); i++) {
-	    for(c = 0; c < len; c++) {
-		values[c] = data[base + offsets[c]] + adds[c];
-	    }
-	    base++;
-	    retval(i, j) = selnth(values, len, nth);
-	}
-	base += dom.rows() - 1;
-    }
-
-    out(0) = octave_value(retval);
-    
-    return out;
-}
-
-// instantiate template functions
-template bool compare<double>(const double, const double);
-template double selnth(double *, int, int);
-template Complex selnth(Complex *, int, int);
-template octave_value_list do_filtering<Matrix, double>(Matrix, int, boolMatrix, Matrix);
-// g++ is broken, explicit instantiation of specialized template function
-// confuses the compiler.
-//template int compare<Complex>(const Complex, const Complex);
-template octave_value_list do_filtering<ComplexMatrix, Complex>(ComplexMatrix, int, boolMatrix, ComplexMatrix);
-
-DEFUN_DLD(cordflt2, args, ,
-"function retval = cordflt2(A, nth, domain, S)\n\
-\n\
- Implementation of two-dimensional ordered filtering. User interface\n\
- in ordfilt2.m")
-{
-    if(args.length() != 4) {
-	print_usage ();
-	return octave_value_list();
-    }
-    
-    // nth is an index to an array, thus - 1
-    int nth = (int) (args(1).vector_value())(0) - 1;
-    boolMatrix dom = args(2).bool_matrix_value();
-
-    octave_value_list retval;
-    
-    if(args(0).is_real_matrix()) {
-	Matrix A = args(0).matrix_value();
-	Matrix S = args(3).matrix_value();
-	retval = do_filtering<Matrix, double>(A, nth, dom, S);
-    } 
-    else if(args(0).is_complex_matrix()) {
-	ComplexMatrix A = args(0).complex_matrix_value();
-	ComplexMatrix S = args(3).complex_matrix_value();
-	retval = do_filtering<ComplexMatrix, Complex>(A, nth, dom, S);
-    } 
-    else {
-	error("A should be real or complex matrix\n");
-	return octave_value_list();
-    }
-    
-    return retval;
-     
-}
deleted file mode 100644
--- a/corr2.m
+++ /dev/null
@@ -1,42 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{r}= corr2 (@var{I},@var{J})
-## returns the correlation coefficient between @var{I} and @var{j}.
-## @var{I,J} must be real type matrices or vectors of same size
-## @end deftypefn
-
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	01/08/2000
-
-function r = corr2 (I, J)
-
-  if !(nargin == 2)
-    usage ("corr2(I,J)");
-  endif
-
-  if !(is_matrix(I) && isreal(I) && is_matrix(J) && isreal(J))
-	error("argument must be a real type matrix");
-  endif
-
-  if (size (I) != size (J))
-    error("arguments must be of same size")
-  endif
-  
-  r = cov (I, J) / (std2(I)*std2(J));    
-endfunction
deleted file mode 100644
--- a/dilate.m
+++ /dev/null
@@ -1,87 +0,0 @@
-## 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{BW2} = } dilate (@var{BW1},@var{SE})
-## @deftypefnx {Function File} {@var{BW2} = } dilate (@var{BW1},@var{SE},@var{alg})
-## @deftypefnx {Function File} {@var{BW2} = } dilate (@var{BW1},@var{SE},...,@var{n})
-## Perform a dilation morphological operation on a binary image.
-##
-## BW2 = dilate(BW1, SE) returns a binary image with the result of a dilation
-## operation on @var{BW1} using neighbour mask @var{SE}.
-##
-## For each point in @var{BW1}, dilate search its neighbours (which are
-## defined by setting to 1 their in @var{SE}). If any of its neighbours
-## is on (1), then pixel is set to 1. If all are off (0) then it is set to 0.
-##
-## Center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
-##
-## Pixels outside the image are considered to be 0.
-##
-## BW2 = dilate(BW1, SE, alg) returns the result of a dilation operation 
-## using algorithm @var{alg}. Only 'spatial' is implemented at the moment.
-##
-## BW2 = dilate(BW1, SE, ..., n) returns the result of @var{n} dilation
-## operations on @var{BW1}.
-##
-## @end deftypefn
-## @seealso{erode}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function BW2 = dilate(BW1, SE, a, b)
-  alg='spatial';
-  n=1;
-  if (nargin < 1 || nargin > 4)
-    usage ("BW2 = dilate(BW1, SE [, alg] [, n])");
-  endif
-  if nargin ==  4
-    alg=a;
-    n=b;
-  elseif nargin == 3
-    if ischar(a)
-      alg=a;
-    else
-      n=a;
-    endif
-  endif
-
-  if !strcmp(alg, 'spatial')
-    error("dilate: alg not implemented.");
-  endif
-
-  # "Binarize" BW1, just in case image is not [1,0]
-  BW1=BW1!=0;
-
-  for i=1:n
-    # create result matrix
-    BW1=filter2(SE,BW1)>0;
-  endfor
-
-  BW2=BW1;
-endfunction
-
-%!demo
-%! dilate(eye(5),ones(2,2))
-%! % returns a thick diagonal.
-
-
-
-%!assert(dilate(eye(3),[1])==eye(3));	# using [1] as a mask returns the same value
-%!assert(dilate(eye(3),[1,0,0])==[[0;0],eye(2);0,0,0]);
-%!assert(dilate(eye(3),[1,0,0,0])==[[0;0],eye(2);0,0,0]); # test if center is correctly calculated on even masks
-
-
deleted file mode 100644
--- a/edge.m
+++ /dev/null
@@ -1,240 +0,0 @@
-function [imout, thresh] = edge( im, method, thresh, param2 )
-# EDGE: find image edges
-# [imout, thresh] = edge( im, method, thresh, param2 )
-#
-# OUTPUT
-#  imout  -> output image
-#  thresh -> output thresholds
-#
-# INPUT
-#  im     -> input image (greyscale)
-#  thresh -> threshold value (value is estimated if not given)
-#  
-# The following methods are based on high pass filtering the image in
-#   two directions, calculating a combined edge weight from and then thresholding
-#
-# method = 'roberts'
-#     filt1= [1 0 ; 0 -1];   filt2= rot90( filt1 )
-#     combine= sqrt( filt1^2 + filt2^2 )  
-# method = 'sobel'
-#     filt1= [1 2 1;0 0 0;-1 -2 -1];      filt2= rot90( filt1 ) 
-#     combine= sqrt( filt1^2 + filt2^2 )  
-# method = 'prewitt'
-#     filt1= [1 1 1;0 0 0;-1 -1 -1];      filt2= rot90( filt1 ) 
-#     combine= sqrt( filt1^2 + filt2^2 )  
-# method = 'kirsh'
-#     filt1= [1 2 1;0 0 0;-1 -2 -1];  filt2 .. filt8 are 45 degree rotations of filt1
-#     combine= max( filt1 ... filt8 )
-#
-# methods based on filtering the image and finding zero crossings
-#
-# method = 'log' -> Laplacian of Gaussians 
-#      param2 is the standard deviation of the filter, default is 2
-# method = 'zerocross' -> generic zero-crossing filter
-#      param2 is the user supplied filter
-# 
-# method = 'andy' -> my idea
-#      A.Adler's idea (c) 1999. somewhat based on the canny method
-#      Step 1: Do a sobel edge detection and to generate an image at
-#               a high and low threshold
-#      Step 2: Edge extend all edges in the LT image by several pixels,
-#               in the vertical, horizontal, and 45degree directions.
-#               Combine these into edge extended (EE) image
-#      Step 3: Dilate the EE image by 1 step
-#      Step 4: Select all EE features that are connected to features in
-#               the HT image
-#                
-#      Parameters:
-#        param2(1)==0 or 4 or 8 -> perform x connected dilatation (step 3)
-#        param2(2)    dilatation coeficient (threshold) in step 3
-#        param2(3)    length of edge extention convolution (step 2)
-#        param2(4)    coeficient of extention convolution in step 2
-#        defaults = [8 1 3 3]
-
-# Copyright (C) 1999 Andy Adler
-# This code has no warrany whatsoever.
-# Do what you like with this code as long as you
-#     leave this copyright in place.
-#
-# $Id$
-
-[n,m]= size(im);
-xx= 2:m-1;
-yy= 2:n-1;
-
-if   strcmp(method,'roberts') || strcmp(method,'sobel') || ...
-     strcmp(method,'prewitt') 
-     
-
-   if strcmp(method,'roberts') 
-      filt= [1 0;0 -1]/4;               tv= 6;
-   elseif strcmp(method,'sobel') 
-      filt= [1 2 1;0 0 0; -1 -2 -1]/8;  tv= 2;
-   elseif strcmp(method,'prewitt') 
-      filt= [1 1 1;0 0 0; -1 -1 -1]/6;  tv= 4;
-   end
-
-   imo= conv2(im, rot90(filt), 'same').^2 + conv2(im, filt, 'same').^2;
-   
-# check to see if the user supplied a threshold
-# if not, calculate one in the same way as Matlab
-
-   if nargin<3
-      thresh= sqrt( tv* mean(mean( imo(yy,xx) ))  );
-   end
-
-# The filters are defined for sqrt(imo), but since we calculated imo, compare
-#  to thresh ^2
-
-   imout= ( imo >= thresh^2 );   
-
-# Thin the wide edges
-   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
-   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
-   imout(yy,xx)= imout(yy,xx) & ( xpeak | ypeak );
-
-elseif strcmp(method,'kirsch')   
-
-   filt1= [1 2 1;0 0 0;-1 -2 -1];   fim1= conv2(im,filt1,'same');
-   filt2= [2 1 0;1 0 -1;0 -1 -2];   fim2= conv2(im,filt2,'same');
-   filt3= [1 0 -1;2 0 -2;1 0 -1];   fim3= conv2(im,filt3,'same');
-   filt4= [0 1 2;-1 0 1;-2 -1 0];   fim4= conv2(im,filt4,'same');
-
-   imo= reshape(max([abs(fim1(:)) abs(fim2(:)) abs(fim3(:)) abs(fim4(:))]'),n,m);
-
-   if nargin<3
-      thresh=  2* mean(mean( imo(yy,xx) )) ;
-   end
-
-   imout=  imo >= thresh ;   
-
-# Thin the wide edges
-   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
-   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
-   imout(yy,xx)= imout(yy,xx) & ( xpeak | ypeak );
-
-elseif  strcmp(method,'log') || strcmp(method,'zerocross') 
-
-   if strcmp(method,'log') 
-      if nargin >= 4;    sd= param2;
-      else               sd= 2;
-      end
-
-      sz= ceil(sd*3);
-      [x,y]= meshgrid( -sz:sz, -sz:sz );
-      filt = exp( -( x.^2 + y.^2 )/2/sd^2 ) .* ...
-                   ( x.^2 + y.^2 - 2*sd^2 ) / 2 / pi / sd^6 ;
-   else
-      filt = param2;
-   end
-   filt = filt - mean(filt(:));
-
-   imo= conv2(im, filt, 'same');
-
-   if nargin<3 || isempty( thresh )
-      thresh=  0.75* mean(mean( abs(imo(yy,xx)) )) ;
-   end
-
-   zcross= imo > 0;
-   yd_zc=  diff( zcross );
-   xd_zc=  diff( zcross' )';
-   yd_io=  abs(diff( imo ) ) > thresh;
-   xd_io=  abs(diff( imo')') > thresh;
-
-# doing it this way puts the transition at the <=0 point
-   xl= zeros(1,m);  yl= zeros(n,1);
-   imout= [    ( yd_zc ==  1 ) & yd_io ; xl] | ...
-          [xl; ( yd_zc == -1 ) & yd_io     ] | ...
-          [    ( xd_zc ==  1 ) & xd_io , yl] | ... 
-          [yl, ( xd_zc == -1 ) & xd_io     ];
-
-elseif  strcmp(method,'canny')  
-    error("method canny not implemented");
-
-elseif  strcmp(method,'andy')  
-
-   filt= [1 2 1;0 0 0; -1 -2 -1]/8;  tv= 2;
-   imo= conv2(im, rot90(filt), 'same').^2 + conv2(im, filt, 'same').^2;
-   if nargin<3 || thresh==[];
-      thresh= sqrt( tv* mean(mean( imo(yy,xx) ))  );
-   end
-#     sum( imo(:)>thresh ) / prod(size(imo))
-   dilate= [1 1 1;1 1 1;1 1 1]; tt= 1; sz=3; dt=3;
-   if nargin>=4
-      # 0 or 4 or 8 connected dilation
-      if length(param2) > 0
-         if      param2(1)==4 ; dilate= [0 1 0;1 1 1;0 1 0];
-         elseif  param2(1)==0 ; dilate= 1;
-         end
-      end
-      # dilation threshold
-      if length(param2) > 2; tt= param2(2); end
-      # edge extention length
-      if length(param2) > 2; sz= param2(3); end
-      # edge extention threshold
-      if length(param2) > 3; dt= param2(4); end
-      
-   end
-   fobliq= [0 0 0 0 1;0 0 0 .5 .5;0 0 0 1 0;0 0 .5 .5 0;0 0 1 0 0; 
-                      0 .5 .5 0 0;0 1 0 0 0;.5 .5 0 0 0;1 0 0 0 0];
-   fobliq= fobliq( 5-sz:5+sz, 3-ceil(sz/2):3+ceil(sz/2) );
-
-   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
-   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
-
-   imht= ( imo >= thresh^2 * 2); # high threshold image   
-   imht(yy,xx)= imht(yy,xx) & ( xpeak | ypeak );
-   imht([1,n],:)=0; imht(:,[1,m])=0;
-
-%  imlt= ( imo >= thresh^2 / 2); # low threshold image   
-   imlt= ( imo >= thresh^2 / 1); # low threshold image   
-   imlt(yy,xx)= imlt(yy,xx) & ( xpeak | ypeak );
-   imlt([1,n],:)=0; imlt(:,[1,m])=0;
-
-# now we edge extend the low thresh image in 4 directions
-
-   imee= ( conv2( imlt, ones(2*sz+1,1)    , 'same') > tt ) | ...
-         ( conv2( imlt, ones(1,2*sz+1)    , 'same') > tt ) | ...
-         ( conv2( imlt, eye(2*sz+1)       , 'same') > tt ) | ...
-         ( conv2( imlt, rot90(eye(2*sz+1)), 'same') > tt ) | ...
-         ( conv2( imlt, fobliq            , 'same') > tt ) | ...
-         ( conv2( imlt, fobliq'           , 'same') > tt ) | ...
-         ( conv2( imlt, rot90(fobliq)     , 'same') > tt ) | ...
-         ( conv2( imlt, flipud(fobliq)    , 'same') > tt );
-#  imee(yy,xx)= conv2(imee(yy,xx),ones(3),'same') & ( xpeak | ypeak );
-   imee= conv2(imee,dilate,'same') > dt; #
-
-%  ff= find( imht==1 );
-%  imout = bwselect( imee, rem(ff-1, n)+1, ceil(ff/n), 8);  
-   imout = imee;
-
-
-else
-
-   error (['Method ' method ' is not recognized']);
-
-end
-
-
-
-
-# 
-# $Log$
-# Revision 1.1  2002/03/17 02:38:52  aadler
-# fill and edge detection operators
-#
-# Revision 1.4  2000/11/20 17:13:07  aadler
-# works?
-#
-# Revision 1.3  1999/06/09 17:29:36  aadler
-# implemented 'andy' mode edge detection
-#
-# Revision 1.2  1999/06/08 14:26:50  aadler
-# zero-cross and LoG filters work
-#
-# Revision 1.1  1999/06/07 21:01:38  aadler
-# Initial revision
-#
-#
-
-#  
deleted file mode 100644
--- a/erode.m
+++ /dev/null
@@ -1,89 +0,0 @@
-## 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{BW2} = } erode (@var{BW1},@var{SE})
-## @deftypefnx {Function File} {@var{BW2} = } erode (@var{BW1},@var{SE},@var{alg})
-## @deftypefnx {Function File} {@var{BW2} = } erode (@var{BW1},@var{SE},...,@var{n})
-## Perform an erosion morphological operation on a binary image.
-##
-## BW2 = erosion(BW1, SE) returns a binary image with the result of an erosion
-## operation on @var{BW1} using neighbour mask @var{SE}.
-##
-## For each point in @var{BW1}, erode searchs its neighbours (which are
-## defined by setting to 1 their in @var{SE}). If all neighbours
-## are on (1), then pixel is set to 1. If any is off (0) then it is set to 0.
-##
-## Center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
-##
-## Pixels outside the image are considered to be 0.
-##
-## BW2 = erode(BW1, SE, alg) returns the result of a erosion operation 
-## using algorithm @var{alg}. Only 'spatial' is implemented at the moment.
-##
-## BW2 = erosion(BW1, SE, ..., n) returns the result of @var{n} erosion
-## operations on @var{BW1}.
-##
-## @end deftypefn
-## @seealso{dilate}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function BW2 = erode(BW1, SE, a, b)
-  alg='spatial';
-  n=1;
-  if (nargin < 1 || nargin > 4)
-    usage ("BW2 = erode(BW1, SE [, alg] [, n])");
-  endif
-  if nargin ==  4
-    alg=a;
-    n=b;
-  elseif nargin == 3
-    if ischar(a)
-      alg=a;
-    else
-      n=a;
-    endif
-  endif
-
-  if !strcmp(alg, 'spatial')
-    error("erode: alg not implemented.");
-  endif
-
-  # count ones in mask
-  thr=sum(SE(:));
-
-  # "Binarize" BW1, just in case image is not [1,0]
-  BW1=BW1!=0;
-
-  for i=1:n
-    # create result matrix
-    BW1=filter2(SE,BW1) == thr;
-  endfor
-
-  BW2=BW1;
-endfunction
-
-%!demo
-%! erode(ones(5,5),ones(3,3))
-%! % creates a zeros border around ones.
-
-
-
-%!assert(erode([0,1,0;1,1,1;0,1,0],[0,0,0;0,0,1;0,1,1])==[1,0,0;0,0,0;0,0,0]);
-%!assert(erode([0,1,0;1,1,1;0,1,0],[0,1;1,1])==[1,0,0;0,0,0;0,0,0]);
-
-
deleted file mode 100644
--- a/fftconv2.m
+++ /dev/null
@@ -1,134 +0,0 @@
-## Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
-##
-## This program is free software; redistribution and use in source and
-## binary forms, with or without modification, are permitted provided that
-## the following conditions are met:
-##
-## 1. Redistributions of source code must retain the above copyright
-##    notice, this list of conditions and the following disclaimer.
-## 2. Redistributions in binary form must reproduce the above copyright
-##    notice, this list of conditions and the following disclaimer in the
-##    documentation and/or other materials provided with the distribution.
-##
-## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-## ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-## SUCH DAMAGE.
-
-## FFTCONV2 Convolve 2 dimensional signals using the FFT.
-##
-## usage: fftconv2(a, b[, shape])
-##        fftconv2(v1, v2, a, shape)
-##
-## This method is faster but less accurate for large a,b.  It
-## also uses more memory. A small complex component will be 
-## introduced even if both a and b are real.
-##
-## see also: conv2
-
-## Author: Stefan van der Walt <stefan@sun.ac.za>
-## Date: 2004
-
-function X = fftconv2(varargin)
-    if (nargin < 2)
-	usage("fftconv2(a,b[,shape]) or fftconv2(v1, v2, a, shape)")
-    endif
-
-    shape = "full";
-    rowcolumn = 0;
-    
-    if ((nargin > 2) && ismatrix(varargin{3}))
-	## usage: fftconv2(v1, v2, a[, shape])
-
-	rowcolumn = 1;
-	v1 = varargin{1}(:)';
-	v2 = varargin{2}(:);
-	orig_a = varargin{3};
-	
-	if (nargin == 4) shape = varargin{4}; endif
-    else
-	## usage: fftconv2(a, b[, shape])
-	
-	a = varargin{1};
-	b = varargin{2};
-	if (nargin == 3) shape = varargin{3}; endif
-
-    endif
-
-    if (rowcolumn)
-	a = fftconv2(orig_a, v2);
-	b = v1;
-    endif
-    
-    ra = rows(a);
-    ca = columns(a);
-    rb = rows(b);
-    cb = columns(b);
-
-    A = fft2(impad(a, [0 cb-1], [0 rb-1]));
-    B = fft2(impad(b, [0 ca-1], [0 ra-1]));
-
-    X = ifft2(A.*B);
-
-    if (rowcolumn)
-	rb = rows(v2);
-	ra = rows(orig_a);
-	cb = columns(v1);
-	ca = columns(orig_a);
-    endif
-    
-    if strcmp(shape,"same")
-	r_top = ceil((rb + 1) / 2);
-	c_top = ceil((cb + 1) / 2);
-	X = X(r_top:r_top + ra - 1, c_top:c_top + ca - 1);
-    elseif strcmp(shape, "valid")
-	X = X(rb:ra, cb:ca);
-    endif
-endfunction
-
-%!# usage: fftconv2(a,b,[, shape])
-%!shared a,b
-%! a = repmat(1:10, 5);
-%! b = repmat(10:-1:3, 7);
-%!assert(norm(fftconv2(a,b)-conv2(a,b)), 0, 1e6*eps)
-%!assert(norm(fftconv2(b,a)-conv2(b,a)), 0, 1e6*eps)
-%!assert(norm(fftconv2(a,b,'full')-conv2(a,b,'full')), 0, 1e6*eps)
-%!assert(norm(fftconv2(b,a,'full')-conv2(b,a,'full')), 0, 1e6*eps)
-%!assert(norm(fftconv2(a,b,'same')-conv2(a,b,'same')), 0, 1e6*eps)
-%!assert(norm(fftconv2(b,a,'same')-conv2(b,a,'same')), 0, 1e6*eps)
-%!assert(isempty(fftconv2(a,b,'valid')));
-%!assert(norm(fftconv2(b,a,'valid')-conv2(b,a,'valid')), 0, 1e6*eps)
-
-%!# usage: fftconv2(v1, v2, a[, shape])
-%!shared x,y,a
-%! x = 1:4; y = 4:-1:1; a = repmat(1:10, 5);
-%!assert(norm(fftconv2(x,y,a)-conv2(x,y,a)), 0, 1e6*eps)
-%!assert(norm(fftconv2(x,y,a,'full')-conv2(x,y,a,'full')), 0, 1e6*eps)
-%!assert(norm(fftconv2(x,y,a,'same')-conv2(x,y,a,'same')), 0, 1e6*eps)
-%!assert(norm(fftconv2(x,y,a,'valid')-conv2(x,y,a,'valid')), 0, 1e6*eps)
-
-%!demo
-%! ## Draw a cross
-%! N = 100;
-%! [x,y] = meshgrid(-N:N, -N:N);
-%! z = 0*x;
-%! z(N,1:2*N+1) = 1; z(1:2*N+1, N) = 1;
-%! imshow(z);
-%!
-%! ## Draw a sinc blob
-%! n = floor(N/10);
-%! [x,y] = meshgrid(-n:n, -n:n);
-%! b = x.^2 + y.^2; b = max(b(:)) - b; b = b / max(b(:));
-%! imshow(b);
-%!
-%! ## Convolve the cross with the blob
-%! imshow(real(fftconv2(z, b, 'same')*N))
-
-
deleted file mode 100644
--- a/flag.m
+++ /dev/null
@@ -1,50 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} flag (@var{n})
-## Create color colormap. 
-## (cycling through red, white, blue and black)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-## flag(number) gives a colormap consists of red, white, blue and black
-## changing with each index
-
-function map = flag (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("flag: argument must be a scalar");
-    endif
-  else
-    usage ("flag (number)");
-  endif
-
-  p = [1, 0, 0; 1, 1, 1; 0, 0, 1; 0, 0, 0];
-  if (rem(number,4) == 0)
-    map=kron (ones (number / 4, 1), p);
-  else
-    map=[kron(ones (fix (number / 4), 1), p); p(1:rem (number, 4), :)];
-  endif
-
-endfunction
deleted file mode 100644
--- a/graycomatrix.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-/* Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-
-   1. Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-   2. Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-#include <octave/oct.h>
-
-DEFUN_DLD(graycomatrix, args, , "\
-\
-usage: P = graycomatrix(I, levels, distances, angles)\n\
-\n\
-  Calculate the gray-level co-occurrence matrix P = f(i,j,d,theta)\n\
-  of a gray-level image.\n\
-\n\
-  P is a 4-dimensional matrix (histogram). The value P(i,j,d,theta)\n\
-  is the number of times that gray-level j occurs at a distance 'd' and\n\
-  at an angle 'theta' from gray-level j.\n\
-\n\
-  'I' is the input image which should contain integers in [0, levels-1],\n\
-  where 'levels' indicate the number of gray-levels counted (typically\n\
-  256 for an 8-bit image).  'distances' and 'angles' are vectors of\n\
-  the different distances and angles to use.\n" ) {
-
-    // 4-dimensional histogram
-    // P = f(i, j, d, theta) where i and j are gray levels
-    // See Pattern Recognition Engineering (Morton Nadler & Eric P. Smith)
-
-    octave_value_list retval;
-
-    if (args.length() != 4) {
-	print_usage ();
-	// 'I' must be integer values [0, nr_of_levels-1]
-
-	return retval;
-    }
-
-    // Input arguments
-    Matrix I = args(0).matrix_value();
-    int L = args(1).int_value();
-    ColumnVector d = ColumnVector(args(2).vector_value());
-    ColumnVector th = ColumnVector(args(3).vector_value());
-
-    if (error_state) {
-	print_usage ();
-	return retval;
-    }
-
-    // Create output NDArray, P
-    dim_vector dim = dim_vector();
-    dim.resize(4);
-    dim(0) = L; dim(1) = L; dim(2) = d.length(); dim(3) = th.length();
-    NDArray P = NDArray(dim, 0);
-
-    // Run through image
-    int d_max = (int)ceil(d.max());
-    int cnt = 0;
-
-    for (int r = 0; r < I.rows(); r++) {
-	for (int c = 0; c < I.columns(); c++) {
-	    int i = (int)I(r,c);
-
-	    for (int d_idx = 0; d_idx < d.length(); d_idx++) {
-		int d_val = (int)d(d_idx);
-		for (int th_idx = 0; th_idx < th.length(); th_idx++) {
-		    
-		    double angle = th(th_idx);
-		    
-		    int row = r + (int)floor(cos(angle) * d_val + 0.5);
-		    int col = c - (int)floor(sin(angle) * d_val + 0.5);
-
-		    if ( ( row >= 0 ) && ( row < I.rows() ) &&
-			 ( col >= 0 ) && ( col < I.cols() ) ) {
-
-			int j = (int)I(row, col);
-
-			if (i >= 0 && i < L && j >= 0 && j < L) {
-			    Array<int> coord = Array<int> (4);
-			    coord(0) = i;
-			    coord(1) = j;
-			    coord(2) = d_idx;
-			    coord(3) = th_idx;
-			    
-			    P(coord)++;			    
-			} else {
-			    warning("Image contains invalid gray-level! (%d, %d)", i, j);
-			} 
-		    }
-
-		}
-	    }
-
-	}
-    }
-
-    return octave_value(P);
-    
-}
-
-/*
-
-%!shared a
-%!test
-%!  a = [0 0 0 1 2;
-%!       1 1 0 1 1;
-%!       2 2 1 0 0;
-%!       1 1 0 2 0;
-%!       0 0 1 0 1];
-%!  squeeze(graycomatrix(a, 3, 1, -pi/4)) == [4 2 0;
-%!                                     2 3 2;
-%!                                     1 2 0];
-%!
-%!assert(size(graycomatrix(a, 3, 1:5, [0:3]*-pi/4)), [3, 3, 5, 4])
-
-%!demo
-%!
-%!  # Pattern Recognition Engineering (Nadler & Smith)
-%!  # Digital Image Processing (Gonzales & Woods), p. 668
-%!
-%!  a = [0 0 0 1 2;
-%!       1 1 0 1 1;
-%!       2 2 1 0 0;
-%!       1 1 0 2 0;
-%!       0 0 1 0 1];
-%!
-%!  graycomatrix(a, 3, 1, [0 1]*-pi/4)
-%!
-
-
-*/
deleted file mode 100644
--- a/grayslice.m
+++ /dev/null
@@ -1,78 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{X} =} grayslice (@var{I},@var{n})
-## @deftypefnx {Function File} {@var{X} =} grayslice (@var{I},@var{v})
-## creates an indexed image @var{X} from an intensitiy image @var{I}
-## using multiple threshold levels.
-## A scalar integer value @var{n} sets the levels to
-## @example
-## 
-## @group
-## 1  2       n-1
-## -, -, ..., ---
-## n  n        n
-## @end group
-## @end example
-##
-## X = grayslice(I,5);
-##
-## For irregular threshold values a real vector @var{v} can be used.
-## The values must be in the range [0,1].
-##
-## @group
-## X = grayslice(I,[0.1,0.33,0.75,0.9])
-## @end group
-##
-## @end deftypefn
-## @seealso{im2bw}
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	03. August 2000
-
-function X = grayslice (I, v)
-
-  if (nargin != 2)
-    usage ("grayslice(...) number of arguments must be 1 or 2");
-  endif
-
-  if (is_scalar(v) && (fix(v) == v))
-
-    v = (1:v - 1) / v;
-
-  elseif (isvector(v))
-
-    if (any (v < 0) || (any (v > 1)))
-      error ("slice vector must be in range [0,1]")
-    endif
-    v = [0,v,1];
-  else
-
-    usage("second argument");
-
-  endif
-
-  [r, c] = size (I);
-  [m, n] = sort ([v(:); I(:)]);
-  lx = length (v);
-  o = cumsum (n <= lx);
-  idx = o (find(n>lx));
-  [m, n] = sort (I(:));
-  [m, n] = sort (n);
-  X = reshape (idx(n), r, c);
-
-endfunction
deleted file mode 100644
--- a/histeq.m
+++ /dev/null
@@ -1,33 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{J}= histeq (@var{I},@var{n})
-## histogram equalization
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	08. August 2000
-
-function J = histeq (I, n)
-
-  [r,c] = size (I); 
-  [X,map] = gray2ind(I);
-  [nn,xx] = imhist(I);
-  Icdf = ceil (n * cumsum (1/prod(size(I)) * nn));
-  J = reshape(Icdf(X),r,c);
-  plot(Icdf,'b;;');
-endfunction
deleted file mode 100644
--- a/hot.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} hot (@var{n})
-## Create color colormap. 
-## (black through dark red, red, orange, yellow to white)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = hot (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1) 
-	if (! is_scalar (number))
-      error ("hot: argument must be a scalar");
-    endif
-  else
-    usage ("hot (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 0];  
-  elseif (number > 1)
-    x = linspace (0, 1, number)';
-    r = (x < 2/5) .* (5/2 * x) + (x >= 2/5);
-    g = (x >= 2/5 & x < 4/5) .* (5/2 * x - 1) + (x >= 4/5);
-    b = (x >= 4/5) .* (5*x - 4);
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/houghtf.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are
-   met:
-
-   1. Redistributions of source code must retain the above copyright notice,
-      this list of conditions and the following disclaimer.
-   2. Redistributions in binary form must reproduce the above copyright
-      notice, this list of conditions and the following disclaimer in the
-      documentation and/or other materials provided with the distribution.
-
-  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-#include <octave/oct.h>
-
-DEFUN_DLD(houghtf, args, , "\
-\
-usage: [H, R]  = houghtf(I[, angles])\n\
-\n\
-  Calculate the straight line Hough transform of an image.\n\
-\n\
-  The image, I, should be a binary image in [0,1].  The angles are given\n\
-  in degrees and defaults to -90..90.\n\
-\n\
-  H is the resulting transform, R the radial distances.\n\
-\n\
-  See also: Digital Image Processing by Gonzales & Woods (2nd ed., p. 587)\n") {
-
-    octave_value_list retval;
-    bool DEF_THETA = false;
-
-    if (args.length() == 1) {
-	DEF_THETA = true;
-    } else if (args.length() != 2) {
-	print_usage ();
-	return retval;
-    } 
-
-    Matrix I = args(0).matrix_value();
-
-    ColumnVector thetas = ColumnVector();
-    if (!DEF_THETA) {
-    	thetas = ColumnVector(args(1).vector_value());
-    } else {
-        thetas = ColumnVector(Range(-90,90).matrix_value());
-    }
-
-    if (error_state) {
-	print_usage ();
-	return retval;
-    }
-
-    thetas = thetas / 180 * M_PI;
-
-    int r = I.rows();
-    int c = I.columns();
-
-    Matrix xMesh = Matrix(r, c);
-    Matrix yMesh = Matrix(r, c);
-    for (int m = 0; m < r; m++) {
-	for (int n = 0; n < c; n++) {
-	    xMesh(m, n) = n+1;
-	    yMesh(m, n) = m+1;
-	}
-    }
-
-    Matrix size = Matrix(1, 2);
-    size(0) = r; size(1) = c;
-    double diag_length = sqrt( size.sumsq()(0) );
-    int nr_bins = 2 * (int)ceil(diag_length) - 1;
-    RowVector bins = RowVector( Range(1, nr_bins).matrix_value() ) - ceil(nr_bins/2.);
-
-    Matrix J = Matrix(bins.length(), 0);
-
-    for (int i = 0; i < thetas.length(); i++) {
-	double theta = thetas(i);
-	ColumnVector rho_count = ColumnVector(bins.length(), 0);
-
-	double cT = cos(theta); double sT = sin(theta);
-	for (int x = 0; x < r; x++) {
-	    for (int y = 0; y < c; y++) {
-		if ( I(x, y) == 1 ) {
-		    int rho = (int)floor( cT*x + sT*y + 0.5 );
-		    int bin = (int)(rho - bins(0));
-		    if ( (bin > 0) && (bin < bins.length()) ) {
-			rho_count( bin )++;
-		    }
-		}
-	    }
-	}
-
-	J = J.append( rho_count );
-    }
-
-    retval.append(J);
-    retval.append(bins);
-    return retval;
-
-}
-
-/*
-%!test
-%! I = zeros(100, 100);
-%! I(1,1) = 1; I(100,100) = 1; I(1,100) = 1; I(100, 1) = 1; I(50,50) = 1;
-%! [J, R] = houghtf(I); J = J / max(J(:));
-%! assert(size(J) == [length(R) 181]);
-%!
-
-%!demo
-%! I = zeros(100, 150);
-%! I(30,:) = 1; I(:, 65) = 1; I(35:45, 35:50) = 1;
-%! for i = 1:90, I(i,i) = 1;endfor
-%! I = imnoise(I, 'salt & pepper');
-%! imshow(I);
-%! J = houghtf(I); J = J / max(J(:));
-%! imshow(J, bone(128), 'truesize');
-
-*/
deleted file mode 100644
--- a/hsv.m
+++ /dev/null
@@ -1,49 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} hsv (@var{n})
-## Create color colormap. 
-## (red through yellow, green, cyan,blue,magenta to red)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = hsv (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("hsv: argument must be a scalar");
-    endif
-  else
-    usage ("hsv (number)");
-  endif
-
-  if (number == 1)
-    map = [1, 0, 0];  
-  elseif (number > 1)
-    h = linspace (0, 1, number)';
-    map = hsv2rgb ([h, ones(number, 1), ones(number, 1)]);
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/im2bw.m
+++ /dev/null
@@ -1,50 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{BW}= im2bw (@var{I},threshold)
-## @deftypefnx {Function File} @var{BW}= im2bw (@var{X},@var{cmap},threshold)
-## converts image data types to a black-white (binary) image.
-## The treshold value should be in the range [0,1].
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	19. March 2000
-
-function BW = im2bw (img, a, b)
-
-  if ( nargin < 2 || nargin > 3)
-    usage("im2bw(I) number of arguments must be 2 or 3");
-  endif
-
-  if (isgray (img))
-    if (is_scalar (a))
-      BW = (img >= a);
-    else
-      error ("threshold value must be scalar");
-    endif
-  elseif (isind (img))
-    if (is_matrix (a) && columns (a) == 3)
-      if (is_scalar (b))
-        I = ind2gray (img, a);
-        BW = (I >= b);
-      endif
-    endif
-  else
-    error ("image matrix must be of index or intensity type");
-  endif
-
-endfunction
deleted file mode 100644
--- a/im2col.m
+++ /dev/null
@@ -1,252 +0,0 @@
-## 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} = } im2col (@var{A}, [@var{m},@var{n}], @var{block_type})
-## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, [@var{m},@var{n}])
-## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, 'indexed', ...)
-## Rearranges image blocks into columns
-##
-## @code{B=im2col(A, [m, n], blocktype)} rearranges blocks in @var{A}
-## into columns in a way that's determined by @var{block_type}, which
-## can take the following values:
-##
-## @table @code
-## @item distinct
-## Rearranges each distinct @var{m}-by-@var{n} block in image @var{A}
-## into a column of @var{B}. Blocks are scanned from left to right and
-## the up to bottom in @var{A}, and columns are added to @var{B} from
-## left to right. If @var{A}'s size is not multiple @var{m}-by-@var{n}
-## it is padded.
-## @item sliding
-## Rearranges any @var{m}-by-@var{n} sliding block of @var{A} in a
-## column of @var{B}, without any padding, so only sliding blocks which
-## can be built using a full @var{m}-by-@var{n} neighbourhood are taken.
-## In consequence, @var{B} has @var{m}*@var{n} rows and
-## (@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) columns (where @var{mm} and
-## @var{nn} are the size of @var{A}).
-##
-## This case is thought to be used applying operations on columns of
-## @var{B} (for instance using sum(:)), so that result is a
-## 1-by-(@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) vector, that is what
-## the complementary function @code{col2im} expects.
-## @end table
-##
-## @code{B=im2col(A,[m,n])} takes @code{distinct} as a default value for
-## @var{block_type}. 
-##
-## @code{B=im2col(A,'indexed',...)} will treat @var{A} as an indexed
-## image, so it will pad using 1 if @var{A} is double. All other cases
-## (incluing indexed matrices with uint8 and uint16 types and
-## non-indexed images) will use 0 as padding value.
-##
-## Any padding needed in 'distinct' processing will be added at right
-## and bottom edges of the image.
-##
-## @strong{Compatibility notes:}
-## 
-## @itemize @bullet
-## @item
-## 'sliding' blocks are arranged into @var{B} in a top-down and
-## left-right order. Since this isn't explicity described in MATLAB
-## documentation, we ignore if it does it this way. It has been
-## deduced because im2col implements inverse operation as a simple
-## reshape (if we chose left to right and then up to down order we would
-## had to transpose result). If you have MATLAB please check this
-## issue.
-## @item
-## MATLAB docs say that when using @code{'indexed'}, padding with 0 is
-## done for uint8 type. Since most functions do that too for uint16, we
-## have chosen to use 0 also for uint16, even if documentation doesn't
-## say it explicity, since it looks as an omission.
-## @end itemize
-##
-## @end deftypefn
-## @seealso{col2im}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function B = im2col(A, varargin)
-  if(nargin<2 || nargin>4)
-    usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
-  endif
-
-  ## check 'indexed' presence
-  indexed=false;
-  p=1;
-  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
-    if(nargin<3)
-      usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
-    endif
-    indexed=true;
-    p+=1;
-    if(isa(A,"uint8") || isa(A,"uint16"))
-	padval=0;
-    else
-      padval=1; 
-    endif
-  else
-    padval=0;
-  endif
-
-  ## check [m,n]
-  if(!isvector(varargin{p}))
-    error("im2col: expected [m,n] but param is not a vector.");
-  endif
-  if(length(varargin{p})!=2)
-    error("im2col: expected [m,n] but param has wrong length.");
-  endif
-  m=varargin{p}(1);
-  n=varargin{p}(2);
-  p+=1;
-
-  block_type='sliding';
-  if(nargin>p)
-    ## we have block_type param
-    if(!ischar(varargin{p}))
-      error("im2col: invalid parameter block_type.");
-    endif
-    block_type=varargin{p};
-    p+=1;
-  endif
-
-  ## if we didn't have 'indexed' but had 4 parameters there's an error
-  if(nargin>p)
-      usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
-  endif
-
-  
-  ## common checks
-  if(!ismatrix(A))
-    error("im2col: A should be a matrix (or vector).");
-  endif
-
-  switch(block_type)
-    case('distinct')
-      ## calc needed padding
-      sp=mod(-size(A)',[m;n]);
-
-      if(any(sp))
-	A=padarray(A,sp,padval,'post');
-      endif
-
-      ## iterate through all blocks
-      B=[];
-      for i=1:m:size(A,1) ## up to bottom
-	for j=1:n:size(A,2) ## left to right
-	  ## TODO: check if we can horzcat([],uint8([10;11])) in a
-	  ## future Octave version > 2.1.58
-	  if(isempty(B))
-	    B=A(i:i+m-1,j:j+n-1)(:);
-	  else
-	    B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
-	  endif
-	endfor
-      endfor
-      
-    case('sliding')
-      if(indexed)
-	disp("WARNING: 'indexed' has no sense when using sliding.");
-      endif
-      if(m>size(A,1) || n>size(A,2))
-	error("im2col: block size can't be greater than image size in sliding");
-      endif
-      ## TODO: check if matlab uses top-down and left-right order
-      B=[];
-      for j=1:1:size(A,2)-n+1 ## left to right
-	for i=1:1:size(A,1)-m+1 ## up to bottom
-	  ## TODO: check if we can horzcat([],uint8([10;11])) in a
-	  ## future Octave version > 2.1.58
-	  if(isempty(B))
-	    B=A(i:i+m-1,j:j+n-1)(:);
-	  else
-	    B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
-	  endif
-	endfor
-      endfor
-      
-    otherwise
-      error("im2col: invalid block_type.");
-  endswitch
-
-endfunction
-
-%!demo
-%! A=[1:10;11:20;21:30;31:40]
-%! B=im2col(A,[2,5],'distinct')
-%! C=col2im(B,[2,5],[4,10],'distinct')
-%! # Divide A using distinct blocks and reverse operation
-
-%!shared B, A, Bs, As, Ap, Bp0, Bp1
-%! v=[1:10]';
-%! r=reshape(v,2,5);
-%! B=[v, v+10, v+20, v+30, v+40, v+50];
-%! A=[r, r+10; r+20, r+30; r+40, r+50];
-%! As=[1,2,3,4,5;6,7,8,9,10;11,12,13,14,15];
-%! b1=As(1:2,1:4)(:);
-%! b2=As(2:3,1:4)(:);
-%! b3=As(1:2,2:5)(:);
-%! b4=As(2:3,2:5)(:);
-%! Bs=[b1,b2,b3,b4];
-%! Ap=A(:,1:9);
-%! Bp1=Bp0=B;
-%! Bp0([9:10],[2,4,6])=0;
-%! Bp1([9:10],[2,4,6])=1;
-
-%!# bad block_type
-%!error(im2col(A,[2,5],'wrong_block_type'));
-
-%!# distinct
-%!assert(im2col(A,[2,5],'distinct'), B);
-
-%!# padding
-%!assert(im2col(Ap,[2,5],'distinct'), Bp0);
-%!assert(im2col(Ap,'indexed',[2,5],'distinct'), Bp1);
-
-%!# now sliding
-%!assert(im2col(As,[2,4]), Bs);
-%!assert(im2col(As,[2,4],'sliding'), Bs);
-%!assert(im2col(As,[3,5],'sliding'), As(:));
-
-%!# disctint uint8 & uint16
-%!assert(im2col(uint8(A),[2,5],'distinct'), uint8(B));
-%!assert(im2col(uint16(A),[2,5],'distinct'), uint16(B));
-
-%!# padding uint8 & uint16 (to 0 even in indexed case)
-%!assert(im2col(uint8(Ap),[2,5],'distinct'), uint8(Bp0));
-%!assert(im2col(uint8(Ap),'indexed',[2,5],'distinct'), uint8(Bp0));
-%!assert(im2col(uint16(Ap),[2,5],'distinct'), uint16(Bp0));
-%!assert(im2col(uint16(Ap),'indexed',[2,5],'distinct'), uint16(Bp0));
-
-%!# now sliding uint8 & uint16
-%!assert(im2col(uint8(As),[2,4],'sliding'), uint8(Bs));
-%!assert(im2col(uint16(As),[2,4],'sliding'), uint16(Bs));
-
-
-
-
-%
-% $Log$
-% Revision 1.3  2005/09/08 02:00:17  pkienzle
-% [for Bill Denney] isstr -> ischar
-%
-% Revision 1.2  2004/09/03 17:37:08  jmones
-% Added support for int* and uint* types
-%
-% Revision 1.1  2004/08/18 14:39:07  jmones
-% im2col and col2im added
-%
-%
deleted file mode 100644
--- a/imadjust.m
+++ /dev/null
@@ -1,353 +0,0 @@
-## 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
-##
-##
-## Based on old imadjust.m (GPL):
-## Copyright (C) 1999,2000  Kai Habel
-
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{J}= imadjust (@var{I})
-## @deftypefnx {Function File} @var{J}= imadjust (@var{I},[@var{low_in};@var{high_in}])
-## @deftypefnx {Function File} @var{J}= imadjust (@var{I},[@var{low_in};@var{high_in}],[@var{low_out};@var{high_out}])
-## @deftypefnx {Function File} @var{J}= imadjust (..., @var{gamma})
-## @deftypefnx {Function File} @var{newmap}= imadjust (@var{map}, ...)
-## @deftypefnx {Function File} @var{RGB_out}= imadjust (@var{RGB}, ...)
-## Adjust image or colormap values to a specified range
-##
-## @code{J=imadjust(I)} adjusts intensity image @var{I} values so that
-## 1% of data on lower and higher values (2% in total) of the image is
-## saturated; choosing for that the corresponding lower and higher
-## bounds (using @code{stretchlim}) and mapping them to 0 and 1. @var{J}
-## is an image of the same size as @var{I} which contains mapped values.
-## This is equivalent to @code{imadjust(I,stretchlim(I))}.
-##
-## @code{J=imadjust(I,[low_in;high_in])} behaves as described but uses
-## @var{low_in} and @var{high_in} values instead of calculating them. It
-## maps those values to 0 and 1; saturates values lower than first limit
-## to 0 and values higher than second to 1; and finally maps all values
-## between limits linearly to a value between 0 and 1. If @code{[]} is
-## passes as @code{[low_in;high_in]} value, then @code{[0;1]} is taken
-## as a default value.
-##
-## @code{J=imadjust(I,[low_in;high_in],[low_out;high_out])} behaves as
-## described but maps output values between @var{low_out} and
-## @var{high_out} instead of 0 and 1. A default value @code{[]} can also
-## be used for this parameter, which is taken as @code{[0;1]}.
-##
-## @code{J=imadjust(...,gamma)} takes, in addition of 3 parameters
-## explained above, an extra parameter @var{gamma}, which specifies the
-## shape of the mapping curve between input elements and output
-## elements, which is linear (as taken if this parameter is omitted). If
-## @var{gamma} is above 1, then function is weighted towards lower
-## values, and if below 1, towards higher values.
-##
-## @code{newmap=imadjust(map,...)} applies a transformation to a
-## colormap @var{map}, which output is @var{newmap}. This transformation
-## is the same as explained above, just using a map instead of an image.
-## @var{low_in}, @var{high_in}, @var{low_out}, @var{high_out} and
-## @var{gamma} can be scalars, in which case the same values are applied
-## for all three color components of a map; or it can be 1-by-3
-## vectors, to define unique mappings for each component.
-##
-## @code{RGB_out=imadjust(RGB,...)} adjust RGB image @var{RGB} (a
-## M-by-N-by-3 array) the same way as specified in images and colormaps.
-## Here too @var{low_in}, @var{high_in}, @var{low_out}, @var{high_out} and
-## @var{gamma} can be scalars or 1-by-3 matrices, to specify the same
-## mapping for all planes, or unique mappings for each.
-##
-## The formula used to realize the mapping (if we omit saturation) is:
-##
-## @code{J = low_out + (high_out - low_out) .* ((I - low_in) / (high_in - low_in)) .^ gamma;}
-##
-## @strong{Compatibility notes:}
-##
-## @itemize @bullet
-## @item
-## Prior versions of imadjust allowed @code{[low_in; high_in]} and
-## @code{[low_out; high_out]} to be row vectors. Compatibility with this
-## behaviour has been keeped, although preferred form is vertical vector
-## (since it extends nicely to 2-by-3 matrices for RGB images and
-## colormaps).
-## @item
-## Previous version of imadjust, if @code{low_in>high_in} it "negated" output.
-## Now it is negated if @code{low_out>high_out}, for compatibility with
-## MATLAB.
-## @item
-## Class of @var{I} is not considered, so limit values are not
-## modified depending on class of the image, just treated "as is". When
-## Octave 2.1.58 is out, limits will be multiplied by 255 for uint8
-## images and by 65535 for uint16 as in MATLAB.
-## @end itemize
-## 
-## @end deftypefn
-## @seealso{stretchlim, brighten}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-## TODO: When Octave 2.1.58 is out multiply indices if input argument is
-## TODO: of class int* or uint*.
-
-function ret = imadjust (image, in, out, gamma)
-
-  if (nargin < 1 || nargin > 4)
-    usage ("imadjust(...) number of arguments must be between 1 and 4");
-  endif
-
-  if (nargin < 4)
-    gamma = 1;              ## default gamma
-  endif
-
-  if !(ismatrix(image))
-    error ("imadjust(image,...) first parameter must be a image matrix or colormap");
-  endif
-
-  if (nargin==1)
-    in=stretchlim(image);   ## this saturates 1% on lower and 1% on
-    out=[0;1];              ## higher values
-  endif
-
-  if (nargin==2)
-    out=[0;1];              ## default out
-  endif
-
-  if !((ismatrix(in) || isempty(in)) && (ismatrix(out) || isempty(out)) )
-    usage("imadjust(image,[low high],[bottom top],gamma)");
-  endif
-
-  if (isempty(in))
-    in=[0;1];               ## default in
-  endif
-
-  if (isempty(out))
-    out=[0;1];              ## default out
-  endif
-  
-  simage=size(image);
-  if (length(simage)==3 && simage(3)==3)
-    ## image is rgb
-    [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma);
-
-    ## make room
-    ret=zeros(size(image));
-
-    ## process each plane
-    for i=1:3
-      ret(:,:,i)=__imadjust_plane__(image(:,:,i),in(1,i),in(2,i),out(1,i),out(2,i),gamma(1,i));
-    endfor
-
-  elseif (length(simage)==2)
-    if(simage(2)==3 && \ 
-       (size(in)==[2,3] || size(out)==[2,3] || size(gamma)==[1,3]) )
-      ## image is a colormap
-      [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma);
-
-      ret=[];
-      ## process each color
-      for i=1:3
-	ret=horzcat(ret,__imadjust_plane__(image(:,i),in(1,i),in(2,i),out(1,i),out(2,i),gamma(i)));
-      endfor
-
-    else
-      ## image is a intensity image
-      if( !isvector(in) || length(in)!=2 || !isvector(out) || length(out)!=2 || !isscalar(gamma) || (gamma<0) || (gamma==Inf) )
-	error("imadjust: on an intensity image, in and out must be 2-by-1 and gamma a positive scalar.");
-      endif
-      ret=__imadjust_plane__(image,in(1),in(2),out(1),out(2),gamma);
-    endif
-
-  else
-    error("imadjust: first parameter must be a colormap, an intensity image or a RGB image");
-  endif
-endfunction
-
-
-## This does all the work. I has a plane; li and hi input low and high
-## values; and lo and ho, output bottom and top values.
-## Image negative is computed if ho<lo although nothing special is
-## needed, since formula automatically handles it.
-function ret=__imadjust_plane__(I, li, hi, lo, ho, gamma)
-  ret = (I < li) .* lo;
-  ret = ret + (I >= li & I < hi) .* (lo + (ho - lo) .* ((I - li) / (hi - li)) .^ gamma);
-  ret = ret + (I >= hi) .* ho;
-endfunction
-
-
-## Checks in, out and gamma to see if they are ok for colormap and RGB
-## cases.
-function [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma)
-  switch(size(in)) 
-    case([2,3]) 
-      ## ok!
-    case([2,1])
-      in=repmat(in,1,3);
-    case([1,2]) ## Compatibility behaviour!
-      in=repmat(in',1,3);
-    otherwise
-      error("imadjust: in must be 2-by-3 or 2-by-1.");
-  endswitch
-  
-  switch(size(out))
-    case([2,3])
-      ## ok!
-    case([2,1])
-      out=repmat(out,1,3);
-    case([1,2]) ## Compatibility behaviour!
-      out=repmat(out',1,3);
-    otherwise
-      error("imadjust: out must be 2-by-3 or 2-by-1.");
-  endswitch
-  
-  switch(size(gamma))
-    case([1,3])
-      ## ok!
-    case([1,1])
-      gamma=repmat(gamma,1,3);
-    otherwise
-      error("imadjust: gamma must be a scalar or a 1-by-3 matrix.");
-  endswitch
-  
-  ## check gamma allowed range
-  if(!all((gamma>=0)&(gamma<Inf)))
-    error("imadjust: gamma values must be in the range [0,Inf]");
-  endif
-
-endfunction
-
-
-# bad arguments
-
-# bad images
-%!error(imadjust("bad argument"));
-%!error(imadjust(zeros(10,10,3,2)));
-%!error(imadjust(zeros(10,10,4)));
-%!error(imadjust("bad argument"));
-
-# bad 2d, 3d or 4th argument
-%!error(imadjust([1:100],"bad argument",[0;1],1));
-%!error(imadjust([1:100],[0,1,1],[0;1],1));
-%!error(imadjust([1:100],[0;1],[0,1,1],1));
-%!error(imadjust([1:100],[0;1],[0;1],[0;1]));
-%!error(imadjust([1:100],[0;1],[0;1],-1));
-
-%!# 1% on each end saturated
-%!assert(imadjust([1:100]),[0,linspace(0,1,98),1]);
-
-%!# test with only input arg
-%!assert(sum(abs((imadjust(linspace(0,1,100),[1/99;98/99]) - \
-%!                [0,linspace(0,1,98),1] )(:))) < 1e-10);
-
-%!# a test with input and output args
-%!assert(imadjust([1:100],[50;90],[-50;-30]), \
-%!	 [-50*ones(1,49), linspace(-50,-30,90-50+1), -30*ones(1,10)]);
-
-%!# a test with input and output args in a row vector (Compatibility behaviour)
-%!assert(imadjust([1:100],[50,90],[-50,-30]), \
-%!	 [-50*ones(1,49), linspace(-50,-30,90-50+1), -30*ones(1,10)]);
-
-%!# the previous test, "negated"
-%!assert(imadjust([1:100],[50;90],[-30;-50]), \
-%!	 [-30*ones(1,49), linspace(-30,-50,90-50+1), -50*ones(1,10)]);
-
-
-%!shared cm,cmn
-%! cm=[[1:10]',[2:11]',[3:12]'];
-%! cmn=([[1:10]',[2:11]',[3:12]']-1)/11;
-
-%!# a colormap
-%!assert(imadjust(cmn,[0;1],[10;11]),cmn+10);
-
-%!# a colormap with params in row (Compatibility behaviour)
-%!assert(imadjust(cmn,[0,1],[10,11]),cmn+10);
-
-%!# a colormap, different output on each
-%!assert(imadjust(cmn,[0;1],[10,20,30;11,21,31]),cmn+repmat([10,20,30],10,1));
-
-%!# a colormap, different input on each, we need increased tolerance for this test
-%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0;1]) -                   \
-%!       [[0,linspace(0,1,6),1,1,1]',                                   \
-%!        [0,0,linspace(0,1,6),1,1]',                                   \
-%!        [0,0,0,linspace(0,1,6),1]']                                   \
-%!       ))(:)) < 1e-10                                                 \     
-%!       );
-
-%!# a colormap, different input and output on each
-%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0,1,2;1,2,3]) -           \
-%!       [[0,linspace(0,1,6),1,1,1]',                                   \
-%!        [0,0,linspace(0,1,6),1,1]'+1,                                 \
-%!        [0,0,0,linspace(0,1,6),1]'+2]                                 \
-%!       ))(:)) < 1e-10                                                 \
-%!       );
-
-%!# a colormap, different gamma, input and output on each
-%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0,1,2;1,2,3],[1,2,3]) -   \
-%!       [[0,linspace(0,1,6),1,1,1]',                                   \
-%!        [0,0,linspace(0,1,6).^2,1,1]'+1,                              \
-%!        [0,0,0,linspace(0,1,6).^3,1]'+2]                              \
-%!       )(:))) < 1e-10                                                 \    
-%!       );
-
-
-%!shared iRGB,iRGBn,oRGB
-%! iRGB=zeros(10,1,3);
-%! iRGB(:,:,1)=[1:10]';
-%! iRGB(:,:,2)=[2:11]';
-%! iRGB(:,:,3)=[3:12]';
-%! iRGBn=(iRGB-1)/11;
-%! oRGB=zeros(10,1,3);
-%! oRGB(:,:,1)=[0,linspace(0,1,6),1,1,1]';
-%! oRGB(:,:,2)=[0,0,linspace(0,1,6),1,1]';
-%! oRGB(:,:,3)=[0,0,0,linspace(0,1,6),1]';
-
-%!# a RGB image
-%!assert(imadjust(iRGBn,[0;1],[10;11]),iRGBn+10);
-
-%!# a RGB image, params in row (compatibility behaviour)
-%!assert(imadjust(iRGBn,[0,1],[10,11]),iRGBn+10);
-
-%!# a RGB, different output on each
-%!test
-%! t=iRGBn;
-%! t(:,:,1)+=10;
-%! t(:,:,2)+=20;
-%! t(:,:,3)+=30;
-%! assert(imadjust(iRGBn,[0;1],[10,20,30;11,21,31]),t);
-
-
-%!# a RGB, different input on each, we need increased tolerance for this test
-%!assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0;1]) - oRGB)(:))) < 1e-10);
-
-%!# a RGB, different input and output on each
-%!test
-%! t=oRGB;
-%! t(:,:,2)+=1;
-%! t(:,:,3)+=2;
-%! assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0,1,2;1,2,3]) - t)(:))) < 1e-10);
-
-%!# a RGB, different gamma, input and output on each
-%!test
-%! t=oRGB;
-%! t(:,:,2)=t(:,:,2).^2+1;
-%! t(:,:,3)=t(:,:,3).^3+2;
-%! assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0,1,2;1,2,3],[1,2,3]) - t)(:))) < 1e-10);
-
-
-%
-% $Log$
-% Revision 1.3  2004/09/01 22:51:14  jmones
-% Fully recoded: NDArray support, docs, tests, more compatible with MATLAB, changed copyright
-%
-%
deleted file mode 100644
--- a/imginfo.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## Copyright (C) 2002 Etienne Grossmann.  All rights reserved.
-##
-## 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, or (at your option) any
-## later version.
-##
-## This 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.
-##
-
-## [h,w] = imginfo (filename) - Get image size from file
-##  hw   = imginfo (filename)
-## 
-## filename : string : Name of image file
-##
-## h        : 1      : Height of image, in pixels
-## w        : 1      : Width  of image, in pixels
-##    or
-## hw=[h,w] : 2      : Height and width of image 
-##
-## NOTE : imginfo relies on the 'convert' program.
-
-## Author:        Etienne Grossmann <etienne@cs.uky.edu>
-## Last modified: Setembro 2002
-
-function [h,w] = imginfo (fn)
-
-[status, res] = system(sprintf("convert -verbose '%s' /dev/null",fn),1);
-
-if status,
-  error (["imginfo : 'convert' exited with status %i ",\
-	  "and produced\n%s\n"],\
-	 status, res);
-end
-
-res = res(index(res," ")+1:length(res));
-
-i = index (res,"x");
-if ! i, error ("imginfo : Can't interpret string (i)\n%s\n", res); end
-
-j = index (res(i-1:-1:1)," ");
-if j<2, error ("imginfo : Can't interpret string (j)\n%s\n", res); end
-w = str2num (res(i-j:i-1));
-
-k = index (res(i+1:length(res))," ");
-if k<2, error ("imginfo : Can't interpret string (k)\n%s\n", res); end
-h = str2num (res(i+1:i+k));
-
-if nargout<2, h = [h,w]; end
deleted file mode 100644
--- a/imhist.m
+++ /dev/null
@@ -1,72 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} imhist (@var{I},@var{n})
-## @deftypefnx {Function File} {} imhist (@var{I})
-## @deftypefnx {Function File} {} imhist (@var{X},@var{cmap})
-## @deftypefnx {Function File} {[@var{n,x}] = } imhist (...)
-## Shows the histogram of an image using hist 
-## @end deftypefn
-## @seealso{hist}
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## July 2000 : Paul Kienzle code simplification for hist() call.
-
-function [varargout] = imhist (I, b)
-
-  if (nargin < 1 || nargin > 2)
-    usage("imhist(image,n)");
-  endif
-
-  b_is_colormap = 0;
-
-  if (nargin == 2)
-    if (is_matrix (b))
-      b_is_colormap = (columns (b) == 3);
-    endif
-  endif
-
-  if (b_is_colormap)
-    ## assuming I is an indexed image
-    ## b is colormap
-    max_idx = max (max (I));
-    bins = rows (b);
-    if (max_idx > bins)
-      warning ("largest index exceedes length of colormap");
-    endif
-  else
-    ## assuming I is an intensity image
-    ## b is number of bins
-    if (nargin == 1)
-      bins = 256;
-    else
-      bins = b;
-    endif
-
-    ## scale image to range [0,1]
-    I = mat2gray (I);
-  endif
-  
-  if (nargout == 2)
-    [nn,xx] = hist (I(:), bins);
-    vr_val_cnt = 1; varargout{vr_val_cnt++} = nn;
-    varargout{vr_val_cnt++} = xx;
-  else
-    hist (I(:), bins);
-  endif
-
-endfunction
deleted file mode 100644
--- a/imnoise.m
+++ /dev/null
@@ -1,72 +0,0 @@
-## Copyright (C) 2000 Paul Kienzle
-##
-## 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
-
-## usage: B = imnoise (A, type)
-##
-## Adds noise to image in A.
-##
-## imnoise (A, 'gaussian' [, mean [, var]])
-##    additive gaussian noise: A = A + noise
-##    defaults to mean=0, var=0.01
-##
-## imnoise (A, 'salt & pepper' [, density])
-##    lost pixels: A = 0 or 1 for density*100% of the pixels
-##    defaults to density=0.05, or 5%
-##
-## imnoise (A, 'speckle' [, var])
-##    multiplicative gaussian noise: A = A + A*noise
-##    defaults to var=0.04
-
-## Modified: Stefan van der Walt <stefan@sun.ac.za>, 2004-02-24
-
-function A = imnoise(A, stype, a, b)
-
-  if (nargin < 2 || nargin > 4 || !is_matrix(A) || !ischar(stype))
-    usage("B = imnoise(A, type, parameters, ...)");
-  endif
-  
-  valid = (min(A(:)) >= 0 && max(A(:)) <= 1);
-
-  stype = tolower(stype);
-  if (strcmp(stype, 'gaussian'))
-    if (nargin < 3), a = 0.0; endif
-    if (nargin < 4), b = 0.01; endif
-    A = A + (a + randn(size(A)) * sqrt(b));
-    ## Variance of Gaussian data with mean 0 is E[X^2]
-  elseif (strcmp(stype, 'salt & pepper'))
-    if (nargin < 3), a = 0.05; endif
-    noise = rand(size(A));
-    A(noise <= a/2) = 0;
-    A(noise >= 1-a/2) = 1;
-  elseif (strcmp(stype, 'speckle'))
-    if (nargin < 3), a = 0.04; endif
-    A = A .* (1 + randn(size(A))*sqrt(a));
-  else
-    error("imnoise: use type 'gaussian', 'salt & pepper', or 'speckle'");
-  endif
-  
-  if valid
-    A(A>1) = 1;
-    A(A<0) = 0;
-  else
-    warning("Image should be in [0,1]");
-  endif
-
-endfunction
-
-%!assert(var(imnoise(ones(10)/2,'gaussian')(:)),0.01,0.005) # probabilistic
-%!assert(length(find(imnoise(ones(10)/2,'salt & pepper')~=0.5)),5,10) # probabilistic
-%!assert(var(imnoise(ones(10)/2,'speckle')(:)),0.01,0.005) # probabilistic
deleted file mode 100644
--- a/impad.m
+++ /dev/null
@@ -1,142 +0,0 @@
-## 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} {} impad(@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
-
-## A nice test matrix for padding:
-## A = 10*[1:5]' * ones(1,5) + ones(5,1)*[1:5]
-
-function retval = impad(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"; endif
-if nargin < 5, const = 1; endif
-if isscalar(xpad), xpad(2) = xpad(1); endif
-if isscalar(ypad), ypad(2) = ypad(1); endif
-  
-origx = size(A,2);
-origy = size(A,1);
-retx = origx + xpad(1) + xpad(2);
-rety = origy + ypad(1) + ypad(2);
-
-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) ];
-    endif                        
-  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))) ];
-    endif      
-  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))) ];
-    endif
-  else    
-    error("Unknown padding type");
-endif
-
-unwind_protect_cleanup
-    empty_list_elements_ok = empty_list_elements_ok_save;
-    warn_empty_list_elements = warn_empty_list_elements_save;
-end_unwind_protect
-      
-endfunction
deleted file mode 100644
--- a/imread.m
+++ /dev/null
@@ -1,159 +0,0 @@
-## Copyright (C) 2002 Andy Adler
-##
-## 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, or (at your option)
-## any later version. USE THIS SOFTWARE AT YOUR OWN RISK.
-
-## usage: I = imread(fname)
-##
-## Read images from various file formats.
-##
-##   The size and numeric class of the output depends on the
-##   format of the image.  A colour image is returned as an
-##   MxNx3 matrix.  Grey-level and black-and-white images are
-##   of size MxN.
-##     The colour depth of the image determines the numeric
-##   class of the output: 'uint8' or 'uint16' for grey
-##   and colour, and 'logical' for black and white.
-##
-##   Note: For image formats other than jpeg and png, the
-##         ImageMagick "convert" and "identify" utilities
-##         are needed. ImageMagick can be found at
-##
-##         www.imagemagick.org
-##
-
-## Author: Andy Adler
-##
-## Modified: Stefan van der Walt <stefan@sun.ac.za>
-## Date: 24 January 2005
-
-function varargout = imread(filename, varargin)
-    if (nargin != 1)
-	usage("I = imread(filename)")
-    endif
-
-    if !isstr(filename)
-	error("imread: filename must be a string")
-    endif
-
-    fn = file_in_path(IMAGE_PATH, filename);
-    if isempty(fn)
-	error("imread: cannot find %s", filename);
-    endif
-
-
-    [ig, ig, ext] = fileparts(fn);
-    ext = upper(ext);    
-    
-    ## divert jpegs and pngs to "jpgread" and "pngread"
-    if ( file_in_loadpath("jpgread.oct") &&
-	(strcmp(ext, ".JPG") || strcmp(ext, ".JPEG")) )
-	varargout{1} = jpgread(fn);
-	break
-    endif
-    if ( file_in_loadpath("pngread.oct") && (strcmp(ext, ".PNG")) )
-	varargout{1} = pngread(fn);
-	break
-    endif
-    
-    ## alternately, use imagemagick
-    if ( file_in_loadpath("__magick_read__.oct") )
-      varargout{:} = __magick_read__(fn, varargin{:});
-      break
-    endif
-    
-    [sys, ident] = system(sprintf('identify -verbose %s | grep -e "Red: " -e Type',
-				  fn));
-    if (sys != 0)
-	error("imread: error running ImageMagick's 'identify' on %s", fn)
-    endif
-    depth = re_grab("Red: ([[:digit:]]{1,2})", ident);
-    imtype = re_grab("Type: ([[:alpha:]]*)", ident);
-
-    depth = str2num(depth);
-    if isempty(depth) || (pow2(nextpow2(depth)) != depth)
-	error("imread: invalid image depth %s", depth)
-    endif
-
-    if !(strcmp(imtype, "Bilevel") || strcmp(imtype, "Grayscale") ||
-	 strcmp(imtype, "TrueColor"))
-	error("imread: unknown image type '%s'", imtype);
-    endif
-
-    switch (imtype)
-	case("Bilevel")
-	    fmt = "pgm";
-	case("Grayscale")
-	    fmt = "pgm";
-	case("TrueColor")
-	    fmt = "ppm";
-    endswitch
-    
-    ## Why are pipes so slow?
-    ##    cmd = sprintf("convert -flatten -strip %s %s:-", fn, fmt);
-    
-    tmpf = [tmpnam(), ".", fmt];
-    cmd = sprintf("convert -flatten -strip +compress '%s' '%s' 2>/dev/null",
-		  fn, tmpf);
-
-    sys = system(cmd);    
-    if (sys != 0)
-	error("imread: error running ImageMagick's 'convert'");
-	unlink(tmpf);
-    endif
-
-    try
-	fid = fopen(tmpf, "rb");
-    catch
-	unlink(tmpf);
-	error("imread: could not open temporary file %s", tmpf)
-    end_try_catch
-
-    fgetl(fid); # P5 or P6 (pgm or ppm)
-    [width, height] = sscanf(fgetl(fid), "%d %d", "C");
-    fgetl(fid); # ignore max components
-
-    if (depth == 16)
-	## PGM format has MSB first, i.e. big endian
-	[data, count] = fread(fid, "uint16", 0, "ieee-be");
-    else
-        [data, count] = fread(fid, "uint8");
-    endif
-    
-    fclose(fid);
-    unlink(tmpf);
-
-    if (imtype == "TrueColor")
-	channels = 3;
-    else
-	channels = 1;
-    endif
-    if (count != width*height*channels)
-	error("imread: image data chunk has invalid size")
-    endif
-
-    varargout = {};
-    switch (imtype)
- 	case ("Bilevel")
- 	    varargout{1} = logical(reshape(data, width, height)');
- 	case ("Grayscale") 
- 	    varargout{1} = uint8(reshape(data, width, height)');
- 	case ("TrueColor")
- 	    varargout{1} = cat(3, reshape(data(1:3:end), width, height)',
- 			       reshape(data(2:3:end), width, height)',
- 			       reshape(data(3:3:end), width, height)');
- 	    eval(sprintf("varargout{1} = uint%d(varargout{1});", depth));
-		
-    endswitch
-endfunction
-
-function value = re_grab(re, str)
-  T = regexp(str,re,'tokens');
-  if (isempty(T))
-    value = "";
-  else
-    value = T{1}{1};
-  endif
-endfunction
deleted file mode 100644
--- a/imresize.m
+++ /dev/null
@@ -1,104 +0,0 @@
-## Copyright (C) 2005 Søren Hauberg
-## 
-## 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}= imresize (@var{A}, @var{m})
-## Scales the image @var{A} by a factor @var{m} using nearest neighbour
-## interpolation. If @var{m} is less than 1 the image size will be reduced,
-## and if @var{m} is greater than 1 the image will be enlarged. If the image
-## is being enlarged the it will be convolved with a 11x11 Gaussian FIR filter
-## to reduce aliasing. See below on how to alter this behavior.
-##
-## @deftypefnx {Function File} @var{B}= imresize (@var{A}, @var{m}, @var{method})
-## Same as above except @var{method} interpolation is performed instead of
-## using nearest neighbour. @var{method} can be any method supported by interp2.
-##
-## @deftypefnx {Function File} @var{B}= imresize (@var{A}, [@var{mrow} @var{mcol}])
-## Scales the image @var{A} to be of size @var{mrow}x@var{mcol} using nearest
-## neighbour interpolation. If the image is being enlarged it will be convolved
-## with a lowpass FIR filter as described above.
-##
-## @deftypefnx {Function File} @var{B}= imresize (@var{A}, [@var{mrow} @var{mcol}], @var{method})
-## Same as above except @var{method} interpolation is performed instead of using
-## nearest neighbour. @var{method} can be any method supported by interp2.
-##
-## @deftypefnx {Function File} @var{B}= imresize (..., @var{method}, @var{fsize})
-## If the image the image is being enlarged it will usually be convolved with
-## a 11x11 Gaussian FIR filter. By setting @var{fsize} to 0 this will be turned
-## off, and if @var{fsize} > 0 the image will be convolved with a @var{fsize}
-## by @var{fsize} Gaussian FIR filter.
-##
-## @deftypefnx {Function File} @var{B}= imresize (..., @var{method}, @var{filter})
-## If the image size is being reduced and the @var{filter} argument is passed to 
-## imresize the image will be convolved with @var{filter} before the resizing
-## takes place.
-##
-## @seealso{interp2}
-## @end deftypefn
-
-## Author: Søren Hauberg <hauberg at gmail dot com>
-## 
-## 2005-04-14 Søren Hauberg <hauberg at gmail dot com>
-## * Initial revision
-
-function [ ret ] = imresize (im, m, method, filter)
-  if (!isgray(im))
-    error("The first argument has to be a gray-scale image.");
-  endif
-  [row col] = size(im);
-
-  # Handle the argument that describes the size of the result
-  if (length(m) == 1)
-    new_row = round(row*m);
-    new_col = round(col*m);
-  elseif (length(m) == 2)
-    new_row = m(1);
-    new_col = m(2);
-    m = min( new_row/row, new_col/col );
-  else
-    error("Bad second argument");
-  end
-
-  # Handle the method argument
-  if (nargin < 3)
-    method = "nearest";
-  endif
-
-  # Handle the filterargument
-  if (!strcmp(method, "nearest"))
-    if (nargin < 4)
-      filter = 11;
-    endif
-    if (m > 1 & filter > 0)
-      # If the image is being enlarged and filter > 0 then
-      # convolve the image with a filter*filter gaussian.
-      mu = round(filter/2);
-      sigma = mu/3;
-      x = 1:filter;
-      gauss = 1/sqrt(2*pi*sigma^2) * exp( (-(x-mu).^2)/(2*sigma^2) );
-      im = conv2(gauss, gauss, im, "same");
-    elseif (m < 1 & nargin == 4)
-      # If the image size is being reduced and a fourth argument
-      # is given, use it as a FIR filter.
-      im = conv2(im, filter, "same");
-    endif
-  endif
-  
-  # Perform the actual resizing
-  [XI YI] = meshgrid( linspace(1,col,new_col), linspace(1,row,new_row) );
-  ret = interp2(im, XI, YI, method);
-
-endfunction
deleted file mode 100644
--- a/imrotate.m
+++ /dev/null
@@ -1,349 +0,0 @@
-## Copyright (C) 2004-2005 Justus H. Piater
-##
-## 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} {} 
-##            imrotate(@var{imgPre}, @var{theta}, @var{method}, @var{bbox})
-## Rotation of a 2D matrix about its center.
-##
-## Input parameters:
-##
-##   @var{imgPre}   a gray-level image matrix
-##
-##   @var{theta}    the rotation angle in degrees counterclockwise
-##
-##   @var{method}
-##     @itemize @w
-##       @item "nearest" neighbor: fast, but produces aliasing effects (default).
-##       @item "bilinear" interpolation: does anti-aliasing, but is slightly slower.
-##       @item "bicubic" interpolation: does anti-aliasing, preserves edges better than bilinear interpolation, but gray levels may slightly overshoot at sharp edges. This is probably the best method for most purposes, but also the slowest.
-##       @item "Fourier" uses Fourier interpolation, decomposing the rotation matrix into 3 shears. This method often results in different artifacts than homography-based methods.  Instead of slightly blurry edges, this method can result in ringing artifacts (little waves near high-contrast edges).  However, Fourier interpolation is better at maintaining the image information, so that unrotating will result in an image closer to the original than the other methods.
-##     @end itemize
-##
-##   @var{bbox}
-##     @itemize @w
-##       @item "loose" grows the image to accommodate the rotated image (default).
-##       @item "crop" rotates the image about its center, clipping any part of the image that is moved outside its boundaries.
-##     @end itemize
-##
-## Output parameters:
-##
-##   @var{imgPost}  the rotated image matrix
-##
-##   @var{H}        the homography mapping original to rotated pixel
-##                   coordinates. To map a coordinate vector c = [x;y] to its
-##           rotated location, compute round((@var{H} * [c; 1])(1:2)).
-## @end deftypefn
-
-## Author: Justus H. Piater  <Justus.Piater@ULg.ac.be>
-## Created: 2004-10-18
-## Version: 0.7
-
-function [imgPost, H] = imrotate(imgPre, thetaDeg, method, bbox)
-  if (nargin < 4)
-    bbox = "loose";
-    if (nargin < 3)
-      method = "nearest";
-      if (nargin < 2)
-	usage("imrotate(img, angle [, method [, bbox]]");
-      endif
-    endif
-  endif
-
-  thetaDeg = mod(thetaDeg, 360); # some code below relies on positive angles
-  theta = thetaDeg * pi/180;
-
-  sizePre = size(imgPre);
-
-  ## We think in x,y coordinates here (rather than row,column), except
-  ## for size... variables that follow the usual size() convention. The
-  ## coordinate system is aligned with the pixel centers.
-
-  R = [cos(theta) sin(theta); -sin(theta) cos(theta)];
-
-  if (nargin >= 4 && strcmp(bbox, "crop"))
-    sizePost = sizePre;
-  else
-    ## Compute new size by projecting zero-base image corner pixel
-    ## coordinates through the rotation:
-    corners = [0, 0;
-	       (R * [sizePre(2) - 1; 0             ])';
-	       (R * [sizePre(2) - 1; sizePre(1) - 1])';
-	       (R * [0             ; sizePre(1) - 1])' ];
-    sizePost(2) = round(max(corners(:,1)) - min(corners(:,1))) + 1;
-    sizePost(1) = round(max(corners(:,2)) - min(corners(:,2))) + 1;
-    ## This size computation yields perfect results for 0-degree (mod
-    ## 90) rotations and, together with the computation of the center of
-    ## rotation below, yields an image whose corresponding region is
-    ## identical to "crop". However, we may lose a boundary of a
-    ## fractional pixel for general angles.
-  endif
-
-  ## Compute the center of rotation and the translational part of the
-  ## homography:
-  oPre  = ([ sizePre(2);  sizePre(1)] + 1) / 2;
-  oPost = ([sizePost(2); sizePost(1)] + 1) / 2;
-  T = oPost - R * oPre;		# translation part of the homography
-
-  ## And here is the homography mapping old to new coordinates:
-  H = [[R; 0 0] [T; 1]];
-
-  ## Treat trivial rotations specially (multiples of 90 degrees):
-  if (mod(thetaDeg, 90) == 0)
-    nRot90 = mod(thetaDeg, 360) / 90;
-    if (mod(thetaDeg, 180) == 0 || sizePre(1) == sizePre(2) ||
-	strcmp(bbox, "loose"))
-      imgPost = rot90(imgPre, nRot90);
-      return;
-    elseif (mod(sizePre(1), 2) == mod(sizePre(2), 2))
-      ## Here, bbox is "crop" and the rotation angle is +/- 90 degrees.
-      ## This works only if the image dimensions are of equal parity.
-      imgRot = rot90(imgPre, nRot90);
-      imgPost = zeros(sizePre);
-      hw = min(sizePre) / 2 - 0.5;
-      imgPost   (round(oPost(2) - hw) : round(oPost(2) + hw),
-		 round(oPost(1) - hw) : round(oPost(1) + hw) ) = ...
-	  imgRot(round(oPost(1) - hw) : round(oPost(1) + hw),
-		 round(oPost(2) - hw) : round(oPost(2) + hw) );
-      return;
-    else
-      ## Here, bbox is "crop", the rotation angle is +/- 90 degrees, and
-      ## the image dimensions are of unequal parity. This case cannot
-      ## correctly be handled by rot90() because the image square to be
-      ## cropped does not align with the pixels - we must interpolate. A
-      ## caller who wants to avoid this should ensure that the image
-      ## dimensions are of equal parity.
-    endif
-  end
-
-  ## For better readability of this spaghetti implementation, I keep the
-  ## branches pertaining to the various 'method's all at the first
-  ## level, even though this causes a slight redundancy in the if
-  ## statements.
-
-  imgPost = [];
-
-  if (strcmp(method, "Fourier"))
-    imgPost = imrotate_Fourier(imgPre, thetaDeg, method, bbox);
-  else
-    ## This section pertains to all non-Fourier methods.
-
-    ## "Pre"  variables hold pre -rotation values;
-    ## "Post" variables hold post-rotation values.
-
-    ## General rotation: map pixel coordinates back from the Post to the
-    ## Pre img
-    Hinv = inv(H);
-
-    ## Target coordinates:
-    [xPost, yPost] = meshgrid(1:(sizePost(2)), 1:(sizePost(1)));
-
-    ## Compute corresponding source coordinates:
-    xPre = Hinv(1,1) * xPost + Hinv(1,2) * yPost + Hinv(1,3);
-    yPre = Hinv(2,1) * xPost + Hinv(2,2) * yPost + Hinv(2,3);
-    ## zPre is guaranteed to be 1, since the last row of H (and thus of
-    ## Hinv) is [0 0 1].
-  endif
-
-  ## Now map the image using the coordinates computed in the else branch above:
-  if (strcmp(method, "nearest"))
-    ## nearest-neighbor: simply round Pre coordinates
-    xPre = round(xPre);
-    yPre = round(yPre);
-    valid = find(1 <= xPre & xPre <= sizePre(2) &
-		 1 <= yPre & yPre <= sizePre(1)  );
-    if (!length(valid))
-      warning("input image too small");
-      imgPost = 0;
-      return;
-    endif
-    
-    iPre  = sub2ind(sizePre , yPre (valid), xPre (valid));
-    iPost = sub2ind(sizePost, yPost(valid), xPost(valid));
-
-    imgPost = zeros(sizePost);
-    imgPost(iPost) = imgPre(iPre);
-  elseif(!strcmp(method, "Fourier"))
-    ## This section pertains to "bilinear" and "bicubic" methods.
-
-    ## With interpolation, one unavoidably loses up to one or two pixel
-    ## rows or columns at the image boundaries.
-
-    xPreFloor = floor(xPre);
-    xPreCeil  = ceil (xPre);
-    yPreFloor = floor(yPre);
-    yPreCeil  = ceil (yPre);
-
-    valid = find(1 <= xPreFloor & xPreCeil <= sizePre(2) &
-		 1 <= yPreFloor & yPreCeil <= sizePre(1)  );
-    if (!length(valid))
-      warning("input image too small");
-      imgPost = 0;
-      return;
-    endif
-
-    xPreFloor = xPreFloor(valid);
-    xPreCeil  = xPreCeil (valid);
-    yPreFloor = yPreFloor(valid);
-    yPreCeil  = yPreCeil (valid);
-
-    ## In the following, FC = floor(x), ceil(y), etc.
-    iPreFF = sub2ind(sizePre, yPreFloor, xPreFloor);
-    iPreCF = sub2ind(sizePre, yPreFloor, xPreCeil );
-    iPreCC = sub2ind(sizePre, yPreCeil , xPreCeil );
-    iPreFC = sub2ind(sizePre, yPreCeil , xPreFloor);
-
-    ## We'll have to weight by the fractional part of the coordinates:
-    xPreFrac = xPre(valid) - xPreFloor;
-    yPreFrac = yPre(valid) - yPreFloor;
-
-    iPost = sub2ind(sizePost, yPost(valid), xPost(valid));
-  endif
-
-  if (strcmp(method, "bilinear"))
-    imgPost = zeros(sizePost);
-    ## bilinear interpolation between the four floor and ceiling coordinates
-    imgPost(iPost) = (imgPre(iPreFF) .* (1 - xPreFrac) .* (1 - yPreFrac) +
-		      imgPre(iPreCF) .*      xPreFrac  .* (1 - yPreFrac) +
-		      imgPre(iPreCC) .*      xPreFrac  .*      yPreFrac  +
-		      imgPre(iPreFC) .* (1 - xPreFrac) .*      yPreFrac   );
-  elseif (strcmp(method, "bicubic"))
-    ## bicubic interpolation (see Numerical Recipes)
-    ## This code, together with the prerequisites above, is not limited
-    ## to this particular use but applies to generic bicubic
-    ## interpolation in the following scenario:
-    ## - source data are stored in a matrix,
-    ## - interpolated coordinates may lie anywhere, no regularity is assumed.
-
-    ## precompute the required derivatives at the source image pixels:
-    imgPreDx  = conv2(imgPre  , [ 0.5 0 -0.5] , "same");
-    imgPreDy  = conv2(imgPre  , [-0.5 0  0.5]', "same");
-    imgPreDxy = conv2(imgPreDx, [-0.5 0  0.5]', "same");
-
-    ## Interpolation is done on a square of pixels and their
-    ## derivatives along x, y, and xy. The square is indexed as:
-    ##   43                        FF CF
-    ##   12  which corresponds to  FC CC
-
-    ## Coefficient matrix W
-    ## C11 12         21            31            41                p deriv
-    W = [1  0 -3  2    0  0  0  0   -3  0  9 -6    2  0 -6  4    ## 1
-	 0  0  0  0    0  0  0  0    3  0 -9  6   -2  0  6 -4	 ## 2
-	 0  0  0  0    0  0  0  0    0  0  9 -6    0  0 -6  4	 ## 3
-	 0  0  3 -2    0  0  0  0    0  0 -9  6    0  0  6 -4	 ## 4
-	 
-	 0  0  0  0    1  0 -3  2   -2  0  6 -4    1  0 -3  2	 ## 1 x
-	 0  0  0  0    0  0  0  0   -1  0  3 -2    1  0 -3  2	 ## 2 x
-	 0  0  0  0    0  0  0  0    0  0 -3  2    0  0  3 -2	 ## 3 x
-	 0  0  0  0    0  0  3 -2    0  0 -6  4    0  0  3 -2	 ## 4 x
-	 
-	 0  1 -2  1    0  0  0  0    0 -3  6 -3    0  2 -4  2	 ## 1 y
-	 0  0  0  0    0  0  0  0    0  3 -6  3    0 -2  4 -2	 ## 2 y
-	 0  0  0  0    0  0  0  0    0  0 -3  3    0  0  2 -2	 ## 3 y
-	 0  0 -1  1    0  0  0  0    0  0  3 -3    0  0 -2  2	 ## 4 y
-	 
-	 0  0  0  0    0  1 -2  1    0 -2  4 -2    0  1 -2  1	 ## 1 xy
-	 0  0  0  0    0  0  0  0    0 -1  2 -1    0  1 -2  1	 ## 2 xy
-	 0  0  0  0    0  0  0  0    0  0  1 -1    0  0 -1  1	 ## 3 xy
-	 0  0  0  0    0  0 -1  1    0  0  2 -2    0  0 -1  1];  ## 4 xy
-
-    u = 1 - yPreFrac;
-    values = zeros(size(valid));
-    for ci = 4:-1:1
-      ## compute ci'th row of matrix C:
-
-      col = 4*(ci - 1) + 1;
-      c{1} = (W( 1,col) * imgPre   (iPreFC) + W( 2,col) * imgPre   (iPreCC) +
-	      W( 5,col) * imgPreDx (iPreFC) + W( 6,col) * imgPreDx (iPreCC)  );
-
-      col++;
-      c{2} = (W( 9,col) * imgPreDy (iPreFC) + W(10,col) * imgPreDy (iPreCC) +
-	      W(13,col) * imgPreDxy(iPreFC) + W(14,col) * imgPreDxy(iPreCC)  );
-
-      for cii = 3:4
-	col++;
-	c{cii} = ...
-	    (W( 1,col) * imgPre   (iPreFC) + W( 2,col) * imgPre   (iPreCC) +
-	     W( 3,col) * imgPre   (iPreCF) + W( 4,col) * imgPre   (iPreFF) +
-	     W( 5,col) * imgPreDx (iPreFC) + W( 6,col) * imgPreDx (iPreCC) +
-	     W( 7,col) * imgPreDx (iPreCF) + W( 8,col) * imgPreDx (iPreFF) +
-	     W( 9,col) * imgPreDy (iPreFC) + W(10,col) * imgPreDy (iPreCC) +
-	     W(11,col) * imgPreDy (iPreCF) + W(12,col) * imgPreDy (iPreFF) +
-	     W(13,col) * imgPreDxy(iPreFC) + W(14,col) * imgPreDxy(iPreCC) +
-	     W(15,col) * imgPreDxy(iPreCF) + W(16,col) * imgPreDxy(iPreFF)  );
-      endfor
-
-      values .*= xPreFrac;
-      values  += ((c{4} .* u + c{3}) .* u + c{2}) .* u + c{1};
-    endfor
-    imgPost = zeros(sizePost);
-    imgPost(iPost) = values;
-  endif
-
-  if (!prod(size(imgPost)))
-    error(sprintf("Interpolation method %s not implemented", method));
-  endif
-endfunction
-
-%!test
-%! ## Verify minimal loss across six rotations that add up to 360 +/- 1 deg.:
-%! methods = { "nearest", "bilinear", "bicubic", "Fourier" };
-%! angles     = [ 59  60  61  ];
-%! tolerances = [ 7.4 8.5 8.6	  # nearest
-%!                3.5 3.1 3.5     # bilinear
-%!                2.7 0.1 2.7     # bicubic
-%!                2.7 1.6 2.8 ];  # Fourier
-%! x = peaks(50);
-%! x -= min(min(x));	      # Fourier does not handle neg. values well
-%! for m = 1:(length(methods))
-%!   y = x;
-%!   for i = 1:5
-%!     y = imrotate(y, 60, methods(m), "crop");
-%!   end
-%!   for a = 1:(length(angles))
-%!     assert(norm((x - imrotate(y, angles(a), methods(m), "crop"))
-%!                 (10:40, 10:40)) < tolerances(m,a));
-%!   end
-%! end
-
-
-%!test
-%! ## Verify exactness of near-90 and 90-degree rotations:
-%! X = rand(99);
-%! for angle = [90 180 270]
-%!   for da = [-0.1 0.1]
-%!     Y = imrotate(X,   angle + da , "nearest");
-%!     Z = imrotate(Y, -(angle + da), "nearest");
-%!     assert(norm(X - Z) == 0); # exact zero-sum rotation
-%!     assert(norm(Y - imrotate(X, angle, "nearest")) == 0); # near zero-sum
-%!   end
-%! end
-
-
-%!test
-%! ## Verify preserved pixel density:
-%! methods = { "nearest", "bilinear", "bicubic", "Fourier" };
-%! ## This test does not seem to do justice to the Fourier method...:
-%! tolerances = [ 4 2.2 2.0 209 ];
-%! range = 3:9:100;
-%! for m = 1:(length(methods))
-%!   t = [];
-%!   for n = range
-%!     t(end + 1) = sum(imrotate(eye(n), 20, methods(m))(:));
-%!   end
-%!   assert(t, range, tolerances(m));
-%! end
-
deleted file mode 100644
--- a/imrotate_Fourier.m
+++ /dev/null
@@ -1,170 +0,0 @@
-## Copyright (C) 2002 Jeff Orchard <jorchard@cs.uwaterloo.ca>
-##
-## 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} {} imrotate(@var{M}, @var{theta}, @var{method}, @var{bbox})
-## Rotation of a 2D matrix.
-##
-## Applies a rotation of @var{THETA} degrees to matrix @var{M}.
-##
-## The @var{method} argument is not implemented, and is only included for compatibility with Matlab.
-## This function uses Fourier interpolation,
-## decomposing the rotation matrix into 3 shears.
-##
-## @var{bbox} can be either 'loose' or 'crop'.
-## 'loose' allows the image to grow to accomodate the rotated image.
-## 'crop' keeps the same size as the original, clipping any part of the image
-## that is moved outside the bounding box.
-## @end deftypefn
-
-## Author: Jeff Orchard <jorchard@cs.uwaterloo.ca>
-## Created: Oct. 14, 2002
-
-function fs = imrotate_Fourier(f,theta,method,bbox)
-
-	if ( nargin == 2 )
-		method = "fourier";
-		bbox = "loose";
-	elseif ( nargin == 3 )
-		bbox = "loose";
-	endif
-
-	# Get original dimensions.
-	[ydim_orig, xdim_orig] = size(f);
-
-	# This finds the index coords of the centre of the image (indices are base-1)
-	#   eg. if xdim_orig=8, then xcentre_orig=4.5 (half-way between 1 and 8)
-	xcentre_orig = (xdim_orig+1) / 2;
-	ycentre_orig = (ydim_orig+1) / 2;
-
-	# Pre-process the angle ===========================================================
-	# Whichever 90 degree multiple theta is closest to, that multiple of 90 will
-	# be implemented by rot90. The remainder will be done by shears.
-
-	# This ensures that 0 <= theta < 360.
-	theta = rem( rem(theta,360) + 360, 360 );
-
-	# This is a flag to keep track of 90-degree rotations.
-	perp = 0;
-
-	if ( theta>=0 && theta<=45 )
-		phi = theta;
-	elseif ( theta>45 && theta<=135 )
-		phi = theta - 90;
-		f = rot90(f,1);
-		perp = 1;
-	elseif ( theta>135 && theta<=225 )
-		phi = theta - 180;
-		f = rot90(f,2);
-	elseif ( theta>225 && theta<=315 )
-		phi = theta - 270;
-		f = rot90(f,3);
-		perp = 1;
-	else
-		phi = theta;
-	endif
-
-
-
-	if ( phi == 0 )
-		fs = f;
-		if ( strcmp(bbox,"loose") == 1 )
-			return;
-		else
-			xmax = xcentre_orig;
-			ymax = ycentre_orig;
-			if ( perp == 1 )
-				xmax = max([xmax ycentre_orig]);
-				ymax = max([ymax xcentre_orig]);
-				[ydim xdim] = size(fs);
-				xpad = ceil( xmax - (xdim+1)/2 );
-				ypad = ceil( ymax - (ydim+1)/2 );
-				fs = impad(fs, [xpad,xpad], [ypad,ypad], "zeros");
-			endif
-			xcentre_new = (size(fs,2)+1) / 2;
-			ycentre_new = (size(fs,1)+1) / 2;
-		endif
-	else
-
-		# At this point, we can assume -45<theta<45 (degrees)
-
-		phi = phi * pi / 180;
-		theta = theta * pi / 180;
-		R = [ cos(theta) -sin(theta) ; sin(theta) cos(theta) ];
-
-		# Find max of each dimension... this will be expanded for "loose" and "crop"
-		xmax = xcentre_orig;
-		ymax = ycentre_orig;
-
-		# If we don't want wrapping, we have to zeropad.
-		# Cropping will be done later, if necessary.
-		if ( strcmp(bbox, "wrap") == 0 )
-			corners = ( [ xdim_orig xdim_orig -xdim_orig -xdim_orig ; ydim_orig -ydim_orig ydim_orig -ydim_orig ] + 1 )/ 2;
-			rot_corners = R * corners;
-			xmax = max([xmax rot_corners(1,:)]);
-			ymax = max([ymax rot_corners(2,:)]);
-
-			# If we are doing a 90-degree rotation first, we need to make sure our
-			# image is large enough to hold the rot90 image as well.
-			if ( perp == 1 )
-				xmax = max([xmax ycentre_orig]);
-				ymax = max([ymax xcentre_orig]);
-			endif
-
-			[ydim xdim] = size(f);
-			xpad = ceil( xmax - xdim/2 );
-			ypad = ceil( ymax - ydim/2 );
-			%f = impad(f, [xpad,xpad], [ypad,ypad], "zeros");
-			xcentre_new = (size(f,2)+1) / 2;
-			ycentre_new = (size(f,1)+1) / 2;
-		endif
-
-		#size(f)
-		[S1 S2] = MakeShears(phi);
-
-		tic;
-		f1 = imshear(f, 'x', S1(1,2), 'loose');
-		f2 = imshear(f1, 'y', S2(2,1), 'loose');
-		fs = real( imshear(f2, 'x', S1(1,2), 'loose') );
-		%fs = f2;
-		xcentre_new = (size(fs,2)+1) / 2;
-		ycentre_new = (size(fs,1)+1) / 2;
-	endif
-
-	if ( strcmp(bbox, "crop") == 1 )
-
-		# Translate the current centre to centre_orig
-		fs = imtranslate(fs, xcentre_orig-xcentre_new, -ycentre_orig+ycentre_new, "wrap");
-
-		# Crop to original dimensions
-		fs = fs(1:ydim_orig, 1:xdim_orig);
-
-	elseif ( strcmp(bbox, "loose") == 1 )
-
-		# Find tight bounds on size of rotated image
-		# These should all be positive, or 0.
-		xmax_loose = ceil( xcentre_new + max(rot_corners(1,:)) );
-		xmin_loose = floor( xcentre_new - max(rot_corners(1,:)) );
-		ymax_loose = ceil( ycentre_new + max(rot_corners(2,:)) );
-		ymin_loose = floor( ycentre_new - max(rot_corners(2,:)) );
-
-		%fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
-		fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
-
-	endif
-
-
-endfunction
deleted file mode 100644
--- a/imshear.m
+++ /dev/null
@@ -1,131 +0,0 @@
-## Copyright (C) 2002 Jeff Orchard
-##
-## 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} {} 
-##            imshear (@var{M}, @var{axis}, @var{alpha}, @var{bbox})
-## Applies a shear to @var{M}.
-##
-## The argument @var{M} is either a matrix or an RGB image.
-##
-## @var{axis} is the axis along which the shear is to be applied, and can
-## be either 'x' or 'y'.
-## For example, to shear sideways is to shear along the 'x' axis. Choosing
-## 'y' causes an up/down shearing.
-##
-## @var{alpha} is the slope of the shear. For an 'x' shear, it is the 
-## horizontal shift (in pixels) applied to the pixel above the 
-## center. For a 'y' shear, it is the vertical shift (in pixels)
-## applied to the pixel just to the right of the center pixel.
-##
-## NOTE: @var{alpha} does NOT need to be an integer.
-##
-## @var{bbox} can be one of 'loose', 'crop' or 'wrap'.
-## 'loose' allows the image to grow to accomodate the new transformed image.
-## 'crop' keeps the same size as the original, clipping any part of the image
-## that is moved outside the bounding box.
-## 'wrap' keeps the same size as the original, but does not clip the part 
-## of the image that is outside the bounding box. Instead, it wraps it back 
-## into the image.
-##
-## If called with only 3 arguments, @var{bbox} is set to 'loose' by default.
-## @end deftypefn
-
-## Author: Jeff Orchard <jjo@sfu.ca>
-## Created: June 2002
-
-function g = imshear(m, axis, alpha, bbox, noshift)
-
-	# The code below only does y-shearing. This is because of
-	# the implementation of fft (operates on columns, but not rows).
-	# So, transpose first for x-shearing.
-	if ( strcmp(axis, "x")==1 )
-		m = m';
-	endif
-
-	if ( nargin < 4 )
-		bbox = "loose";
-		noshift = 0;
-	elseif ( nargin < 5 )
-		noshift = 0;
-	endif
-
-	[ydim_orig xdim_orig] = size(m);
-	if ( strcmp(bbox, "wrap") == 0 )
-		ypad = ceil( (xdim_orig+1)/2 * abs(alpha) );
-		m = impad(m, [0,0], [ypad,ypad]);
-	endif
-
-	[ydim_new xdim_new] = size(m);
-	xcentre = ( xdim_new + 1 ) / 2;
-	ycentre = ( ydim_new + 1 ) / 2;
-
-	# This applies FFT to columns of m (x-axis remains a spatial axis).
-	# Because the way that fft and fftshift are implemented, the origin
-	# will move by 1/2 pixel, depending on the polarity of the image
-	# dimensions.
-	#
-	# If dim is even (=2n), then the origin of the fft below is located
-	# at the centre of pixel (n+1). ie. if dim=16, then centre is at 9.
-	#
-	# If dim is odd (=2n+1), then the origin of the fft below is located
-	# at the centre of pixel (n). ie. if dim=15, then centre is at 8.
-	if ( noshift==1 )
-		M = fft(m);
-	else
-		#M = imtranslate(fft(imtranslate(m, -xcentre, ycentre, "wrap")), xcentre, -ycentre, "wrap");
-		M = fftshift(fft(fftshift(m)));
-	endif
-
-	[ydim xdim] = size(m);
-	x = zeros(ydim, xdim);
-
-	# Find coords of the origin of the image.
-	if ( noshift==1 )
-		xc_coord = 1;
-		yc_coord = 1;
-		l = (1:ydim)' - yc_coord;
-		r = (1:xdim) - xc_coord;
-		if ( strcmp(bbox, "wrap")==1 )
-			l((ydim/2):ydim) = l((ydim/2):ydim) - ydim;
-			r((xdim/2):xdim) = r((xdim/2):xdim) - xdim;
-		endif
-	else
-		xc_coord = (xdim+1)/2;
-		yc_coord = (ydim+1)/2;
-		l = (1:ydim)' - yc_coord;
-		r = (1:xdim) - xc_coord;
-	endif
-	x = l * r;
-
-	Ms = M.* exp(2*pi*I*alpha/ydim * x);
-
-	if ( noshift==1 )
-		g = abs(ifft(Ms));
-	else
-		#g = abs(imtranslate( ifft( imtranslate(Ms, -xcentre, ycentre, "wrap") ), xcentre, -ycentre, "wrap"));
-		g = abs( fftshift(ifft(ifftshift(Ms))) );
-	endif
-
-	if ( strcmp(bbox, "crop")==1 )
-		g = g(ypad+1:ydim_orig+ypad, :);
-	endif
-
-	# Un-transpose if x-shearing was wanted
-	if ( strcmp(axis, "x")==1 )
-		g = g';
-	endif
-endfunction
deleted file mode 100644
--- a/imtranslate.m
+++ /dev/null
@@ -1,70 +0,0 @@
-## Copyright (C) 2002 Jeff Orchard
-##
-## 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{Y}} =
-##             imtranslate (@var{M}, @var{x}, @var{y} [, @var{bbox}])
-## Translate a 2D image by (x,y) using Fourier interpolation.
-##
-## @var{M} is a matrix, and is translated to the right by @var{X} pixels
-## and translated up by @var{Y} pixels.
-##
-## @var{bbox} can be either 'crop' or 'wrap' (default).
-##
-## @end deftypefn
-
-## Author: Jeff Orchard <jjo@cs.sfu.ca>
-
-function Y = imtranslate(X, a, b, bbox_in)
-
-	bbox = "wrap";
-	if ( nargin > 3 )
-		bbox = bbox_in;
-	endif
-
-	if ( strcmp(bbox, "crop")==1 )
-
-		xpad = [0,0];
-		if (a>0)
-			xpad = [0,ceil(a)];
-		elseif (a<0)
-			xpad = [-ceil(a),0];
-		endif
-
-		ypad = [0,0];
-		if (b>0)
-			ypad = [ceil(b),0];
-		elseif (b<0)
-			ypad = [0,-ceil(b)];
-		endif
-
-		X = impad(X, xpad, ypad, 'zeros');
-	endif
-
-
-	[dimy, dimx] = size(X);
-	x = ifftshift(fft2(fftshift(X)));
-	px = exp(-2*pi*i*a*(0:dimx-1)/dimx);
-	py = exp(-2*pi*i*b*(0:dimy-1)/dimy)';
-	P = py * px;
-	y = x .* P;
-	Y = abs( ifftshift(ifft2(fftshift(y))) );
-	#Y = ifftshift(ifft2(fftshift(y)));
-
-	if ( strcmp(bbox, "crop")==1 )
-		Y = Y(  ypad(1)+1:dimy-ypad(2) , xpad(1)+1:dimx-xpad(2));
-	endif
-endfunction
deleted file mode 100644
--- a/imwrite.m
+++ /dev/null
@@ -1,273 +0,0 @@
-## Copyright (C) 2002 Andy Adler
-##
-## 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, or (at your option)
-## any later version. USE THIS SOFTWARE AT YOUR OWN RISK.
-
-#IMWRITE: write image from octave to various file formats
-#
-# Note: this requires the ImageMagick "convert" utility.
-#       get this from www.imagemagick.org if required
-#       additional documentation of options is available from the
-#       convert man page
-#
-# BASIC USAGE:
-# imwrite( fname, img )
-#                 - img is a greyscale (0-255) of image in fname
-# imwrite( fname, img, map )
-#                 - map is a matrix of [r,g,b], 0-1 triples
-#                 - img is a matrix on indeces into map
-# imwrite( fname, r,g,b );
-#                 - r,g,b are red,green,blue (0-255) compondents
-#
-# Formats for image fname
-#   1. simple guess from extention ie "fig.jpg", "blah.gif"
-#   2. specify explicitly             "jpg:fig.jpg", "gif:blah.gif"
-#   3. specify subimage for multi-image format "tiff:file.tif[3]"
-#   4. raw images (row major format) specify geometry
-#                                      "raw:img[256x180]"
-#
-# IMREAD OPTIONS:
-# imread will support most of the options for convert.1
-#
-# imwrite( fname, img, options )
-# imwrite( fname, img, map, options )
-# imwrite( fname, r,g,b, options );
-#
-# where options is a string matrix (or list) of options
-#
-# example:   options= ["-rotate 25";
-#                      "-crop 200x200+150+150";
-#                      "-sample 200%" ];
-#   will rotate, crop, and then expand the image.
-#   note that the order of operations is important
-#
-# The following options are supported
-#  -antialias           remove pixel-aliasing
-#  -background color    background color
-#  -blur geometry       blur the image
-#  -border geometry     surround image with a border of color
-#  -bordercolor color   border color
-#  -box color           color for annotation bounding box
-#  -charcoal radius     simulate a charcoal drawing
-#  -colorize value      colorize the image with the fill color
-#  -colors value        preferred number of colors in the image
-#  -colorspace type     alternate image colorspace
-#  -comment string      annotate image with comment
-#  -compress type       type of image compression
-#  -contrast            enhance or reduce the image contrast
-#  -crop geometry       preferred size and location of the cropped image
-#  -density geometry    vertical and horizontal density of the image
-#  -depth value         depth of the image
-#  -despeckle           reduce the speckles within an image
-#  -dispose method      GIF disposal method
-#  -dither              apply Floyd/Steinberg error diffusion to image
-#  -draw string         annotate the image with a graphic primitive
-#  -edge radius         apply a filter to detect edges in the image
-#  -emboss radius       emboss an image
-#  -enhance             apply a digital filter to enhance a noisy image
-#  -equalize            perform histogram equalization to an image
-#  -fill color          color to use when filling a graphic primitive
-#  -filter type         use this filter when resizing an image
-#  -flip                flip image in the vertical direction
-#  -flop                flop image in the horizontal direction
-#  -font name           font for rendering text
-#  -frame geometry      surround image with an ornamental border
-#  -fuzz distance       colors within this distance are considered equal
-#  -gamma value         level of gamma correction
-#  -geometry geometry   perferred size or location of the image
-#  -gaussian geometry   gaussian blur an image
-#  -gravity type        vertical and horizontal text placement
-#  -implode amount      implode image pixels about the center
-#  -intent type         Absolute, Perceptual, Relative, or Saturation
-#  -interlace type      None, Line, Plane, or Partition
-#  -label name          assign a label to an image
-#  -level value         adjust the level of image contrast
-#  -list type           Color, Delegate, Format, Magic, Module, or Type
-#  -map filename        transform image colors to match this set of colors
-#  -matte               store matte channel if the image has one
-#  -median radius       apply a median filter to the image
-#  -modulate value      vary the brightness, saturation, and hue
-#  -monochrome          transform image to black and white
-#  -morph value         morph an image sequence
-#  -negate              replace every pixel with its complementary color 
-#  -noise radius        add or reduce noise in an image
-#  -normalize           transform image to span the full range of colors
-#  -opaque color        change this color to the fill color
-#  -page geometry       size and location of an image canvas
-#  -paint radius        simulate an oil painting
-#  -profile filename    add ICM or IPTC information profile to image
-#  -quality value       JPEG/MIFF/PNG compression level
-#  -raise value         lighten/darken image edges to create a 3-D effect
-#  -region geometry     apply options to a portion of the image
-#  -roll geometry       roll an image vertically or horizontally
-#  -rotate degrees      apply Paeth rotation to the image
-#  -sample geometry     scale image with pixel sampling
-#  -scale geometry      resize image
-#  -segment values      segment an image
-#  -seed value          pseudo-random number generator seed value
-#  -shade degrees       shade the image using a distant light source
-#  -sharpen geometry    sharpen the image
-#  -shave geometry      shave pixels from the image edges
-#  -shear geometry      slide one edge of the image along the X or Y axis
-#  -size geometry       width and height of image
-#  -solarize threshold  negate all pixels above the threshold level
-#  -spread amount       displace image pixels by a random amount
-#  -stroke color        color to use when stoking a graphic primitive
-#  -strokewidth value   width of stroke
-#  -swirl degrees       swirl image pixels about the center
-#  -texture filename    name of texture to tile onto the image background
-#  -threshold value     threshold the image
-#  -tile filename       tile image when filling a graphic primitive
-#  -transparent color   make this color transparent within the image
-#  -treedepth value     depth of the color tree
-#  -type type           image type
-#  -units type          PixelsPerInch, PixelsPerCentimeter, or Undefined
-#  -unsharp geometry    sharpen the image
-
-function imwrite(fname, p2, p3 ,p4 ,p5 );
-
-try save_empty_list_elements_ok= empty_list_elements_ok;
-catch save_empty_list_elements_ok= 0;
-end
-try save_warn_empty_list_elements= warn_empty_list_elements;
-catch save_warn_empty_list_elements= 0;
-end
-unwind_protect
-empty_list_elements_ok= 1;
-warn_empty_list_elements= 0;
-
-# some older versions of octave didn't seem handle piped output correctly
-usepipe=1;
-
-if  ( nargin <= 1 )     || ...
-    ( ! ischar (fname))  || ...
-    ( nargin == 2 && ischar(p2) )
-    usage([ ...
-    "imwrite( fname, img )\n", ...
-    "imwrite( fname, img, map )\n", ...
-    "imwrite( fname, r,g,b );\n", ...
-    "imwrite( fname, img, options )\n", ...
-    "imwrite( fname, img, map, options )\n", ...
-    "imwrite( fname, r,g,b, options );\n"]);
-endif
-
-# Put together the options string
-# TODO: add some error checking to options
-option_str="";
-n_mat= nargin-1;
-
-options= eval(sprintf("p%d",nargin));
-# process options strings if given
-if    ischar(options)
-   n_mat--;
-   for i= 1:size(options,1)
-      option_str=[option_str," ", options(i,:) ];
-   end
-elseif is_list( options )
-   n_mat--;
-   for i= 1:length(options)
-      option_str=[option_str," ", nth(options,i) ];
-   end
-end
-
-[hig,wid] = size(p2);
-if n_mat==1
-   data= p2';
-   outputtype="pgm";
-   pnm_sig="P5";
-elseif n_mat==2
-   img= p2';
-   data= [ 255*reshape(p3(img,1),1, hig*wid);
-           255*reshape(p3(img,2),1, hig*wid);
-           255*reshape(p3(img,3),1, hig*wid) ];
-   outputtype="ppm";
-   pnm_sig="P6";
-elseif n_mat==3
-   data= [ reshape(p2',1, hig*wid);
-           reshape(p3',1, hig*wid);
-           reshape(p4',1, hig*wid) ];
-   outputtype="ppm";
-   pnm_sig="P6";
-else
-   error("imwrite: too many data matrices specified");
-end
-
-if usepipe
-   pname= sprintf("convert %s %s:- '%s' 2>/dev/null",
-                  option_str, outputtype, fname);
-   fid= popen(pname ,'w');
-
-   if fid<0;
-      error('could not create image data. Is ImageMagick installed?');
-   end
-else
-   tnam= tmpnam();
-   cmd= sprintf("convert %s '%s:%s' '%s' 2>/dev/null",
-                 option_str, outputtype, tnam, fname);
-   fid= fopen(tnam, "wb");
-end   
-
-   fprintf(fid,"%s\n%d %d\n255\n",pnm_sig,wid,hig);
-   write_count= fwrite(fid,data(:));
-   if write_count != prod(size(data))
-      fclose(fid);
-      if ~usepipe
-         unlink(tnam);
-      end
-      error(['Problem writing image: ', fname ]);
-   end
-
-   fclose(fid);
-   if ~usepipe
-      retcode = system(cmd);
-      if retcode !=0 
-         error('could not call imagemagick convert');
-      end
-      unlink( tnam );
-   end
-
-unwind_protect_cleanup
-empty_list_elements_ok= save_empty_list_elements_ok;
-warn_empty_list_elements= save_warn_empty_list_elements;
-end_unwind_protect
-
-#
-# $Log$
-# Revision 1.11  2006/03/22 17:50:47  qspencer
-# Change calls to 'system' function to reflect new ordering of output arguments.
-#
-# Revision 1.10  2005/09/08 02:00:17  pkienzle
-# [for Bill Denney] isstr -> ischar
-#
-# Revision 1.9  2005/07/21 16:03:02  aadler
-# Improve error messages and use pipes
-#
-# Revision 1.8  2005/05/25 03:43:40  pkienzle
-# Author/Copyright consistency
-#
-# Revision 1.7  2005/04/25 01:05:28  aadler
-# added GPL copyrights
-#
-# Revision 1.6  2003/09/12 14:22:42  adb014
-# Changes to allow use with latest CVS of octave (do_fortran_indexing, etc)
-#
-# Revision 1.5  2003/07/25 19:11:41  pkienzle
-# Make sure all files names referenced in system calls are wrapped in quotes
-# to protect against spaces in the path.
-#
-# Revision 1.4  2002/11/27 08:40:11  pkienzle
-# author/license updates
-#
-# Revision 1.3  2002/03/19 18:14:13  aadler
-# unfortunately using popen seems to create problems, mostly
-# on win32, but also on linux, so we need to move to a tmpfile approach
-#
-# Revision 1.2  2002/03/17 05:26:14  aadler
-# now accept filenames with spaces
-#
-# Revision 1.1  2002/03/11 01:56:47  aadler
-# general image read/write functionality using imagemagick utilities
-#
-#
new file mode 100644
--- /dev/null
+++ b/inst/MakeShears.m
@@ -0,0 +1,7 @@
+function [S1, S2] = MakeShears(theta)
+
+S1 = eye(2);
+S2 = eye(2);
+
+S1(1,2) = -tan(theta/2);
+S2(2,1) = sin(theta);
new file mode 100644
--- /dev/null
+++ b/inst/applylut.m
@@ -0,0 +1,62 @@
+## 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{A} = } applylut (@var{BW},@var{LUT})
+## Uses lookup tables to perform a neighbour operation on binary images.
+##
+## A = applylut(BW,LUT) returns the result of a neighbour operation
+## using the lookup table @var{LUT} which can be created by makelut.
+##
+## It first computes a matrix with the index of each element in the
+## lookup table. To do this, it convolves the original matrix with a
+## matrix which assigns each of the neighbours a bit in the resulting
+## index. Then @var{LUT} is accessed to compute the result.
+##
+## @end deftypefn
+## @seealso{makelut}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function A = applylut(BW, LUT)
+  if (nargin != 2)
+    usage ("A = applylut(BW, LUT)");
+  endif
+
+  nq=log2(length(LUT));
+  n=sqrt(nq);
+  if (floor(n)!=n)
+    error ("applylut: LUT length is not as expected. Use makelut to create it.");
+  endif
+  w=reshape(2.^[nq-1:-1:0],n,n);
+  A=LUT(filter2(w,BW)+1);
+endfunction
+
+%!demo
+%! lut=makelut(inline('sum(x(:))>=3','x'), 3);
+%! applylut(eye(5),lut)
+%! % everything should be 0 despite a diagonal which
+%! % doesn't reach borders.
+
+
+%!assert(prod(applylut(eye(3),makelut(inline('x(1,1)==1','x'),2))==eye(3))==1); % 2-by-2 test
+%!assert(prod(applylut(eye(3),makelut(inline('x(2,2)==1','x'),3))==eye(3))==1); % 3-by-3 test
+%!assert(prod(applylut(eye(3),makelut(inline('x(3,3)==1','x'),3))== \
+%!	      applylut(eye(3),makelut(inline('x(2,2)==1','x'),2)))==1);
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/inst/autumn.m
@@ -0,0 +1,51 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} autumn (@var{n})
+## Create color colormap. 
+## (red through orange to yellow)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = autumn (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("autumn: argument must be a scalar");
+    endif
+  else
+    usage ("autumn (number)");
+  endif
+
+  if (number == 1)
+    map = [1, 0, 0];  
+  elseif (number > 1)
+    r = ones (number, 1);
+    g = (0:number - 1)' ./ (number - 1);
+    b = zeros (number, 1);
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/bestblk.m
@@ -0,0 +1,113 @@
+## 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{siz} = } bestblk ([@var{m} @var{n}], @var{k})
+## @deftypefnx {Function File} {[@var{mb} @var{nb}] = } bestblk ([@var{m} @var{n}], @var{k})
+## Calculates the best size of block for block processing.
+##
+## @code{siz=bestblk([m,n],k)} calculates the optimal block size for block
+## processing for a @var{m}-by-@var{n} image. @var{k} is the maximum
+## side dimension of the block. Its default value is 100. @var{siz} is a
+## row vector which contains row and column dimensions for the block.
+##
+## @code{[mb,nb]=bestblk([m,n],k)} behaves as described above but
+## returns block dimensions to @var{mb} and @var{nb}.
+##
+## @strong{Algorithm:}
+##
+## For each dimension (@var{m} and @var{n}), it follows this algorithm:
+##
+## 1.- If dimension is less or equal than @var{k}, it returns the
+## dimension value.
+##
+## 2.- If not then returns the value between
+## @code{round(min(dimension/10,k/2))} which minimizes padding.
+##
+##
+## @end deftypefn
+## @seealso{blkproc}
+
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function [varargout] = bestblk(ims,k)
+  if(nargin<1 || nargin>2)
+    usage("siz=bestblk([m,n],k), [mb,nb]=bestblk([m,n],k)");
+  endif
+  if(nargout>2)
+    usage("siz=bestblk([m,n],k), [mb,nb]=bestblk([m,n],k)");
+  endif
+  if(nargin<2)
+    k=100;
+  endif
+  if(!isvector(ims))
+    error("bestblk: first parameter is not a vector.");
+  endif
+  ims=ims(:);
+  if(length(ims)!=2)
+    error("bestblk: length of first parameter is not 2.");
+  endif
+
+  mb=mi=ims(1);
+  p=mi;
+  if(mi>k)
+    for i=round(min(mi/10,k/2)):k
+      pt=rem(mi,i);
+      if(pt<p)
+	p=pt;
+	mb=i;
+      endif
+    endfor
+  endif
+
+  nb=ni=ims(2);
+  p=ni;
+  if(ni>k)
+    for i=round(min(ni/10,k/2)):k
+      pt=rem(ni,i);
+      if(pt<p)
+	p=pt;
+	nb=i;
+      endif
+    endfor
+  endif
+
+  if(nargout<=1)
+    varargout{1}=[mb;nb];
+  else
+    varargout{1}=mb;
+    varargout{2}=nb;
+  endif
+
+endfunction
+
+%!demo
+%! siz=bestblk([200;10],50)
+%! # Best block is [20,10]
+
+%!assert(bestblk([300;100],150),[30;100]);
+%!assert(bestblk([256,128],17),[16;16]);
+
+% $Log$
+% Revision 1.1  2006/08/20 12:59:31  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.2  2005/07/03 01:10:19  pkienzle
+% Try to correct for missing newline at the end of the file
+%
+% Revision 1.1  2004/08/15 19:01:05  jmones
+% bestblk added: Calculates best block size for block processing
new file mode 100644
--- /dev/null
+++ b/inst/blkproc.m
@@ -0,0 +1,193 @@
+## 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} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun})
+## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], @var{fun}, ...)
+## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, [@var{m},@var{n}], [@var{mborder},@var{nborder}], @var{fun}, @var{...})
+## @deftypefnx {Function File} {@var{B} = } blkproc (@var{A}, 'indexed', ...)
+## Processes image in blocks using user-supplied function
+##
+## @code{B=blkproc(A,[m,n],fun)} divides image @var{A} in
+## @var{m}-by-@var{n} blocks, and passes them to user-supplied function
+## @var{fun}, which result is concatenated to build returning matrix
+## @var{B}. If padding is needed to build @var{m}-by-@var{n}, it is added
+## at the bottom and right borders of the image.  0 is used as a padding
+## value.
+##
+## @code{B=blkproc(A,[m,n],fun,...)} behaves as described above but
+## passes extra parameters to function @var{fun}.
+##
+## @code{B=blkproc(A,[m,n],[mborder,nborder],fun,...)} behaves as
+## described but uses blocks which overlap with neighbour blocks.
+## Overlapping dimensions are @var{mborder} vertically and @var{nborder}
+## horizontally. This doesn't change the number of blocks in an image
+## (which depends only on size(@var{A}) and [@var{m},@var{n}]). Adding a
+## border requires extra padding on all edges of the image. 0 is used as
+## a padding value.
+##
+## @code{B=blkproc(A,'indexed',...)} assumes that @var{A} is an indexed
+## image, so it pads the image using proper value: 0 for uint8 and
+## uint16 images and 1 for double images. Keep in mind that if 'indexed'
+## is not specified padding is always done using 0.
+##
+## @end deftypefn
+## @seealso{colfilt,inline,bestblk}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function B = blkproc(A, varargin)
+  if(nargin<3)
+    error("blkproc: invalid number of parameters.");
+  endif
+  
+  ## check 'indexed' presence
+  indexed=false;
+  p=1;
+  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
+    indexed=true;
+    p+=1;
+    if(isa(A,"uint8") || isa(A,"uint16"))
+	padval=0;
+    else
+      padval=1; 
+    endif
+  else
+    padval=0;
+  endif
+
+  ## check [m,n]
+  if(!isvector(varargin{p}))
+    error("blkproc: expected [m,n] but param is not a vector.");
+  endif
+  if(length(varargin{p})!=2)
+    error("blkproc: expected [m,n] but param has wrong length.");
+  endif
+  sblk=varargin{p}(:);
+  p+=1;
+
+  ## check [mborder,nborder]
+  if(nargin<p)
+    error("blkproc: required parameters haven't been supplied.");
+  endif
+
+  if(isvector(varargin{p}))
+    if(length(varargin{p})!=2)
+      error("blkproc: expected [mborder,nborder] but param has wrong length.");
+    endif
+    sborder=varargin{p}(:);
+    p+=1;
+  else
+    sborder=[0;0];
+  endif
+
+  ## check fun
+  ## TODO: add proper checks for this one
+  if(nargin<p)
+    error("blkproc: required parameters haven't been supplied.");
+  endif
+
+  fun=varargin{p};
+  if(!isa(fun,"function handle") &&
+     !isa(fun,"inline function") &&
+     !ischar(fun))
+    error("blkproc: invalid fun parameter.");
+  endif
+  
+  ## remaining params are params to fun
+  ## extra params are p+1:nargin-1
+
+  ## First of all we calc needed padding which will be applied on bottom
+  ## and right borders
+  ## The "-" makes the function output needed elements to fill another
+  ## block directly
+  sp=mod(-size(A)',sblk);
+
+  if(any(sp))
+    A=padarray(A,sp,padval,'post');
+  endif
+
+  ## we store A size without border padding to iterate later
+  soa=size(A);
+  
+  ## If we have borders then we need more padding
+  if(any(sborder))
+    A=padarray(A,sborder,padval);
+  endif
+
+  ## calculate end of block
+  eblk=sblk+sborder*2-1;
+
+  ## now we can process by blocks
+  ## we try to preserve fun return type by concatenating everything
+  for i=1:sblk(1):soa(1)
+    ## This assures r has the same class as returned by fun
+    r=feval(fun,A(i:i+eblk(1),1:1+eblk(2)),varargin{p+1:nargin-1});
+    for j=1+sblk(2):sblk(2):soa(2)
+      r=horzcat(r,feval(fun,A(i:i+eblk(1),j:j+eblk(2)),varargin{p+1:nargin-1}));
+    endfor
+    if(i==1) ## this assures B has the same class as A
+      B=r;
+    else
+      B=vertcat(B,r);
+    endif
+  endfor
+endfunction
+
+%!demo
+%! blkproc(eye(6),[2,2],inline("any(x(:))","x"))
+%! # Returns a 3-by-3 diagonal
+
+
+%!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],@sum));
+%!assert(blkproc(eye(6),[2,2],"sum"),blkproc(eye(6),[2,2],inline("sum(x)","x")));
+%!assert(blkproc(eye(6),[1,2],@sum),kron(eye(3),[1;1]));
+%!assert(blkproc(eye(6),[2,2],inline("any(x(:))","x")),eye(3)!=0);
+%!assert(blkproc(eye(6),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
+%!assert(blkproc(eye(6),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[8,5,6;6,2,3;5,3,4;4,3,5;3,2,6;6,5,8]);
+%!assert(blkproc(eye(6),[2,3],[4,3],inline("sum(x(:))","x")),ones(3,2)*6);
+
+% Some int* and uint* tests
+%!assert(blkproc(eye(6),[2,2],inline("int8(sum(x(:)))","x")),eye(3,"int8")*2);
+
+% Padding is 0 even for indexed
+%!assert(blkproc(uint8(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
+%!assert(blkproc(uint8(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
+%!assert(blkproc(uint16(eye(6)),[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
+%!assert(blkproc(uint16(eye(6)),'indexed',[1,2],[1,1],inline("sum(x(:))","x")),[2,1,0;3,2,0;2,3,1;1,3,2;0,2,3;0,1,2]);
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:31  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.5  2005/09/08 02:00:17  pkienzle
+% [for Bill Denney] isstr -> ischar
+%
+% Revision 1.4  2004/11/15 16:04:20  pkienzle
+% Fix tests for functions which return boolean matrices
+%
+% Revision 1.3  2004/09/03 17:49:37  jmones
+% Improved uint8 and uint16 padding expections
+%
+% Revision 1.2  2004/09/03 13:40:13  jmones
+% Check result has same class as function result, and improved fun param checking
+%
+% Revision 1.1  2004/08/15 19:27:46  jmones
+% blkproc: block process an image using user-supplied function
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/bmpwrite.m
@@ -0,0 +1,88 @@
+## bmpwrite(X,map,file)
+##   Write the bitmap X into file (8-bit indexed uncompressed).
+##   The values in X are indices into the given RGB colour map.
+## bmpwrite(X,file)
+##   Write the bitmap X into file (24-bit truecolor uncompressed).
+##   X is an m x n x 3 array of R,G,B values.
+
+## This code is in the public domain.
+## Author: Paul Kienzle <pkienzle@users.sf.net>
+
+function bmpwrite(x,map,file)
+  if nargin==2
+     bmpwrite_truecolor(x,map);
+  else
+     bmpwrite_indexed(x,map,file);
+  endif
+endfunction
+
+function bmpwrite_truecolor(x,file)
+    h = rows(x); w = columns(x);
+    padw = ceil(3*w/4)*4-3*w;
+    header = 14+40;
+    filesize = header+h*(3*w+padw);
+    arch = "ieee-le";
+    file = fopen(file, "wb");
+    fwrite(file,toascii("BM"),"uchar",0,arch); # file tag
+    fwrite(file,filesize,"long",0,arch);    # length of file
+    fwrite(file,0,"long",0,arch);           # reserved
+    fwrite(file,header,"long",0,arch);      # offset of raster data in file
+
+    fwrite(file,40,"long",0,arch);          # header size
+    fwrite(file,w,"long",0,arch);           # image width
+    fwrite(file,h,"long",0,arch);           # image height
+    fwrite(file,1,"short",0,arch);          # number of planes
+    fwrite(file,24,"short",0,arch);         # pixels per plane
+    fwrite(file,0,"long",0,arch);           # compression (none)
+    fwrite(file,0,"long",0,arch);           # compressed size of image
+    resolution = 72/2.54*100;               # 72 dpi / 2.54 cm/in * 100 cm/m
+    fwrite(file,resolution,"long",0,arch);  # horizontal resolution
+    fwrite(file,resolution,"long",0,arch);  # vertical resolution
+    fwrite(file,0,"long",0,arch);           # number of colours used
+    fwrite(file,0,"long",0,arch);           # number of "important" colors
+
+    ## raster image, lines written bottom to top.
+    R = x(end:-1:1,:,1)';
+    G = x(end:-1:1,:,2)';
+    B = x(end:-1:1,:,3)';
+    RGB=[B(:),G(:),R(:)]';  # Now [[B;G;R],[B;G;R],...,[B;G;R]]
+    RGB=reshape(RGB,3*w,h); # Now [[B;G;R;...;B;G;R],...,[B;G;R;...;B;G;R]]
+    fwrite(file,[RGB;zeros(padw,h)],"uchar",0,arch);
+    fclose(file);
+endfunction
+
+function bmpwrite_indexed(x,map,file)
+    [h,w] = size(x);
+    padw = ceil(w/4)*4-w;
+    header = 14+40+4*rows(map);
+    filesize = header+(w+padw)*h;
+    arch = "ieee-le";
+    file = fopen(file, "wb");
+    fwrite(file,toascii("BM"),"uchar",0,arch); # file tag
+    fwrite(file,filesize,"long",0,arch);    # length of file
+    fwrite(file,0,"long",0,arch);           # reserved
+    fwrite(file,header,"long",0,arch);      # offset of raster data in file
+
+    fwrite(file,40,"long",0,arch);          # header size
+    fwrite(file,w,"long",0,arch);           # image width
+    fwrite(file,h,"long",0,arch);           # image height
+    fwrite(file,1,"short",0,arch);          # number of planes
+    fwrite(file,8,"short",0,arch);          # pixels per plane
+    fwrite(file,0,"long",0,arch);           # compression (none)
+    fwrite(file,0,"long",0,arch);           # compressed size of image
+    resolution = 72/2.54*100;               # 72 dpi / 2.54 cm/in * 100 cm/m
+    fwrite(file,resolution,"long",0,arch);  # horizontal resolution
+    fwrite(file,resolution,"long",0,arch);  # vertical resolution
+    fwrite(file,rows(map),"long",0,arch);   # number of colours used
+    fwrite(file,0,"long",0,arch);           # number of "important" colors
+
+    ## colormap BGR0BGR0BGR0BGR0...
+    map=[round(map*255), zeros(rows(map),1)];
+    map=map(:,[3,2,1,4]);
+    fwrite(file,map',"uchar",0,arch);
+
+    ## raster image, each line on a 32-bit boundary, padded with zeros
+    ## lines written bottom to top.
+    fwrite(file,[flipud(x-1)';zeros(padw,h)],"uchar",0,arch);
+    fclose(file);
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/bone.m
@@ -0,0 +1,54 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} bone (@var{n})
+## Create color colormap. 
+## (a gray colormap with a light blue tone)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = bone (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("bone: argument must be a scalar");
+    endif
+  else
+    usage ("bone (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 0];  
+  elseif (number > 1)
+    x = linspace (0, 1, number)';
+
+    r = (x < 3/4) .* (7/8 * x) + (x >= 3/4) .* (11/8 * x - 3/8);
+    g = (x < 3/8) .* (7/8 * x)\
+      + (x >= 3/8 & x < 3/4) .* (29/24 * x - 1/8)\
+      + (x >= 3/4) .* (7/8 * x + 1/8);
+    b = (x < 3/8) .* (29/24 * x) + (x >= 3/8) .* (7/8 * x + 1/8);
+    map=[r, g, b];
+  else
+    map = [];
+  endif
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/brighten.m
@@ -0,0 +1,65 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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{map_out}= brighten (@var{map},@var{beta})
+## @deftypefnx {Function File} @var{map_out}= brighten (@var{beta})
+## darkens or brightens the given colormap.
+## If the @var{map} argument is omitted, the function is applied to the
+## current colormap.
+## Should the resulting colormap @var{map_out} not be assigned, it will be
+## written to the current colormap.
+## The argument @var{beta} should be a scalar between -1 and 1,
+## where a negative value darkens and a positive value brightens
+## the colormap.
+##
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	05. March 2000
+
+function [Rmap] = brighten (m, beta)
+
+  if (nargin == 1)
+    beta = m;
+    m = colormap;
+
+  elseif (nargin == 2)
+    if ( (!is_matrix (m)) || (size (m, 2) != 3) )
+      error ("brighten(map,beta) map must be a matrix of size nx3.");
+    endif
+
+  else
+    usage ("brighten(...) number of arguments must be 1 or 2.");
+  endif
+
+  if ( (!is_scalar (beta)) || (beta <= -1) || (beta >= 1) )
+    error ("brighten(...,beta) beta must be a scalar in the range (-1,1).");
+  endif
+
+  if (beta > 0)
+    gamma = 1 - beta;
+  else
+    gamma = 1 / (1 + beta);
+  endif
+
+  if (nargout == 0)
+    colormap (m .^ gamma);
+  else
+    Rmap = m .^ gamma;
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/bwarea.m
@@ -0,0 +1,57 @@
+## Copyright (C) 2005 Søren Hauberg
+## 
+## 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{total}= bwarea(@var{bw})
+## Estimates the area of the "on" pixels of @var{bw}.
+## If @var{bw} is a binary image "on" pixels are defined as pixels
+## valued 1. If @var{bw} is a grayscale image "on" pixels is defined
+## as pixels with values larger than zero.
+## This algorithm is not the same as counting the number of "on"
+## pixels as it tries to estimate the area of the original object
+## and not the image object.
+## @end deftypefn
+
+## Author: Søren Hauberg <hauberg at gmail dot com>
+## 
+## 2005-06-05 Søren Hauberg <hauberg at gmail dot com>
+## * Initial revision
+
+
+function total = bwarea(bw)
+  if (isgray(bw))
+    bw = (bw > 0);
+  endif
+
+  if (!isbw(bw))
+    error("input image muste be either binary or gray scale.\n");
+  endif
+  
+  four = ones(2);
+  two  = diag([1 1]);
+
+  fours = conv2(bw, four);
+  twos  = conv2(bw, two);
+
+  nQ1 = sum(fours(:) == 1);
+  nQ3 = sum(fours(:) == 3);
+  nQ4 = sum(fours(:) == 4);
+  nQD = sum(fours(:) == 2 & twos(:) != 1);
+  nQ2 = sum(fours(:) == 2 & twos(:) == 1);
+
+  total = 0.25*nQ1 + 0.5*nQ2 + 0.875*nQ3 + nQ4 + 0.75*nQD;
+  
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/bwborder.m
@@ -0,0 +1,35 @@
+## Copyright (C) 2000  Etienne Grossmann
+##
+## 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
+
+##       b = bwborder(im)
+##
+## b is the borders in the 0-1 matrix im. 4-neighborhood is considered.
+## 
+## A pixel is on the border if it is set in im, and it has at least one
+## neighbor that is not set.
+
+## Author:        Etienne Grossmann <etienne@cs.uky.edu>
+## Last modified: January 2000
+
+function b = bwborder(im)
+
+[R,C]=size(im);
+
+b = im & ...
+    !([im(2:R,:) ;  zeros(1,C) ] & ...
+      [zeros(1,C); im(1:R-1,:) ] & ...
+      [im(:,2:C) ,  zeros(R,1) ] & ...
+      [zeros(R,1),  im(:,1:C-1)] ) ;
new file mode 100644
--- /dev/null
+++ b/inst/bweuler.m
@@ -0,0 +1,102 @@
+## 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{eul} = } bweuler (@var{BW},@var{n})
+## Calculates the Euler number of a binary image
+##
+## eul=bweuler(BW,n) calculates the Euler number @var{eul} of a binary
+## image @var{BW}, which is a scalar whose value is the total number of
+## objects in an image minus the number of holes.
+##
+## @var{n} can have the values:
+## @table @code
+## @item 4
+## bweuler will use 4-connected neighbourhood definition.
+## @item 8
+## bweuler will use 8-connected neighbourhood definition. This is the
+## default value.
+## @end table
+##
+## This function uses Bit Quads as described in "Digital Image
+## Processing" to calculate euler number.
+##
+## References:
+## W. K. Pratt, "Digital Image Processing", 3rd Edition, pp 593-595
+##
+## @end deftypefn
+## @seealso qtgetblk
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function eul = bweuler(BW, n)
+  if(nargin<1 || nargin>2)
+    usage("eul=bweuler(BW,n)");
+  endif
+  if(nargin<2)
+    n=8;
+  endif
+
+  ## q1lut=makelut(inline("sum(x(:))==1","x"),2);
+  ## q3lut=makelut(inline("sum(x(:))==3","x"),2);
+  ## qdlut=makelut(inline("all((x==eye(2))(:))||all((x==fliplr(eye(2)))(:))","x"),2);
+  ## lut_4=(q1lut-q3lut+2*qdlut)/4;  # everything in one lut will be quicker
+  ## lut_8=(q1lut-q3lut-2*qdlut)/4;
+  ## we precalculate this...
+  if(n==8)
+    lut=[0;.25;.25;0;.25;0;-.5;-.25;.25;-.5;0;-.25;0;-.25;-.25;0];
+  elseif(n==4)
+    lut=[0;.25;.25;0;.25;0;.5;-.25;.25;.5;0;-.25;0;-.25;-.25;0];
+  else
+    error("bweuler: n can only be 4 or 8.");
+  endif
+  
+  eul=sum(applylut(BW,lut)(:));
+endfunction
+
+%!demo
+%! A=zeros(9,10);
+%! A([2,5,8],2:9)=1;
+%! A(2:8,[2,9])=1
+%! bweuler(A)
+%! # Euler number (objects minus holes) is 1-2=-1 in an 8-like object
+
+%!test
+%! A=zeros(10,10);
+%! A(2:9,3:8)=1;
+%! A(4,4)=0;
+%! A(8,8)=0; # not a hole
+%! A(6,6)=0;
+%! assert(bweuler(A),-1);
+
+%!# This will test if n=4 and n=8 behave differently
+%!test
+%! A=zeros(10,10);
+%! A(2:4,2:4)=1;
+%! A(5:8,5:8)=1;
+%! assert(bweuler(A,4),2);
+%! assert(bweuler(A,8),1);
+%! assert(bweuler(A),1);
+
+% $Log$
+% Revision 1.1  2006/08/20 12:59:31  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.2  2005/07/03 01:10:19  pkienzle
+% Try to correct for missing newline at the end of the file
+%
+% Revision 1.1  2004/08/15 19:33:20  jmones
+% bweuler: Calculates the Euler number of a binary image
new file mode 100644
--- /dev/null
+++ b/inst/bwlabel.m
@@ -0,0 +1,231 @@
+## Copyright (C) 2000  Etienne Grossmann
+##
+## 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
+
+##       [im2,npix,bb] = bwlabel(im, mins, maxs, verbose)
+##
+## Find the connected regions of an image.
+##  
+## im  : RxC 0-1 matrix
+##
+## im2 : RxC int matrix in which the connected regions of im have been
+##       numbered. 4-neighborhoods are considered.
+##
+## npix : 1xQ int number of pixel in each region
+##
+## bb   : 4xQ int bounding boxes of the regions. Rows are minrow,
+##        maxrow, mincol, maxcol.
+##
+## Options :
+##
+## mins     : Minimum size of the regions (set to zero for no minimum)
+## maxs     : Maximum size of the regions (set to zero for no maximum)
+## verbose  : Level of output comments in range 0 to 2.
+##
+
+## Author:        Etienne Grossmann <etienne@cs.uky.edu>
+## Last modified: July 2002
+##
+
+## Modified by David Fletcher <david@megapico.co.uk> to avoid artificially
+## separate regions which actually touch (as indicated when "prudent" is set)
+## through addition of lrow update within loop over touching regions. Also
+## removed "sayif" function references, and call to read_options. Enabled
+## options, setting of output verbosity. "Prudent" is left in place, but
+## should no longer find any errors.
+
+function [im2,npix,bb] = bwlabel(im, mins, maxs, verbose)
+
+  if (nargin == 1)
+    mins = 0;
+    maxs = 0;
+    prudent = 1;
+    verbose = 0;
+  elseif (nargin == 2)
+    maxs = 0;
+    prudent = 1;
+    verbose = 0;
+  elseif (nargin == 3)
+    prudent = 1;
+    verbose = 0;
+  elseif ((nargin == 4) && (verbose >= 0) && (verbose <= 2))
+    prudent = 1;
+  else
+    usage ("bwlabel2(im, mins, maxs, verbose)");
+  endif
+
+if any(im(:)&im(:)!=1),
+  printf("bwlabel : im is not binary\n");
+  return
+end
+
+
+[R,C]=size(im);
+tr = 0 ;
+				# Loop as little as possible
+if R<C, tr = 1; im = im' ; [R,C]=size(im); end
+
+gsize = 100 ;			# Predicted number of slices
+
+im2 = zeros(R,C);
+				# find horizontal up/down going edges
+imup =  max(im2, diff([zeros(1,C);im])) ;
+imdo = -min(im2, diff([im;zeros(1,C)])) ;
+
+im2 = ones(R,C);
+######################################################################
+## Find connected regions ############################################
+
+rc = 1 ;			# Counter of region slices 
+
+rnum = ones(1,gsize);		# List of labels of each slice
+npix = zeros(1,gsize);		# Sizes of regions (actual size is in
+				# region's first slice)
+bb = zeros(4,gsize);		# Bounding boxes
+
+if (verbose >= 1) printf("bwlabel : There will be %i loops ... \n%5i ",C,0) ; endif;
+
+lrow = zeros(R,1);		# Last treated image column
+ 
+for i=1:C,
+  t1 = find(imup(:,i)) ;
+  t2 = find(imdo(:,i)) ;
+  
+  nrow = zeros(R,1);		# Next row
+
+  for j = 1:rows(t1(:)) ,	# Loop over slices of i'th column
+
+    rc++ ;			# rc = number of current slice.
+    im2(t1(j):t2(j),i) = rc ;
+				# Slices from previous column that touch
+				# this slice.
+    rr = create_set(lrow(t1(j):t2(j))) ;
+    if !isempty(rr) && !rr(1), rr = rr(2:length(rr)) ; end
+
+    if rc>size(rnum,2),		# Get more space (uncertain effect on
+				# speed; avoids resizing rnum and npix)
+      tmp = 2*(ceil(C*rc/i)-rc+1+rows(t1(:))-j) ;
+      if (verbose == 2) printf("bwlabel : (i=%i) Foreseeing %i more regions\n",i,tmp); endif;
+      rnum = [ rnum, ones(1,tmp) ] ;
+      npix = [ npix,zeros(1,tmp) ] ;
+      bb = [ bb,zeros(4,tmp) ] ;
+    end
+
+    if isempty(rr),			# New region 
+      if (verbose == 2) printf("bwlabel : creating region %i\n",rc); endif;
+
+      r0 = rc ;			# r0 = number of the region
+
+      bb(1,r0) = t1(j) ;
+      bb(2,r0) = t2(j) ;
+      bb(3:4,r0) = i ;
+
+    else			# Add to already existing region #####
+
+      r0 = rnum(rr(1)) ;
+      [i, j, r0];
+
+      bb(1,r0) = min(bb(1,r0),t1(j)) ;
+      bb(2,r0) = max(bb(2,r0),t2(j)) ;
+      bb(4,r0) = i ;
+
+				# Touches region r0
+      if (verbose == 2) printf("bwlabel : adding to region %i\n",r0); endif;
+
+				# Touches other regions too
+      for k = rr(find(rr!=r0)),	# Loop over other touching regions, that
+				# should be merged to the first.
+	if (verbose == 2) printf("bwlabel : merging regions %i and %i\n",k,r0); endif;
+	rnum(find(rnum==k)) = r0 ;
+	lrow(find(lrow==k)) = r0 ; ##Update lrow for next comparsion loop
+	npix(r0) = npix(r0) + npix(k) ;
+	bb([1,3],r0) = min(bb([1,3],r0)',bb([1,3],k)')' ;
+	bb([2,4],r0) = max(bb([2,4],r0)',bb([2,4],k)')' ;
+      end
+      
+    end				# End of add to already existing region
+    ## if r0==259 && i==39,"r0==259",keyboard;end
+    rnum(rc) = r0 ;
+
+    npix(r0) = npix(r0) + 1+t2(j)-t1(j) ;
+
+    nrow(t1(j):t2(j)) = r0 ;
+  end				# End of looping over slices
+  lrow = nrow ;
+  if (verbose >= 1)
+    printf(".");
+    if (!rem(i,70) && i<C) printf("\n%5i ",i); end
+  end
+end				# End of looping over columns
+
+if (verbose >= 1) printf("\n"); endif;
+
+keep = ones(1,rc) ; 
+
+if mins, keep = keep & (npix(rnum(1:rc))>=mins) ; end
+if maxs, keep = keep & (npix(rnum(1:rc))<=maxs) ; end
+keep(1) = 1 ;
+keep = find(keep) ;		# Indices of slices to be kept
+
+foo = create_set(rnum(keep)) ;	# Indices of regions to be kept
+nr = prod(size(foo)) ;		# Number of regions (including bg)
+## lrow = zeros(1,nr) ;
+tmp = zeros(1,rc) ;
+tmp(foo) = 0:nr-1 ;
+
+bar = zeros(1,rc) ;
+bar(keep) = tmp(rnum(keep)) ;
+
+## keyboard
+
+im2 = reshape(bar(im2),R,C) ;
+
+npix = npix(foo(2:nr));
+bb = bb(:,foo(2:nr));
+
+if 0,				# Draw bb on the image (will ruin
+				# coherence)
+  for i=1:nr-1,
+    im2([bb(1,i),bb(2,i)] ,bb(3,i):bb(4,i) ) = i ;
+    im2( bb(1,i):bb(2,i) ,[bb(3,i),bb(4,i)]) = i ;
+  end
+end
+
+## keyboard
+if prudent,
+
+  if (verbose >= 1) printf("bwlabel : Checking coherence\n"); endif;
+
+  hcontact = im2 & im2!=[im2(:,2:C),zeros(R,1)] & [im2(:,2:C),zeros(R,1)] ;
+  vcontact = im2 & im2!=[im2(2:R,:);zeros(1,C)] & [im2(2:R,:);zeros(1,C)] ;
+  ok = 1 ;
+  if (any(hcontact(:)))
+    if (verbose == 2) [x,y] = find(hcontact) endif; 
+    ok = 0 ;
+    printf("bwlabel: Whoa! Found horizontally connected separated regions\n");
+  end
+  if (any(vcontact(:)))
+    if (verbose == 2)[x,y] = find(vcontact) endif; 
+    ok = 0 ;
+    printf("bwlabel: Whoa! Found vertically connected separated regions\n");
+  end
+  if !ok, keyboard ; end
+end
+
+## Eventually transpose result
+if tr, 
+  im2 = im2' ; 
+  bb = bb([3,4,1,2],:);
+end
new file mode 100644
--- /dev/null
+++ b/inst/bwmorph.m
@@ -0,0 +1,614 @@
+## 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{BW2} = } bwmorph (@var{BW},@var{operation})
+## @deftypefnx {Function File} {@var{BW2} = } bwmorph (@var{BW},@var{operation},@var{n})
+## Perform a morphological operation on a binary image
+##
+## BW2=bwmorph(BW,operation) performs a morphological operation
+## specified by @var{operation} on binary image @var{BW}. All possible
+## operations and their meaning are specified in a table below.
+##
+## BW2=bwmorph(BW,operation,n) performs a morphological operation
+## @var{n} times. Keep in mind that it has no sense to apply some
+## operations more than once, since some of them return the same result
+## regardless how many iterations we request. Those return a warning if
+## are called with n>1 and they compute the result for n=1.
+##
+## @var{n}>1 is actually used for the following operations: diag,
+## dilate, erode, majority, shrink, skel, spur, thicken and thin.
+##
+## @table @code
+## @item 'bothat'
+## Performs a bottom hat operation, a closing operation (which is a
+## dilation followed by an erosion) and finally substracts the original
+## image.
+##
+## @item 'bridge'
+## Performs a bridge operation. Sets a pixel to 1 if it has two nonzero
+## neighbours which are not connected, so it "bridges" them. There are
+## 119 3-by-3 patterns which trigger setting a pixel to 1.
+##
+## @item 'clean'
+## Performs an isolated pixel remove operation. Sets a pixel to 0 if all
+## of its eight-connected neighbours are 0.
+##
+## @item 'close'
+## Performs closing operation, which is a dilation followed by erosion.
+## It uses a ones(3) matrix as structuring element for both operations.
+##
+## @item 'diag'
+## Performs a diagonal fill operation. Sets a pixel to 1 if that
+## eliminates eight-connectivity of the background.
+##
+## @item 'dilate'
+## Performs a dilation operation. It uses ones(3) as structuring element.
+##
+## @item 'erode'
+## Performs an erosion operation. It uses ones(3) as structuring element.
+##
+## @item 'fill'
+## Performs a interior fill operation. Sets a pixel to 1 if all
+## four-connected pixels are 1.
+##
+## @item 'hbreak'
+## Performs a H-break operation. Breaks (sets to 0) pixels that are
+## H-connected.
+##
+## @item 'majority'
+## Performs a majority black operation. Sets a pixel to 1 if five
+## or more pixels in a 3-by-3 window are 1. If not it is set to 0.
+##
+## @item 'open'
+## Performs an opening operation, which is an erosion followed by a
+## dilation. It uses ones(3) as structuring element.
+##
+## @item 'remove'
+## Performs a iterior pixel remove operation. Sets a pixel to 0 if 
+## all of its four-connected neighbours are 1.
+##
+## @item 'shrink'
+## Performs a shrink operation. Sets pixels to 0 such that an object
+## without holes erodes to a single pixel (set to 1) at or near its
+## center of mass. An object with holes erodes to a connected ring lying
+## midway between each hole and its nearest outer boundary. It preserves
+## Euler number.
+##
+## @item 'skel'
+## Performs a skeletonization operation. It calculates a "median axis
+## skeleton" so that points of this skeleton are at the same distance of
+## its nearby borders. It preserver Euler number. Please read
+## compatibility notes for more info.
+##
+## It uses the same algorithm as skel-pratt but this could change for
+## compatibility in the future.
+##
+## @item 'skel-lantuejol'
+## Performs a skeletonization operation as described in Gonzalez & Woods
+## "Digital Image Processing" pp 538-540. The text references Lantuejoul
+## as authour of this algorithm.
+##
+## It has the beauty of being a clean and simple approach, but skeletons
+## are thicker than they need to and, in addition, not guaranteed to be
+## connected.
+##
+## This algorithm is iterative. It will be applied the minimum value of
+## @var{n} times or number of iterations specified in algorithm
+## description. It's most useful to run this algorithm with @code{n=Inf}.
+##
+## @item 'skel-pratt'
+## Performs a skeletonization operation as described by William K. Pratt
+## in "Digital Image Processing".
+##
+## @item 'spur'
+## Performs a remove spur operation. It sets pixel to 0 if it has only
+## one eight-connected pixel in its neighbourhood.
+##
+## @item 'thicken'
+## Performs a thickening operation. This operation "thickens" objects
+## avoiding their fusion. Its implemented as a thinning of the
+## background. That is, thinning on negated image. Finally a diagonal
+## fill operation is performed to avoid "eight-connecting" objects.
+##
+## @item 'thin'
+## Performs a thinning operation. When n=Inf, thinning sets pixels to 0
+## such that an object without holes is converted to a stroke
+## equidistant from its nearest outer boundaries. If the object has
+## holes it creates a ring midway between each hole and its near outer
+## boundary. This differ from shrink in that shrink converts objects
+## without holes to a single pixels and thin to a stroke. It preserves
+## Euler number.
+##
+## @item 'tophat'
+## Performs a top hat operation, a opening operation (which is an
+## erosion followed by a dilation) and finally substracts the original
+## image.
+## @end table
+##
+## Some useful concepts to understant operators:
+##
+## Operations are defined on 3-by-3 blocks of data, where the pixel in
+## the center of the block. Those pixels are numerated as follows:
+##
+## @multitable @columnfractions 0.05 0.05 0.05
+## @item X3 @tab X2 @tab X1
+## @item X4 @tab  X @tab X0
+## @item X5 @tab X6 @tab X7
+## @end multitable
+##
+## @strong{Neighbourhood definitions used in operation descriptions:}
+## @table @code
+## @item 'four-connected'
+## It refers to pixels which are connected horizontally or vertically to
+## X: X1, X3, X5 and X7.
+## @item 'eight-connected'
+## It refers to all pixels which are connected to X: X0, X1, X2, X3, X4,
+## X5, X6 and X7.
+## @end table
+## 
+## @strong{Compatibility notes:}
+## @table @code
+## @item 'fill'
+## Checking MATLAB behaviour is needed because its documentation doesn't
+## make clear if it creates a black pixel if all eight-connected pixels
+## are black or if four-connected suffice (as we do currently following
+## Pratt's book).
+## @item 'skel'
+## Algorithm used here is described in Pratt's book. When applying it to
+## the "circles" image in MATLAB documentation, results are not the
+## same. Perhaps MATLAB uses Blum's algoritm (for further info please
+## read comments in code).
+## @item 'skel-pratt'
+## This option is not available in MATLAB.
+## @item 'skel-lantuejoul'
+## This option is not available in MATLAB.
+## @item 'thicken'
+## This implementation also thickens image borders. This can easily be
+## avoided i necessary. MATLAB documentation doesn't state how it behaves.
+## @end table
+##
+## References:
+## W. K. Pratt, "Digital Image Processing"
+## Gonzalez and Woods, "Digital Image Processing"
+##
+## @end deftypefn
+## @seealso dilate erode makelut applylut
+
+
+## TODO: As soon as Octave doesn't segfault when assigning values to a
+## TODO: bool matrix, remove all conversions from lut to logical and
+## TODO: just create it as a logical from the beginning.
+
+## TODO: n behaviour should be tested in all cases for compatibility.
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function BW2 = bwmorph(BW, operation, n)
+  if(nargin<2 || nargin>3)
+    usage("BW2=bwmorph(BW, operation [,n])");
+  endif
+  if(nargin<3)
+    n=1;
+  endif
+  if(n<0)
+    error("bwmorph: n should be > 0");
+  elseif(n==0) ## we'll just return the same matrix (check this!)
+    BW2=BW;
+  endif
+
+  ## post processing command
+  postcmd="";
+    
+  switch(operation)
+    case('bothat')
+      se=ones(3);
+      BW2=erode(dilate(BW, se), se)-BW;
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok. Should I just ignore it
+	## TODO: without a warning?
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('bridge')
+      ## see __bridge_lut_fun__ for rules
+      ## lut=makelut("__bridge_lut_fun__",3);
+      lut=logical([0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   1;1;1;1;1;1;1;1;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   1;1;1;1;1;1;1;1;1;1;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;0;0;0;0;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      BW2=applylut(BW, lut);
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('clean')
+      ## BW(j,k)=X&&(X0||X1||...||X7)
+      ## lut=makelut(inline("x(2,2)&&any((x.*[1,1,1;1,0,1;1,1,1])(:))","x"),3);
+      ## which is the same as...
+      lut=repmat([zeros(16,1);ones(16,1)],16,1);  ## identity
+      lut(17)=0;                                  ## isolated to 0
+      ## I'd prefer to create lut directly as a logical, but assigning a
+      ## value to a logical segfaults 2.1.57. We'll change it as soon as
+      ## it works.
+      BW2=applylut(BW, logical(lut));
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('close')
+      se=ones(3);
+      BW2=erode(dilate(BW, se), se);
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('diag')
+      ## see __diagonal_fill_lut_fun__ for rules
+      ## lut=makelut("__diagonal_fill_lut_fun__",3);
+      lut=logical([0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;1;1;0;0;0;0;0;0;1;1;0;0;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      cmd="BW2=applylut(BW, lut);";
+      
+
+    case('dilate')
+      cmd="BW2=dilate(BW, ones(3));";
+
+    case('erode')
+      cmd="BW2=erode(BW, ones(3));";
+      
+    case('fill')
+      ## lut=makelut(inline("x(2,2)||(sum((x&[0,1,0;1,0,1;0,1,0])(:))==4)","x"),3);
+      ## which is the same as...
+      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
+      ## 16 exceptions
+      lut([171,172,175,176,235,236,239,240,427,428,431,432,491,492,495,496])=1;
+      BW2=applylut(BW, logical(lut));
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+
+    case('hbreak')
+      ## lut=makelut(inline("x(2,2)&&!(all(x==[1,1,1;0,1,0;1,1,1])||all(x==[1,0,1;1,1,1;1,0,1]))","x"),3);
+      ## which is the same as
+      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
+      lut([382,472])=0;                          ## the 2 exceptions
+      BW2=applylut(BW, logical(lut));
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('majority')
+      ## lut=makelut(inline("sum((x&ones(3,3))(:))>=5"),3);
+      lut=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;
+		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;0;0;1;0;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		   0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      cmd="BW2=applylut(BW, lut);";
+
+    case('open')
+      se=ones(3);
+      BW2=dilate(erode(BW, se), se);
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+    case('remove')
+      ## lut=makelut(inline("x(2,2)&&!(sum((x&[0,1,0;1,1,1;0,1,0])(:))==5)","x"),3);
+      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
+      ## 16 qualifying patterns
+      lut([187,188,191,192,251,252,255,256,443,444,447,448,507,508,511,512])=0;
+      BW2=applylut(BW, logical(lut));
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+      
+    case('shrink')
+      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"S");
+      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;1;0;1;1;1;1;0;1;0;0;1;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;1;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;0;1;1;0;0]);
+      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'S')","m"),3);
+      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;0;0;1;0;0;0;0;0;1;0;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;0;0;0;0;0;0;1;1;0;0;1;0;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;0;0;0;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;1;0;1;0;0;1;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;1;1;0;1;0;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;0;0;1;0;1;0;0;1;0;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;0;0;1;0;1;0;0;1;0;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
+
+    case({'skel','skel-pratt'})
+      ## WARNING: Result doesn't look as MATLAB's sample. It has been
+      ## WARNING: coded following Pratt's guidelines for what he calls
+      ## WARNING: is a "reasonably close approximation". I couldn't find
+      ## WARNING: any bug.
+      ## WARNING: Perhaps MATLAB uses Blum's algorithm (which Pratt
+      ## WARNING: refers to) in: H. Blum, "A Transformation for
+      ## WARNING: Extracting New Descriptors of Shape", Symposium Models
+      ## WARNING: for Perception of Speech and Visual Form, W.
+      ## WARNING: Whaten-Dunn, Ed. MIT Press, Cambridge, MA, 1967.
+
+      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"K");
+      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;1;1;1;1;0]);
+
+      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'K')","m"),3);
+      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;0;1;0;0;0;1;0;1;1;0;0;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;0;0;0;1;1;0;0;1;1;0;0;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;0;0;0;1;0;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;1;1;0;1;1;1;0;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;1;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;0;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
+      postcmd="BW2=bwmorph(BW2,'bridge');";
+
+    case('skel-lantuejoul')
+      ## init values
+      se=ones(3,3);              ## structuring element used everywhere
+      BW2=zeros(size(BW));       ## skeleton result
+      eBW=BW;                    ## eBW will hold k-times eroded BW
+      i=1;
+      while i<=n
+	if(!any(eBW))            ## if erosion result is 0-matrix then
+	  break;                 ## we are over
+	endif
+	BW2|=eBW-dilate(erode(eBW, se), se); ## eBW - opening operation on eBW
+                                  	     ## contributes to skeleton
+	eBW=erode(eBW,se);        
+	i++;
+      endwhile
+      return;                    ## no general loop in this case
+
+    case('spur')
+      ## lut=makelut(inline("xor(x(2,2),(sum((x&[0,1,0;1,0,1;0,1,0])(:))==0)&&(sum((x&[1,0,1;0,0,0;1,0,1])(:))==1)&&x(2,2))","x"),3);
+      ## which is the same as
+      lut=repmat([zeros(16,1);ones(16,1)],16,1); ## identity
+      lut([18,21,81,273])=0; ## 4 qualifying patterns
+      lut=logical(lut);
+      cmd="BW2=applylut(BW, lut);";
+
+    case('thicken')
+      ## This implementation also "thickens" the border. To avoid this,
+      ## a simple solution could be to add a border of 1 to the reversed
+      ## image.
+      BW2=bwmorph(!BW,'thin',n);
+      BW2=bwmorph(BW2,'diag');
+      return;
+
+    case('thin')
+      ## lut1=makelut("__conditional_mark_patterns_lut_fun__",3,"T");
+      lut1=logical([0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;1;1;0;0;1;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;1;1;0;1;1;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;0;0;0;0;0;0;0;0;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;0;0;0;0;1;1;0;1;0;0;0;1;
+		    0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;1;0;0;0;1;0;1;1;1;1;0;0;1;1;0;0]);
+      ## lut2=makelut(inline("!m(2,2)||__unconditional_mark_patterns_lut_fun__(m,'T')","m"),3);
+      lut2=logical([1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;1;1;0;1;0;1;1;0;0;0;0;1;0;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;0;0;0;0;0;1;1;0;0;1;0;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;1;1;1;0;0;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;0;0;1;0;1;0;0;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;1;1;0;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;1;0;1;0;0;1;0;1;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;0;1;0;1;1;1;0;1;0;1;0;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;1;0;1;0;0;1;0;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;0;0;1;0;1;0;0;1;0;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;0;1;1;1;1;1;1;1;
+		    1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1;1]);
+      cmd="BW2=BW&applylut(applylut(BW, lut1), lut2);";
+
+
+    case('tophat')
+      se=ones(3);
+      BW2=BW-dilate(erode(BW, se), se);
+      if(n>1)
+	## TODO: check if ignoring n>1 is ok.
+	disp("WARNING: n>1 has no sense here. Using n=1. Please fill a bug if you think this behaviour is not correct");
+      endif
+      return;
+
+
+    otherwise
+      error("bwmorph: unknown operation type requested.");
+  endswitch
+
+  ## we use this assignment because of the swap operation inside the
+  ## while.
+  BW2=BW;
+
+  ## if it doesn't change we don't need to process it further
+  i=1;
+  while(i<=n) ## for wouldn't work because n can be Inf
+    [BW,BW2]=swap(BW,BW2);
+    eval(cmd);
+    if(all((BW2==BW)(:)))
+      break
+    endif
+    i+=1;
+  endwhile
+
+  ## process post processing commands if needed
+  if(postcmd!="")
+    eval(postcmd);
+  endif
+
+endfunction
+
+
+%!demo
+%! bwmorph(ones(11),'shrink', Inf)
+%! # Should return 0 matrix with 1 pixel set to 1 at (6,6)
+
+## TODO: code tests 
+
+
+## Test skel-lantuejoul using Gozalez&Woods example (fig 8.39)
+%!shared slBW, rslBW
+%! uint8(0); # fail for 2.1.57 or less instead of crashing later
+%! slBW=logical(zeros(12,7));
+%! slBW(2,2)=true;
+%! slBW(3:4,3:4)=true;
+%! rslBW=slBW;
+%! slBW(5:6,3:5)=true;
+%! slBW(7:11,2:6)=true;
+%! rslBW([6,7,9],4)=true;
+
+%!assert(bwmorph(slBW,'skel-lantuejoul',1),[rslBW(1:5,:);logical(zeros(7,7))]);
+%!assert(bwmorph(slBW,'skel-lantuejoul',2),[rslBW(1:8,:);logical(zeros(4,7))]);
+%!assert(bwmorph(slBW,'skel-lantuejoul',3),rslBW);
+%!assert(bwmorph(slBW,'skel-lantuejoul',Inf),rslBW);
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:32  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.6  2004/09/16 02:14:40  pkienzle
+% Use frivolous uint8() call to block tests for version 2.1.57 and earlier
+%
+% Revision 1.5  2004/09/15 20:36:57  jmones
+% logical(1) => true
+%
+% Revision 1.4  2004/09/15 20:00:00  jmones
+% Updated tests to match Gonzalez&Woods example
+%
+% Revision 1.3  2004/09/15 13:51:10  pkienzle
+% Use logical in tests; reduce number of shared variables in tests.
+%
+% Revision 1.2  2004/09/01 22:35:47  jmones
+% Added Lantuejoul skeletonizing algorithm from Gonzalez&Woods
+%
+% Revision 1.1  2004/08/15 19:47:04  jmones
+% bwmorph added: Perform a morphological operation on a binary image
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/bwselect.m
@@ -0,0 +1,40 @@
+function [imout, idx] = bwselect( im, cols, rows, connect )
+# BWSELECT: select connected regions in a binary image
+# [imout, idx] = bwselect( im, cols, rows, connect )
+#
+#   im          -> binary input image
+#   [cols,rows] -> vectors of starting points (x,y)
+#   connect     -> connectedness 4 or 8. default is 8
+#   imout       -> the image of all objects in image im that overlap
+#                  pixels in (cols,rows)
+#   idx         -> index of pixels in imout
+
+# Copyright (C) 1999 Andy Adler
+# This code has no warrany whatsoever.
+# Do what you like with this code as long as you
+#     leave this copyright in place.
+#
+# $Id$
+
+if nargin<4
+   connect= 8;
+end
+
+[jnk,idx]= bwfill( ~im, cols,rows, connect );
+
+imout= zeros( size(jnk) );
+imout( idx ) = 1;
+
+# 
+# $Log$
+# Revision 1.1  2006/08/20 12:59:32  hauberg
+# Changed the structure to match the package system
+#
+# Revision 1.1  2002/03/17 02:38:52  aadler
+# fill and edge detection operators
+#
+# Revision 1.1  1999/06/08 17:06:01  aadler
+# Initial revision
+#
+#
+
new file mode 100644
--- /dev/null
+++ b/inst/cmpermute.m
@@ -0,0 +1,127 @@
+## 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{Y}, @var{newmap}] = } cmpermute (@var{X},@var{map})
+## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmpermute (@var{X},@var{map},@var{index})
+## Reorders colors in a colormap
+##
+## @code{[Y,newmap]=cmpermute(X,map)} rearranges colormap @var{map}
+## randomly returning colormap @var{newmap} and generates indexed image
+## @var{Y} so that it mantains correspondence between indices and the
+## colormap from original indexed image @var{X} (both image and colormap
+## pairs produce the same result).
+##
+## @code{[Y,newmap]=cmpermute(X,map,index)} behaves as described above
+## but instead of sorting colors randomly, it uses @var{index} to define
+## the order of the colors in the new colormap.
+##
+## @strong{Note:} @code{index} shouldn't have repeated elements, this
+## function won't explicitly check this, but it will fail if it has.
+##
+## @end deftypefn
+
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function [Y, newmap] = cmpermute(X, map, index)
+  switch(nargin)
+    case(2)
+      index=randperm(rows(map));
+    case(3)
+      if(!isvector(index) || length(index)!=rows(map))
+	error("cmpermute: invalid parameter index.");
+      endif
+    otherwise
+      usage("[Y, newmap] = cmpermute(X, map [, index])");
+  endswitch
+
+  ## new colormap
+  newmap=map(index,:);
+
+  ## build reverse index
+  rindex = zeros(size(index));
+  rindex(index) = 1:length(index);
+ 
+  ## readapt indices
+  if(isa(X,"uint8"))
+    rindex=uint8(rindex-1);
+    ## 0-based indices
+    Y=rindex(double(X)+1);
+  else
+    Y=rindex(X);
+  endif
+endfunction
+
+
+%!demo
+%! [Y,newmap]=cmpermute([1:4],hot(4),4:-1:1)
+%! # colormap will be arranged in reverse order (so will image)
+
+%!shared X,map
+%! X=magic(16);
+%! [X,map]=cmunique(X);
+
+%!test # random permutation, 0-based index
+%! [Y,newmap]=cmpermute(X,map);
+%! # test we didn't lose colors
+%! assert(sort(map),sortrows(newmap)); 
+%! # test if images are equal
+%! assert(map(double(X)+1),newmap(double(Y)+1));
+
+%!test # reverse map, 0-based index
+%! [Y,newmap]=cmpermute(X,map,rows(map):-1:1);
+%! # we expect a reversed colormap
+%! assert(newmap(rows(newmap):-1:1,:),map);
+%! # we expect reversed indices in image
+%! assert(X,max(Y(:))-Y);
+
+%!shared X,map
+%! X=magic(20);
+%! [X,map]=cmunique(X);
+
+%!test # random permutation, 1-based index
+%! [Y,newmap]=cmpermute(X,map);
+%! # test we didn't lose colors
+%! assert(sort(map),sortrows(newmap)); 
+%! # test if images are equal
+%! assert(map(X),newmap(Y));
+
+%!test # reverse map, 1-based index
+%! [Y,newmap]=cmpermute(X,map,rows(map):-1:1);
+%! # we expect a reversed colormap
+%! assert(newmap(rows(newmap):-1:1,:),map);
+%! # we expect reversed indices in image
+%! assert(X,max(Y(:))+1-Y);
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:32  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.4  2004/09/08 15:01:28  pkienzle
+% Redo tests: reduce # of shared variables; force full range of uint8
+%
+% Revision 1.3  2004/09/08 14:13:08  jmones
+% Synchronized with cmunique. uint8 support added. Tests working for 2.1.58
+%
+% Revision 1.2  2004/08/18 14:57:42  jmones
+% speed improvement suggested by Paul Kienzle
+%
+% Revision 1.1  2004/08/17 19:18:42  jmones
+% cmpermute added: Reorders colors in a colormap
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/cmunique.m
@@ -0,0 +1,206 @@
+## 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{Y}, @var{newmap}] = } cmunique (@var{X},@var{map})
+## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{RGB})
+## @deftypefnx {Function File} {[@var{Y}, @var{newmap}] = } cmunique (@var{I})
+## Finds colormap with unique colors and corresponding image
+##
+## @code{[Y,newmap]=cmunique(X,map)} returns an indexed image @var{y}
+## along with its associated colormap @var{newmap} equivalent (which
+## produce the same image) to supplied @var{X} and its colormap
+## @var{map}; but eliminating any repeated rows in colormap colors and
+## adjusting indices in the image matrix as needed.
+##
+## @code{[Y,newmap]=cmunique(RGB)} returns an indexed image @var{y}
+## along with its associated colormap @var{newmap} computed from a
+## true-color image @var{RGB} (a m-by-n-by-3 array), where @var{newmap}
+## is the smallest colormap possible (alhough it could be as long as
+## number of pixels in image).
+##
+## @code{[Y,newmap]=cmunique(I)} returns an indexed image @var{y}
+## along with its associated colormap @var{newmap} computed from a
+## intensity image @var{I}, where @var{newmap} is the smallest
+## colormap possible (alhough it could be as long as number of pixels
+## in image).
+##
+## @strong{Notes:}
+##
+## @var{newmap} is always a @var{m}-by-3 matrix, even if input image is
+## a intensity grey-scale image @var{I} (all three RGB planes are
+## assigned the same value).
+##
+## @var{newmap} is always of class double. If we use a RGB or intensity
+## image of class uint8 or uint16, the colors in the colormap will be of
+## class double in the range [0,1] (they are divided by intmax("uint8")
+## and intmax("uint16") respectively.
+##
+## @end deftypefn
+
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function [Y, newmap] = cmunique(P1, P2)
+  if (nargin<1 || nargin>2)
+    usage("[Y, newmap] = cmunique(X, map), [Y, newmap] = cmunique(RGB), [Y, newmap] = cmunique(I)");
+  endif
+  
+
+  if(nargin==2)
+    ## (X, map) case
+    [newmap,i,j]=unique(P2,'rows');                 ## calculate unique colormap
+    if(isa(P1,"double"))
+      Y=j(P1);                                      ## find new indices
+    else
+      Y=j(double(P1)+1);                            ## find new indices
+    endif
+  else
+    switch(size(P1,3))
+      case(1)
+	## I case
+	[newmap,i,j]=unique(P1);                        ## calculate unique colormap
+	newmap=repmat(newmap,1,3);                      ## get a RGB colormap
+	Y=reshape(j,rows(P1),columns(P1));              ## Y is j reshaped
+      case(3)
+	## RGB case
+	map=[P1(:,:,1)(:), P1(:,:,2)(:), P1(:,:,3)(:)]; ## build a map with all values
+	[newmap,i,j]=unique(map, 'rows');               ## calculate unique colormap
+	Y=reshape(j,rows(P1),columns(P1));              ## Y is j reshaped
+      otherwise
+	error("cmunique: first parameter is invalid.");
+    endswitch
+    
+    ## if image was uint8 or uint16 we have to convert newmap to [0,1] range
+    if(!isa(P1,"double"))
+      newmap=double(newmap)/double(intmax(class(P1)));
+    endif
+  endif
+
+  if(rows(newmap)<=256)
+    ## convert Y to uint8 (0-based indices then)
+    Y=uint8(Y-1);
+  endif
+
+  
+endfunction
+
+
+%!demo
+%! [Y,newmap]=cmunique([1:4;5:8],[hot(4);hot(4)])
+%! # Both rows are equal since map maps colors to the same value
+%! # cmunique will give the same indices to both
+
+
+%!# This triggers invalid first parameter
+%!error(cmunique(zeros(3,3,2)));
+
+%!# Check that output is uint8 in short colormaps
+%!test
+%! [Y,newmap]=cmunique([1:4;5:8], [hot(4);hot(4)]);
+%! assert(Y,uint8([0:3;0:3]));
+%! assert(newmap,hot(4));
+
+%!# Check that output is double in bigger
+%!test
+%! [Y,newmap]=cmunique([1:300;301:600], [hot(300);hot(300)]);
+%! assert(Y,[1:300;1:300]);
+%! assert(newmap,hot(300));
+
+%!# Check boundary case 256
+%!test
+%! [Y,newmap]=cmunique([1:256;257:512], [hot(256);hot(256)]);
+%! assert(Y,uint8([0:255;0:255]));
+%! assert(newmap,hot(256));
+
+%!# Check boundary case 257
+%!test
+%! [Y,newmap]=cmunique([1:257;258:514], [hot(257);hot(257)]);
+%! assert(Y,[1:257;1:257]);
+%! assert(newmap,hot(257));
+
+%!# Random RGB image
+%!test
+%! RGB=rand(10,10,3);
+%! [Y,newmap]=cmunique(RGB);
+%! assert(RGB(:,:,1),newmap(:,1)(Y+1));
+%! assert(RGB(:,:,2),newmap(:,2)(Y+1));
+%! assert(RGB(:,:,3),newmap(:,3)(Y+1));
+
+%!# Random uint8 RGB image
+%!test
+%! RGB=uint8(rand(10,10,3)*255);
+%! RGBd=double(RGB)/255;
+%! [Y,newmap]=cmunique(RGB);
+%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
+%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
+%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
+
+%!# Random uint16 RGB image
+%!test
+%! RGB=uint16(rand(10,10,3)*65535);
+%! RGBd=double(RGB)/65535;
+%! [Y,newmap]=cmunique(RGB);
+%! assert(RGBd(:,:,1),newmap(:,1)(Y+1));
+%! assert(RGBd(:,:,2),newmap(:,2)(Y+1));
+%! assert(RGBd(:,:,3),newmap(:,3)(Y+1));
+
+%!# Random I image
+%!test
+%! I=rand(10,10);
+%! [Y,newmap]=cmunique(I);
+%! assert(I,newmap(:,1)(Y+1));
+%! assert(I,newmap(:,2)(Y+1));
+%! assert(I,newmap(:,3)(Y+1));
+
+%!# Random uint8 I image
+%!test
+%! I=uint8(rand(10,10)*256);
+%! Id=double(I)/255;
+%! [Y,newmap]=cmunique(I);
+%! assert(Id,newmap(:,1)(Y+1));
+%! assert(Id,newmap(:,2)(Y+1));
+%! assert(Id,newmap(:,3)(Y+1));
+
+%!# Random uint16 I image
+%!test
+%! I=uint16(rand(10,10)*65535);
+%! Id=double(I)/65535;
+%! [Y,newmap]=cmunique(I);
+%! assert(Id,newmap(:,1)(Y+1));
+%! assert(Id,newmap(:,2)(Y+1));
+%! assert(Id,newmap(:,3)(Y+1));
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:32  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.4  2004/09/08 16:06:31  jmones
+% Solved problem with uint8 indexing and reduced tests on types (suggested by P. Kienzle)
+%
+% Revision 1.3  2004/09/03 17:07:26  jmones
+% Support for uint8 and uint16 types added.
+%
+% Revision 1.2  2004/08/17 15:48:03  jmones
+% Clarified expected data for RGB images in doc
+%
+% Revision 1.1  2004/08/17 15:45:40  jmones
+% cmunique: Finds colormap with unique colors and corresponding image
+%
+%
+	
+
new file mode 100644
--- /dev/null
+++ b/inst/col2im.m
@@ -0,0 +1,172 @@
+## 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{A} = } col2im (@var{B}, [@var{m},@var{n}], [@var{mm},@var{nn}], @var{block_type})
+## @deftypefnx {Function File} {@var{A} = } col2im (@var{B}, [@var{m},@var{n}], [@var{mm},@var{nn}])
+## Rearranges matrix columns into blocks
+##
+## @code{A=col2im(B,[m,n],[mm,nn],block_type)} rearranges columns of
+## matrix @var{B} intro blocks in a way controlled by @var{block_type}
+## param, which can take the following values:
+##
+## @table @code
+## @item distinct
+## It uses @var{m}-by-@var{n} distinct blocks (which are not
+## overlapped), and are rearranged to form a @var{mm}-by-@var{nn} matrix
+## @var{A}. @var{B}'s height must be @var{m}*@var{n} and @code{col2im}
+## rearranges each column to a @var{m}-by-@var{n} block and uses them to
+## fill the whole matrix in left-to-right and then up-to-down order.
+## @item sliding
+## Is uses @var{m}-by-@var{n} sliding blocks. It rearranges row vector
+## @var{B} to a (@var{mm}-@var{m}+1)-by-(@var{nn}-@var{n}+1) matrix
+## @var{A}. @var{B} must be a
+## 1-by-(@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1).
+## @end table
+##
+## @code{A=col2im(B,[m,n],[mm,nn])} takes @code{distinct} as a default
+## value for @var{block_type}.
+##
+## @end deftypefn
+## @seealso{im2col}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function A = col2im(B, sblock, sb, block_type)
+  if(nargin<3 || nargin>4)
+    usage("A=col2im(B, [m,n], [mm,nn] [, block_type])");
+  endif
+  
+  if(nargin!=4)
+    block_type='sliding';
+  endif
+
+  ## common checks
+  if(!ismatrix(B))
+    error("col2im: B should be a matrix (or vector).");
+  endif
+  if(!isvector(sblock) || length(sblock)!=2)
+    error("col2im: expected [m,n] as second parameter.");
+  endif
+  if(!isvector(sb) || length(sb)!=2)
+    error("col2im: expected [mm,nn] as third parameter.");
+  endif
+
+  m=sblock(1);
+  n=sblock(2);
+  mm=sb(1);
+  nn=sb(2);
+
+  switch(block_type)
+    case('distinct')
+      if(rows(B)!=m*n)
+	error("col2im: B height must be m*n for 'distinct' block_type.");
+      endif
+      if(rem(mm,m)!=0)
+	error("col2im: mm should be multiple of m");
+      endif
+      if(rem(nn,n)!=0)
+	error("col2im: nn should be multiple of n");
+      endif
+      mt=mm/m;
+      nt=nn/n;
+      if(columns(B)<mt*nt)
+	error("col2im: B's width is too small (should be mm*nn/(m*m)).");
+      endif
+      c=1;
+      for i=1:mt
+	## TODO: check if we can horzcat([],uint8([10;11])) in a
+	## future Octave version > 2.1.58 in order to deuglify this!
+	r=reshape(B(:,c),m,n);
+	c+=1;
+	for j=2:nt
+	  r=horzcat(r, reshape(B(:,c),m,n));
+	  c+=1;
+	endfor
+	if(i==1) ## this workarrounds a bug in ver<=2.1.57 cat implementation
+	  A=r;
+	else
+	  A=vertcat(A,r);
+	endif
+      endfor
+	
+    case('sliding')
+      if(!all(size(B)==[1,(mm-m+1)*(nn-n+1)]))
+	error("col2im: wrong B size. Should be 1-by-(mm-m+1)*(nn-n+1).");
+      endif
+      A=reshape(B, mm-m+1, nn-n+1);
+      
+    otherwise
+      error("col2im: invalid block_type.");
+  endswitch
+
+endfunction
+
+%!demo
+%! A=[1:10;11:20;21:30;31:40]
+%! B=im2col(A,[2,5],'distinct')
+%! C=col2im(B,[2,5],[4,10],'distinct')
+%! # Divide A using distinct blocks and reverse operation
+
+
+%!shared B, Ad
+%! v=[1:10]';
+%! r=reshape(v,2,5);
+%! B=[v, v+10, v+20, v+30, v+40, v+50];
+%! Ad=[r, r+10; r+20, r+30; r+40, r+50];
+
+%!# bad m
+%!error(col2im(B,[3,5],[6,10],'distinct'));
+
+%!# bad n
+%!error(col2im(B,[2,3],[6,10],'distinct'));
+
+%!# bad mm
+%!error(col2im(B,[2,5],[7,10],'distinct'));
+
+%!# bad nn
+%!error(col2im(B,[2,5],[6,11],'distinct'));
+
+%!# bad block_type
+%!error(col2im(B,[2,5],[6,10],'wrong_block_type'));
+
+%!# this should be ok
+%!assert(col2im(B,[2,5],[6,10],'distinct'), Ad);
+
+%!# now sliding
+%!assert(col2im(ones(1,(10-2+1)*(7-3+1)),[2,3],[10,7]), ones((10-2+1),(7-3+1)));
+%!assert(col2im(ones(1,(10-2+1)*(7-3+1)),[2,3],[10,7],'sliding'), ones((10-2+1),(7-3+1)));
+
+
+%!# disctint on uint8
+%!assert(col2im(uint8(B),[2,5],[6,10],'distinct'), uint8(Ad));
+
+%!# now sliding on uint8
+%!assert(col2im(ones(1,(10-2+1)*(7-3+1),"uint8"),[2,3],[10,7]), ones((10-2+1),(7-3+1),"uint8"));
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:32  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.2  2004/09/03 17:57:42  jmones
+% Added support for int* and uint* types
+%
+% Revision 1.1  2004/08/18 14:39:07  jmones
+% im2col and col2im added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/colfilt.m
@@ -0,0 +1,94 @@
+## COLFILT Apply filter to matrix blocks
+## colfilt(A,[r c],[m n],'sliding',f,...)
+##   For each r x c overlapping subblock of A, add a column in matrix C
+##   f(C,...) should return a row vector which is then reshaped into a
+##   a matrix of size A and returned.  A is processed in chunks of size m x n.
+## colfilt(A,[r c],[m n],'distinct',f,...)
+##   For each r x c non-overlapping subblock of A, add a column in matrix C
+##   f(C,...) should return a matrix of size C each column of which is
+##   placed back into the subblock from whence it came.  A is processed
+##   in chunks of size m x n.
+##
+## The present version requires [m n], but for compatibility it should
+## be optional.  Use colfilt(A,[r c],size(A),...)
+##
+## The present version requires that [m n] divide size(A), but for
+## compatibility it should work even if [m n] does not divide A. Use
+## the following instead:
+##    [r c] = size(A);
+##    padA = zeros (m*ceil(r/m),n*ceil(c/n));
+##    padA(1:r,1:c) = A;
+##    B = colfilt(padA,...);
+##    B = B(1:r,1:c);
+##
+## The present version does not handle 'distinct'
+
+## This software is granted to the public domain
+## Author: Paul Kienzle <pkienzle@users.sf.net>
+
+function B = colfilt(A,filtsize,blksize,blktype,f,varargin)
+
+   [m,n]=size(A);
+   r = filtsize(1);
+   c = filtsize(2);
+   mblock = blksize(1);
+   nblock = blksize(2);
+
+   switch blktype
+   case 'sliding'
+     # pad with zeros
+     padm = (m+r-1);
+     padn = (n+c-1);
+     padA = zeros(padm, padn);
+     padA([1:m]+floor((r-1)/2),[1:n]+floor((c-1)/2)) = A;
+     padA = padA(:);
+
+     # throw away old A to save memory.
+     B=A; clear A;  
+
+     # build the index vector
+     colidx = [0:r-1]'*ones(1,c) + padm*ones(r,1)*[0:c-1];
+     offset = [1:mblock]'*ones(1,nblock) + padm*ones(mblock,1)*[0:nblock-1];
+     idx = colidx(:)*ones(1,mblock*nblock) + ones(r*c,1)*offset(:)';
+     clear colidx offset;
+
+     # process the matrix, one block at a time
+     idxA = zeros(r*c,mblock*nblock);
+     tmp = zeros(mblock,nblock);
+     for i = 0:m/mblock-1
+       for j = 0:n/nblock-1
+         idxA(:) = padA(idx + (i*mblock + padm*j*nblock));
+         tmp(:) = feval(f,idxA,varargin{:});
+         B(1+i*mblock:(i+1)*mblock, 1+j*nblock:(j+1)*nblock) = tmp;
+       end
+     end
+
+   case 'old-sliding'  # processes the whole matrix at a time
+     padA = zeros(m+r-1,n+c-1);
+     padA([1:m]+floor(r/2),[1:n]+floor(c/2)) = A;
+     [padm,padn] = size(padA);
+     colidx = [0:r-1]'*ones(1,c) + padm*ones(r,1)*[0:c-1];
+     offset = [1:m]'*ones(1,n) + padm*ones(m,1)*[0:n-1];
+     idx = colidx(:)*ones(1,m*n) + ones(r*c,1)*offset(:)';
+     idxA = zeros(r*c,m*n);
+     idxA(:) = padA(:)(idx);
+     B = zeros(size(A));
+     B(:) = feval(f,idxA,varargin{:});
+   case 'old-distinct' # processes the whole matrix at a time
+     if (r*floor(m/r) != m || c*floor(n/c) != n)
+        error("colfilt expected blocks to exactly fill A");
+     endif
+     colidx = [0:r-1]'*ones(1,c) + m*ones(r,1)*[0:c-1];
+     offset = [1:r:m]'*ones(1,n/c) + m*ones(m/r,1)*[0:c:n-1];
+     idx =colidx(:)*ones(1,m*n/r/c) + ones(r*c,1)*offset(:)';
+     idxA = zeros(r*c,m*n/r/c);
+     idxA(:) = A(:)(idx);
+     B = zeros(prod(size(A)),1);
+     B(idx) = feval(f,idxA,varargin{:});
+     B = reshape(B,size(A));
+   endswitch
+endfunction
+
+%!test
+%! A = reshape(1:36,6,6);
+%! assert(colfilt(A,[2,2],[3,3],'sliding','sum'), conv2(A,ones(2),'same'));
new file mode 100644
--- /dev/null
+++ b/inst/colorgradient.m
@@ -0,0 +1,52 @@
+## M = colorgradient(C,w,n)
+## Define a colour map which smoothly traverses the given colors.
+## C contains the colours, one row per r,g,b value.
+## w(i) is the relative length of the transition from colour i to colour i+1
+## in the entire gradient.  The default is ones(rows(C)-1,1).
+## n is the length of the colour map.  The default is rows(colormap).
+##
+## E.g., 
+##    colorgradient([0,0,1; 1,1,0; 1,0,0])  # blue -> yellow -> red
+##    x = linspace(0,1,200);
+##    imagesc(x(:,ones(30,1)))';
+
+## This program is granted to the public domain.
+## Author: Paul Kienzle <pkienzle@users.sf.net>
+
+function ret = colorgradient(C,w,n)
+  if nargin < 1 || nargin > 3
+    usage("M = colorgradient(C,w,n)")
+  endif
+
+  if nargin == 1
+    n = rows(colormap);
+    w = ones(length(C)-1,1);
+  elseif nargin == 2
+    if (length(w) == 1)
+      n = w;
+      w = ones(rows(C)-1,1);
+    else
+      n = rows(colormap);
+    endif
+  endif
+
+  if (length(w)+1 != rows(C))
+    error("must have one weight for each color interval");
+  endif
+
+  w = 1+round((n-1)*cumsum([0;w(:)])/sum(w));
+  map = zeros(n,3);
+  for i=1:length(w)-1
+    if (w(i) != w(i+1))
+      map(w(i):w(i+1),1) = linspace(C(i,1),C(i+1,1),w(i+1)-w(i)+1)';
+      map(w(i):w(i+1),2) = linspace(C(i,2),C(i+1,2),w(i+1)-w(i)+1)';
+      map(w(i):w(i+1),3) = linspace(C(i,3),C(i+1,3),w(i+1)-w(i)+1)';
+    endif
+  endfor
+
+  if nargout == 0
+    colormap(map);
+  else
+    ret = map;
+  endif
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/conndef.m
@@ -0,0 +1,109 @@
+## 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{conn} = } conndef (@var{num_dims}, @var{type})
+## Creates a connectivity array
+##
+## @code{conn=conndef(num_dims,type)} creates a connectivity array
+## (@var{CONN}) of @var{num_dims} dimensions and which type is defined
+## by @var{type} as follows:
+## @table @code
+## @item minimal
+## Neighbours touch the central element on a (@var{num_dims}-1)-dimensional
+## surface.
+## @item maximal
+## Neighbours touch the central element in any way. Equivalent to
+## @code{ones(repmat(3,1,@var{num_dims}))}.
+## @end table
+##
+## @end deftypefn
+
+
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function conn = conndef(num_dims,conntype)
+  if(nargin!=2)
+    usage("conn=conndef(num_dims, type)");
+  endif
+  if(num_dims<=0)
+    error("conndef: num_dims must be > 0");
+  endif
+    
+  if(strcmp(conntype,"minimal"))
+    if(num_dims==1)
+      conn=[1;1;1];
+    elseif(num_dims==2)
+      conn=[0,1,0;1,1,1;0,1,0];
+    else
+      conn=zeros(repmat(3,1,num_dims));
+      idx={};
+      idx{1}=1:3;
+      for i=2:num_dims
+	idx{i}=2;
+      endfor
+      conn(idx{:})=1;
+      for i=2:num_dims
+	idx{i-1}=2;
+	idx{i}=1:3;
+	conn(idx{:})=1;
+      endfor
+    endif
+    
+  elseif(strcmp(conntype,"maximal"))
+    if(num_dims==1)
+      conn=[1;1;1];
+    else
+      conn=ones(repmat(3,1,num_dims));
+    endif
+  else
+    error("conndef: invalid type parameter.");
+  endif
+  
+endfunction
+
+%!demo
+%! conndef(2,'minimal')
+%! % Create a 2-D minimal connectivity array
+
+%!assert(conndef(1,'minimal'), [1;1;1]);
+
+%!assert(conndef(2,'minimal'), [0,1,0;1,1,1;0,1,0]);
+
+%!test
+%! C=zeros(3,3);
+%! C(2,2,1)=1;
+%! C(2,2,3)=1;
+%! C(:,:,2)=[0,1,0;1,1,1;0,1,0];
+%! assert(conndef(3,'minimal'), C);
+
+%!assert(conndef(1,'maximal'), ones(3,1));
+%!assert(conndef(2,'maximal'), ones(3,3));
+%!assert(conndef(3,'maximal'), ones(3,3,3));
+%!assert(conndef(4,'maximal'), ones(3,3,3,3));
+
+
+
+% $Log$
+% Revision 1.1  2006/08/20 12:59:32  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.2  2005/07/03 01:10:19  pkienzle
+% Try to correct for missing newline at the end of the file
+%
+% Revision 1.1  2004/08/15 19:38:44  jmones
+% conndef added: Creates a connectivity array
new file mode 100644
--- /dev/null
+++ b/inst/cool.m
@@ -0,0 +1,51 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} cool (@var{n})
+## Create color colormap. 
+## (cyan to magenta)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = cool (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("cool: argument must be a scalar");
+    endif
+  else
+    usage ("cool (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 1, 1];  
+  elseif (number > 1)
+    r = (0:number - 1)' ./ (number - 1);
+    g = 1 - r;
+    b = ones (number, 1);
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/copper.m
@@ -0,0 +1,52 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} copper (@var{n})
+## Create color colormap. 
+## (black to a light copper tone)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = copper (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("copper: argument must be a scalar");
+    endif
+  else
+    usage ("copper (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 0];  
+  elseif (number > 1)
+    x = linspace (0, 1, number)';
+    r = (x < 4/5) .* (5/4 * x) + (x >= 4/5);
+    g = 4/5 * x;
+    b = 1/2 * x;
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/corr2.m
@@ -0,0 +1,42 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{r}= corr2 (@var{I},@var{J})
+## returns the correlation coefficient between @var{I} and @var{j}.
+## @var{I,J} must be real type matrices or vectors of same size
+## @end deftypefn
+
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	01/08/2000
+
+function r = corr2 (I, J)
+
+  if !(nargin == 2)
+    usage ("corr2(I,J)");
+  endif
+
+  if !(is_matrix(I) && isreal(I) && is_matrix(J) && isreal(J))
+	error("argument must be a real type matrix");
+  endif
+
+  if (size (I) != size (J))
+    error("arguments must be of same size")
+  endif
+  
+  r = cov (I, J) / (std2(I)*std2(J));    
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/dilate.m
@@ -0,0 +1,87 @@
+## 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{BW2} = } dilate (@var{BW1},@var{SE})
+## @deftypefnx {Function File} {@var{BW2} = } dilate (@var{BW1},@var{SE},@var{alg})
+## @deftypefnx {Function File} {@var{BW2} = } dilate (@var{BW1},@var{SE},...,@var{n})
+## Perform a dilation morphological operation on a binary image.
+##
+## BW2 = dilate(BW1, SE) returns a binary image with the result of a dilation
+## operation on @var{BW1} using neighbour mask @var{SE}.
+##
+## For each point in @var{BW1}, dilate search its neighbours (which are
+## defined by setting to 1 their in @var{SE}). If any of its neighbours
+## is on (1), then pixel is set to 1. If all are off (0) then it is set to 0.
+##
+## Center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
+##
+## Pixels outside the image are considered to be 0.
+##
+## BW2 = dilate(BW1, SE, alg) returns the result of a dilation operation 
+## using algorithm @var{alg}. Only 'spatial' is implemented at the moment.
+##
+## BW2 = dilate(BW1, SE, ..., n) returns the result of @var{n} dilation
+## operations on @var{BW1}.
+##
+## @end deftypefn
+## @seealso{erode}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function BW2 = dilate(BW1, SE, a, b)
+  alg='spatial';
+  n=1;
+  if (nargin < 1 || nargin > 4)
+    usage ("BW2 = dilate(BW1, SE [, alg] [, n])");
+  endif
+  if nargin ==  4
+    alg=a;
+    n=b;
+  elseif nargin == 3
+    if ischar(a)
+      alg=a;
+    else
+      n=a;
+    endif
+  endif
+
+  if !strcmp(alg, 'spatial')
+    error("dilate: alg not implemented.");
+  endif
+
+  # "Binarize" BW1, just in case image is not [1,0]
+  BW1=BW1!=0;
+
+  for i=1:n
+    # create result matrix
+    BW1=filter2(SE,BW1)>0;
+  endfor
+
+  BW2=BW1;
+endfunction
+
+%!demo
+%! dilate(eye(5),ones(2,2))
+%! % returns a thick diagonal.
+
+
+
+%!assert(dilate(eye(3),[1])==eye(3));	# using [1] as a mask returns the same value
+%!assert(dilate(eye(3),[1,0,0])==[[0;0],eye(2);0,0,0]);
+%!assert(dilate(eye(3),[1,0,0,0])==[[0;0],eye(2);0,0,0]); # test if center is correctly calculated on even masks
+
+
new file mode 100644
--- /dev/null
+++ b/inst/edge.m
@@ -0,0 +1,243 @@
+function [imout, thresh] = edge( im, method, thresh, param2 )
+# EDGE: find image edges
+# [imout, thresh] = edge( im, method, thresh, param2 )
+#
+# OUTPUT
+#  imout  -> output image
+#  thresh -> output thresholds
+#
+# INPUT
+#  im     -> input image (greyscale)
+#  thresh -> threshold value (value is estimated if not given)
+#  
+# The following methods are based on high pass filtering the image in
+#   two directions, calculating a combined edge weight from and then thresholding
+#
+# method = 'roberts'
+#     filt1= [1 0 ; 0 -1];   filt2= rot90( filt1 )
+#     combine= sqrt( filt1^2 + filt2^2 )  
+# method = 'sobel'
+#     filt1= [1 2 1;0 0 0;-1 -2 -1];      filt2= rot90( filt1 ) 
+#     combine= sqrt( filt1^2 + filt2^2 )  
+# method = 'prewitt'
+#     filt1= [1 1 1;0 0 0;-1 -1 -1];      filt2= rot90( filt1 ) 
+#     combine= sqrt( filt1^2 + filt2^2 )  
+# method = 'kirsh'
+#     filt1= [1 2 1;0 0 0;-1 -2 -1];  filt2 .. filt8 are 45 degree rotations of filt1
+#     combine= max( filt1 ... filt8 )
+#
+# methods based on filtering the image and finding zero crossings
+#
+# method = 'log' -> Laplacian of Gaussians 
+#      param2 is the standard deviation of the filter, default is 2
+# method = 'zerocross' -> generic zero-crossing filter
+#      param2 is the user supplied filter
+# 
+# method = 'andy' -> my idea
+#      A.Adler's idea (c) 1999. somewhat based on the canny method
+#      Step 1: Do a sobel edge detection and to generate an image at
+#               a high and low threshold
+#      Step 2: Edge extend all edges in the LT image by several pixels,
+#               in the vertical, horizontal, and 45degree directions.
+#               Combine these into edge extended (EE) image
+#      Step 3: Dilate the EE image by 1 step
+#      Step 4: Select all EE features that are connected to features in
+#               the HT image
+#                
+#      Parameters:
+#        param2(1)==0 or 4 or 8 -> perform x connected dilatation (step 3)
+#        param2(2)    dilatation coeficient (threshold) in step 3
+#        param2(3)    length of edge extention convolution (step 2)
+#        param2(4)    coeficient of extention convolution in step 2
+#        defaults = [8 1 3 3]
+
+# Copyright (C) 1999 Andy Adler
+# This code has no warrany whatsoever.
+# Do what you like with this code as long as you
+#     leave this copyright in place.
+#
+# $Id$
+
+[n,m]= size(im);
+xx= 2:m-1;
+yy= 2:n-1;
+
+if   strcmp(method,'roberts') || strcmp(method,'sobel') || ...
+     strcmp(method,'prewitt') 
+     
+
+   if strcmp(method,'roberts') 
+      filt= [1 0;0 -1]/4;               tv= 6;
+   elseif strcmp(method,'sobel') 
+      filt= [1 2 1;0 0 0; -1 -2 -1]/8;  tv= 2;
+   elseif strcmp(method,'prewitt') 
+      filt= [1 1 1;0 0 0; -1 -1 -1]/6;  tv= 4;
+   end
+
+   imo= conv2(im, rot90(filt), 'same').^2 + conv2(im, filt, 'same').^2;
+   
+# check to see if the user supplied a threshold
+# if not, calculate one in the same way as Matlab
+
+   if nargin<3
+      thresh= sqrt( tv* mean(mean( imo(yy,xx) ))  );
+   end
+
+# The filters are defined for sqrt(imo), but since we calculated imo, compare
+#  to thresh ^2
+
+   imout= ( imo >= thresh^2 );   
+
+# Thin the wide edges
+   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
+   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
+   imout(yy,xx)= imout(yy,xx) & ( xpeak | ypeak );
+
+elseif strcmp(method,'kirsch')   
+
+   filt1= [1 2 1;0 0 0;-1 -2 -1];   fim1= conv2(im,filt1,'same');
+   filt2= [2 1 0;1 0 -1;0 -1 -2];   fim2= conv2(im,filt2,'same');
+   filt3= [1 0 -1;2 0 -2;1 0 -1];   fim3= conv2(im,filt3,'same');
+   filt4= [0 1 2;-1 0 1;-2 -1 0];   fim4= conv2(im,filt4,'same');
+
+   imo= reshape(max([abs(fim1(:)) abs(fim2(:)) abs(fim3(:)) abs(fim4(:))]'),n,m);
+
+   if nargin<3
+      thresh=  2* mean(mean( imo(yy,xx) )) ;
+   end
+
+   imout=  imo >= thresh ;   
+
+# Thin the wide edges
+   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
+   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
+   imout(yy,xx)= imout(yy,xx) & ( xpeak | ypeak );
+
+elseif  strcmp(method,'log') || strcmp(method,'zerocross') 
+
+   if strcmp(method,'log') 
+      if nargin >= 4;    sd= param2;
+      else               sd= 2;
+      end
+
+      sz= ceil(sd*3);
+      [x,y]= meshgrid( -sz:sz, -sz:sz );
+      filt = exp( -( x.^2 + y.^2 )/2/sd^2 ) .* ...
+                   ( x.^2 + y.^2 - 2*sd^2 ) / 2 / pi / sd^6 ;
+   else
+      filt = param2;
+   end
+   filt = filt - mean(filt(:));
+
+   imo= conv2(im, filt, 'same');
+
+   if nargin<3 || isempty( thresh )
+      thresh=  0.75* mean(mean( abs(imo(yy,xx)) )) ;
+   end
+
+   zcross= imo > 0;
+   yd_zc=  diff( zcross );
+   xd_zc=  diff( zcross' )';
+   yd_io=  abs(diff( imo ) ) > thresh;
+   xd_io=  abs(diff( imo')') > thresh;
+
+# doing it this way puts the transition at the <=0 point
+   xl= zeros(1,m);  yl= zeros(n,1);
+   imout= [    ( yd_zc ==  1 ) & yd_io ; xl] | ...
+          [xl; ( yd_zc == -1 ) & yd_io     ] | ...
+          [    ( xd_zc ==  1 ) & xd_io , yl] | ... 
+          [yl, ( xd_zc == -1 ) & xd_io     ];
+
+elseif  strcmp(method,'canny')  
+    error("method canny not implemented");
+
+elseif  strcmp(method,'andy')  
+
+   filt= [1 2 1;0 0 0; -1 -2 -1]/8;  tv= 2;
+   imo= conv2(im, rot90(filt), 'same').^2 + conv2(im, filt, 'same').^2;
+   if nargin<3 || thresh==[];
+      thresh= sqrt( tv* mean(mean( imo(yy,xx) ))  );
+   end
+#     sum( imo(:)>thresh ) / prod(size(imo))
+   dilate= [1 1 1;1 1 1;1 1 1]; tt= 1; sz=3; dt=3;
+   if nargin>=4
+      # 0 or 4 or 8 connected dilation
+      if length(param2) > 0
+         if      param2(1)==4 ; dilate= [0 1 0;1 1 1;0 1 0];
+         elseif  param2(1)==0 ; dilate= 1;
+         end
+      end
+      # dilation threshold
+      if length(param2) > 2; tt= param2(2); end
+      # edge extention length
+      if length(param2) > 2; sz= param2(3); end
+      # edge extention threshold
+      if length(param2) > 3; dt= param2(4); end
+      
+   end
+   fobliq= [0 0 0 0 1;0 0 0 .5 .5;0 0 0 1 0;0 0 .5 .5 0;0 0 1 0 0; 
+                      0 .5 .5 0 0;0 1 0 0 0;.5 .5 0 0 0;1 0 0 0 0];
+   fobliq= fobliq( 5-sz:5+sz, 3-ceil(sz/2):3+ceil(sz/2) );
+
+   xpeak= imo(yy,xx-1) <= imo(yy,xx) & imo(yy,xx) > imo(yy,xx+1) ;
+   ypeak= imo(yy-1,xx) <= imo(yy,xx) & imo(yy,xx) > imo(yy+1,xx) ;
+
+   imht= ( imo >= thresh^2 * 2); # high threshold image   
+   imht(yy,xx)= imht(yy,xx) & ( xpeak | ypeak );
+   imht([1,n],:)=0; imht(:,[1,m])=0;
+
+%  imlt= ( imo >= thresh^2 / 2); # low threshold image   
+   imlt= ( imo >= thresh^2 / 1); # low threshold image   
+   imlt(yy,xx)= imlt(yy,xx) & ( xpeak | ypeak );
+   imlt([1,n],:)=0; imlt(:,[1,m])=0;
+
+# now we edge extend the low thresh image in 4 directions
+
+   imee= ( conv2( imlt, ones(2*sz+1,1)    , 'same') > tt ) | ...
+         ( conv2( imlt, ones(1,2*sz+1)    , 'same') > tt ) | ...
+         ( conv2( imlt, eye(2*sz+1)       , 'same') > tt ) | ...
+         ( conv2( imlt, rot90(eye(2*sz+1)), 'same') > tt ) | ...
+         ( conv2( imlt, fobliq            , 'same') > tt ) | ...
+         ( conv2( imlt, fobliq'           , 'same') > tt ) | ...
+         ( conv2( imlt, rot90(fobliq)     , 'same') > tt ) | ...
+         ( conv2( imlt, flipud(fobliq)    , 'same') > tt );
+#  imee(yy,xx)= conv2(imee(yy,xx),ones(3),'same') & ( xpeak | ypeak );
+   imee= conv2(imee,dilate,'same') > dt; #
+
+%  ff= find( imht==1 );
+%  imout = bwselect( imee, rem(ff-1, n)+1, ceil(ff/n), 8);  
+   imout = imee;
+
+
+else
+
+   error (['Method ' method ' is not recognized']);
+
+end
+
+
+
+
+# 
+# $Log$
+# Revision 1.1  2006/08/20 12:59:32  hauberg
+# Changed the structure to match the package system
+#
+# Revision 1.1  2002/03/17 02:38:52  aadler
+# fill and edge detection operators
+#
+# Revision 1.4  2000/11/20 17:13:07  aadler
+# works?
+#
+# Revision 1.3  1999/06/09 17:29:36  aadler
+# implemented 'andy' mode edge detection
+#
+# Revision 1.2  1999/06/08 14:26:50  aadler
+# zero-cross and LoG filters work
+#
+# Revision 1.1  1999/06/07 21:01:38  aadler
+# Initial revision
+#
+#
+
+#  
new file mode 100644
--- /dev/null
+++ b/inst/erode.m
@@ -0,0 +1,89 @@
+## 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{BW2} = } erode (@var{BW1},@var{SE})
+## @deftypefnx {Function File} {@var{BW2} = } erode (@var{BW1},@var{SE},@var{alg})
+## @deftypefnx {Function File} {@var{BW2} = } erode (@var{BW1},@var{SE},...,@var{n})
+## Perform an erosion morphological operation on a binary image.
+##
+## BW2 = erosion(BW1, SE) returns a binary image with the result of an erosion
+## operation on @var{BW1} using neighbour mask @var{SE}.
+##
+## For each point in @var{BW1}, erode searchs its neighbours (which are
+## defined by setting to 1 their in @var{SE}). If all neighbours
+## are on (1), then pixel is set to 1. If any is off (0) then it is set to 0.
+##
+## Center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
+##
+## Pixels outside the image are considered to be 0.
+##
+## BW2 = erode(BW1, SE, alg) returns the result of a erosion operation 
+## using algorithm @var{alg}. Only 'spatial' is implemented at the moment.
+##
+## BW2 = erosion(BW1, SE, ..., n) returns the result of @var{n} erosion
+## operations on @var{BW1}.
+##
+## @end deftypefn
+## @seealso{dilate}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function BW2 = erode(BW1, SE, a, b)
+  alg='spatial';
+  n=1;
+  if (nargin < 1 || nargin > 4)
+    usage ("BW2 = erode(BW1, SE [, alg] [, n])");
+  endif
+  if nargin ==  4
+    alg=a;
+    n=b;
+  elseif nargin == 3
+    if ischar(a)
+      alg=a;
+    else
+      n=a;
+    endif
+  endif
+
+  if !strcmp(alg, 'spatial')
+    error("erode: alg not implemented.");
+  endif
+
+  # count ones in mask
+  thr=sum(SE(:));
+
+  # "Binarize" BW1, just in case image is not [1,0]
+  BW1=BW1!=0;
+
+  for i=1:n
+    # create result matrix
+    BW1=filter2(SE,BW1) == thr;
+  endfor
+
+  BW2=BW1;
+endfunction
+
+%!demo
+%! erode(ones(5,5),ones(3,3))
+%! % creates a zeros border around ones.
+
+
+
+%!assert(erode([0,1,0;1,1,1;0,1,0],[0,0,0;0,0,1;0,1,1])==[1,0,0;0,0,0;0,0,0]);
+%!assert(erode([0,1,0;1,1,1;0,1,0],[0,1;1,1])==[1,0,0;0,0,0;0,0,0]);
+
+
new file mode 100644
--- /dev/null
+++ b/inst/fftconv2.m
@@ -0,0 +1,134 @@
+## Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
+##
+## This program is free software; redistribution and use in source and
+## binary forms, with or without modification, are permitted provided that
+## the following conditions are met:
+##
+## 1. Redistributions of source code must retain the above copyright
+##    notice, this list of conditions and the following disclaimer.
+## 2. Redistributions in binary form must reproduce the above copyright
+##    notice, this list of conditions and the following disclaimer in the
+##    documentation and/or other materials provided with the distribution.
+##
+## THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+## ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+## ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+## DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+## OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+## LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+## OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+## SUCH DAMAGE.
+
+## FFTCONV2 Convolve 2 dimensional signals using the FFT.
+##
+## usage: fftconv2(a, b[, shape])
+##        fftconv2(v1, v2, a, shape)
+##
+## This method is faster but less accurate for large a,b.  It
+## also uses more memory. A small complex component will be 
+## introduced even if both a and b are real.
+##
+## see also: conv2
+
+## Author: Stefan van der Walt <stefan@sun.ac.za>
+## Date: 2004
+
+function X = fftconv2(varargin)
+    if (nargin < 2)
+	usage("fftconv2(a,b[,shape]) or fftconv2(v1, v2, a, shape)")
+    endif
+
+    shape = "full";
+    rowcolumn = 0;
+    
+    if ((nargin > 2) && ismatrix(varargin{3}))
+	## usage: fftconv2(v1, v2, a[, shape])
+
+	rowcolumn = 1;
+	v1 = varargin{1}(:)';
+	v2 = varargin{2}(:);
+	orig_a = varargin{3};
+	
+	if (nargin == 4) shape = varargin{4}; endif
+    else
+	## usage: fftconv2(a, b[, shape])
+	
+	a = varargin{1};
+	b = varargin{2};
+	if (nargin == 3) shape = varargin{3}; endif
+
+    endif
+
+    if (rowcolumn)
+	a = fftconv2(orig_a, v2);
+	b = v1;
+    endif
+    
+    ra = rows(a);
+    ca = columns(a);
+    rb = rows(b);
+    cb = columns(b);
+
+    A = fft2(impad(a, [0 cb-1], [0 rb-1]));
+    B = fft2(impad(b, [0 ca-1], [0 ra-1]));
+
+    X = ifft2(A.*B);
+
+    if (rowcolumn)
+	rb = rows(v2);
+	ra = rows(orig_a);
+	cb = columns(v1);
+	ca = columns(orig_a);
+    endif
+    
+    if strcmp(shape,"same")
+	r_top = ceil((rb + 1) / 2);
+	c_top = ceil((cb + 1) / 2);
+	X = X(r_top:r_top + ra - 1, c_top:c_top + ca - 1);
+    elseif strcmp(shape, "valid")
+	X = X(rb:ra, cb:ca);
+    endif
+endfunction
+
+%!# usage: fftconv2(a,b,[, shape])
+%!shared a,b
+%! a = repmat(1:10, 5);
+%! b = repmat(10:-1:3, 7);
+%!assert(norm(fftconv2(a,b)-conv2(a,b)), 0, 1e6*eps)
+%!assert(norm(fftconv2(b,a)-conv2(b,a)), 0, 1e6*eps)
+%!assert(norm(fftconv2(a,b,'full')-conv2(a,b,'full')), 0, 1e6*eps)
+%!assert(norm(fftconv2(b,a,'full')-conv2(b,a,'full')), 0, 1e6*eps)
+%!assert(norm(fftconv2(a,b,'same')-conv2(a,b,'same')), 0, 1e6*eps)
+%!assert(norm(fftconv2(b,a,'same')-conv2(b,a,'same')), 0, 1e6*eps)
+%!assert(isempty(fftconv2(a,b,'valid')));
+%!assert(norm(fftconv2(b,a,'valid')-conv2(b,a,'valid')), 0, 1e6*eps)
+
+%!# usage: fftconv2(v1, v2, a[, shape])
+%!shared x,y,a
+%! x = 1:4; y = 4:-1:1; a = repmat(1:10, 5);
+%!assert(norm(fftconv2(x,y,a)-conv2(x,y,a)), 0, 1e6*eps)
+%!assert(norm(fftconv2(x,y,a,'full')-conv2(x,y,a,'full')), 0, 1e6*eps)
+%!assert(norm(fftconv2(x,y,a,'same')-conv2(x,y,a,'same')), 0, 1e6*eps)
+%!assert(norm(fftconv2(x,y,a,'valid')-conv2(x,y,a,'valid')), 0, 1e6*eps)
+
+%!demo
+%! ## Draw a cross
+%! N = 100;
+%! [x,y] = meshgrid(-N:N, -N:N);
+%! z = 0*x;
+%! z(N,1:2*N+1) = 1; z(1:2*N+1, N) = 1;
+%! imshow(z);
+%!
+%! ## Draw a sinc blob
+%! n = floor(N/10);
+%! [x,y] = meshgrid(-n:n, -n:n);
+%! b = x.^2 + y.^2; b = max(b(:)) - b; b = b / max(b(:));
+%! imshow(b);
+%!
+%! ## Convolve the cross with the blob
+%! imshow(real(fftconv2(z, b, 'same')*N))
+
+
new file mode 100644
--- /dev/null
+++ b/inst/flag.m
@@ -0,0 +1,50 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} flag (@var{n})
+## Create color colormap. 
+## (cycling through red, white, blue and black)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+## flag(number) gives a colormap consists of red, white, blue and black
+## changing with each index
+
+function map = flag (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("flag: argument must be a scalar");
+    endif
+  else
+    usage ("flag (number)");
+  endif
+
+  p = [1, 0, 0; 1, 1, 1; 0, 0, 1; 0, 0, 0];
+  if (rem(number,4) == 0)
+    map=kron (ones (number / 4, 1), p);
+  else
+    map=[kron(ones (fix (number / 4), 1), p); p(1:rem (number, 4), :)];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/grayslice.m
@@ -0,0 +1,78 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{X} =} grayslice (@var{I},@var{n})
+## @deftypefnx {Function File} {@var{X} =} grayslice (@var{I},@var{v})
+## creates an indexed image @var{X} from an intensitiy image @var{I}
+## using multiple threshold levels.
+## A scalar integer value @var{n} sets the levels to
+## @example
+## 
+## @group
+## 1  2       n-1
+## -, -, ..., ---
+## n  n        n
+## @end group
+## @end example
+##
+## X = grayslice(I,5);
+##
+## For irregular threshold values a real vector @var{v} can be used.
+## The values must be in the range [0,1].
+##
+## @group
+## X = grayslice(I,[0.1,0.33,0.75,0.9])
+## @end group
+##
+## @end deftypefn
+## @seealso{im2bw}
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	03. August 2000
+
+function X = grayslice (I, v)
+
+  if (nargin != 2)
+    usage ("grayslice(...) number of arguments must be 1 or 2");
+  endif
+
+  if (is_scalar(v) && (fix(v) == v))
+
+    v = (1:v - 1) / v;
+
+  elseif (isvector(v))
+
+    if (any (v < 0) || (any (v > 1)))
+      error ("slice vector must be in range [0,1]")
+    endif
+    v = [0,v,1];
+  else
+
+    usage("second argument");
+
+  endif
+
+  [r, c] = size (I);
+  [m, n] = sort ([v(:); I(:)]);
+  lx = length (v);
+  o = cumsum (n <= lx);
+  idx = o (find(n>lx));
+  [m, n] = sort (I(:));
+  [m, n] = sort (n);
+  X = reshape (idx(n), r, c);
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/histeq.m
@@ -0,0 +1,33 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{J}= histeq (@var{I},@var{n})
+## histogram equalization
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	08. August 2000
+
+function J = histeq (I, n)
+
+  [r,c] = size (I); 
+  [X,map] = gray2ind(I);
+  [nn,xx] = imhist(I);
+  Icdf = ceil (n * cumsum (1/prod(size(I)) * nn));
+  J = reshape(Icdf(X),r,c);
+  plot(Icdf,'b;;');
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/hot.m
@@ -0,0 +1,52 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} hot (@var{n})
+## Create color colormap. 
+## (black through dark red, red, orange, yellow to white)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = hot (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1) 
+	if (! is_scalar (number))
+      error ("hot: argument must be a scalar");
+    endif
+  else
+    usage ("hot (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 0];  
+  elseif (number > 1)
+    x = linspace (0, 1, number)';
+    r = (x < 2/5) .* (5/2 * x) + (x >= 2/5);
+    g = (x >= 2/5 & x < 4/5) .* (5/2 * x - 1) + (x >= 4/5);
+    b = (x >= 4/5) .* (5*x - 4);
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/hsv.m
@@ -0,0 +1,49 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} hsv (@var{n})
+## Create color colormap. 
+## (red through yellow, green, cyan,blue,magenta to red)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = hsv (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("hsv: argument must be a scalar");
+    endif
+  else
+    usage ("hsv (number)");
+  endif
+
+  if (number == 1)
+    map = [1, 0, 0];  
+  elseif (number > 1)
+    h = linspace (0, 1, number)';
+    map = hsv2rgb ([h, ones(number, 1), ones(number, 1)]);
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/im2bw.m
@@ -0,0 +1,50 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{BW}= im2bw (@var{I},threshold)
+## @deftypefnx {Function File} @var{BW}= im2bw (@var{X},@var{cmap},threshold)
+## converts image data types to a black-white (binary) image.
+## The treshold value should be in the range [0,1].
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	19. March 2000
+
+function BW = im2bw (img, a, b)
+
+  if ( nargin < 2 || nargin > 3)
+    usage("im2bw(I) number of arguments must be 2 or 3");
+  endif
+
+  if (isgray (img))
+    if (is_scalar (a))
+      BW = (img >= a);
+    else
+      error ("threshold value must be scalar");
+    endif
+  elseif (isind (img))
+    if (is_matrix (a) && columns (a) == 3)
+      if (is_scalar (b))
+        I = ind2gray (img, a);
+        BW = (I >= b);
+      endif
+    endif
+  else
+    error ("image matrix must be of index or intensity type");
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/im2col.m
@@ -0,0 +1,255 @@
+## 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} = } im2col (@var{A}, [@var{m},@var{n}], @var{block_type})
+## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, [@var{m},@var{n}])
+## @deftypefnx {Function File} {@var{B} = } im2col (@var{A}, 'indexed', ...)
+## Rearranges image blocks into columns
+##
+## @code{B=im2col(A, [m, n], blocktype)} rearranges blocks in @var{A}
+## into columns in a way that's determined by @var{block_type}, which
+## can take the following values:
+##
+## @table @code
+## @item distinct
+## Rearranges each distinct @var{m}-by-@var{n} block in image @var{A}
+## into a column of @var{B}. Blocks are scanned from left to right and
+## the up to bottom in @var{A}, and columns are added to @var{B} from
+## left to right. If @var{A}'s size is not multiple @var{m}-by-@var{n}
+## it is padded.
+## @item sliding
+## Rearranges any @var{m}-by-@var{n} sliding block of @var{A} in a
+## column of @var{B}, without any padding, so only sliding blocks which
+## can be built using a full @var{m}-by-@var{n} neighbourhood are taken.
+## In consequence, @var{B} has @var{m}*@var{n} rows and
+## (@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) columns (where @var{mm} and
+## @var{nn} are the size of @var{A}).
+##
+## This case is thought to be used applying operations on columns of
+## @var{B} (for instance using sum(:)), so that result is a
+## 1-by-(@var{mm}-@var{m}+1)*(@var{nn}-@var{n}+1) vector, that is what
+## the complementary function @code{col2im} expects.
+## @end table
+##
+## @code{B=im2col(A,[m,n])} takes @code{distinct} as a default value for
+## @var{block_type}. 
+##
+## @code{B=im2col(A,'indexed',...)} will treat @var{A} as an indexed
+## image, so it will pad using 1 if @var{A} is double. All other cases
+## (incluing indexed matrices with uint8 and uint16 types and
+## non-indexed images) will use 0 as padding value.
+##
+## Any padding needed in 'distinct' processing will be added at right
+## and bottom edges of the image.
+##
+## @strong{Compatibility notes:}
+## 
+## @itemize @bullet
+## @item
+## 'sliding' blocks are arranged into @var{B} in a top-down and
+## left-right order. Since this isn't explicity described in MATLAB
+## documentation, we ignore if it does it this way. It has been
+## deduced because im2col implements inverse operation as a simple
+## reshape (if we chose left to right and then up to down order we would
+## had to transpose result). If you have MATLAB please check this
+## issue.
+## @item
+## MATLAB docs say that when using @code{'indexed'}, padding with 0 is
+## done for uint8 type. Since most functions do that too for uint16, we
+## have chosen to use 0 also for uint16, even if documentation doesn't
+## say it explicity, since it looks as an omission.
+## @end itemize
+##
+## @end deftypefn
+## @seealso{col2im}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function B = im2col(A, varargin)
+  if(nargin<2 || nargin>4)
+    usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
+  endif
+
+  ## check 'indexed' presence
+  indexed=false;
+  p=1;
+  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
+    if(nargin<3)
+      usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
+    endif
+    indexed=true;
+    p+=1;
+    if(isa(A,"uint8") || isa(A,"uint16"))
+	padval=0;
+    else
+      padval=1; 
+    endif
+  else
+    padval=0;
+  endif
+
+  ## check [m,n]
+  if(!isvector(varargin{p}))
+    error("im2col: expected [m,n] but param is not a vector.");
+  endif
+  if(length(varargin{p})!=2)
+    error("im2col: expected [m,n] but param has wrong length.");
+  endif
+  m=varargin{p}(1);
+  n=varargin{p}(2);
+  p+=1;
+
+  block_type='sliding';
+  if(nargin>p)
+    ## we have block_type param
+    if(!ischar(varargin{p}))
+      error("im2col: invalid parameter block_type.");
+    endif
+    block_type=varargin{p};
+    p+=1;
+  endif
+
+  ## if we didn't have 'indexed' but had 4 parameters there's an error
+  if(nargin>p)
+      usage("B=im2col(B [, 'indexed'], [m,n] [, block_type])");
+  endif
+
+  
+  ## common checks
+  if(!ismatrix(A))
+    error("im2col: A should be a matrix (or vector).");
+  endif
+
+  switch(block_type)
+    case('distinct')
+      ## calc needed padding
+      sp=mod(-size(A)',[m;n]);
+
+      if(any(sp))
+	A=padarray(A,sp,padval,'post');
+      endif
+
+      ## iterate through all blocks
+      B=[];
+      for i=1:m:size(A,1) ## up to bottom
+	for j=1:n:size(A,2) ## left to right
+	  ## TODO: check if we can horzcat([],uint8([10;11])) in a
+	  ## future Octave version > 2.1.58
+	  if(isempty(B))
+	    B=A(i:i+m-1,j:j+n-1)(:);
+	  else
+	    B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
+	  endif
+	endfor
+      endfor
+      
+    case('sliding')
+      if(indexed)
+	disp("WARNING: 'indexed' has no sense when using sliding.");
+      endif
+      if(m>size(A,1) || n>size(A,2))
+	error("im2col: block size can't be greater than image size in sliding");
+      endif
+      ## TODO: check if matlab uses top-down and left-right order
+      B=[];
+      for j=1:1:size(A,2)-n+1 ## left to right
+	for i=1:1:size(A,1)-m+1 ## up to bottom
+	  ## TODO: check if we can horzcat([],uint8([10;11])) in a
+	  ## future Octave version > 2.1.58
+	  if(isempty(B))
+	    B=A(i:i+m-1,j:j+n-1)(:);
+	  else
+	    B=horzcat(B, A(i:i+m-1,j:j+n-1)(:));
+	  endif
+	endfor
+      endfor
+      
+    otherwise
+      error("im2col: invalid block_type.");
+  endswitch
+
+endfunction
+
+%!demo
+%! A=[1:10;11:20;21:30;31:40]
+%! B=im2col(A,[2,5],'distinct')
+%! C=col2im(B,[2,5],[4,10],'distinct')
+%! # Divide A using distinct blocks and reverse operation
+
+%!shared B, A, Bs, As, Ap, Bp0, Bp1
+%! v=[1:10]';
+%! r=reshape(v,2,5);
+%! B=[v, v+10, v+20, v+30, v+40, v+50];
+%! A=[r, r+10; r+20, r+30; r+40, r+50];
+%! As=[1,2,3,4,5;6,7,8,9,10;11,12,13,14,15];
+%! b1=As(1:2,1:4)(:);
+%! b2=As(2:3,1:4)(:);
+%! b3=As(1:2,2:5)(:);
+%! b4=As(2:3,2:5)(:);
+%! Bs=[b1,b2,b3,b4];
+%! Ap=A(:,1:9);
+%! Bp1=Bp0=B;
+%! Bp0([9:10],[2,4,6])=0;
+%! Bp1([9:10],[2,4,6])=1;
+
+%!# bad block_type
+%!error(im2col(A,[2,5],'wrong_block_type'));
+
+%!# distinct
+%!assert(im2col(A,[2,5],'distinct'), B);
+
+%!# padding
+%!assert(im2col(Ap,[2,5],'distinct'), Bp0);
+%!assert(im2col(Ap,'indexed',[2,5],'distinct'), Bp1);
+
+%!# now sliding
+%!assert(im2col(As,[2,4]), Bs);
+%!assert(im2col(As,[2,4],'sliding'), Bs);
+%!assert(im2col(As,[3,5],'sliding'), As(:));
+
+%!# disctint uint8 & uint16
+%!assert(im2col(uint8(A),[2,5],'distinct'), uint8(B));
+%!assert(im2col(uint16(A),[2,5],'distinct'), uint16(B));
+
+%!# padding uint8 & uint16 (to 0 even in indexed case)
+%!assert(im2col(uint8(Ap),[2,5],'distinct'), uint8(Bp0));
+%!assert(im2col(uint8(Ap),'indexed',[2,5],'distinct'), uint8(Bp0));
+%!assert(im2col(uint16(Ap),[2,5],'distinct'), uint16(Bp0));
+%!assert(im2col(uint16(Ap),'indexed',[2,5],'distinct'), uint16(Bp0));
+
+%!# now sliding uint8 & uint16
+%!assert(im2col(uint8(As),[2,4],'sliding'), uint8(Bs));
+%!assert(im2col(uint16(As),[2,4],'sliding'), uint16(Bs));
+
+
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:33  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.3  2005/09/08 02:00:17  pkienzle
+% [for Bill Denney] isstr -> ischar
+%
+% Revision 1.2  2004/09/03 17:37:08  jmones
+% Added support for int* and uint* types
+%
+% Revision 1.1  2004/08/18 14:39:07  jmones
+% im2col and col2im added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/imadjust.m
@@ -0,0 +1,356 @@
+## 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
+##
+##
+## Based on old imadjust.m (GPL):
+## Copyright (C) 1999,2000  Kai Habel
+
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{J}= imadjust (@var{I})
+## @deftypefnx {Function File} @var{J}= imadjust (@var{I},[@var{low_in};@var{high_in}])
+## @deftypefnx {Function File} @var{J}= imadjust (@var{I},[@var{low_in};@var{high_in}],[@var{low_out};@var{high_out}])
+## @deftypefnx {Function File} @var{J}= imadjust (..., @var{gamma})
+## @deftypefnx {Function File} @var{newmap}= imadjust (@var{map}, ...)
+## @deftypefnx {Function File} @var{RGB_out}= imadjust (@var{RGB}, ...)
+## Adjust image or colormap values to a specified range
+##
+## @code{J=imadjust(I)} adjusts intensity image @var{I} values so that
+## 1% of data on lower and higher values (2% in total) of the image is
+## saturated; choosing for that the corresponding lower and higher
+## bounds (using @code{stretchlim}) and mapping them to 0 and 1. @var{J}
+## is an image of the same size as @var{I} which contains mapped values.
+## This is equivalent to @code{imadjust(I,stretchlim(I))}.
+##
+## @code{J=imadjust(I,[low_in;high_in])} behaves as described but uses
+## @var{low_in} and @var{high_in} values instead of calculating them. It
+## maps those values to 0 and 1; saturates values lower than first limit
+## to 0 and values higher than second to 1; and finally maps all values
+## between limits linearly to a value between 0 and 1. If @code{[]} is
+## passes as @code{[low_in;high_in]} value, then @code{[0;1]} is taken
+## as a default value.
+##
+## @code{J=imadjust(I,[low_in;high_in],[low_out;high_out])} behaves as
+## described but maps output values between @var{low_out} and
+## @var{high_out} instead of 0 and 1. A default value @code{[]} can also
+## be used for this parameter, which is taken as @code{[0;1]}.
+##
+## @code{J=imadjust(...,gamma)} takes, in addition of 3 parameters
+## explained above, an extra parameter @var{gamma}, which specifies the
+## shape of the mapping curve between input elements and output
+## elements, which is linear (as taken if this parameter is omitted). If
+## @var{gamma} is above 1, then function is weighted towards lower
+## values, and if below 1, towards higher values.
+##
+## @code{newmap=imadjust(map,...)} applies a transformation to a
+## colormap @var{map}, which output is @var{newmap}. This transformation
+## is the same as explained above, just using a map instead of an image.
+## @var{low_in}, @var{high_in}, @var{low_out}, @var{high_out} and
+## @var{gamma} can be scalars, in which case the same values are applied
+## for all three color components of a map; or it can be 1-by-3
+## vectors, to define unique mappings for each component.
+##
+## @code{RGB_out=imadjust(RGB,...)} adjust RGB image @var{RGB} (a
+## M-by-N-by-3 array) the same way as specified in images and colormaps.
+## Here too @var{low_in}, @var{high_in}, @var{low_out}, @var{high_out} and
+## @var{gamma} can be scalars or 1-by-3 matrices, to specify the same
+## mapping for all planes, or unique mappings for each.
+##
+## The formula used to realize the mapping (if we omit saturation) is:
+##
+## @code{J = low_out + (high_out - low_out) .* ((I - low_in) / (high_in - low_in)) .^ gamma;}
+##
+## @strong{Compatibility notes:}
+##
+## @itemize @bullet
+## @item
+## Prior versions of imadjust allowed @code{[low_in; high_in]} and
+## @code{[low_out; high_out]} to be row vectors. Compatibility with this
+## behaviour has been keeped, although preferred form is vertical vector
+## (since it extends nicely to 2-by-3 matrices for RGB images and
+## colormaps).
+## @item
+## Previous version of imadjust, if @code{low_in>high_in} it "negated" output.
+## Now it is negated if @code{low_out>high_out}, for compatibility with
+## MATLAB.
+## @item
+## Class of @var{I} is not considered, so limit values are not
+## modified depending on class of the image, just treated "as is". When
+## Octave 2.1.58 is out, limits will be multiplied by 255 for uint8
+## images and by 65535 for uint16 as in MATLAB.
+## @end itemize
+## 
+## @end deftypefn
+## @seealso{stretchlim, brighten}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+## TODO: When Octave 2.1.58 is out multiply indices if input argument is
+## TODO: of class int* or uint*.
+
+function ret = imadjust (image, in, out, gamma)
+
+  if (nargin < 1 || nargin > 4)
+    usage ("imadjust(...) number of arguments must be between 1 and 4");
+  endif
+
+  if (nargin < 4)
+    gamma = 1;              ## default gamma
+  endif
+
+  if !(ismatrix(image))
+    error ("imadjust(image,...) first parameter must be a image matrix or colormap");
+  endif
+
+  if (nargin==1)
+    in=stretchlim(image);   ## this saturates 1% on lower and 1% on
+    out=[0;1];              ## higher values
+  endif
+
+  if (nargin==2)
+    out=[0;1];              ## default out
+  endif
+
+  if !((ismatrix(in) || isempty(in)) && (ismatrix(out) || isempty(out)) )
+    usage("imadjust(image,[low high],[bottom top],gamma)");
+  endif
+
+  if (isempty(in))
+    in=[0;1];               ## default in
+  endif
+
+  if (isempty(out))
+    out=[0;1];              ## default out
+  endif
+  
+  simage=size(image);
+  if (length(simage)==3 && simage(3)==3)
+    ## image is rgb
+    [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma);
+
+    ## make room
+    ret=zeros(size(image));
+
+    ## process each plane
+    for i=1:3
+      ret(:,:,i)=__imadjust_plane__(image(:,:,i),in(1,i),in(2,i),out(1,i),out(2,i),gamma(1,i));
+    endfor
+
+  elseif (length(simage)==2)
+    if(simage(2)==3 && \ 
+       (size(in)==[2,3] || size(out)==[2,3] || size(gamma)==[1,3]) )
+      ## image is a colormap
+      [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma);
+
+      ret=[];
+      ## process each color
+      for i=1:3
+	ret=horzcat(ret,__imadjust_plane__(image(:,i),in(1,i),in(2,i),out(1,i),out(2,i),gamma(i)));
+      endfor
+
+    else
+      ## image is a intensity image
+      if( !isvector(in) || length(in)!=2 || !isvector(out) || length(out)!=2 || !isscalar(gamma) || (gamma<0) || (gamma==Inf) )
+	error("imadjust: on an intensity image, in and out must be 2-by-1 and gamma a positive scalar.");
+      endif
+      ret=__imadjust_plane__(image,in(1),in(2),out(1),out(2),gamma);
+    endif
+
+  else
+    error("imadjust: first parameter must be a colormap, an intensity image or a RGB image");
+  endif
+endfunction
+
+
+## This does all the work. I has a plane; li and hi input low and high
+## values; and lo and ho, output bottom and top values.
+## Image negative is computed if ho<lo although nothing special is
+## needed, since formula automatically handles it.
+function ret=__imadjust_plane__(I, li, hi, lo, ho, gamma)
+  ret = (I < li) .* lo;
+  ret = ret + (I >= li & I < hi) .* (lo + (ho - lo) .* ((I - li) / (hi - li)) .^ gamma);
+  ret = ret + (I >= hi) .* ho;
+endfunction
+
+
+## Checks in, out and gamma to see if they are ok for colormap and RGB
+## cases.
+function [in, out, gamma]=__imadjust_check_3d_args__(in, out, gamma)
+  switch(size(in)) 
+    case([2,3]) 
+      ## ok!
+    case([2,1])
+      in=repmat(in,1,3);
+    case([1,2]) ## Compatibility behaviour!
+      in=repmat(in',1,3);
+    otherwise
+      error("imadjust: in must be 2-by-3 or 2-by-1.");
+  endswitch
+  
+  switch(size(out))
+    case([2,3])
+      ## ok!
+    case([2,1])
+      out=repmat(out,1,3);
+    case([1,2]) ## Compatibility behaviour!
+      out=repmat(out',1,3);
+    otherwise
+      error("imadjust: out must be 2-by-3 or 2-by-1.");
+  endswitch
+  
+  switch(size(gamma))
+    case([1,3])
+      ## ok!
+    case([1,1])
+      gamma=repmat(gamma,1,3);
+    otherwise
+      error("imadjust: gamma must be a scalar or a 1-by-3 matrix.");
+  endswitch
+  
+  ## check gamma allowed range
+  if(!all((gamma>=0)&(gamma<Inf)))
+    error("imadjust: gamma values must be in the range [0,Inf]");
+  endif
+
+endfunction
+
+
+# bad arguments
+
+# bad images
+%!error(imadjust("bad argument"));
+%!error(imadjust(zeros(10,10,3,2)));
+%!error(imadjust(zeros(10,10,4)));
+%!error(imadjust("bad argument"));
+
+# bad 2d, 3d or 4th argument
+%!error(imadjust([1:100],"bad argument",[0;1],1));
+%!error(imadjust([1:100],[0,1,1],[0;1],1));
+%!error(imadjust([1:100],[0;1],[0,1,1],1));
+%!error(imadjust([1:100],[0;1],[0;1],[0;1]));
+%!error(imadjust([1:100],[0;1],[0;1],-1));
+
+%!# 1% on each end saturated
+%!assert(imadjust([1:100]),[0,linspace(0,1,98),1]);
+
+%!# test with only input arg
+%!assert(sum(abs((imadjust(linspace(0,1,100),[1/99;98/99]) - \
+%!                [0,linspace(0,1,98),1] )(:))) < 1e-10);
+
+%!# a test with input and output args
+%!assert(imadjust([1:100],[50;90],[-50;-30]), \
+%!	 [-50*ones(1,49), linspace(-50,-30,90-50+1), -30*ones(1,10)]);
+
+%!# a test with input and output args in a row vector (Compatibility behaviour)
+%!assert(imadjust([1:100],[50,90],[-50,-30]), \
+%!	 [-50*ones(1,49), linspace(-50,-30,90-50+1), -30*ones(1,10)]);
+
+%!# the previous test, "negated"
+%!assert(imadjust([1:100],[50;90],[-30;-50]), \
+%!	 [-30*ones(1,49), linspace(-30,-50,90-50+1), -50*ones(1,10)]);
+
+
+%!shared cm,cmn
+%! cm=[[1:10]',[2:11]',[3:12]'];
+%! cmn=([[1:10]',[2:11]',[3:12]']-1)/11;
+
+%!# a colormap
+%!assert(imadjust(cmn,[0;1],[10;11]),cmn+10);
+
+%!# a colormap with params in row (Compatibility behaviour)
+%!assert(imadjust(cmn,[0,1],[10,11]),cmn+10);
+
+%!# a colormap, different output on each
+%!assert(imadjust(cmn,[0;1],[10,20,30;11,21,31]),cmn+repmat([10,20,30],10,1));
+
+%!# a colormap, different input on each, we need increased tolerance for this test
+%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0;1]) -                   \
+%!       [[0,linspace(0,1,6),1,1,1]',                                   \
+%!        [0,0,linspace(0,1,6),1,1]',                                   \
+%!        [0,0,0,linspace(0,1,6),1]']                                   \
+%!       ))(:)) < 1e-10                                                 \     
+%!       );
+
+%!# a colormap, different input and output on each
+%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0,1,2;1,2,3]) -           \
+%!       [[0,linspace(0,1,6),1,1,1]',                                   \
+%!        [0,0,linspace(0,1,6),1,1]'+1,                                 \
+%!        [0,0,0,linspace(0,1,6),1]'+2]                                 \
+%!       ))(:)) < 1e-10                                                 \
+%!       );
+
+%!# a colormap, different gamma, input and output on each
+%!assert(sum(abs((imadjust(cm,[2,4,6;7,9,11],[0,1,2;1,2,3],[1,2,3]) -   \
+%!       [[0,linspace(0,1,6),1,1,1]',                                   \
+%!        [0,0,linspace(0,1,6).^2,1,1]'+1,                              \
+%!        [0,0,0,linspace(0,1,6).^3,1]'+2]                              \
+%!       )(:))) < 1e-10                                                 \    
+%!       );
+
+
+%!shared iRGB,iRGBn,oRGB
+%! iRGB=zeros(10,1,3);
+%! iRGB(:,:,1)=[1:10]';
+%! iRGB(:,:,2)=[2:11]';
+%! iRGB(:,:,3)=[3:12]';
+%! iRGBn=(iRGB-1)/11;
+%! oRGB=zeros(10,1,3);
+%! oRGB(:,:,1)=[0,linspace(0,1,6),1,1,1]';
+%! oRGB(:,:,2)=[0,0,linspace(0,1,6),1,1]';
+%! oRGB(:,:,3)=[0,0,0,linspace(0,1,6),1]';
+
+%!# a RGB image
+%!assert(imadjust(iRGBn,[0;1],[10;11]),iRGBn+10);
+
+%!# a RGB image, params in row (compatibility behaviour)
+%!assert(imadjust(iRGBn,[0,1],[10,11]),iRGBn+10);
+
+%!# a RGB, different output on each
+%!test
+%! t=iRGBn;
+%! t(:,:,1)+=10;
+%! t(:,:,2)+=20;
+%! t(:,:,3)+=30;
+%! assert(imadjust(iRGBn,[0;1],[10,20,30;11,21,31]),t);
+
+
+%!# a RGB, different input on each, we need increased tolerance for this test
+%!assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0;1]) - oRGB)(:))) < 1e-10);
+
+%!# a RGB, different input and output on each
+%!test
+%! t=oRGB;
+%! t(:,:,2)+=1;
+%! t(:,:,3)+=2;
+%! assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0,1,2;1,2,3]) - t)(:))) < 1e-10);
+
+%!# a RGB, different gamma, input and output on each
+%!test
+%! t=oRGB;
+%! t(:,:,2)=t(:,:,2).^2+1;
+%! t(:,:,3)=t(:,:,3).^3+2;
+%! assert(sum(abs((imadjust(iRGB,[2,4,6;7,9,11],[0,1,2;1,2,3],[1,2,3]) - t)(:))) < 1e-10);
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:33  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.3  2004/09/01 22:51:14  jmones
+% Fully recoded: NDArray support, docs, tests, more compatible with MATLAB, changed copyright
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/imginfo.m
@@ -0,0 +1,52 @@
+## Copyright (C) 2002 Etienne Grossmann.  All rights reserved.
+##
+## 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, or (at your option) any
+## later version.
+##
+## This 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.
+##
+
+## [h,w] = imginfo (filename) - Get image size from file
+##  hw   = imginfo (filename)
+## 
+## filename : string : Name of image file
+##
+## h        : 1      : Height of image, in pixels
+## w        : 1      : Width  of image, in pixels
+##    or
+## hw=[h,w] : 2      : Height and width of image 
+##
+## NOTE : imginfo relies on the 'convert' program.
+
+## Author:        Etienne Grossmann <etienne@cs.uky.edu>
+## Last modified: Setembro 2002
+
+function [h,w] = imginfo (fn)
+
+[status, res] = system(sprintf("convert -verbose '%s' /dev/null",fn),1);
+
+if status,
+  error (["imginfo : 'convert' exited with status %i ",\
+	  "and produced\n%s\n"],\
+	 status, res);
+end
+
+res = res(index(res," ")+1:length(res));
+
+i = index (res,"x");
+if ! i, error ("imginfo : Can't interpret string (i)\n%s\n", res); end
+
+j = index (res(i-1:-1:1)," ");
+if j<2, error ("imginfo : Can't interpret string (j)\n%s\n", res); end
+w = str2num (res(i-j:i-1));
+
+k = index (res(i+1:length(res))," ");
+if k<2, error ("imginfo : Can't interpret string (k)\n%s\n", res); end
+h = str2num (res(i+1:i+k));
+
+if nargout<2, h = [h,w]; end
new file mode 100644
--- /dev/null
+++ b/inst/imhist.m
@@ -0,0 +1,72 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} imhist (@var{I},@var{n})
+## @deftypefnx {Function File} {} imhist (@var{I})
+## @deftypefnx {Function File} {} imhist (@var{X},@var{cmap})
+## @deftypefnx {Function File} {[@var{n,x}] = } imhist (...)
+## Shows the histogram of an image using hist 
+## @end deftypefn
+## @seealso{hist}
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## July 2000 : Paul Kienzle code simplification for hist() call.
+
+function [varargout] = imhist (I, b)
+
+  if (nargin < 1 || nargin > 2)
+    usage("imhist(image,n)");
+  endif
+
+  b_is_colormap = 0;
+
+  if (nargin == 2)
+    if (is_matrix (b))
+      b_is_colormap = (columns (b) == 3);
+    endif
+  endif
+
+  if (b_is_colormap)
+    ## assuming I is an indexed image
+    ## b is colormap
+    max_idx = max (max (I));
+    bins = rows (b);
+    if (max_idx > bins)
+      warning ("largest index exceedes length of colormap");
+    endif
+  else
+    ## assuming I is an intensity image
+    ## b is number of bins
+    if (nargin == 1)
+      bins = 256;
+    else
+      bins = b;
+    endif
+
+    ## scale image to range [0,1]
+    I = mat2gray (I);
+  endif
+  
+  if (nargout == 2)
+    [nn,xx] = hist (I(:), bins);
+    vr_val_cnt = 1; varargout{vr_val_cnt++} = nn;
+    varargout{vr_val_cnt++} = xx;
+  else
+    hist (I(:), bins);
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imnoise.m
@@ -0,0 +1,72 @@
+## Copyright (C) 2000 Paul Kienzle
+##
+## 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
+
+## usage: B = imnoise (A, type)
+##
+## Adds noise to image in A.
+##
+## imnoise (A, 'gaussian' [, mean [, var]])
+##    additive gaussian noise: A = A + noise
+##    defaults to mean=0, var=0.01
+##
+## imnoise (A, 'salt & pepper' [, density])
+##    lost pixels: A = 0 or 1 for density*100% of the pixels
+##    defaults to density=0.05, or 5%
+##
+## imnoise (A, 'speckle' [, var])
+##    multiplicative gaussian noise: A = A + A*noise
+##    defaults to var=0.04
+
+## Modified: Stefan van der Walt <stefan@sun.ac.za>, 2004-02-24
+
+function A = imnoise(A, stype, a, b)
+
+  if (nargin < 2 || nargin > 4 || !is_matrix(A) || !ischar(stype))
+    usage("B = imnoise(A, type, parameters, ...)");
+  endif
+  
+  valid = (min(A(:)) >= 0 && max(A(:)) <= 1);
+
+  stype = tolower(stype);
+  if (strcmp(stype, 'gaussian'))
+    if (nargin < 3), a = 0.0; endif
+    if (nargin < 4), b = 0.01; endif
+    A = A + (a + randn(size(A)) * sqrt(b));
+    ## Variance of Gaussian data with mean 0 is E[X^2]
+  elseif (strcmp(stype, 'salt & pepper'))
+    if (nargin < 3), a = 0.05; endif
+    noise = rand(size(A));
+    A(noise <= a/2) = 0;
+    A(noise >= 1-a/2) = 1;
+  elseif (strcmp(stype, 'speckle'))
+    if (nargin < 3), a = 0.04; endif
+    A = A .* (1 + randn(size(A))*sqrt(a));
+  else
+    error("imnoise: use type 'gaussian', 'salt & pepper', or 'speckle'");
+  endif
+  
+  if valid
+    A(A>1) = 1;
+    A(A<0) = 0;
+  else
+    warning("Image should be in [0,1]");
+  endif
+
+endfunction
+
+%!assert(var(imnoise(ones(10)/2,'gaussian')(:)),0.01,0.005) # probabilistic
+%!assert(length(find(imnoise(ones(10)/2,'salt & pepper')~=0.5)),5,10) # probabilistic
+%!assert(var(imnoise(ones(10)/2,'speckle')(:)),0.01,0.005) # probabilistic
new file mode 100644
--- /dev/null
+++ b/inst/impad.m
@@ -0,0 +1,142 @@
+## 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} {} impad(@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
+
+## A nice test matrix for padding:
+## A = 10*[1:5]' * ones(1,5) + ones(5,1)*[1:5]
+
+function retval = impad(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"; endif
+if nargin < 5, const = 1; endif
+if isscalar(xpad), xpad(2) = xpad(1); endif
+if isscalar(ypad), ypad(2) = ypad(1); endif
+  
+origx = size(A,2);
+origy = size(A,1);
+retx = origx + xpad(1) + xpad(2);
+rety = origy + ypad(1) + ypad(2);
+
+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) ];
+    endif                        
+  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))) ];
+    endif      
+  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))) ];
+    endif
+  else    
+    error("Unknown padding type");
+endif
+
+unwind_protect_cleanup
+    empty_list_elements_ok = empty_list_elements_ok_save;
+    warn_empty_list_elements = warn_empty_list_elements_save;
+end_unwind_protect
+      
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imread.m
@@ -0,0 +1,159 @@
+## Copyright (C) 2002 Andy Adler
+##
+## 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, or (at your option)
+## any later version. USE THIS SOFTWARE AT YOUR OWN RISK.
+
+## usage: I = imread(fname)
+##
+## Read images from various file formats.
+##
+##   The size and numeric class of the output depends on the
+##   format of the image.  A colour image is returned as an
+##   MxNx3 matrix.  Grey-level and black-and-white images are
+##   of size MxN.
+##     The colour depth of the image determines the numeric
+##   class of the output: 'uint8' or 'uint16' for grey
+##   and colour, and 'logical' for black and white.
+##
+##   Note: For image formats other than jpeg and png, the
+##         ImageMagick "convert" and "identify" utilities
+##         are needed. ImageMagick can be found at
+##
+##         www.imagemagick.org
+##
+
+## Author: Andy Adler
+##
+## Modified: Stefan van der Walt <stefan@sun.ac.za>
+## Date: 24 January 2005
+
+function varargout = imread(filename, varargin)
+    if (nargin != 1)
+	usage("I = imread(filename)")
+    endif
+
+    if !isstr(filename)
+	error("imread: filename must be a string")
+    endif
+
+    fn = file_in_path(IMAGE_PATH, filename);
+    if isempty(fn)
+	error("imread: cannot find %s", filename);
+    endif
+
+
+    [ig, ig, ext] = fileparts(fn);
+    ext = upper(ext);    
+    
+    ## divert jpegs and pngs to "jpgread" and "pngread"
+    if ( file_in_loadpath("jpgread.oct") &&
+	(strcmp(ext, ".JPG") || strcmp(ext, ".JPEG")) )
+	varargout{1} = jpgread(fn);
+	break
+    endif
+    if ( file_in_loadpath("pngread.oct") && (strcmp(ext, ".PNG")) )
+	varargout{1} = pngread(fn);
+	break
+    endif
+    
+    ## alternately, use imagemagick
+    if ( file_in_loadpath("__magick_read__.oct") )
+      varargout{:} = __magick_read__(fn, varargin{:});
+      break
+    endif
+    
+    [sys, ident] = system(sprintf('identify -verbose %s | grep -e "Red: " -e Type',
+				  fn));
+    if (sys != 0)
+	error("imread: error running ImageMagick's 'identify' on %s", fn)
+    endif
+    depth = re_grab("Red: ([[:digit:]]{1,2})", ident);
+    imtype = re_grab("Type: ([[:alpha:]]*)", ident);
+
+    depth = str2num(depth);
+    if isempty(depth) || (pow2(nextpow2(depth)) != depth)
+	error("imread: invalid image depth %s", depth)
+    endif
+
+    if !(strcmp(imtype, "Bilevel") || strcmp(imtype, "Grayscale") ||
+	 strcmp(imtype, "TrueColor"))
+	error("imread: unknown image type '%s'", imtype);
+    endif
+
+    switch (imtype)
+	case("Bilevel")
+	    fmt = "pgm";
+	case("Grayscale")
+	    fmt = "pgm";
+	case("TrueColor")
+	    fmt = "ppm";
+    endswitch
+    
+    ## Why are pipes so slow?
+    ##    cmd = sprintf("convert -flatten -strip %s %s:-", fn, fmt);
+    
+    tmpf = [tmpnam(), ".", fmt];
+    cmd = sprintf("convert -flatten -strip +compress '%s' '%s' 2>/dev/null",
+		  fn, tmpf);
+
+    sys = system(cmd);    
+    if (sys != 0)
+	error("imread: error running ImageMagick's 'convert'");
+	unlink(tmpf);
+    endif
+
+    try
+	fid = fopen(tmpf, "rb");
+    catch
+	unlink(tmpf);
+	error("imread: could not open temporary file %s", tmpf)
+    end_try_catch
+
+    fgetl(fid); # P5 or P6 (pgm or ppm)
+    [width, height] = sscanf(fgetl(fid), "%d %d", "C");
+    fgetl(fid); # ignore max components
+
+    if (depth == 16)
+	## PGM format has MSB first, i.e. big endian
+	[data, count] = fread(fid, "uint16", 0, "ieee-be");
+    else
+        [data, count] = fread(fid, "uint8");
+    endif
+    
+    fclose(fid);
+    unlink(tmpf);
+
+    if (imtype == "TrueColor")
+	channels = 3;
+    else
+	channels = 1;
+    endif
+    if (count != width*height*channels)
+	error("imread: image data chunk has invalid size")
+    endif
+
+    varargout = {};
+    switch (imtype)
+ 	case ("Bilevel")
+ 	    varargout{1} = logical(reshape(data, width, height)');
+ 	case ("Grayscale") 
+ 	    varargout{1} = uint8(reshape(data, width, height)');
+ 	case ("TrueColor")
+ 	    varargout{1} = cat(3, reshape(data(1:3:end), width, height)',
+ 			       reshape(data(2:3:end), width, height)',
+ 			       reshape(data(3:3:end), width, height)');
+ 	    eval(sprintf("varargout{1} = uint%d(varargout{1});", depth));
+		
+    endswitch
+endfunction
+
+function value = re_grab(re, str)
+  T = regexp(str,re,'tokens');
+  if (isempty(T))
+    value = "";
+  else
+    value = T{1}{1};
+  endif
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imresize.m
@@ -0,0 +1,104 @@
+## Copyright (C) 2005 Søren Hauberg
+## 
+## 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}= imresize (@var{A}, @var{m})
+## Scales the image @var{A} by a factor @var{m} using nearest neighbour
+## interpolation. If @var{m} is less than 1 the image size will be reduced,
+## and if @var{m} is greater than 1 the image will be enlarged. If the image
+## is being enlarged the it will be convolved with a 11x11 Gaussian FIR filter
+## to reduce aliasing. See below on how to alter this behavior.
+##
+## @deftypefnx {Function File} @var{B}= imresize (@var{A}, @var{m}, @var{method})
+## Same as above except @var{method} interpolation is performed instead of
+## using nearest neighbour. @var{method} can be any method supported by interp2.
+##
+## @deftypefnx {Function File} @var{B}= imresize (@var{A}, [@var{mrow} @var{mcol}])
+## Scales the image @var{A} to be of size @var{mrow}x@var{mcol} using nearest
+## neighbour interpolation. If the image is being enlarged it will be convolved
+## with a lowpass FIR filter as described above.
+##
+## @deftypefnx {Function File} @var{B}= imresize (@var{A}, [@var{mrow} @var{mcol}], @var{method})
+## Same as above except @var{method} interpolation is performed instead of using
+## nearest neighbour. @var{method} can be any method supported by interp2.
+##
+## @deftypefnx {Function File} @var{B}= imresize (..., @var{method}, @var{fsize})
+## If the image the image is being enlarged it will usually be convolved with
+## a 11x11 Gaussian FIR filter. By setting @var{fsize} to 0 this will be turned
+## off, and if @var{fsize} > 0 the image will be convolved with a @var{fsize}
+## by @var{fsize} Gaussian FIR filter.
+##
+## @deftypefnx {Function File} @var{B}= imresize (..., @var{method}, @var{filter})
+## If the image size is being reduced and the @var{filter} argument is passed to 
+## imresize the image will be convolved with @var{filter} before the resizing
+## takes place.
+##
+## @seealso{interp2}
+## @end deftypefn
+
+## Author: Søren Hauberg <hauberg at gmail dot com>
+## 
+## 2005-04-14 Søren Hauberg <hauberg at gmail dot com>
+## * Initial revision
+
+function [ ret ] = imresize (im, m, method, filter)
+  if (!isgray(im))
+    error("The first argument has to be a gray-scale image.");
+  endif
+  [row col] = size(im);
+
+  # Handle the argument that describes the size of the result
+  if (length(m) == 1)
+    new_row = round(row*m);
+    new_col = round(col*m);
+  elseif (length(m) == 2)
+    new_row = m(1);
+    new_col = m(2);
+    m = min( new_row/row, new_col/col );
+  else
+    error("Bad second argument");
+  end
+
+  # Handle the method argument
+  if (nargin < 3)
+    method = "nearest";
+  endif
+
+  # Handle the filterargument
+  if (!strcmp(method, "nearest"))
+    if (nargin < 4)
+      filter = 11;
+    endif
+    if (m > 1 & filter > 0)
+      # If the image is being enlarged and filter > 0 then
+      # convolve the image with a filter*filter gaussian.
+      mu = round(filter/2);
+      sigma = mu/3;
+      x = 1:filter;
+      gauss = 1/sqrt(2*pi*sigma^2) * exp( (-(x-mu).^2)/(2*sigma^2) );
+      im = conv2(gauss, gauss, im, "same");
+    elseif (m < 1 & nargin == 4)
+      # If the image size is being reduced and a fourth argument
+      # is given, use it as a FIR filter.
+      im = conv2(im, filter, "same");
+    endif
+  endif
+  
+  # Perform the actual resizing
+  [XI YI] = meshgrid( linspace(1,col,new_col), linspace(1,row,new_row) );
+  ret = interp2(im, XI, YI, method);
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imrotate.m
@@ -0,0 +1,349 @@
+## Copyright (C) 2004-2005 Justus H. Piater
+##
+## 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} {} 
+##            imrotate(@var{imgPre}, @var{theta}, @var{method}, @var{bbox})
+## Rotation of a 2D matrix about its center.
+##
+## Input parameters:
+##
+##   @var{imgPre}   a gray-level image matrix
+##
+##   @var{theta}    the rotation angle in degrees counterclockwise
+##
+##   @var{method}
+##     @itemize @w
+##       @item "nearest" neighbor: fast, but produces aliasing effects (default).
+##       @item "bilinear" interpolation: does anti-aliasing, but is slightly slower.
+##       @item "bicubic" interpolation: does anti-aliasing, preserves edges better than bilinear interpolation, but gray levels may slightly overshoot at sharp edges. This is probably the best method for most purposes, but also the slowest.
+##       @item "Fourier" uses Fourier interpolation, decomposing the rotation matrix into 3 shears. This method often results in different artifacts than homography-based methods.  Instead of slightly blurry edges, this method can result in ringing artifacts (little waves near high-contrast edges).  However, Fourier interpolation is better at maintaining the image information, so that unrotating will result in an image closer to the original than the other methods.
+##     @end itemize
+##
+##   @var{bbox}
+##     @itemize @w
+##       @item "loose" grows the image to accommodate the rotated image (default).
+##       @item "crop" rotates the image about its center, clipping any part of the image that is moved outside its boundaries.
+##     @end itemize
+##
+## Output parameters:
+##
+##   @var{imgPost}  the rotated image matrix
+##
+##   @var{H}        the homography mapping original to rotated pixel
+##                   coordinates. To map a coordinate vector c = [x;y] to its
+##           rotated location, compute round((@var{H} * [c; 1])(1:2)).
+## @end deftypefn
+
+## Author: Justus H. Piater  <Justus.Piater@ULg.ac.be>
+## Created: 2004-10-18
+## Version: 0.7
+
+function [imgPost, H] = imrotate(imgPre, thetaDeg, method, bbox)
+  if (nargin < 4)
+    bbox = "loose";
+    if (nargin < 3)
+      method = "nearest";
+      if (nargin < 2)
+	usage("imrotate(img, angle [, method [, bbox]]");
+      endif
+    endif
+  endif
+
+  thetaDeg = mod(thetaDeg, 360); # some code below relies on positive angles
+  theta = thetaDeg * pi/180;
+
+  sizePre = size(imgPre);
+
+  ## We think in x,y coordinates here (rather than row,column), except
+  ## for size... variables that follow the usual size() convention. The
+  ## coordinate system is aligned with the pixel centers.
+
+  R = [cos(theta) sin(theta); -sin(theta) cos(theta)];
+
+  if (nargin >= 4 && strcmp(bbox, "crop"))
+    sizePost = sizePre;
+  else
+    ## Compute new size by projecting zero-base image corner pixel
+    ## coordinates through the rotation:
+    corners = [0, 0;
+	       (R * [sizePre(2) - 1; 0             ])';
+	       (R * [sizePre(2) - 1; sizePre(1) - 1])';
+	       (R * [0             ; sizePre(1) - 1])' ];
+    sizePost(2) = round(max(corners(:,1)) - min(corners(:,1))) + 1;
+    sizePost(1) = round(max(corners(:,2)) - min(corners(:,2))) + 1;
+    ## This size computation yields perfect results for 0-degree (mod
+    ## 90) rotations and, together with the computation of the center of
+    ## rotation below, yields an image whose corresponding region is
+    ## identical to "crop". However, we may lose a boundary of a
+    ## fractional pixel for general angles.
+  endif
+
+  ## Compute the center of rotation and the translational part of the
+  ## homography:
+  oPre  = ([ sizePre(2);  sizePre(1)] + 1) / 2;
+  oPost = ([sizePost(2); sizePost(1)] + 1) / 2;
+  T = oPost - R * oPre;		# translation part of the homography
+
+  ## And here is the homography mapping old to new coordinates:
+  H = [[R; 0 0] [T; 1]];
+
+  ## Treat trivial rotations specially (multiples of 90 degrees):
+  if (mod(thetaDeg, 90) == 0)
+    nRot90 = mod(thetaDeg, 360) / 90;
+    if (mod(thetaDeg, 180) == 0 || sizePre(1) == sizePre(2) ||
+	strcmp(bbox, "loose"))
+      imgPost = rot90(imgPre, nRot90);
+      return;
+    elseif (mod(sizePre(1), 2) == mod(sizePre(2), 2))
+      ## Here, bbox is "crop" and the rotation angle is +/- 90 degrees.
+      ## This works only if the image dimensions are of equal parity.
+      imgRot = rot90(imgPre, nRot90);
+      imgPost = zeros(sizePre);
+      hw = min(sizePre) / 2 - 0.5;
+      imgPost   (round(oPost(2) - hw) : round(oPost(2) + hw),
+		 round(oPost(1) - hw) : round(oPost(1) + hw) ) = ...
+	  imgRot(round(oPost(1) - hw) : round(oPost(1) + hw),
+		 round(oPost(2) - hw) : round(oPost(2) + hw) );
+      return;
+    else
+      ## Here, bbox is "crop", the rotation angle is +/- 90 degrees, and
+      ## the image dimensions are of unequal parity. This case cannot
+      ## correctly be handled by rot90() because the image square to be
+      ## cropped does not align with the pixels - we must interpolate. A
+      ## caller who wants to avoid this should ensure that the image
+      ## dimensions are of equal parity.
+    endif
+  end
+
+  ## For better readability of this spaghetti implementation, I keep the
+  ## branches pertaining to the various 'method's all at the first
+  ## level, even though this causes a slight redundancy in the if
+  ## statements.
+
+  imgPost = [];
+
+  if (strcmp(method, "Fourier"))
+    imgPost = imrotate_Fourier(imgPre, thetaDeg, method, bbox);
+  else
+    ## This section pertains to all non-Fourier methods.
+
+    ## "Pre"  variables hold pre -rotation values;
+    ## "Post" variables hold post-rotation values.
+
+    ## General rotation: map pixel coordinates back from the Post to the
+    ## Pre img
+    Hinv = inv(H);
+
+    ## Target coordinates:
+    [xPost, yPost] = meshgrid(1:(sizePost(2)), 1:(sizePost(1)));
+
+    ## Compute corresponding source coordinates:
+    xPre = Hinv(1,1) * xPost + Hinv(1,2) * yPost + Hinv(1,3);
+    yPre = Hinv(2,1) * xPost + Hinv(2,2) * yPost + Hinv(2,3);
+    ## zPre is guaranteed to be 1, since the last row of H (and thus of
+    ## Hinv) is [0 0 1].
+  endif
+
+  ## Now map the image using the coordinates computed in the else branch above:
+  if (strcmp(method, "nearest"))
+    ## nearest-neighbor: simply round Pre coordinates
+    xPre = round(xPre);
+    yPre = round(yPre);
+    valid = find(1 <= xPre & xPre <= sizePre(2) &
+		 1 <= yPre & yPre <= sizePre(1)  );
+    if (!length(valid))
+      warning("input image too small");
+      imgPost = 0;
+      return;
+    endif
+    
+    iPre  = sub2ind(sizePre , yPre (valid), xPre (valid));
+    iPost = sub2ind(sizePost, yPost(valid), xPost(valid));
+
+    imgPost = zeros(sizePost);
+    imgPost(iPost) = imgPre(iPre);
+  elseif(!strcmp(method, "Fourier"))
+    ## This section pertains to "bilinear" and "bicubic" methods.
+
+    ## With interpolation, one unavoidably loses up to one or two pixel
+    ## rows or columns at the image boundaries.
+
+    xPreFloor = floor(xPre);
+    xPreCeil  = ceil (xPre);
+    yPreFloor = floor(yPre);
+    yPreCeil  = ceil (yPre);
+
+    valid = find(1 <= xPreFloor & xPreCeil <= sizePre(2) &
+		 1 <= yPreFloor & yPreCeil <= sizePre(1)  );
+    if (!length(valid))
+      warning("input image too small");
+      imgPost = 0;
+      return;
+    endif
+
+    xPreFloor = xPreFloor(valid);
+    xPreCeil  = xPreCeil (valid);
+    yPreFloor = yPreFloor(valid);
+    yPreCeil  = yPreCeil (valid);
+
+    ## In the following, FC = floor(x), ceil(y), etc.
+    iPreFF = sub2ind(sizePre, yPreFloor, xPreFloor);
+    iPreCF = sub2ind(sizePre, yPreFloor, xPreCeil );
+    iPreCC = sub2ind(sizePre, yPreCeil , xPreCeil );
+    iPreFC = sub2ind(sizePre, yPreCeil , xPreFloor);
+
+    ## We'll have to weight by the fractional part of the coordinates:
+    xPreFrac = xPre(valid) - xPreFloor;
+    yPreFrac = yPre(valid) - yPreFloor;
+
+    iPost = sub2ind(sizePost, yPost(valid), xPost(valid));
+  endif
+
+  if (strcmp(method, "bilinear"))
+    imgPost = zeros(sizePost);
+    ## bilinear interpolation between the four floor and ceiling coordinates
+    imgPost(iPost) = (imgPre(iPreFF) .* (1 - xPreFrac) .* (1 - yPreFrac) +
+		      imgPre(iPreCF) .*      xPreFrac  .* (1 - yPreFrac) +
+		      imgPre(iPreCC) .*      xPreFrac  .*      yPreFrac  +
+		      imgPre(iPreFC) .* (1 - xPreFrac) .*      yPreFrac   );
+  elseif (strcmp(method, "bicubic"))
+    ## bicubic interpolation (see Numerical Recipes)
+    ## This code, together with the prerequisites above, is not limited
+    ## to this particular use but applies to generic bicubic
+    ## interpolation in the following scenario:
+    ## - source data are stored in a matrix,
+    ## - interpolated coordinates may lie anywhere, no regularity is assumed.
+
+    ## precompute the required derivatives at the source image pixels:
+    imgPreDx  = conv2(imgPre  , [ 0.5 0 -0.5] , "same");
+    imgPreDy  = conv2(imgPre  , [-0.5 0  0.5]', "same");
+    imgPreDxy = conv2(imgPreDx, [-0.5 0  0.5]', "same");
+
+    ## Interpolation is done on a square of pixels and their
+    ## derivatives along x, y, and xy. The square is indexed as:
+    ##   43                        FF CF
+    ##   12  which corresponds to  FC CC
+
+    ## Coefficient matrix W
+    ## C11 12         21            31            41                p deriv
+    W = [1  0 -3  2    0  0  0  0   -3  0  9 -6    2  0 -6  4    ## 1
+	 0  0  0  0    0  0  0  0    3  0 -9  6   -2  0  6 -4	 ## 2
+	 0  0  0  0    0  0  0  0    0  0  9 -6    0  0 -6  4	 ## 3
+	 0  0  3 -2    0  0  0  0    0  0 -9  6    0  0  6 -4	 ## 4
+	 
+	 0  0  0  0    1  0 -3  2   -2  0  6 -4    1  0 -3  2	 ## 1 x
+	 0  0  0  0    0  0  0  0   -1  0  3 -2    1  0 -3  2	 ## 2 x
+	 0  0  0  0    0  0  0  0    0  0 -3  2    0  0  3 -2	 ## 3 x
+	 0  0  0  0    0  0  3 -2    0  0 -6  4    0  0  3 -2	 ## 4 x
+	 
+	 0  1 -2  1    0  0  0  0    0 -3  6 -3    0  2 -4  2	 ## 1 y
+	 0  0  0  0    0  0  0  0    0  3 -6  3    0 -2  4 -2	 ## 2 y
+	 0  0  0  0    0  0  0  0    0  0 -3  3    0  0  2 -2	 ## 3 y
+	 0  0 -1  1    0  0  0  0    0  0  3 -3    0  0 -2  2	 ## 4 y
+	 
+	 0  0  0  0    0  1 -2  1    0 -2  4 -2    0  1 -2  1	 ## 1 xy
+	 0  0  0  0    0  0  0  0    0 -1  2 -1    0  1 -2  1	 ## 2 xy
+	 0  0  0  0    0  0  0  0    0  0  1 -1    0  0 -1  1	 ## 3 xy
+	 0  0  0  0    0  0 -1  1    0  0  2 -2    0  0 -1  1];  ## 4 xy
+
+    u = 1 - yPreFrac;
+    values = zeros(size(valid));
+    for ci = 4:-1:1
+      ## compute ci'th row of matrix C:
+
+      col = 4*(ci - 1) + 1;
+      c{1} = (W( 1,col) * imgPre   (iPreFC) + W( 2,col) * imgPre   (iPreCC) +
+	      W( 5,col) * imgPreDx (iPreFC) + W( 6,col) * imgPreDx (iPreCC)  );
+
+      col++;
+      c{2} = (W( 9,col) * imgPreDy (iPreFC) + W(10,col) * imgPreDy (iPreCC) +
+	      W(13,col) * imgPreDxy(iPreFC) + W(14,col) * imgPreDxy(iPreCC)  );
+
+      for cii = 3:4
+	col++;
+	c{cii} = ...
+	    (W( 1,col) * imgPre   (iPreFC) + W( 2,col) * imgPre   (iPreCC) +
+	     W( 3,col) * imgPre   (iPreCF) + W( 4,col) * imgPre   (iPreFF) +
+	     W( 5,col) * imgPreDx (iPreFC) + W( 6,col) * imgPreDx (iPreCC) +
+	     W( 7,col) * imgPreDx (iPreCF) + W( 8,col) * imgPreDx (iPreFF) +
+	     W( 9,col) * imgPreDy (iPreFC) + W(10,col) * imgPreDy (iPreCC) +
+	     W(11,col) * imgPreDy (iPreCF) + W(12,col) * imgPreDy (iPreFF) +
+	     W(13,col) * imgPreDxy(iPreFC) + W(14,col) * imgPreDxy(iPreCC) +
+	     W(15,col) * imgPreDxy(iPreCF) + W(16,col) * imgPreDxy(iPreFF)  );
+      endfor
+
+      values .*= xPreFrac;
+      values  += ((c{4} .* u + c{3}) .* u + c{2}) .* u + c{1};
+    endfor
+    imgPost = zeros(sizePost);
+    imgPost(iPost) = values;
+  endif
+
+  if (!prod(size(imgPost)))
+    error(sprintf("Interpolation method %s not implemented", method));
+  endif
+endfunction
+
+%!test
+%! ## Verify minimal loss across six rotations that add up to 360 +/- 1 deg.:
+%! methods = { "nearest", "bilinear", "bicubic", "Fourier" };
+%! angles     = [ 59  60  61  ];
+%! tolerances = [ 7.4 8.5 8.6	  # nearest
+%!                3.5 3.1 3.5     # bilinear
+%!                2.7 0.1 2.7     # bicubic
+%!                2.7 1.6 2.8 ];  # Fourier
+%! x = peaks(50);
+%! x -= min(min(x));	      # Fourier does not handle neg. values well
+%! for m = 1:(length(methods))
+%!   y = x;
+%!   for i = 1:5
+%!     y = imrotate(y, 60, methods(m), "crop");
+%!   end
+%!   for a = 1:(length(angles))
+%!     assert(norm((x - imrotate(y, angles(a), methods(m), "crop"))
+%!                 (10:40, 10:40)) < tolerances(m,a));
+%!   end
+%! end
+
+
+%!test
+%! ## Verify exactness of near-90 and 90-degree rotations:
+%! X = rand(99);
+%! for angle = [90 180 270]
+%!   for da = [-0.1 0.1]
+%!     Y = imrotate(X,   angle + da , "nearest");
+%!     Z = imrotate(Y, -(angle + da), "nearest");
+%!     assert(norm(X - Z) == 0); # exact zero-sum rotation
+%!     assert(norm(Y - imrotate(X, angle, "nearest")) == 0); # near zero-sum
+%!   end
+%! end
+
+
+%!test
+%! ## Verify preserved pixel density:
+%! methods = { "nearest", "bilinear", "bicubic", "Fourier" };
+%! ## This test does not seem to do justice to the Fourier method...:
+%! tolerances = [ 4 2.2 2.0 209 ];
+%! range = 3:9:100;
+%! for m = 1:(length(methods))
+%!   t = [];
+%!   for n = range
+%!     t(end + 1) = sum(imrotate(eye(n), 20, methods(m))(:));
+%!   end
+%!   assert(t, range, tolerances(m));
+%! end
+
new file mode 100644
--- /dev/null
+++ b/inst/imrotate_Fourier.m
@@ -0,0 +1,170 @@
+## Copyright (C) 2002 Jeff Orchard <jorchard@cs.uwaterloo.ca>
+##
+## 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} {} imrotate(@var{M}, @var{theta}, @var{method}, @var{bbox})
+## Rotation of a 2D matrix.
+##
+## Applies a rotation of @var{THETA} degrees to matrix @var{M}.
+##
+## The @var{method} argument is not implemented, and is only included for compatibility with Matlab.
+## This function uses Fourier interpolation,
+## decomposing the rotation matrix into 3 shears.
+##
+## @var{bbox} can be either 'loose' or 'crop'.
+## 'loose' allows the image to grow to accomodate the rotated image.
+## 'crop' keeps the same size as the original, clipping any part of the image
+## that is moved outside the bounding box.
+## @end deftypefn
+
+## Author: Jeff Orchard <jorchard@cs.uwaterloo.ca>
+## Created: Oct. 14, 2002
+
+function fs = imrotate_Fourier(f,theta,method,bbox)
+
+	if ( nargin == 2 )
+		method = "fourier";
+		bbox = "loose";
+	elseif ( nargin == 3 )
+		bbox = "loose";
+	endif
+
+	# Get original dimensions.
+	[ydim_orig, xdim_orig] = size(f);
+
+	# This finds the index coords of the centre of the image (indices are base-1)
+	#   eg. if xdim_orig=8, then xcentre_orig=4.5 (half-way between 1 and 8)
+	xcentre_orig = (xdim_orig+1) / 2;
+	ycentre_orig = (ydim_orig+1) / 2;
+
+	# Pre-process the angle ===========================================================
+	# Whichever 90 degree multiple theta is closest to, that multiple of 90 will
+	# be implemented by rot90. The remainder will be done by shears.
+
+	# This ensures that 0 <= theta < 360.
+	theta = rem( rem(theta,360) + 360, 360 );
+
+	# This is a flag to keep track of 90-degree rotations.
+	perp = 0;
+
+	if ( theta>=0 && theta<=45 )
+		phi = theta;
+	elseif ( theta>45 && theta<=135 )
+		phi = theta - 90;
+		f = rot90(f,1);
+		perp = 1;
+	elseif ( theta>135 && theta<=225 )
+		phi = theta - 180;
+		f = rot90(f,2);
+	elseif ( theta>225 && theta<=315 )
+		phi = theta - 270;
+		f = rot90(f,3);
+		perp = 1;
+	else
+		phi = theta;
+	endif
+
+
+
+	if ( phi == 0 )
+		fs = f;
+		if ( strcmp(bbox,"loose") == 1 )
+			return;
+		else
+			xmax = xcentre_orig;
+			ymax = ycentre_orig;
+			if ( perp == 1 )
+				xmax = max([xmax ycentre_orig]);
+				ymax = max([ymax xcentre_orig]);
+				[ydim xdim] = size(fs);
+				xpad = ceil( xmax - (xdim+1)/2 );
+				ypad = ceil( ymax - (ydim+1)/2 );
+				fs = impad(fs, [xpad,xpad], [ypad,ypad], "zeros");
+			endif
+			xcentre_new = (size(fs,2)+1) / 2;
+			ycentre_new = (size(fs,1)+1) / 2;
+		endif
+	else
+
+		# At this point, we can assume -45<theta<45 (degrees)
+
+		phi = phi * pi / 180;
+		theta = theta * pi / 180;
+		R = [ cos(theta) -sin(theta) ; sin(theta) cos(theta) ];
+
+		# Find max of each dimension... this will be expanded for "loose" and "crop"
+		xmax = xcentre_orig;
+		ymax = ycentre_orig;
+
+		# If we don't want wrapping, we have to zeropad.
+		# Cropping will be done later, if necessary.
+		if ( strcmp(bbox, "wrap") == 0 )
+			corners = ( [ xdim_orig xdim_orig -xdim_orig -xdim_orig ; ydim_orig -ydim_orig ydim_orig -ydim_orig ] + 1 )/ 2;
+			rot_corners = R * corners;
+			xmax = max([xmax rot_corners(1,:)]);
+			ymax = max([ymax rot_corners(2,:)]);
+
+			# If we are doing a 90-degree rotation first, we need to make sure our
+			# image is large enough to hold the rot90 image as well.
+			if ( perp == 1 )
+				xmax = max([xmax ycentre_orig]);
+				ymax = max([ymax xcentre_orig]);
+			endif
+
+			[ydim xdim] = size(f);
+			xpad = ceil( xmax - xdim/2 );
+			ypad = ceil( ymax - ydim/2 );
+			%f = impad(f, [xpad,xpad], [ypad,ypad], "zeros");
+			xcentre_new = (size(f,2)+1) / 2;
+			ycentre_new = (size(f,1)+1) / 2;
+		endif
+
+		#size(f)
+		[S1 S2] = MakeShears(phi);
+
+		tic;
+		f1 = imshear(f, 'x', S1(1,2), 'loose');
+		f2 = imshear(f1, 'y', S2(2,1), 'loose');
+		fs = real( imshear(f2, 'x', S1(1,2), 'loose') );
+		%fs = f2;
+		xcentre_new = (size(fs,2)+1) / 2;
+		ycentre_new = (size(fs,1)+1) / 2;
+	endif
+
+	if ( strcmp(bbox, "crop") == 1 )
+
+		# Translate the current centre to centre_orig
+		fs = imtranslate(fs, xcentre_orig-xcentre_new, -ycentre_orig+ycentre_new, "wrap");
+
+		# Crop to original dimensions
+		fs = fs(1:ydim_orig, 1:xdim_orig);
+
+	elseif ( strcmp(bbox, "loose") == 1 )
+
+		# Find tight bounds on size of rotated image
+		# These should all be positive, or 0.
+		xmax_loose = ceil( xcentre_new + max(rot_corners(1,:)) );
+		xmin_loose = floor( xcentre_new - max(rot_corners(1,:)) );
+		ymax_loose = ceil( ycentre_new + max(rot_corners(2,:)) );
+		ymin_loose = floor( ycentre_new - max(rot_corners(2,:)) );
+
+		%fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
+		fs = fs( (ymin_loose+1):(ymax_loose-1) , (xmin_loose+1):(xmax_loose-1) );
+
+	endif
+
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imshear.m
@@ -0,0 +1,131 @@
+## Copyright (C) 2002 Jeff Orchard
+##
+## 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} {} 
+##            imshear (@var{M}, @var{axis}, @var{alpha}, @var{bbox})
+## Applies a shear to @var{M}.
+##
+## The argument @var{M} is either a matrix or an RGB image.
+##
+## @var{axis} is the axis along which the shear is to be applied, and can
+## be either 'x' or 'y'.
+## For example, to shear sideways is to shear along the 'x' axis. Choosing
+## 'y' causes an up/down shearing.
+##
+## @var{alpha} is the slope of the shear. For an 'x' shear, it is the 
+## horizontal shift (in pixels) applied to the pixel above the 
+## center. For a 'y' shear, it is the vertical shift (in pixels)
+## applied to the pixel just to the right of the center pixel.
+##
+## NOTE: @var{alpha} does NOT need to be an integer.
+##
+## @var{bbox} can be one of 'loose', 'crop' or 'wrap'.
+## 'loose' allows the image to grow to accomodate the new transformed image.
+## 'crop' keeps the same size as the original, clipping any part of the image
+## that is moved outside the bounding box.
+## 'wrap' keeps the same size as the original, but does not clip the part 
+## of the image that is outside the bounding box. Instead, it wraps it back 
+## into the image.
+##
+## If called with only 3 arguments, @var{bbox} is set to 'loose' by default.
+## @end deftypefn
+
+## Author: Jeff Orchard <jjo@sfu.ca>
+## Created: June 2002
+
+function g = imshear(m, axis, alpha, bbox, noshift)
+
+	# The code below only does y-shearing. This is because of
+	# the implementation of fft (operates on columns, but not rows).
+	# So, transpose first for x-shearing.
+	if ( strcmp(axis, "x")==1 )
+		m = m';
+	endif
+
+	if ( nargin < 4 )
+		bbox = "loose";
+		noshift = 0;
+	elseif ( nargin < 5 )
+		noshift = 0;
+	endif
+
+	[ydim_orig xdim_orig] = size(m);
+	if ( strcmp(bbox, "wrap") == 0 )
+		ypad = ceil( (xdim_orig+1)/2 * abs(alpha) );
+		m = impad(m, [0,0], [ypad,ypad]);
+	endif
+
+	[ydim_new xdim_new] = size(m);
+	xcentre = ( xdim_new + 1 ) / 2;
+	ycentre = ( ydim_new + 1 ) / 2;
+
+	# This applies FFT to columns of m (x-axis remains a spatial axis).
+	# Because the way that fft and fftshift are implemented, the origin
+	# will move by 1/2 pixel, depending on the polarity of the image
+	# dimensions.
+	#
+	# If dim is even (=2n), then the origin of the fft below is located
+	# at the centre of pixel (n+1). ie. if dim=16, then centre is at 9.
+	#
+	# If dim is odd (=2n+1), then the origin of the fft below is located
+	# at the centre of pixel (n). ie. if dim=15, then centre is at 8.
+	if ( noshift==1 )
+		M = fft(m);
+	else
+		#M = imtranslate(fft(imtranslate(m, -xcentre, ycentre, "wrap")), xcentre, -ycentre, "wrap");
+		M = fftshift(fft(fftshift(m)));
+	endif
+
+	[ydim xdim] = size(m);
+	x = zeros(ydim, xdim);
+
+	# Find coords of the origin of the image.
+	if ( noshift==1 )
+		xc_coord = 1;
+		yc_coord = 1;
+		l = (1:ydim)' - yc_coord;
+		r = (1:xdim) - xc_coord;
+		if ( strcmp(bbox, "wrap")==1 )
+			l((ydim/2):ydim) = l((ydim/2):ydim) - ydim;
+			r((xdim/2):xdim) = r((xdim/2):xdim) - xdim;
+		endif
+	else
+		xc_coord = (xdim+1)/2;
+		yc_coord = (ydim+1)/2;
+		l = (1:ydim)' - yc_coord;
+		r = (1:xdim) - xc_coord;
+	endif
+	x = l * r;
+
+	Ms = M.* exp(2*pi*I*alpha/ydim * x);
+
+	if ( noshift==1 )
+		g = abs(ifft(Ms));
+	else
+		#g = abs(imtranslate( ifft( imtranslate(Ms, -xcentre, ycentre, "wrap") ), xcentre, -ycentre, "wrap"));
+		g = abs( fftshift(ifft(ifftshift(Ms))) );
+	endif
+
+	if ( strcmp(bbox, "crop")==1 )
+		g = g(ypad+1:ydim_orig+ypad, :);
+	endif
+
+	# Un-transpose if x-shearing was wanted
+	if ( strcmp(axis, "x")==1 )
+		g = g';
+	endif
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imtranslate.m
@@ -0,0 +1,70 @@
+## Copyright (C) 2002 Jeff Orchard
+##
+## 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{Y}} =
+##             imtranslate (@var{M}, @var{x}, @var{y} [, @var{bbox}])
+## Translate a 2D image by (x,y) using Fourier interpolation.
+##
+## @var{M} is a matrix, and is translated to the right by @var{X} pixels
+## and translated up by @var{Y} pixels.
+##
+## @var{bbox} can be either 'crop' or 'wrap' (default).
+##
+## @end deftypefn
+
+## Author: Jeff Orchard <jjo@cs.sfu.ca>
+
+function Y = imtranslate(X, a, b, bbox_in)
+
+	bbox = "wrap";
+	if ( nargin > 3 )
+		bbox = bbox_in;
+	endif
+
+	if ( strcmp(bbox, "crop")==1 )
+
+		xpad = [0,0];
+		if (a>0)
+			xpad = [0,ceil(a)];
+		elseif (a<0)
+			xpad = [-ceil(a),0];
+		endif
+
+		ypad = [0,0];
+		if (b>0)
+			ypad = [ceil(b),0];
+		elseif (b<0)
+			ypad = [0,-ceil(b)];
+		endif
+
+		X = impad(X, xpad, ypad, 'zeros');
+	endif
+
+
+	[dimy, dimx] = size(X);
+	x = ifftshift(fft2(fftshift(X)));
+	px = exp(-2*pi*i*a*(0:dimx-1)/dimx);
+	py = exp(-2*pi*i*b*(0:dimy-1)/dimy)';
+	P = py * px;
+	y = x .* P;
+	Y = abs( ifftshift(ifft2(fftshift(y))) );
+	#Y = ifftshift(ifft2(fftshift(y)));
+
+	if ( strcmp(bbox, "crop")==1 )
+		Y = Y(  ypad(1)+1:dimy-ypad(2) , xpad(1)+1:dimx-xpad(2));
+	endif
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/imwrite.m
@@ -0,0 +1,276 @@
+## Copyright (C) 2002 Andy Adler
+##
+## 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, or (at your option)
+## any later version. USE THIS SOFTWARE AT YOUR OWN RISK.
+
+#IMWRITE: write image from octave to various file formats
+#
+# Note: this requires the ImageMagick "convert" utility.
+#       get this from www.imagemagick.org if required
+#       additional documentation of options is available from the
+#       convert man page
+#
+# BASIC USAGE:
+# imwrite( fname, img )
+#                 - img is a greyscale (0-255) of image in fname
+# imwrite( fname, img, map )
+#                 - map is a matrix of [r,g,b], 0-1 triples
+#                 - img is a matrix on indeces into map
+# imwrite( fname, r,g,b );
+#                 - r,g,b are red,green,blue (0-255) compondents
+#
+# Formats for image fname
+#   1. simple guess from extention ie "fig.jpg", "blah.gif"
+#   2. specify explicitly             "jpg:fig.jpg", "gif:blah.gif"
+#   3. specify subimage for multi-image format "tiff:file.tif[3]"
+#   4. raw images (row major format) specify geometry
+#                                      "raw:img[256x180]"
+#
+# IMREAD OPTIONS:
+# imread will support most of the options for convert.1
+#
+# imwrite( fname, img, options )
+# imwrite( fname, img, map, options )
+# imwrite( fname, r,g,b, options );
+#
+# where options is a string matrix (or list) of options
+#
+# example:   options= ["-rotate 25";
+#                      "-crop 200x200+150+150";
+#                      "-sample 200%" ];
+#   will rotate, crop, and then expand the image.
+#   note that the order of operations is important
+#
+# The following options are supported
+#  -antialias           remove pixel-aliasing
+#  -background color    background color
+#  -blur geometry       blur the image
+#  -border geometry     surround image with a border of color
+#  -bordercolor color   border color
+#  -box color           color for annotation bounding box
+#  -charcoal radius     simulate a charcoal drawing
+#  -colorize value      colorize the image with the fill color
+#  -colors value        preferred number of colors in the image
+#  -colorspace type     alternate image colorspace
+#  -comment string      annotate image with comment
+#  -compress type       type of image compression
+#  -contrast            enhance or reduce the image contrast
+#  -crop geometry       preferred size and location of the cropped image
+#  -density geometry    vertical and horizontal density of the image
+#  -depth value         depth of the image
+#  -despeckle           reduce the speckles within an image
+#  -dispose method      GIF disposal method
+#  -dither              apply Floyd/Steinberg error diffusion to image
+#  -draw string         annotate the image with a graphic primitive
+#  -edge radius         apply a filter to detect edges in the image
+#  -emboss radius       emboss an image
+#  -enhance             apply a digital filter to enhance a noisy image
+#  -equalize            perform histogram equalization to an image
+#  -fill color          color to use when filling a graphic primitive
+#  -filter type         use this filter when resizing an image
+#  -flip                flip image in the vertical direction
+#  -flop                flop image in the horizontal direction
+#  -font name           font for rendering text
+#  -frame geometry      surround image with an ornamental border
+#  -fuzz distance       colors within this distance are considered equal
+#  -gamma value         level of gamma correction
+#  -geometry geometry   perferred size or location of the image
+#  -gaussian geometry   gaussian blur an image
+#  -gravity type        vertical and horizontal text placement
+#  -implode amount      implode image pixels about the center
+#  -intent type         Absolute, Perceptual, Relative, or Saturation
+#  -interlace type      None, Line, Plane, or Partition
+#  -label name          assign a label to an image
+#  -level value         adjust the level of image contrast
+#  -list type           Color, Delegate, Format, Magic, Module, or Type
+#  -map filename        transform image colors to match this set of colors
+#  -matte               store matte channel if the image has one
+#  -median radius       apply a median filter to the image
+#  -modulate value      vary the brightness, saturation, and hue
+#  -monochrome          transform image to black and white
+#  -morph value         morph an image sequence
+#  -negate              replace every pixel with its complementary color 
+#  -noise radius        add or reduce noise in an image
+#  -normalize           transform image to span the full range of colors
+#  -opaque color        change this color to the fill color
+#  -page geometry       size and location of an image canvas
+#  -paint radius        simulate an oil painting
+#  -profile filename    add ICM or IPTC information profile to image
+#  -quality value       JPEG/MIFF/PNG compression level
+#  -raise value         lighten/darken image edges to create a 3-D effect
+#  -region geometry     apply options to a portion of the image
+#  -roll geometry       roll an image vertically or horizontally
+#  -rotate degrees      apply Paeth rotation to the image
+#  -sample geometry     scale image with pixel sampling
+#  -scale geometry      resize image
+#  -segment values      segment an image
+#  -seed value          pseudo-random number generator seed value
+#  -shade degrees       shade the image using a distant light source
+#  -sharpen geometry    sharpen the image
+#  -shave geometry      shave pixels from the image edges
+#  -shear geometry      slide one edge of the image along the X or Y axis
+#  -size geometry       width and height of image
+#  -solarize threshold  negate all pixels above the threshold level
+#  -spread amount       displace image pixels by a random amount
+#  -stroke color        color to use when stoking a graphic primitive
+#  -strokewidth value   width of stroke
+#  -swirl degrees       swirl image pixels about the center
+#  -texture filename    name of texture to tile onto the image background
+#  -threshold value     threshold the image
+#  -tile filename       tile image when filling a graphic primitive
+#  -transparent color   make this color transparent within the image
+#  -treedepth value     depth of the color tree
+#  -type type           image type
+#  -units type          PixelsPerInch, PixelsPerCentimeter, or Undefined
+#  -unsharp geometry    sharpen the image
+
+function imwrite(fname, p2, p3 ,p4 ,p5 );
+
+try save_empty_list_elements_ok= empty_list_elements_ok;
+catch save_empty_list_elements_ok= 0;
+end
+try save_warn_empty_list_elements= warn_empty_list_elements;
+catch save_warn_empty_list_elements= 0;
+end
+unwind_protect
+empty_list_elements_ok= 1;
+warn_empty_list_elements= 0;
+
+# some older versions of octave didn't seem handle piped output correctly
+usepipe=1;
+
+if  ( nargin <= 1 )     || ...
+    ( ! ischar (fname))  || ...
+    ( nargin == 2 && ischar(p2) )
+    usage([ ...
+    "imwrite( fname, img )\n", ...
+    "imwrite( fname, img, map )\n", ...
+    "imwrite( fname, r,g,b );\n", ...
+    "imwrite( fname, img, options )\n", ...
+    "imwrite( fname, img, map, options )\n", ...
+    "imwrite( fname, r,g,b, options );\n"]);
+endif
+
+# Put together the options string
+# TODO: add some error checking to options
+option_str="";
+n_mat= nargin-1;
+
+options= eval(sprintf("p%d",nargin));
+# process options strings if given
+if    ischar(options)
+   n_mat--;
+   for i= 1:size(options,1)
+      option_str=[option_str," ", options(i,:) ];
+   end
+elseif is_list( options )
+   n_mat--;
+   for i= 1:length(options)
+      option_str=[option_str," ", nth(options,i) ];
+   end
+end
+
+[hig,wid] = size(p2);
+if n_mat==1
+   data= p2';
+   outputtype="pgm";
+   pnm_sig="P5";
+elseif n_mat==2
+   img= p2';
+   data= [ 255*reshape(p3(img,1),1, hig*wid);
+           255*reshape(p3(img,2),1, hig*wid);
+           255*reshape(p3(img,3),1, hig*wid) ];
+   outputtype="ppm";
+   pnm_sig="P6";
+elseif n_mat==3
+   data= [ reshape(p2',1, hig*wid);
+           reshape(p3',1, hig*wid);
+           reshape(p4',1, hig*wid) ];
+   outputtype="ppm";
+   pnm_sig="P6";
+else
+   error("imwrite: too many data matrices specified");
+end
+
+if usepipe
+   pname= sprintf("convert %s %s:- '%s' 2>/dev/null",
+                  option_str, outputtype, fname);
+   fid= popen(pname ,'w');
+
+   if fid<0;
+      error('could not create image data. Is ImageMagick installed?');
+   end
+else
+   tnam= tmpnam();
+   cmd= sprintf("convert %s '%s:%s' '%s' 2>/dev/null",
+                 option_str, outputtype, tnam, fname);
+   fid= fopen(tnam, "wb");
+end   
+
+   fprintf(fid,"%s\n%d %d\n255\n",pnm_sig,wid,hig);
+   write_count= fwrite(fid,data(:));
+   if write_count != prod(size(data))
+      fclose(fid);
+      if ~usepipe
+         unlink(tnam);
+      end
+      error(['Problem writing image: ', fname ]);
+   end
+
+   fclose(fid);
+   if ~usepipe
+      retcode = system(cmd);
+      if retcode !=0 
+         error('could not call imagemagick convert');
+      end
+      unlink( tnam );
+   end
+
+unwind_protect_cleanup
+empty_list_elements_ok= save_empty_list_elements_ok;
+warn_empty_list_elements= save_warn_empty_list_elements;
+end_unwind_protect
+
+#
+# $Log$
+# Revision 1.1  2006/08/20 12:59:34  hauberg
+# Changed the structure to match the package system
+#
+# Revision 1.11  2006/03/22 17:50:47  qspencer
+# Change calls to 'system' function to reflect new ordering of output arguments.
+#
+# Revision 1.10  2005/09/08 02:00:17  pkienzle
+# [for Bill Denney] isstr -> ischar
+#
+# Revision 1.9  2005/07/21 16:03:02  aadler
+# Improve error messages and use pipes
+#
+# Revision 1.8  2005/05/25 03:43:40  pkienzle
+# Author/Copyright consistency
+#
+# Revision 1.7  2005/04/25 01:05:28  aadler
+# added GPL copyrights
+#
+# Revision 1.6  2003/09/12 14:22:42  adb014
+# Changes to allow use with latest CVS of octave (do_fortran_indexing, etc)
+#
+# Revision 1.5  2003/07/25 19:11:41  pkienzle
+# Make sure all files names referenced in system calls are wrapped in quotes
+# to protect against spaces in the path.
+#
+# Revision 1.4  2002/11/27 08:40:11  pkienzle
+# author/license updates
+#
+# Revision 1.3  2002/03/19 18:14:13  aadler
+# unfortunately using popen seems to create problems, mostly
+# on win32, but also on linux, so we need to move to a tmpfile approach
+#
+# Revision 1.2  2002/03/17 05:26:14  aadler
+# now accept filenames with spaces
+#
+# Revision 1.1  2002/03/11 01:56:47  aadler
+# general image read/write functionality using imagemagick utilities
+#
+#
new file mode 100644
--- /dev/null
+++ b/inst/isbw.m
@@ -0,0 +1,39 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{bool}= isbw (@var{BW})
+## returns true for a black-white (binary) image.
+## All values must be either 0 or 1
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	20/03/2000
+
+function bool = isbw (BW)
+
+  bool = 0;	
+  if !(nargin == 1)
+    usage ("isbw(BW)");
+  endif
+
+  if !(is_matrix(BW))
+    return;
+  endif
+
+  bool = all (all ((BW == 1) + (BW == 0)));
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/isgray.m
@@ -0,0 +1,40 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{bool}= isgray (@var{I})
+## returns true for an intensity image. All intensity values must
+## be in the range [0,1].
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	20/03/2000
+
+function bool = isgray (I)
+
+  bool = 0;
+
+  if !(nargin == 1)
+    usage ("isgray(I)");
+  endif
+
+  if (!is_matrix(I))
+    return;
+  endif
+
+  bool = all (all ((I >= 0) && (I <= 1)));
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/isind.m
@@ -0,0 +1,43 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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 WXTHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABXLXTY or FXTNESS FOR A PARTXCULAR 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, Xnc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{bool}= isind (@var{X})
+## returns true for an index image. All index values must
+## be intergers and greater than  or equal to 1.
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	20/03/2000
+
+function ret = isind (X)
+
+  if nargin != 1
+    usage ("isind(X)");
+  endif
+
+  ret =  isreal (X) && length (size (X)) == 2 ...
+	&& all ( X(:) == floor (X(:)) ) && all ( X(:) >= 1 ); 
+
+endfunction
+
+%!assert(isind([]))
+%!assert(isind(1:10))
+%!assert(!isind(0:10))
+%!assert(isind(1))
+%!assert(!isind(0))
+%!assert(!isind([1.3,2.4]))
+%!assert(isind([1,2;3,4]))
new file mode 100644
--- /dev/null
+++ b/inst/isrgb.m
@@ -0,0 +1,81 @@
+## 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{flag} = } isrgb (@var{A})
+## Returns true if parameter is a RGB image
+##
+## @code{flag=isrgb(A)} returns 1 if @var{A} is a RGB image and 0 if
+## not.
+##
+## To the decide @code{isrgb} uses the follow algorithm:
+## @itemize @bullet
+## @item
+## If @var{A} is of class double then it checks if all values are
+## between 0 and 1, and if size is m-by-n-by-3.
+## @item
+## If @var{A} is of class uint16, uint8 or logical then it checks is m-by-n-by-3.
+## @end itemize
+##
+## @strong{Compatibility notes:}
+##
+## Information needed on whether MATLAB accepts logical arrays as RGB
+## images (now this functions accepts them if they are m-by-n-by-3 arrays.
+##
+## @end deftypefn
+
+## TODO: Check if logical arrays should be considered RGB
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function flag = isrgb(A)
+  if (nargin!=1)
+    usage("flag=isrgb(A)");
+  endif
+  
+  if(ismatrix(A))
+    flag=1;
+    s=size(A);
+    if(length(s)!=3 || s(3)!=3)
+      flag=0; ## false if not m-by-n-by-3
+    elseif(strcmp(typeinfo(A),"matrix") && (any(A(:)<0) || any(A(:)>1)))
+      flag=0; ## false if class double but items are <0 or >1
+    endif
+  else
+    flag=0;
+  endif
+endfunction
+
+
+%!demo
+%! isrgb(rand(1,2,3))
+%! # A 1-by-2-by-3 double matrix with elements between 0 and 1 is a RGB image.
+
+
+%!# Non-matrix
+%!assert(isrgb("this is not a RGB image"),0);
+
+%!# Double matrix tests
+%!assert(isrgb(rand(5,5)),0);
+%!assert(isrgb(rand(5,5,1,5)),0);
+%!assert(isrgb(rand(5,5,3,5)),0);
+%!assert(isrgb(rand(5,5,3)),1);
+%!assert(isrgb(ones(5,5,3)),1);
+%!assert(isrgb(ones(5,5,3)+.0001),0);
+%!assert(isrgb(zeros(5,5,3)-.0001),0);
+
+%!# Logical
+%!assert(isrgb(logical(round(rand(5,5,3)))),1);
new file mode 100644
--- /dev/null
+++ b/inst/jet.m
@@ -0,0 +1,55 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} jet (@var{n})
+## Create color colormap. 
+## (dark blue through blue, cyan, green, yellow, red to dark red)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = jet (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("jet: argument must be a scalar");
+    endif
+  else
+    usage ("jet (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 0.5];  
+  elseif (number > 1)
+    x = linspace(0, 1, number)';
+    r = (x >= 3/8 & x < 5/8) .* (4 * x - 3/2)\
+      + (x >= 5/8 & x < 7/8) + (x >= 7/8) .* (-4 * x + 9/2);
+    g = (x >= 1/8 & x < 3/8) .* (4 * x - 1/2)\
+      + (x >= 3/8 & x < 5/8) + (x >= 5/8 & x < 7/8) .* (-4 * x + 7/2);
+    b = (x < 1/8) .* (4 * x + 1/2) + (x >= 1/8 & x < 3/8)\
+      + (x >= 3/8 & x < 5/8) .* (-4 * x + 5/2);
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/makelut.m
@@ -0,0 +1,73 @@
+## 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{lut} = } makelut (@var{fun},@var{n})
+## @deftypefnx {Function File} {@var{lut} = } makelut (@var{fun},@var{n},@var{P1},@var{P2},...)
+## Create a lookup table which can be used by applylut.
+##
+## lut = makelut(fun,n) returns a vector which can be used by applylut
+## as a lookup table. 
+##
+## @var{fun} can be a function object as created by inline, or simply a
+## string which contains the name of a function. @var{fun} should accept a
+## @var{n}-by-@var{n} matrix whose elements are binary (0 or 1) and
+## returns an scalar (actually anything suitable to be included in a
+## vector).
+##
+## makelut calls @var{fun} with all possible matrices and builds a
+## vector with its result, suitable to be used by applylut. The length
+## of this vector is 2^(@var{n}^2), so 16 for 2-by-2 and 512 for 3-by-3.
+##
+## makelut also passes parameters @var{P1}, @var{P2}, .... to @var{fun}. 
+##
+## @end deftypefn
+## @seealso{applylut}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function lut = makelut(fun, n, varargin)
+  if (nargin < 2)
+    usage ("lut = makelut(fun, n [, ...])");
+  endif
+
+  if (n<2)
+    error ("makelut: n should be a natural number >= 2");
+  endif
+
+  nq=n^2;
+  c=2^nq;
+  lut=zeros(c,1);
+  w=reshape(2.^[nq-1:-1:0],n,n);
+  for i=0:c-1
+    idx=bitand(w,i)>0;
+    lut(i+1)= feval(fun, idx, all_va_args);
+  endfor
+endfunction
+
+%!demo
+%! makelut(inline('sum(x(:))>=3','x'), 2)
+%! % Returns '1' if one or more values
+%! % in the input matrix are 1
+
+%!assert(prod(makelut(inline('sum(x(:))==2','x'),2)==makelut(inline('sum(x(:))==a*b*c*d','x','a','b','c','d'),2,2/(3*4*5),3,4,5))); # test multiple params
+%!assert(prod(makelut(inline('x(1,1)==1','x'),2)==[zeros(2^3,1);ones(2^3,1)])==1); # test 2-by-2
+%!assert(prod(makelut(inline('x(1,1)==1','x'),3)==[zeros(2^8,1);ones(2^8,1)])==1); # test 3-by-3
+%!assert(prod(makelut(inline('x(1,1)==1','x'),4)==[zeros(2^15,1);ones(2^15,1)])==1); # test 4-by-4
+%!assert(prod(makelut(inline('x(2,1)==1','x'),3)==[zeros(2^7,1);ones(2^7,1);zeros(2^7,1);ones(2^7,1)])==1); # another test for 3-by-3
+
+
+
new file mode 100644
--- /dev/null
+++ b/inst/mat2gray.m
@@ -0,0 +1,49 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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{I}= mat2gray (@var{M},[min max])
+## converts a matrix to a intensity image
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	22/03/2000
+
+function I = mat2gray (M, scale)
+
+  if (nargin < 1|| nargin > 2)
+    usage ("mat2gray(...) number of arguments must be 1 or 2");
+  endif
+
+  if (!is_matrix (M))
+    usage ("mat2gray(M,...) M must be a matrix");
+  endif
+
+  if (nargin == 1)
+    Mmin = min (min (M));
+    Mmax = max (max (M));
+  else 
+    if (isvector (scale))
+      Mmin = min (scale (1), scale (2));
+      Mmax = max (scale (1), scale (2));
+    endif
+  endif
+
+  I = (M < Mmin) .* 0;
+  I = I + (M >= Mmin & M < Mmax) .* (1 / (Mmax - Mmin) * (M - Mmin));
+  I = I + (M >= Mmax);
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/mean2.m
@@ -0,0 +1,39 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{m}= mean2 (@var{I})
+## returns the mean value for a 2d real type matrix.
+## Uses @code{mean(I(:))}
+## @end deftypefn
+## @seealso{std2,mean}
+
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	01/08/2000
+
+function m = mean2 (I)
+
+  if !(nargin == 1)
+    usage ("mean2(I)");
+  endif
+
+  if !(is_matrix(I) && isreal(I))
+	error("argument must be a real type matrix");
+  endif
+
+  m = mean (I(:));
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/medfilt2.m
@@ -0,0 +1,68 @@
+## 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} {} medfilt2(@var{A}, [@var{domain}, @var{padding}])
+## Two dimensional median filtering.
+##
+## Replaces elements of @var{A} with the median of their neighbours defined 
+## by true elements of logical matrix @var{domain}. The default @var{domain} 
+## is a 3 by 3 matrix with all elements equal to 1. If @var{domain} is 1 by 2
+## row vector, the domain matrix will be 
+## logical(ones(@var{domain}(2), @var{domain}(1))).
+##
+## Optional variable @var{padding} defines the padding used in augmenting 
+## the borders of @var{A}. See impad for details.
+##
+## @end deftypefn
+## @seealso{ordfilt2}
+
+## Author: Teemu Ikonen <tpikonen@pcu.helsinki.fi>
+## Created: 5.5.2000
+## Keywords: image processing median filtering
+
+%!test
+%! b = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];
+%! assert(medfilt2(b),[0,1,2,0;1,4,12,3;4,12,20,12;0,7,20,0]);
+
+function retval = medfilt2(A, varargin)
+
+padding = "zeros";
+domain = logical(ones(3,3));
+
+for i=1:length(varargin)
+  a = varargin{i};
+  if(ischar(a))
+    padding = a;
+  elseif(isvector(a) && size(a) == [1, 2])
+    domain = logical(ones(a(2), a(1)));
+  elseif(is_matrix(a))
+    domain = logical(a);
+  endif
+endfor
+
+n = sum(sum(domain));
+if((n - 2*floor(n/2)) == 0) % n even - more work
+  nth = floor(n/2);
+  a = ordfilt2(A, nth, domain, padding);
+  b = ordfilt2(A, nth + 1, domain, padding);
+  retval = (a + b)./2;
+else
+  nth = floor(n/2) + 1;
+  retval = ordfilt2(A, nth, domain, padding);
+endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/nlfilter.m
@@ -0,0 +1,170 @@
+## 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} = } nlfilter (@var{A}, [@var{m},@var{n}], @var{fun})
+## @deftypefnx {Function File} {@var{B} = } nlfilter (@var{A}, [@var{m},@var{n}], @var{fun}, ...)
+## @deftypefnx {Function File} {@var{B} = } nlfilter (@var{A},'indexed', ...)
+## Processes image in sliding blocks using user-supplied function
+##
+## @code{B=nlfilter(A,[m,n],fun)} passes sliding @var{m}-by-@var{n}
+## blocks to user-supplied function @var{fun}. A block is build for
+## every pixel in @var{A}, such as it is centered within the block.
+## @var{fun} must return a scalar, and it is used to create matrix
+## @var{B}. @var{nlfilter} pads the @var{m}-by-@var{n} block at the
+## edges if necessary.
+## 
+## Center of block is taken at ceil([@var{m},@var{n}]/2).
+##
+## @code{B=nlfilter(A,[m,n],fun,...)} behaves as described above but
+## passes extra parameters to function @var{fun}.
+##
+## @code{B=nlfilter(A,'indexed',...)} assumes that @var{A} is an indexed
+## image, so it pads the image using proper value: 0 for uint8 and
+## uint16 images and 1 for double images. Keep in mind that if 'indexed'
+## is not specified padding is always done using 0.
+##
+## @end deftypefn
+## @seealso{colfilt,blkproc,inline}
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function B = nlfilter(A, varargin)
+  if(nargin<3)
+    error("nlfilter: invalid number of parameters.");
+  endif
+  
+  ## check 'indexed' presence
+  indexed=false;
+  p=1;
+  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
+    indexed=true;
+    p+=1;
+    if(isa(A,"uint8") || isa(A,"uint16"))
+	padval=0;
+    else
+      padval=1; 
+    endif
+  else
+    padval=0;
+  endif
+
+  ## check [m,n]
+  if(!isvector(varargin{p}))
+    error("nlfilter: expected [m,n] but param is not a vector.");
+  endif
+  if(length(varargin{p})!=2)
+    error("nlfilter: expected [m,n] but param has wrong length.");
+  endif
+  sblk=varargin{p}(:);
+  p+=1;
+
+  ## check fun
+  ## TODO: add proper checks for this one
+  if(nargin<p)
+    error("nlfilter: required parameters haven't been supplied.");
+  endif
+  fun=varargin{p};
+  
+  ## remaining params are params to fun
+  ## extra params are p+1:nargin-1
+
+  ## We take an easy approach... feel free to optimize it (coding this
+  ## in C++ would be a great idea).
+  
+  ## Calculate center of block
+  c=ceil(sblk/2);
+  
+  ## Pre-padding
+  prepad=c-ones(2,1);
+  
+  ## Post-padding
+  postpad=sblk-c;
+  
+  ## Save A size
+  as=size(A);
+
+  ## Pad data
+  if(all(prepad==postpad))
+    if(any(prepad>0))
+      A=padarray(A,prepad,padval,'both');
+    endif
+  else
+    if(any(prepad>0))
+      A=padarray(A,prepad,padval,'pre');
+    endif
+    if(any(postpad>0))
+      A=padarray(A,postpad,padval,'post');
+    endif
+  endif
+
+  ## calc end offsets
+  me=postpad(1)+prepad(1);
+  ne=postpad(2)+prepad(2);
+	
+  ## We concatenate everything to preserve fun return type
+  for i=1:as(1)
+    r=feval(fun,A(i:i+me,1:1+ne),varargin{p+1:nargin-1});
+    for j=2:as(2)
+      r=horzcat(r,feval(fun,A(i:i+me,j:j+ne),varargin{p+1:nargin-1}));
+    endfor
+    if(i==1)
+      B=r;
+    else
+      B=vertcat(B,r);
+    endif
+  endfor
+
+endfunction
+
+%!demo
+%! nlfilter(eye(10),[3,3],inline("any(x(:)>0)","x"))
+%! # creates a "wide" diagonal	
+
+%!assert(nlfilter(eye(4),[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
+%!assert(nlfilter(eye(4),'indexed',[2,3],inline("sum(x(:))","x")),[4,2,1,2;3,2,2,3;2,1,2,4;4,3,4,5]);
+%!assert(nlfilter(eye(4),'indexed',[2,3],inline("sum(x(:))==y","x","y"),2),[0,1,0,1;0,1,1,0;1,0,1,0;0,0,0,0]!=0);
+
+% Check uint8 and uint16 padding
+%!assert(nlfilter(uint8(eye(4)),'indexed',[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
+%!assert(nlfilter(uint16(eye(4)),'indexed',[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
+
+% Check if function class is preserved
+%!assert(nlfilter(uint8(eye(4)),'indexed',[2,3],inline("int8(sum(x(:)))","x")),int8([2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]));
+
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.5  2005/09/08 02:00:17  pkienzle
+% [for Bill Denney] isstr -> ischar
+%
+% Revision 1.4  2004/11/15 16:04:20  pkienzle
+% Fix tests for functions which return boolean matrices
+%
+% Revision 1.3  2004/09/03 13:28:32  jmones
+% Corrected behaviour for int* and uint* types
+%
+% Revision 1.2  2004/08/15 19:43:11  jmones
+% corrected a typo in doc
+%
+% Revision 1.1  2004/08/15 19:42:14  jmones
+% nlfilter: Processes image in siliding blocks using user-supplied function
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/ordfilt2.m
@@ -0,0 +1,72 @@
+## 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} {} ordfilt2(@var{A}, @var{nth}, @var{domain}, [@var{S}, @var{padding}])
+## Two dimensional ordered filtering.
+##
+## Ordered filter replaces an element of @var{A} with the @var{nth} 
+## element of the sorted set of neighbours defined by the logical 
+## (boolean) matrix @var{domain}.
+## Neighbour elements are selected to the sort if the corresponding 
+## element in the @var{domain} matrix is true.
+## 
+## The optional variable @var{S} is a matrix of size(@var{domain}). 
+## Values of @var{S} corresponding to nonzero values of domain are 
+## added to values obtained from @var{A} when doing the sorting.
+##
+## Optional variable @var{padding} determines how the matrix @var{A} 
+## is padded from the edges. See impad for details.
+## 
+## @end deftypefn
+## @seealso{medfilt2}
+
+
+## Author: Teemu Ikonen <tpikonen@pcu.helsinki.fi>
+## Created: 5.5.2000
+## Keywords: image processing filtering
+
+function retval = ordfilt2(A, nth, domain, varargin)
+
+S = zeros(size(domain));
+padding = "zeros";
+for i=1:length(varargin)
+  a = varargin{:};
+  if(ischar(a))
+    padding = a;
+  elseif(is_matrix(a) && size(a) == size(domain))
+    S = a;
+  endif
+endfor
+
+if(!islogical(domain))
+  %  warning("domain should be a boolean matrix, converting");
+  domain = logical(domain);
+endif;
+
+xpad(1) = floor((size(domain, 2)+1)/2) - 1;
+xpad(2) = size(domain,2) - xpad(1) - 1;
+ypad(1) = floor((size(domain, 1)+1)/2) - 1;
+ypad(2) = size(domain,1) - ypad(1) - 1;
+
+if(ypad(1) >= size(A,1) || xpad(1) >= size(A,2))
+  error("domain matrix too large");
+endif;
+
+A = impad(A, xpad, ypad, padding);
+retval = cordflt2(A, nth, domain, S);
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/padarray.m
@@ -0,0 +1,365 @@
+## 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
+
+  ## Assure padsize is a row vector
+  padsize=padsize(:).';
+
+  # 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 (ischar(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,class(A));       ## class(pad) = class(A)
+	else
+	  pad=padval*ones(ps,class(A)); ## class(pad) = class(A)
+	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)]);
+
+% Test padding on 3D array
+%!test
+%! int8(0); % fail for octave <= 2.1.57 without crashing
+%! assert(padarray([1,2,3;4,5,6],[3,2,1]), cat(3, 			\
+%! 	zeros(8,7),							\
+%! 	[zeros(3,7); [zeros(2,2), [1,2,3;4,5,6], zeros(2,2)]; zeros(3,7)], \
+%! 	zeros(8,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 vertical padsize
+%!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));
+
+% Repeat some tests with int* uint* class types
+%!assert(padarray(int8([1;2]),[1]), int8([0;1;2;0]));
+%!assert(padarray(uint8([3,4]),[0,2]), uint8([0,0,3,4,0,0]));
+%!assert(padarray(int16([1;2]),[1],4), int16([4;1;2;4]));
+%!assert(padarray(uint16([1;2]),[1],0), uint16([0;1;2;0]));
+%!assert(padarray(int32([1;2]),[1],int32(4),'pre'), int32([4;1;2]));
+%!assert(padarray(uint32([1;2]),[1],6,'post'), uint32([1;2;6]));
+
+% Test circular padding with int* uint* class types
+%!test
+%! A=int8([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 with int* uint* class types
+%!test
+%! A=uint8([1,2;3,4]);
+%! B=[ones(10,5,"uint8")*1,ones(10,5,"uint8")*2; \
+%!    ones(10,5,"uint8")*3,ones(10,5,"uint8")*4];
+%! 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 with int* uint* class types
+%!test
+%! A=int16([1:3;4:6]);
+%! HA=int16([3:-1:1;6:-1:4]);
+%! VA=int16([4:6;1:3]);
+%! VHA=int16([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  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.6  2005/09/08 02:00:17  pkienzle
+% [for Bill Denney] isstr -> ischar
+%
+% Revision 1.5  2004/09/03 18:33:11  pkienzle
+% skip tests which use cat(3,X,Y) for octave <= 2.1.57
+%
+% Revision 1.4  2004/09/03 13:37:10  jmones
+% Corrected behaviour for int* and uint* types
+%
+% Revision 1.3  2004/08/15 19:21:50  jmones
+% support column vector padsize
+%
+% Revision 1.2  2004/08/11 15:04:59  pkienzle
+% Convert dos line endings to unix line endings
+%
+% Revision 1.1  2004/08/08 21:20:25  jmones
+% uintlut and padarray functions added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/pink.m
@@ -0,0 +1,55 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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} {} pink (@var{n})
+## Create color colormap. 
+## (gives a sephia tone on b/w images)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = pink (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("pink: argument must be a scalar");
+    endif
+  else
+    usage ("pink (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 0];  
+  elseif (number > 1)
+    x = linspace (0, 1, number)';
+    r = (x < 3/8) .* (14/9 * x) + (x >= 3/8) .* (2/3 * x + 1/3);
+    g = (x < 3/8) .* (2/3 * x)\
+      + (x >= 3/8 & x < 3/4) .* (14/9 * x - 1/3)\
+      + (x >= 3/4) .* (2/3 * x + 1/3);
+    b = (x < 3/4) .* (2/3 * x) + (x >= 3/4) .* (2 * x - 1);
+
+    map = sqrt ([r, g, b]);
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/poly2mask.m
@@ -0,0 +1,256 @@
+## 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{BW} = } poly2mask (@var{x},@var{y},@var{m},@var{n})
+## Convert a polygon to a region mask
+##
+## BW=poly2mask(x,y,m,n) converts a polygon, specified by a list of
+## vertices in @var{x} and @var{y} and returns in a @var{m}-by-@var{n}
+## logical mask @var{BW} the filled polygon. Region inside the polygon
+## is set to 1, values outside the shape are set to 0.
+##
+## @var{x} and @var{y} should always represent a closed polygon, first
+## and last points should be coincident. If they are not poly2mask will
+## close it for you. If @var{x} or @var{y} are fractional they are
+## nearest integer.
+##
+## If all the polygon or part of it falls outside the masking area
+## (1:m,1:n), it is discarded or clipped.
+##
+## This function uses scan-line polygon filling algorithm as described
+## in http://www.cs.rit.edu/~icss571/filling/ with some minor
+## modifications: capability of clipping and scan order, which can
+## affect the results of the algorithm (algorithm is described not to
+## reach ymax, xmax border when filling to avoid enlarging shapes). In
+## this function we scan the image backwards (we begin at ymax and end
+## at ymin), and we don't reach ymin, xmin, which we believe should be
+## compatible with MATLAB.
+## @end deftypefn
+
+
+## TODO: check how to create a logical BW without any conversion
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function BW = poly2mask(x, y, m, n)
+  if (nargin!=4)
+    usage("BW = poly2mask(x, y, m, n)");
+  endif
+
+  ## check x and y
+  x=round(x(:)');
+  y=round(y(:)');
+  if(length(x)<3)
+    error("poly2mask: polygon must have at least 3 vertices.");
+  endif
+  if(length(x)!=length(y))
+    error("poly2mask: length of x doesn't match length of y.");
+  endif
+
+  ## create output matrix
+  uint8(0); ## This fails for octave < 2.1.58
+  BW=logical(zeros(m,n,"uint8"));
+
+  ## close polygon if needed
+  if((x(1)!=x(length(x)))||(y(1)!=y(length(y))))
+    x=horzcat(x,x(1));
+    y=horzcat(y,y(1));
+  endif
+
+  ## build global edge table
+  ex=[x(1:length(x)-1);x(1,2:length(x))]; ## x values for each edge
+  ey=[y(1:length(y)-1);y(1,2:length(y))]; ## y values for each edge
+  idx=find(ey(1,:)!=ey(2,:));             ## eliminate horizontal edges
+  ex=ex(:,idx);
+  ey=ey(:,idx);
+  eminy=min(ey);                          ## minimum y for each edge
+  emaxy=max(ey);                          ## maximum y for each edge
+  t=ey==[eminy;eminy];                    ## values associated to miny
+  exminy=ex(:)(find(t));                  ## x values associated to min y
+  exmaxy=ex(:)(find(!t));                 ## x values associated to max y
+  emaxy=emaxy';                           ## we want them vertical now...
+  eminy=eminy';
+  m_inv=(exmaxy-exminy)./(emaxy-eminy);   ## calculate inverse slope
+  ge=[emaxy, eminy, exmaxy, m_inv];       ## build global edge table
+  ge=sortrows(ge,[1,3]);                  ## sort on eminy and exminy
+
+  ## we add an extra dummy edge at the end just to avoid checking
+  ## while indexing it
+  ge=[-Inf,-Inf,-Inf,-Inf;ge];
+
+  ## initial parity is even (0)
+  parity=0;
+
+  ## init scan line set to bottom line
+  sl=ge(size(ge,1),1);
+
+  ## init active edge table
+  ## we use a loop because the table is sorted and edge list could be
+  ## huge
+  ae=[];
+  gei=size(ge,1);
+  while sl==ge(gei,1)
+    ae=[ge(gei,2:4);ae];
+    gei-=1;
+  endwhile
+
+  ## calc minimum y to draw
+  miny=min(y);
+  if (miny<1)
+    miny=1;
+  endif
+
+  while sl>=miny
+    ## check vert clipping
+    if(sl<=m)
+      ## draw current scan line
+      ## we have to round because 1/m is fractional
+      ie=round(reshape(ae(:,2),2,size(ae)/2));
+
+      ## this discards left border of image (this differs from version at
+      ## http://www.cs.rit.edu/~icss571/filling/ which discards right
+      ## border) but keeps an exception when the point is a vertex.
+      ie(1,:)+=ie(1,:)!=ie(2,:);
+
+      ## we'll clip too, just in case m,n is not big enough
+      ie(1,find(ie(1,:)<1))=1;
+      ie(2,find(ie(2,:)>n))=n;
+
+      ## we eliminate segments outside window
+      ie=ie(:,find(ie(1,:)<=n));
+      ie=ie(:,find(ie(2,:)>=1));
+      for i=1:columns(ie)
+	BW(sl,ie(1,i):ie(2,i))=true;
+      endfor
+    endif
+
+    ## decrement scan line
+    sl-=1;
+
+    ## eliminate edges that eymax==sl
+    ## this discards ymin border of image (this differs from version at
+    ## http://www.cs.rit.edu/~icss571/filling/ which discards ymax).
+    ae=ae(find(ae(:,1)!=sl),:);
+
+    ## update x (x1=x0-1/m)
+    ae(:,2)-=ae(:,3);
+
+    ## update ae with new values
+    while sl==ge(gei,1)
+      ae=vertcat(ae,ge(gei,2:4));
+      gei-=1;
+    endwhile
+
+    ## order the edges in ae by x value
+    if(rows(ae)>0)
+      ae=sortrows(ae,2);
+    endif
+  endwhile
+endfunction
+
+
+%!demo
+%! s=[0:pi/4:2*pi];
+%! x=cos(s)*90+101;
+%! y=sin(s)*90+101;
+%! bw=poly2mask(x,y,200,200);
+%! imshow(bw);
+%! %Creates a filled octagon
+
+%!demo
+%! s=[0:2*pi/5:pi*4];
+%! s=s([1,3,5,2,4,6]);
+%! x=cos(s)*90+101;
+%! y=sin(s)*90+101;
+%! bw=poly2mask(x,y,200,200);
+%! imshow(bw);
+%! %Creates a 5-vertex star
+
+%!# Convex polygons
+
+%!shared xs, ys, Rs, xt, yt, Rt
+%! xs=[3,3,10,10];
+%! ys=[4,12,12,4];
+%! Rs=zeros(16,14);
+%! Rs(5:12,4:10)=1;
+%! Rs=logical(Rs);
+%! xt=[1,4,7];
+%! yt=[1,4,1];
+%! Rt=[0,0,0,0,0,0,0;
+%!     0,0,1,1,1,1,0;
+%!     0,0,0,1,1,0,0;
+%!     0,0,0,1,0,0,0;
+%!     0,0,0,0,0,0,0];
+%! Rt=logical(Rt);
+
+%!assert(poly2mask(xs,ys,16,14),Rs);          # rectangle
+%!assert(poly2mask(xs,ys,8,7),Rs(1:8,1:7));   # clipped
+%!assert(poly2mask(xs-7,ys-8,8,7),Rs(9:16,8:14)); # more clipping
+
+%!assert(poly2mask(xt,yt,5,7),Rt);            # triangle
+%!assert(poly2mask(xt,yt,3,3),Rt(1:3,1:3));   # clipped
+
+
+%!# Concave polygons
+
+%!test
+%! x=[3,3,5,5,8,8,10,10];
+%! y=[4,12,12,8,8,11,11,4];
+%! R=zeros(16,14);
+%! R(5:12,4:5)=1;
+%! R(5:8,6:8)=1;
+%! R(5:11,9:10)=1;
+%! R=logical(R);
+%! assert(poly2mask(x,y,16,14), R);
+
+%!# Complex polygons
+%!test
+%! x=[1,5,1,5];
+%! y=[1,1,4,4];
+%! R=[0,0,0,0,0,0;
+%!    0,0,1,1,0,0;
+%!    0,0,1,1,0,0;
+%!    0,1,1,1,1,0;
+%!    0,0,0,0,0,0];
+%! R=logical(R);
+%! assert(poly2mask(x,y,5,6), R);
+
+
+
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.5  2004/09/07 14:47:50  pkienzle
+% Avoid segfaults on pre-2.1.58 octave.  Invisible whitespace changes.
+%
+% Revision 1.4  2004/09/03 17:12:36  jmones
+% Uses uint8 to save some temporal memory (suggested by David Bateman)
+%
+% Revision 1.3  2004/09/03 13:32:07  jmones
+% Work with logical arrays from BW creation
+%
+% Revision 1.2  2004/08/11 17:39:51  jmones
+% Algorithm url in docs corrected.
+%
+% Revision 1.1  2004/08/11 17:34:11  jmones
+% poly2mask added: creates filled polygon bw mask
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/prism.m
@@ -0,0 +1,48 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} prism (@var{n})
+## Create color colormap. 
+## (cycling trough red, orange, yellow, green, blue and violet)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = prism (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("prism: argument must be a scalar");
+    endif
+  else
+    usage ("prism (number)");
+  endif
+
+  p = [1, 0, 0; 1, 1/2, 0; 1, 1, 0; 0, 1, 0; 0, 0, 1; 2/3, 0, 1];
+
+  if (rem (number, 6) == 0)
+    map = kron(ones (fix (number / 6), 1), p);
+  else
+    map = [kron(ones (fix (number / 6), 1), p); p(1:rem (number, 6), :)];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/qtdecomp.m
@@ -0,0 +1,331 @@
+## 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{S} = } qtdecomp (@var{I})
+## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold})
+## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{mindim})
+## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{[mindim maxdim]})
+## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun})
+## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun},@var{P1},@var{P2},...)
+## Performs quadtree decomposition
+##
+## qtdecomp decomposes a square image @var{I} into four equal-sized
+## blocks. Then it performs some kind of test on each block to decide if
+## it should decompose them further. This process is repeated
+## iteratively until there's no block left to be decomposed.
+##
+## Note that blocks are not decomposed if their dimensions are not even.
+##
+## The output is a sparse matrix whose non-zero elements determine the
+## position of the block (the element is at top-left position in the
+## block) and size of each block (the value of the element determines
+## length of a side of the square-shaped block).
+##
+## S = qtdecomp(I) decomposes an intensity image @var{I} as described
+## above. By default it doesn't split a block if all elements are equal.
+##
+## S = qtdecomp(I, threshold) decomposes an image as decribed, but only
+## splits a block if the maximum value in the block minus the minimum
+## value is greater than @var{threshold}, which is a value between 0 and
+## 1. If @var{I} is of class uint8, @var{threshold} is multiplied by 255
+## before use. Also, if@var{I} is of class uint16, @var{threshold} is 
+## multiplied by 65535.
+##
+## S = qtdecomp(I, threshold, mindim) decomposes an image using the
+## @var{threshold} as just described, but doesn't produce blocks smaller
+## than mindim.
+##
+## S = qtdecomp(I, threshold, [mindim maxdim]) decomposes an image as
+## described, but produces blocks that can't be bigger than maxdim. It
+## decomposes to maxdim even if it isn't needed if only @var{threshold}
+## was considered.
+##
+## S = qtdecomp(I, fun) decomposes an image @var{I} and uses function
+## @var{fun} to decide if a block should be splitted or not. @var{fun}
+## is called with a m-by-m-by-k  array of m-by-m blocks to be
+## considered, and should return a vector of size k, whose elements
+## represent each block in the stacked array. @var{fun} sets the
+## corresponding value to 1 if the block should be split, and 0
+## otherwise.
+##
+## S = qtdecomp(I, fun, ...) behaves as qtdecomp(I, fun) but passes
+## extra parameters to @var{fun}.
+##
+## @end deftypefn
+## @seealso qtgetblk, qtsetblk
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function S = qtdecomp(I, p1, varargin)
+  if (nargin<1)
+    usage("S=qtdecomp(I)");
+  endif
+  
+  if (!ismatrix(I) || size(I,1)!=size(I,2))
+    error("qtdecomp: I should be a square matrix.");
+  endif
+
+  ## current size (assumed to be square)
+  curr_size=size(I,1);
+
+  ## initial mindim to a sensible value
+  mindim=1;
+ 
+  ## sensible default maxdim value
+  maxdim=curr_size;
+
+  if (nargin<2)
+    ## Initialize decision method variable
+    ## We could have implemented threshold as a function and use an
+    ## uniform interface (function handle) to decide whether to split or
+    ## not blocks. We have decided not to do so because block
+    ## rearrangement that is needed as a parameter to functions is
+    ## expensive.
+    decision_method=0;
+  elseif (isreal(p1))
+    ## p1 is threshold
+    threshold=p1;
+    decision_method=1;
+
+    if(strcmp(typeinfo(I), 'uint8 matrix'))
+      threshold*=255;
+    elseif(strcmp(typeinfo(I), 'uint16 matrix'))
+      threshold*=65535;
+    endif
+
+    if (nargin>3)
+      usage("S=qtdecomp(I,threshold,mindim),        \
+	  S=qtdecomp(I,threshold,[mindim maxdim])");
+    elseif (nargin==3)
+      dims=varargin{1};
+      if (isvector(dims)&&length(dims)==2)
+	mindim=dims(1);
+	maxdim=dims(2);
+      elseif (isreal(dims))
+	mindim=dims;
+      else
+	error("qtdecomp: third parameter must be 'mindim' or '[mindim maxdim]'");
+      endif
+      ## we won't check if mindim or maxdim are powers of 2. It's too
+      ## restrictive and don't need it at all.
+    endif
+    
+  elseif strcmp(typeinfo(p1),"function handle") ...
+  	  || strcmp(typeinfo(p1),"inline function")
+    ## function handles seem to return true to isscalar
+    fun=p1;
+    decision_method=2;
+  else
+    error("qtdecomp: second parameter must be a integer (threshold) or a function handle (fun).");
+  endif
+  
+  ## initialize results matrices
+  res=[];
+
+  ## bool to flag end
+  finished=false;
+
+  ## array of offsets to blocks to evaluate
+  offsets=[1,1];
+
+  if (maxdim<mindim)
+    error("qtdecomp: mindim must be smaller than maxdim.");
+  endif
+
+  ## See if we have to split a minimum regarless other considerations.
+  if (maxdim<curr_size)
+    initial_splits=ceil(log2(curr_size/maxdim));
+    if(initial_splits>0)
+      divs=2^initial_splits;
+      if (rem(curr_size,divs)!=0)
+	error("qtdecomp: Can't decompose I enough times to fulfill maxdim requirement.");
+      endif
+      ## update curr_size
+      curr_size/=divs;
+      if(curr_size<mindim)
+	error("qtdecomp: maxdim restriction collides with mindim restriction.");
+      endif
+      els=transpose([0:divs-1]*curr_size+1);
+      offsets=[kron(els,ones(divs,1)), kron(ones(divs,1),els)];
+    endif
+  endif
+
+  while(!finished && rows(offsets)>0)
+    ## check other ending conditions:
+    ## is size is odd?
+    ## is splitted size < than mindim?
+    if ((rem(curr_size,2)!=0)||((curr_size/2)<mindim))
+      ## can't continue, lets add current evaluation blocks to results
+      res=[res; offsets, ones(size(offsets,1),1)*curr_size];
+      finished = true;
+    else
+      if (decision_method<2)
+	db=logical(ones(rows(offsets),1));
+	for r=1:rows(offsets)
+	  o=offsets(r,:);
+	  fo=offsets(r,:)+curr_size-1;
+
+	  if(decision_method==0)
+	    ## is everything equal?
+	    if (all(I(o(1),o(2))==I(o(1):fo(1),o(2):fo(2))))
+	      db(r)=0;
+	    endif
+	  else
+	    ## check threshold
+	    t=I(o(1):fo(1),o(2):fo(2));
+	    t=t(:);
+	    if ((max(t)-min(t))<=threshold)
+	      db(r)=0;
+	    endif
+	  endif
+	endfor
+      elseif(decision_method==2)
+	## function handle decision method
+	## build blocks
+	b=zeros(curr_size,curr_size,rows(offsets));
+	rbc=offsets(:,1:2)+curr_size-1;
+	for r=1:rows(offsets)
+	  b(:,:,r)=I(offsets(r,1):rbc(r,1),offsets(r,2):rbc(r,2));
+	endfor
+
+	db=feval(fun, b, varargin{:});
+      else
+	error("qtdecomp: execution shouldn't reach here. Please report this as a bug.");
+      endif
+
+      ## Add blocks that won't divide to results
+      nd=offsets(find(!db),:);
+      res=[res; nd, ones(size(nd,1),1)*curr_size];
+      
+      ## Update curr_size for next iteration
+      curr_size/=2;
+      
+      ## Prepare offsets for next iteration
+      otemp=offsets(find(db),:);
+      hs=ones(rows(otemp),1)*curr_size;
+      zs=zeros(size(hs));
+      offsets=[otemp;otemp+[hs,zs];otemp+[zs,hs];otemp+[hs,hs]];
+    endif
+  endwhile
+
+  S=sparse(res(:,1),res(:,2),res(:,3),size(I,1),size(I,2));
+endfunction
+
+
+%!demo
+%! full(qtdecomp(eye(8)))
+%! %It finds 2 big blocks of 0 and it decomposes further where 0 and 1 are mixed.
+
+
+%!# Test if odd-sized limits split
+%!assert(full(qtdecomp(eye(5))), reshape([5,zeros(1,24)],5,5));
+%!assert(full(qtdecomp(eye(6))), repmat(reshape([3,zeros(1,8)],3,3),2,2));
+
+%!# Test 'equal' method
+%!test
+%! a=ones(2,2);
+%! b=[2,0;0,0];
+%! assert(full(qtdecomp(eye(4))), [a,b;b,a]);
+
+%!shared A, B2, B4
+%! A=[ 1, 4, 2, 5,54,55,61,62;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!    23,42,42,42,99,99,99,99;    
+%!    27,42,42,42,99,99,99,99;    
+%!    23,22,26,25,99,99,99,99;    
+%!    22,22,24,22,99,99,99,99];
+%! B2=[2,0;0,0];
+%! B4=zeros(4); B4(1,1)=4;
+
+%!test
+%! R=[ones(4,8); [ones(2),B2;ones(2,4)], B4];
+%! assert(full(qtdecomp(A)), R);
+%! assert(full(qtdecomp(A,0)), R);
+
+%!# Test 'threshold' method
+%!test
+%! R=[ones(4,8); [ones(2),B2;B2,ones(2)],B4];
+%! assert(full(qtdecomp(A,1)), R);
+
+%!test
+%! R=[[B4,[B2,B2;B2,B2]]; [[ones(2),B2;B2,B2],B4]];
+%! assert(full(qtdecomp(A,10)), R);
+
+%!test
+%! R=[[B4,[B2,B2;B2,B2]]; [[B2,B2;B2,B2],B4]];
+%! assert(full(qtdecomp(A,10,2)), R);
+
+%!assert(full(qtdecomp(A,100,[2, 4])), [B4,B4;B4,B4]);
+
+%!# Test 'fun' method
+%!# Can't define a function inside tests because Octave
+%!# complains about nested functions. If you know how to
+%!# do it please add function handle tests.
+
+%!# inline version
+%!# We use [size(A),1](3) as a trick since size(A,3) fails if A is 2D.
+
+%!# no params
+%!test
+%! first_eq=inline("(A(1,1,:)!=(54*ones(1,1,[size(A),1](3))))(:)","A");
+%! assert(full(qtdecomp(A,first_eq)),[ones(4),B4;ones(4,8)]); 
+
+%!# 1 param
+%!test
+%! first_eq=inline("(A(1,1,:)!=(c*ones(1,1,[size(A),1](3))))(:)","A","c");
+%! assert(full(qtdecomp(A,first_eq,54)),[ones(4),B4;ones(4,8)]); 
+
+%!# 3 params
+%!test
+%! first_eq=inline("(A(1,1,:)!=((c1+c2+c3)*ones(1,1,[size(A),1](3))))(:)","A","c1","c2","c3");
+%! assert(full(qtdecomp(A,first_eq,4,40,10)),[ones(4),B4;ones(4,8)]); 
+
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.8  2006/01/03 02:09:15  pkienzle
+% Reorder tests so that shared variables are displayed unless relevant.
+%
+% Revision 1.7  2006/01/02 22:05:06  pkienzle
+% Reduce number of shared variables in tests
+%
+% Revision 1.6  2004/09/09 19:36:35  jmones
+% all_va_args -> varargin{:}. Now works on 2.1.58
+%
+% Revision 1.5  2004/09/08 14:07:22  pkienzle
+% Fix test for 'inline function'
+%
+% Revision 1.4  2004/08/11 19:52:41  jmones
+% qtsetblk added
+%
+% Revision 1.3  2004/08/11 00:05:21  jmones
+% seealso qtgetblk added to doc
+%
+% Revision 1.2  2004/08/10 00:19:42  jmones
+% Corrected misleading comment.
+%
+% Revision 1.1  2004/08/09 01:48:54  jmones
+% Added qtdecomp: quadtree decomposition
+%
+%
+
new file mode 100644
--- /dev/null
+++ b/inst/qtgetblk.m
@@ -0,0 +1,154 @@
+## 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{vals}] = } qtgetblk (@var{I},@var{S},@var{dim})
+## @deftypefnx {Function File} {[@var{vals},@var{idx}] = } qtgetblk (@var{I},@var{S},@var{dim})
+## @deftypefnx {Function File} {[@var{vals},@var{r},@var{c}] = } qtgetblk (@var{I},@var{S},@var{dim})
+## Obtain block values from a quadtree decomposition
+##
+## [vals]=qtgetblk(I,S,dim) returns a dim-by-dim-by-k array in
+## @var{vals} which contains the dim-by-dim blocks in the quadtree
+## decomposition (@var{S}, which is returned by qtdecomp) of @var{I}. If
+## there are no blocks, an empty matrix is returned.
+##
+## [vals,idx]=qtgetblk(I,S,dim) returns @var{vals} as described above.
+## In addition, it returns @var{idx}, a vector which contains the linear
+## indices of the upper left corner of each block returned (the same
+## result as find(full(S)==dim)).
+##
+## [vals,r,c]=qtgetblk(I,S,dim) returns @var{vals} as described, and two
+## vectors, @var{r} and @var{c}, which contain the row and column
+## coordinates of the blocks returned.
+##
+## @end deftypefn
+## @seealso qtdecomp, qtsetblk
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function [varargout] = qtgetblk(I, S, dim)
+  if (nargin!=3)
+    usage("[vals,r,c]=qtgetblk(I,S,dim), [vals,idx]=qtgetblk(I,S,dim)");
+  endif
+  if (nargout>3)
+    usage("[vals,r,c]=qtgetblk(I,S,dim), [vals,idx]=qtgetblk(I,S,dim)");
+  endif
+
+  ## get blocks
+  [i,j,v]=spfind(S);
+
+  ## filter the ones which match dim
+  idx=find(v==dim);
+  
+  if(length(idx)==0)
+    for i=1:nargout
+      varargout{i}=[];
+    endfor
+  else
+    r=i(idx);
+    c=j(idx);
+    
+    ## copy to a dim-by-dim-by-k array
+    vals=zeros(dim,dim,length(idx));
+    for i=1:length(idx)
+      vals(:,:,i)=I(r(i):r(i)+dim-1,c(i):c(i)+dim-1);
+    endfor
+    
+    varargout{1}=vals;
+  
+    if(nargout==3)
+      varargout{2}=r;
+      varargout{3}=c;
+    elseif(nargout==2)
+      varargout{2}=(c-1)*rows(I)+r;
+    endif
+  endif
+endfunction
+
+
+%!demo
+%! [vals,r,c]=qtgetblk(eye(4),qtdecomp(eye(4)),2)
+%! % Returns 2 blocks, at [1,3] and [3,1] (2*2 zeros blocks)
+
+%!shared A,S
+%! A=[ 1, 4, 2, 5,54,55,61,62;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!    23,42,42,42,99,99,99,99;    
+%!    27,42,42,42,99,99,99,99;    
+%!    23,22,26,25,99,99,99,99;    
+%!    22,22,24,22,99,99,99,99];
+%! S=qtdecomp(A,10);
+
+%!test
+%! [va]=qtgetblk(A,S,8);
+%! [vb,r,c]=qtgetblk(A,S,8);
+%! [vc,i]=qtgetblk(A,S,8);
+%! assert(va, vb);
+%! assert(va, vc);
+%! assert(i,[]);
+%! assert(r,[]);
+%! assert(c,[]);
+%! R=[];
+%! assert(va,R);
+
+
+%!test
+%! [va]=qtgetblk(A,S,4);
+%! [vb,r,c]=qtgetblk(A,S,4);
+%! [vc,i]=qtgetblk(A,S,4);
+%! assert(va, vb);
+%! assert(va, vc);
+%! assert(i, find(full(S)==4));
+%! assert(r,[1;5]);
+%! assert(c,[1;5]);
+%! R=zeros(4,4,2);
+%! R(:,:,1)=A(1:4,1:4);
+%! R(:,:,2)=A(5:8,5:8);
+%! assert(va,R);
+
+%!test
+%! [va]=qtgetblk(A,S,2);
+%! [vb,r,c]=qtgetblk(A,S,2);
+%! [vc,i]=qtgetblk(A,S,2);
+%! assert(va, vb);
+%! assert(va, vc);
+%! assert(i, find(full(S)==2));
+%! assert(r,[7;5;7;1;3;1;3]);
+%! assert(c,[1;3;3;5;5;7;7]);
+%! R=zeros(2,2,7);
+%! R(:,:,1)=A(7:8,1:2);
+%! R(:,:,2)=A(5:6,3:4);
+%! R(:,:,3)=A(7:8,3:4);
+%! R(:,:,4)=A(1:2,5:6);
+%! R(:,:,5)=A(3:4,5:6);
+%! R(:,:,6)=A(1:2,7:8);
+%! R(:,:,7)=A(3:4,7:8);
+%! assert(va,R);
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.3  2006/01/02 20:53:42  pkienzle
+% Reduce number of shared variables in tests
+%
+% Revision 1.2  2004/08/11 19:52:41  jmones
+% qtsetblk added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/qtsetblk.m
@@ -0,0 +1,105 @@
+## 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{J} = } qtsetblk (@var{I},@var{S},@var{dim},@var{vals})
+## Set block values in a quadtree decomposition
+##
+## J=qtsetblk(I,S,dim,vals) sets all the @var{dim}-by-@var{dim} blocks
+## in the quadtree decomposition (@var{S} returned by qtdecomp) of
+## @var{I} to @var{dim}-by-@var{dim} blocks in @var{vals}, which is
+## itself a @var{dim}-by-@var{dim}-by-k array. k is the number of
+## @var{dim}-by-@var{dim} blocks in the quadtree decomposition.
+## @end deftypefn
+## @seealso qtdecomp, qtgetblk
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function J = qtsetblk(I, S, dim, vals)
+  if (nargin!=4)
+    usage("J=qtsetblk(I,S,dim,vals)");
+  endif
+
+  ## get blocks
+  [ii,ji,v]=spfind(S);
+
+  ## filter the ones which match dim
+  idx=find(v==dim);
+  if(size(vals,3)<length(idx)) ## we won't complain if k>num blocks
+    error("qtsetblk: k (vals 3rd dimension) is not equal to number of blocks.");
+  endif
+  ii=ii(idx);
+  ji=ji(idx);
+  
+  ## calc end vertex
+  ie=ii+dim-1;
+  je=ji+dim-1;
+
+
+  J=I;
+  for b=1:length(idx)
+    J(ii(b):ie(b),ji(b):je(b))=vals(:,:,b);
+  endfor
+endfunction
+
+
+%!demo
+%! J=qtsetblk(eye(4),qtdecomp(eye(4)),2,ones(2,2,2))
+%! % Sets upper-right and lower-left blocks of 2*2 zeros to ones
+
+%!shared A, S
+%! A=[ 1, 4, 2, 5,54,55,61,62;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!     3, 6, 3, 1,58,53,67,65;
+%!    23,42,42,42,99,99,99,99;    
+%!    27,42,42,42,99,99,99,99;    
+%!    23,22,26,25,99,99,99,99;    
+%!    22,22,24,22,99,99,99,99];
+%! S=qtdecomp(A,10);
+
+%!test
+%! R=A;
+%! vals=zeros(4,4,2);
+%! vals(:,:,1)=reshape([1:16],4,4);
+%! vals(:,:,2)=reshape([21:36],4,4);
+%! R(1:4,1:4)=reshape([1:16],4,4);
+%! R(5:8,5:8)=reshape([21:36],4,4);
+%! assert(qtsetblk(A,S,4,vals),R);
+
+%!test
+%! R=A;
+%! R(1:4,5:8)=1;
+%! R(7:8,1:4)=1;
+%! R(5:6,3:4)=1;
+%! assert(qtsetblk(A,S,2,ones(2,2,7)),R);
+
+%!test
+%! R=A;
+%! R(5:6,1:2)=10;
+%! assert(qtsetblk(A,S,1,ones(1,1,4)*10),R);
+
+
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.1  2004/08/11 19:52:41  jmones
+% qtsetblk added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/rainbow.m
@@ -0,0 +1,56 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} rainbow (@var{n})
+## Create color colormap. 
+## (red through orange, yellow, green, blue to violet)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = rainbow (number)
+## this colormap is not part of matlab, it is like the prism
+## colormap map but with a continuous map
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("rainbow: argument must be a scalar");
+    endif
+  else
+    usage ("rainbow (number)");
+  endif
+
+  if (number == 1)
+    map = [1, 0, 0];  
+  elseif (number > 1)
+    x = linspace (0, 1, number)';
+    r = (x < 2/5) + (x >= 2/5 & x < 3/5) .* (-5 * x + 3)\
+      + (x >= 4/5) .* (10/3 * x - 8/3);
+    g = (x < 2/5) .* (5/2 * x) + (x >= 2/5 & x < 3/5)\
+      + (x >= 3/5 & x < 4/5) .* (-5 * x + 4);
+    b = (x >= 3/5 & x < 4/5) .* (5 * x - 3) + (x >= 4/5);
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/rgb2gray.m
@@ -0,0 +1,47 @@
+## Copyright (C) 2000, 2001  Kai Habel
+##
+## 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{I}= rgb2gray (@var{M})
+## converts a color map to a gray map. 
+## The RGB map is converted into the YIQ space of ntsc. The luminance
+## value (Y) is taken to create a gray color map.
+## R = G = B = Y
+## @end deftypefn
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	19. March 2000
+
+function graymap = rgb2gray (rgb)
+
+  if (nargin != 1)
+    usage ("graymap = rgb2gray (map)");
+  endif
+
+  msg = "rgb2gray: argument must be a matrix of size n x 3";
+  if (! is_matrix (rgb))
+    error (msg);
+  endif
+
+  nc = columns (rgb);
+  if (nc != 3)
+    error (msg);
+  endif
+
+  ntscmap = rgb2ntsc (rgb);
+
+  graymap = ntscmap (:, 1) * ones (1, 3);
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/roicolor.m
@@ -0,0 +1,77 @@
+## 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{BW} = } roicolor (@var{A},@var{low},@var{high})
+## @deftypefnx {Function File} {@var{BW} = } roicolor (@var{A},@var{v})
+## Select a Region Of Interest of an image based on color.
+##
+## BW = roicolor(A,low,high) selects a region of interest (ROI) of an
+## image @var{A} returning a black and white image in a logical array (1 for
+## pixels inside ROI and 0 outside ROI), which is formed by all pixels
+## whose values lie within the colormap range specified by [@var{low}
+## @var{high}].
+##
+## BW = roicolor(A,v) selects a region of interest (ROI) formed by all
+## pixels that match values in @var{v}.
+## @end deftypefn
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function BW = roicolor(A, p1, p2)
+  if (nargin < 2 || nargin > 3)
+    usage("BW = roicolor(A, low, high), BW = roicolor(A, v)");
+  endif
+
+  if (nargin == 2)
+    if (!isvector(p1))
+      error("BW = roicolor(A, v): v should be a vector.");
+    endif
+    BW=logical(zeros(size(A)));
+    for c=p1
+      BW|=(A==c);
+    endfor
+  elseif (nargin==3)
+    if (!isscalar(p1) || !isscalar(p2))
+      error("BW = roicolor(A, low, high): low and high must be scalars.");
+    endif
+    BW=logical((A>=p1)&(A<=p2));
+  endif
+endfunction
+
+%!demo
+%! roicolor([1:10],2,4);
+%! % Returns '1' where input values are between 2 and 4 (both included).
+
+%!assert(roicolor([1:10],2,4),logical([0,1,1,1,zeros(1,6)]));
+%!assert(roicolor([1,2;3,4],3,3),logical([0,0;1,0]));
+%!assert(roicolor([1,2;3,4],[1,4]),logical([1,0;0,1]));
+
+%
+% $Log$
+% Revision 1.1  2006/08/20 12:59:35  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.3  2004/09/15 17:54:59  pkienzle
+% test that data type matches during assert
+%
+% Revision 1.2  2004/08/11 15:04:59  pkienzle
+% Convert dos line endings to unix line endings
+%
+% Revision 1.1  2004/08/08 21:02:44  jmones
+% Add roicolor function (selects ROI based on color)
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/spring.m
@@ -0,0 +1,51 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} spring (@var{n})
+## Create color colormap. 
+## (magenta to yellow)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = spring (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("spring: argument must be a scalar");
+    endif
+  else
+    usage ("spring (number)");
+  endif
+
+  if (number == 1)
+    map = [1, 0, 1];  
+  elseif (number > 1)
+    r = ones (number, 1);
+    g = (0:number - 1)' ./ (number - 1);
+    b = 1 - g;
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/std2.m
@@ -0,0 +1,38 @@
+## Copyright (C) 2000  Kai Habel
+##
+## 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{s}= std2 (@var{I})
+## returns the standard deviation for a 2d real type matrix.
+## Uses @code{std (I(:))}
+## @end deftypefn
+## @seealso{mean2,std}
+
+## Author:	Kai Habel <kai.habel@gmx.de>
+## Date:	01/08/2000
+
+function s = std2 (I)
+
+  if !(nargin == 1)
+    usage ("std2(I)");
+  endif
+
+  if !(is_matrix(I) && isreal(I))
+	error("argument must be a real type matrix");
+  endif
+
+  s = std (I(:));
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/stretchlim.m
@@ -0,0 +1,209 @@
+## 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{LOW_HIGH} = } stretchlim (@var{I},@var{TOL})
+## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{I})
+## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{RGB},@var{TOL})
+## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{RGB})
+## Finds limits to contrast stretch an image
+##
+## @code{LOW_HIGH=stretchlim(I,TOL)} returns a vector @var{LOW_HIGH}
+## which contains a pair of intensities which can be used in
+## @code{imadjust} to stretch the contrast of an image, first of them
+## will be lower value (@code{imadjust} would assign 0 to it) and second
+## is the upper bound. @var{TOL} specifies the fraction of the image to
+## saturate at lower and upper limits. It can be a vector of length 2:
+## @code{[LOW_FRACT, HIGH_FRACT]}, or it can be a scalar, in that case
+## @code{[LOW_FRACT, HIGH_FRACT]=[TOL, 1-TOL]}.
+##
+## @var{TOL} can't be larger than 0.50 and for TOL=0 then
+## @code{LOW_HIGH=[min(I(:)), max(I(:))]}.
+##
+## @code{LOW_HIGH=stretchlim(I)} behaves as described but defaults
+## @var{TOL} to @code{[0.01, 0.99]}.
+##
+## @code{LOW_HIGH=stretchlim(RGB,TOL)} returns a 2-by-3 matrix in
+## @var{LOW_HIGH} of lower and upper values to saturate for each plane
+## of the RGB image in M-by-N-by-3 array @var{RGB}. @var{TOL} is a
+## vector or a scalar, as described above, and the same fractions are
+## applied for each plane.
+##
+## @code{LOW_HIGH=stretchlim(RGB)} uses @code{[0.01, 0.99]} as default
+## value for @var{TOL}.
+##
+## @strong{Notes:}
+##
+## Values in @var{LOW_HIGH} are of type double and comprised between 0
+## and 1 regardless class of input image.
+##
+## @strong{Compatibility notes:}
+##
+## @itemize @bullet
+## @item
+## int* and uint* types are still not implemented (waiting for support
+## in Octave 2.1.58).
+## @item
+## This function tries to find limits that are nearer to saturate
+## requested interval. So, for instance, if you requested a 5% and it
+## has to choose between discarding a 1% and a 7%, it will choose the
+## later despite being more than requested. This should be test against
+## MATLAB behaviour.
+## @end itemize
+##
+## @end deftypefn
+## @seealso imadjust
+
+## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
+
+function LOW_HIGH = stretchlim(image, TOL)
+  if (nargin<1 || nargin>2)
+    usage("LOW_HIGH=stretchlim(I [, TOL]), LOW_HIGH=stretchlim(RGB [, TOL])");
+  endif
+  
+  if(!ismatrix(image))
+    error("stretchlim: image should be a matrix");
+  endif
+  
+  ## Prepare limits
+  if(nargin==1)
+    low_count=0.01;
+    high_count=0.01;                ## we use this definition in __stretchlim_plane__
+  else
+    if(isscalar(TOL))
+      if(TOL<0 || TOL>=0.5)
+	error("stretchlim: TOL out of bounds. Expected: 0<=TOL<0.5");
+      endif
+      low_count=TOL;
+      high_count=TOL;               ## as before...
+    elseif(isvector(TOL))
+      if(length(TOL)!=2)
+	error("stretchlim: TOL length must be 2.");
+      endif
+      low_count=TOL(1);
+      high_count=1-TOL(2);          ## as before...
+    else
+      error("stretchlim: TOL contains an invalid value.");
+    endif
+  endif
+
+  ## well use size of image several times...
+  simage=size(image);
+
+  ## Convert fractions to pixels
+  psimage=prod(simage(1:2));
+  low_count*=psimage;
+  high_count*=psimage;
+	 
+  if(length(simage)<=2)
+    ## intensity
+    LOW_HIGH=__stretchlim_plane__(image, low_count, high_count);
+  elseif(length(simage)==3 && simage(3)==3)
+    ## RGB
+    LOW_HIGH=zeros(2,3);
+    for i=1:3
+      LOW_HIGH(:,i)=__stretchlim_plane__(image(:,:,i), low_count, \
+					 high_count);
+    endfor
+  else
+    error("stretchlim: invalid image.");
+  endif
+endfunction
+
+
+## Processes a plane
+## high_count is defined so that high_count=elements is the same as
+## low_count=elements (and not total_elements-elements)
+function LOW_HIGH = __stretchlim_plane__(plane, low_count, high_count)
+  ## check exceptions
+  if(low_count==0 && high_count==0)
+    LOW_HIGH=[min(plane(:)); max(plane(:))];
+  else
+
+    ## we sort values
+    sorted=sort(plane(:));
+    
+    low=sorted(round(low_count+1));
+    pos=find(sorted>low);
+    if(length(pos)>0)
+      low2=sorted(pos(1));
+      d1=low_count-sum(sorted<low);
+      d2=sum(sorted<low2)-low_count;
+      if(d2<d1)
+	low=low2;
+      endif
+    endif
+      
+    high=sorted(end-round(high_count));
+    pos=find(sorted<high);
+    if(length(pos)>0)
+      high2=sorted(pos(end));
+      d1=high_count-sum(sorted>high);
+      d2=sum(sorted>high2)-high_count;
+      if(d2<d1)
+	high=high2;
+      endif
+    endif
+
+    ## set result variable
+    LOW_HIGH=[low;high];
+  endif
+endfunction
+
+%!demo
+%! stretchlim([1:100])
+%! # This discards 1% of data from each end, 1 and 100.
+%! # So result should be [2;99]
+
+%!# some invalid params
+%!error(stretchlim());
+%!error(stretchlim("bad parameter"));
+%!error(stretchlim(zeros(10,10,4)));
+%!error(stretchlim(zeros(10,10,3,2)));
+%!error(stretchlim(zeros(10,10),"bad parameter"));
+%!error(stretchlim(zeros(10,10),0.01,2));
+
+
+%!# default param
+%!assert(stretchlim([1:100]),[2;99]);
+
+%!# scalar TOL
+%!assert(stretchlim([1:100],0.01),[2;99]);
+
+%!# vector TOL
+%!assert(stretchlim([1:100],[0.01,0.98]),[2;98]);
+
+%!# TOL=0
+%!assert(stretchlim([1:100],0),[1;100]);
+
+%!# non uniform histogram tests
+%!assert(stretchlim([1,ones(1,90)*2,92:100],0.05),[2;95]);
+%!assert(stretchlim([1,ones(1,4)*2,6:100],0.05),[6;95]);
+
+%!# test limit rounding...
+%!assert(stretchlim([1,ones(1,5)*2,7:100],0.05),[7;95]); # 6% lost 
+%!assert(stretchlim([1,ones(1,6)*2,8:100],0.05),[8;95]); # 7% lost
+%!assert(stretchlim([1,ones(1,7)*2,9:100],0.05),[9;95]); # 8% lost
+%!assert(stretchlim([1,ones(1,8)*2,10:100],0.05),[2;95]); # now he limit at 2 => 1% lost
+
+%!# test RGB
+%!test
+%! RGB=zeros(100,1,3);
+%! RGB(:,:,1)=[1:100];
+%! RGB(:,:,2)=[2:2:200];
+%! RGB(:,:,3)=[4:4:400];
+%! assert(stretchlim(RGB),[2,4,8;99,198,396]);
+
new file mode 100644
--- /dev/null
+++ b/inst/summer.m
@@ -0,0 +1,52 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} summer (@var{n})
+## Create color colormap. 
+## (green to yellow)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+## Date:  06/03/2000
+function map = summer (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("summer: argument must be a scalar");
+    endif
+  else
+    usage ("summer (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0.5, 0.4];  
+  elseif (number > 1)
+    r = (0:number - 1)' ./ (number - 1);
+    g = 0.5 + r ./ 2;
+    b = 0.4 * ones (number, 1);
+
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/testimio.m
@@ -0,0 +1,56 @@
+## This program is public domain.
+
+## build image for image r/w tests
+x=linspace(-8,8,200);
+[xx,yy]=meshgrid(x,x);
+r=sqrt(xx.^2+yy.^2) + eps;
+map=colormap(hsv);
+A=sin(r)./r;
+minval = min(A(:));
+maxval = max(A(:));
+z = round ((A-minval)/(maxval - minval) * (rows(colormap) - 1)) + 1;
+Rw=Gw=Bw=z;
+Rw(:)=fix(255*map(z,1));
+Gw(:)=fix(255*map(z,2));
+Bw(:)=fix(255*map(z,3));
+Aw=fix(255*(1-r/max(r(:)))); ## Fade to nothing at the corners
+
+if exist("jpgwrite")
+  disp(">jpgwrite"); 
+  jpgwrite('test.jpg',Rw,Gw,Bw);
+  stats=stat("test.jpg");
+  assert(stats.size,6423);
+  disp(">jpgread");
+  im = jpgread('test.jpg');
+  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
+  assert(all(Rw(:)-double(Rr(:))<35));
+  assert(all(Gw(:)-double(Gr(:))<35));
+  assert(all(Bw(:)-double(Br(:))<35));
+  unlink('test.jpg');
+else
+  disp(">jpgread ... not available");
+  disp(">jpgwrite ... not available");
+endif
+
+if exist("pngwrite")
+  disp(">pngwrite"); 
+  pngwrite('test.png',Rw,Gw,Bw,Aw);
+  stats=stat("test.png");
+  assert(stats.size,24738);
+  disp(">pngread");
+  im = pngread('test.png');
+  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
+  assert(all(double(Rr(:))==Rw(:)));
+  assert(all(double(Gr(:))==Gw(:)));
+  assert(all(double(Br(:))==Bw(:)));
+  [im,Ar] = pngread('test.png');
+  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
+  assert(all(double(Rr(:))==Rw(:)));
+  assert(all(double(Gr(:))==Gw(:)));
+  assert(all(double(Br(:))==Bw(:)));
+  assert(all(double(Ar(:))==Aw(:)));
+  unlink('test.png');
+else
+  disp(">pngread ... not available");
+  disp(">pngwrite ... not available");
+endif
new file mode 100644
--- /dev/null
+++ b/inst/uintlut.m
@@ -0,0 +1,60 @@
+## 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  2006/08/20 12:59:36  hauberg
+% Changed the structure to match the package system
+%
+% Revision 1.2  2004/08/11 15:04:59  pkienzle
+% Convert dos line endings to unix line endings
+%
+% Revision 1.1  2004/08/08 21:20:25  jmones
+% uintlut and padarray functions added
+%
+%
new file mode 100644
--- /dev/null
+++ b/inst/white.m
@@ -0,0 +1,46 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} white (@var{n})
+## Create color colormap. 
+## (completly white)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = white (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("white: argument must be a scalar");
+    endif
+  else
+    usage ("white (number)");
+  endif
+
+  if (number > 0)
+    map = ones (number, 3);
+  else
+    map = [];
+  endif
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/inst/winter.m
@@ -0,0 +1,52 @@
+## Copyright (C) 1999,2000  Kai Habel
+##
+## 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} {} winter (@var{n})
+## Create color colormap. 
+## (blue to green)
+## The argument @var{n} should be a scalar.  If it
+## is omitted, the length of the current colormap or 64 is assumed.
+## @end deftypefn
+## @seealso{colormap}
+
+## Author:  Kai Habel <kai.habel@gmx.de>
+
+function map = winter (number)
+
+  if (nargin == 0)
+    number = rows (colormap);
+  elseif (nargin == 1)
+    if (! is_scalar (number))
+      error ("winter: argument must be a scalar");
+    endif
+  else
+    usage ("winter (number)");
+  endif
+
+  if (number == 1)
+    map = [0, 0, 1];  
+  elseif (number > 1)
+    r = zeros (number, 1);
+    g = (0:number - 1)' ./ (number - 1);
+    b = 1 - g ./ 2;
+
+    map = [r, g, b];
+  else
+    map = [];
+  endif
+
+endfunction
deleted file mode 100644
--- a/isbw.m
+++ /dev/null
@@ -1,39 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{bool}= isbw (@var{BW})
-## returns true for a black-white (binary) image.
-## All values must be either 0 or 1
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	20/03/2000
-
-function bool = isbw (BW)
-
-  bool = 0;	
-  if !(nargin == 1)
-    usage ("isbw(BW)");
-  endif
-
-  if !(is_matrix(BW))
-    return;
-  endif
-
-  bool = all (all ((BW == 1) + (BW == 0)));
-
-endfunction
deleted file mode 100644
--- a/isgray.m
+++ /dev/null
@@ -1,40 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{bool}= isgray (@var{I})
-## returns true for an intensity image. All intensity values must
-## be in the range [0,1].
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	20/03/2000
-
-function bool = isgray (I)
-
-  bool = 0;
-
-  if !(nargin == 1)
-    usage ("isgray(I)");
-  endif
-
-  if (!is_matrix(I))
-    return;
-  endif
-
-  bool = all (all ((I >= 0) && (I <= 1)));
-
-endfunction
deleted file mode 100644
--- a/isind.m
+++ /dev/null
@@ -1,43 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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 WXTHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABXLXTY or FXTNESS FOR A PARTXCULAR 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, Xnc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{bool}= isind (@var{X})
-## returns true for an index image. All index values must
-## be intergers and greater than  or equal to 1.
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	20/03/2000
-
-function ret = isind (X)
-
-  if nargin != 1
-    usage ("isind(X)");
-  endif
-
-  ret =  isreal (X) && length (size (X)) == 2 ...
-	&& all ( X(:) == floor (X(:)) ) && all ( X(:) >= 1 ); 
-
-endfunction
-
-%!assert(isind([]))
-%!assert(isind(1:10))
-%!assert(!isind(0:10))
-%!assert(isind(1))
-%!assert(!isind(0))
-%!assert(!isind([1.3,2.4]))
-%!assert(isind([1,2;3,4]))
deleted file mode 100644
--- a/isrgb.m
+++ /dev/null
@@ -1,81 +0,0 @@
-## 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{flag} = } isrgb (@var{A})
-## Returns true if parameter is a RGB image
-##
-## @code{flag=isrgb(A)} returns 1 if @var{A} is a RGB image and 0 if
-## not.
-##
-## To the decide @code{isrgb} uses the follow algorithm:
-## @itemize @bullet
-## @item
-## If @var{A} is of class double then it checks if all values are
-## between 0 and 1, and if size is m-by-n-by-3.
-## @item
-## If @var{A} is of class uint16, uint8 or logical then it checks is m-by-n-by-3.
-## @end itemize
-##
-## @strong{Compatibility notes:}
-##
-## Information needed on whether MATLAB accepts logical arrays as RGB
-## images (now this functions accepts them if they are m-by-n-by-3 arrays.
-##
-## @end deftypefn
-
-## TODO: Check if logical arrays should be considered RGB
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function flag = isrgb(A)
-  if (nargin!=1)
-    usage("flag=isrgb(A)");
-  endif
-  
-  if(ismatrix(A))
-    flag=1;
-    s=size(A);
-    if(length(s)!=3 || s(3)!=3)
-      flag=0; ## false if not m-by-n-by-3
-    elseif(strcmp(typeinfo(A),"matrix") && (any(A(:)<0) || any(A(:)>1)))
-      flag=0; ## false if class double but items are <0 or >1
-    endif
-  else
-    flag=0;
-  endif
-endfunction
-
-
-%!demo
-%! isrgb(rand(1,2,3))
-%! # A 1-by-2-by-3 double matrix with elements between 0 and 1 is a RGB image.
-
-
-%!# Non-matrix
-%!assert(isrgb("this is not a RGB image"),0);
-
-%!# Double matrix tests
-%!assert(isrgb(rand(5,5)),0);
-%!assert(isrgb(rand(5,5,1,5)),0);
-%!assert(isrgb(rand(5,5,3,5)),0);
-%!assert(isrgb(rand(5,5,3)),1);
-%!assert(isrgb(ones(5,5,3)),1);
-%!assert(isrgb(ones(5,5,3)+.0001),0);
-%!assert(isrgb(zeros(5,5,3)-.0001),0);
-
-%!# Logical
-%!assert(isrgb(logical(round(rand(5,5,3)))),1);
deleted file mode 100644
--- a/jet.m
+++ /dev/null
@@ -1,55 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} jet (@var{n})
-## Create color colormap. 
-## (dark blue through blue, cyan, green, yellow, red to dark red)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = jet (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("jet: argument must be a scalar");
-    endif
-  else
-    usage ("jet (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 0.5];  
-  elseif (number > 1)
-    x = linspace(0, 1, number)';
-    r = (x >= 3/8 & x < 5/8) .* (4 * x - 3/2)\
-      + (x >= 5/8 & x < 7/8) + (x >= 7/8) .* (-4 * x + 9/2);
-    g = (x >= 1/8 & x < 3/8) .* (4 * x - 1/2)\
-      + (x >= 3/8 & x < 5/8) + (x >= 5/8 & x < 7/8) .* (-4 * x + 7/2);
-    b = (x < 1/8) .* (4 * x + 1/2) + (x >= 1/8 & x < 3/8)\
-      + (x >= 3/8 & x < 5/8) .* (-4 * x + 5/2);
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/jpgread.cc
+++ /dev/null
@@ -1,181 +0,0 @@
- //
- // This is a hack into octave 
- //   based on jpgread.c by jpgread by Drea Thomas, The Mathworks and the
- //        examples in the IJG distribution. 
- //
- // (C) 1998 Andy Adler. This code is in the public domain
- // USE THIS CODE AT YOUR OWN RISK 
- //
- // $Id$                                     
- //
-
-/* Modified: Stefan van der Walt <stefan@sun.ac.za>
- * Date: 27 January 2004
- * - Manual error handler to prevent segfaults in Octave.
- * - Use uint8NDArray for output.
- */
-
-/*
- * Compilation:
- * First, try
- *   mkoctfile jpgread.cc -ljpeg
- *
- * If this doesn't work, install the jpeg library which is part of
- * "The Independent JPEG Group's JPEG software" collection.
- *
- * The jpeg library came from
- *
- * ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6.tar.gz
- *
- * Extract and build the library:
- * tar xvfz jpegsrc.v6.tar.gz
- * cd jpeg-6b
- * ./configure
- * make
- * make test
- *
- * Compile this file using:
- * mkoctfile jpgread.cc -I<jpeg-6b include dir> -L<jpeg-6b lib dir> -ljpeg
- */
-
-#include <octave/oct.h>
-#include <iostream>
-#include <csetjmp>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "jpeglib.h"
-
-#ifdef __cplusplus
-} //extern "C"
-#endif
-
-struct oct_error_mgr {
-    struct jpeg_error_mgr pub;    /* "public" fields */
-    jmp_buf setjmp_buffer;        /* for return to caller */
-};
-
-typedef struct oct_error_mgr * oct_error_ptr;
-
-METHODDEF(void)
-oct_error_exit (j_common_ptr cinfo)
-{
-    /* cinfo->err really points to an oct_error_mgr struct, so coerce pointer */
-    oct_error_ptr octerr = (oct_error_ptr) cinfo->err;
-    
-    /* Format error message and send to interpreter */
-    char errmsg[JMSG_LENGTH_MAX];
-    (octerr->pub.format_message)(cinfo, errmsg);
-    error("jpgread: %s", errmsg);
-    
-    /* Return control to the setjmp point */
-    longjmp(octerr->setjmp_buffer, 1);
-}
-
-DEFUN_DLD (jpgread, args, nargout ,
-"usage: I = jpgread('filename')\n\
-\n\
-  Read a JPEG file from disk.\n\
-\n\
-  For a grey-level image, the output is an MxN matrix. For a\n\
-  colour image, three such matrices are returned (MxNx3),\n\
-  representing the red, green and blue components. The output\n\
-  is of class 'uint8'.\n\
-\n\
-  See also: imread, im2double, im2gray, im2rgb.")
-{ 
-    octave_value_list retval;
-    int nargin  = args.length();
-    
-    FILE * infile;
-    
-    JSAMPARRAY buffer;
-    long row_stride;
-    struct jpeg_decompress_struct cinfo;
-    struct oct_error_mgr jerr;
-
-    //
-    // We bail out if the input parameters are bad
-    //
-    if ((nargin != 1) || !args(0).is_string() || (nargout != 1)) {
-	print_usage ();
-	return retval;
-    }    
-    
-    //
-    // Open jpg file
-    //
-    std::string filename = args(0).string_value();
-    if ((infile = fopen(filename.c_str(), "rb")) == NULL) {
-	error("jpgread: couldn't open file %s", filename.c_str());
-	return retval;
-    }
-    
-    //
-    // Initialize the jpeg library
-    //
-    cinfo.err = jpeg_std_error(&jerr.pub);
-    jerr.pub.error_exit = oct_error_exit;
-    if (setjmp(jerr.setjmp_buffer)) {
-	/* If we get here, the JPEG code has signaled an error.
-	 * We need to clean up the JPEG object, close the input file, and return.
-	 */
-	jpeg_destroy_decompress(&cinfo);
-	fclose(infile);
-	return retval;
-    }
-    
-    jpeg_create_decompress(&cinfo);
-    
-    //
-    // Read the jpg header to get info about size and color depth
-    //
-    jpeg_stdio_src(&cinfo, infile);
-    jpeg_read_header(&cinfo, TRUE);
-    jpeg_start_decompress(&cinfo);
-    
-    //
-    // Allocate buffer for one scan line
-    //
-    row_stride = cinfo.output_width * cinfo.output_components;
-    buffer = (*cinfo.mem->alloc_sarray)
-	((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-    
-    //
-    // Create an NDArray for the output.  Loop through each of the
-    // scanlines and copy the image data from the buffer.
-    //
-    
-    dim_vector dim = dim_vector();
-    dim.resize(3);
-    dim(0) = cinfo.output_height;
-    dim(1) = cinfo.output_width;
-    dim(2) = cinfo.output_components;
-    uint8NDArray out = uint8NDArray(dim, 0);
-    
-    Array<int> coord = Array<int> (3);
-    for (unsigned long j=0; cinfo.output_scanline < cinfo.output_height; j++) {
-	jpeg_read_scanlines(&cinfo, buffer, 1);
-	
-	coord(0) = j;
-	for (unsigned long i=0; i<cinfo.output_width; i++) {
-	    coord(1) = i;
-	    for (unsigned int c = 0; c < cinfo.output_components; c++) {
-		coord(2) = c;
-		out(coord) = buffer[0][i*cinfo.output_components+c];
-	    }
-	}
-    }
-    retval.append(out.squeeze());
-    
-    //
-    // Clean up
-    //
-    jpeg_finish_decompress(&cinfo);
-    jpeg_destroy_decompress(&cinfo);
-    fclose(infile);
-    
-    return retval;
-}
deleted file mode 100644
--- a/jpgwrite.cc
+++ /dev/null
@@ -1,221 +0,0 @@
- // This is a hack into octave
- //   based on jpgwrite.c by jpgread by Drea Thomas, The Mathworks, and the
- //        examples in the IJG distribution.
- //
- // (C) 1998 Andy Adler. This code is in the public domain
- //  USE THIS CODE AT YOUR OWN RISK 
- //
- // $Id$                                     
- //                                                       
-
-#include <octave/oct.h>
-#include <iostream>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "jpeglib.h"
-
-#ifdef __cplusplus
-} //extern "C"
-#endif
-
-#define GRAYIMAGES
-
-/*
- * Simple jpeg writing MEX-file. 
- *
- * Synopsis:
- *   jpgwrite(filename,r,g,b,quality)
- *
- * Compilation:
- * First, try
- *   mkoctfile jpgwrite.cc -ljpeg
- *
- * If this doesn't work, then do
- *
- * Calls the jpeg library which is part of 
- * "The Independent JPEG Group's JPEG software" collection.
- *
- * The jpeg library came from,
- *
- * ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6.tar.gz
- */
-
-DEFUN_DLD (jpgwrite, args, ,
-"JPGWRITE Write a JPEG file to disk.\n\
-   jpgwrite('filename',R,G,B,quality) writes the specified file\n\
-   using the Red, Green, and Blue intensity matrices, at the given quality.\n\
-   \n\
-   jpgwrite('filename',M,quality) writes a grey-scale image.\n\
-   \n\
-   Data must be [0 255] or the high bytes will be lost\n\
-   \n\
-   If specified, quality should be in the range 1-100 and will default to \n\
-   75 if not specified.  100 is best quality, 1 is best compression.\n\
-   \n\
-   See also JPGREAD")
-{
-   octave_value_list retval;
-   int nargin  = args.length();
-
-   FILE * outfile;
-
-   JSAMPARRAY buffer;
-   struct jpeg_compress_struct cinfo;
-   struct jpeg_error_mgr jerr;
-   int quality=75; //default value
-
-//
-// We bail out if the input parameters are bad
-//
-   if (nargin < 2 || !args(0).is_string() ) {
-      print_usage ();
-      return retval;
-   }
-
-
-//
-// Open jpg file
-//
-   std::string filename = args(0).string_value();
-   if ((outfile = fopen(filename.c_str(), "wb")) == NULL) {
-      error("Couldn't open file");
-      return retval;
-   }
-
-//
-// Set Jpeg parameters
-//
-   if (nargin == 3) {
-      quality= (int) args(2).double_value();
-   } else if (nargin == 5) {
-      quality= (int) args(4).double_value();
-   }
-  
-//
-// Initialize the jpeg library
-// Read the jpg header to get info about size and color depth 
-//
-   cinfo.err = jpeg_std_error(&jerr);
-   jpeg_create_compress(&cinfo);
-   jpeg_stdio_dest(&cinfo, outfile);
-
-
-//
-// set parameters for compression
-//
-      
-   if ( nargin <= 3 ) {
-//
-// we're here because only one matrix of grey scale values was provided
-//
-      Matrix avg= args(1).matrix_value();
-      long image_width  = args(1).columns();
-      long image_height = args(1).rows();
-
-
-      cinfo.image_width = image_width; 	/* image width and height, in pixels */
-      cinfo.image_height = image_height;
-#ifdef GRAYIMAGES
-      cinfo.input_components = 1;
-      cinfo.input_components = JCS_GRAYSCALE;
-#else
-      cinfo.input_components = 3;
-      cinfo.in_color_space = JCS_RGB;
-#endif
-      jpeg_set_defaults(&cinfo);
-      jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
-//
-//  start compressor
-//
-      jpeg_start_compress(&cinfo, TRUE);
-
-//
-// Allocate buffer for one scan line
-//
-      long row_stride = image_width * cinfo.input_components ;
-      buffer = (*cinfo.mem->alloc_sarray)
-      		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-//
-// Now, loop thru each of the scanlines. For each, copy the image
-// data from the buffer, data must be [0 255]
-//
-      for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
-         for(unsigned long i=0; i<cinfo.image_width; i++) {
-#ifdef GRAYIMAGES
-            buffer[0][i] = (unsigned char) avg(j,i);
-#else
-            buffer[0][i*3+0] = (unsigned char) avg(j,i);
-            buffer[0][i*3+1] = (unsigned char) avg(j,i);
-            buffer[0][i*3+2] = (unsigned char) avg(j,i);
-#endif
-         }
-         jpeg_write_scanlines(&cinfo, buffer,1);
-      }
-
-   } // if nargin <= 3
-   else {
-//
-// we're here because red green and blue matrices were provided
-//  we assume that they're the same size
-//
-      Matrix red  = args(1).matrix_value();
-      Matrix green= args(2).matrix_value();
-      Matrix blue = args(3).matrix_value();
-      long image_width  = args(1).columns();
-      long image_height = args(1).rows();
-
-      if ( args(2).columns() != image_width  ||
-           args(3).columns() != image_width  ||
-           args(2).rows()    != image_height ||
-           args(3).rows()    != image_height ) {
-         error("R,G,B matrix sizes aren't the same");
-         return retval;
-      }
-
-      cinfo.image_width = image_width; 	/* image width and height, in pixels */
-      cinfo.image_height = image_height;
-      cinfo.input_components = 3;		/* # of color components per pixel */
-      cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
-      jpeg_set_defaults(&cinfo);
-      jpeg_set_quality(&cinfo, quality, TRUE );
-//
-//  start compressor
-//
-      jpeg_start_compress(&cinfo, TRUE);
-
-//
-// Allocate buffer for one scan line
-//
-      long row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */
-      buffer = (*cinfo.mem->alloc_sarray)
-      		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-//
-// Now, loop thru each of the scanlines. For each, copy the image
-// data from the buffer, data must be [0 255]
-//
-      for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
-         for(unsigned long i=0; i<cinfo.image_width; i++) {
-            buffer[0][i*3+0] = (unsigned char) red(j,i);
-            buffer[0][i*3+1] = (unsigned char) green(j,i);
-            buffer[0][i*3+2] = (unsigned char) blue(j,i);
-         }
-         jpeg_write_scanlines(&cinfo, buffer,1);
-      }
-
-   } // else nargin > 3
-
-//
-// Clean up
-//
-
-   jpeg_finish_compress(&cinfo);
-   fclose(outfile);
-   jpeg_destroy_compress(&cinfo);
-
-
-   return retval;
-
-}
deleted file mode 100644
--- a/makelut.m
+++ /dev/null
@@ -1,73 +0,0 @@
-## 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{lut} = } makelut (@var{fun},@var{n})
-## @deftypefnx {Function File} {@var{lut} = } makelut (@var{fun},@var{n},@var{P1},@var{P2},...)
-## Create a lookup table which can be used by applylut.
-##
-## lut = makelut(fun,n) returns a vector which can be used by applylut
-## as a lookup table. 
-##
-## @var{fun} can be a function object as created by inline, or simply a
-## string which contains the name of a function. @var{fun} should accept a
-## @var{n}-by-@var{n} matrix whose elements are binary (0 or 1) and
-## returns an scalar (actually anything suitable to be included in a
-## vector).
-##
-## makelut calls @var{fun} with all possible matrices and builds a
-## vector with its result, suitable to be used by applylut. The length
-## of this vector is 2^(@var{n}^2), so 16 for 2-by-2 and 512 for 3-by-3.
-##
-## makelut also passes parameters @var{P1}, @var{P2}, .... to @var{fun}. 
-##
-## @end deftypefn
-## @seealso{applylut}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function lut = makelut(fun, n, varargin)
-  if (nargin < 2)
-    usage ("lut = makelut(fun, n [, ...])");
-  endif
-
-  if (n<2)
-    error ("makelut: n should be a natural number >= 2");
-  endif
-
-  nq=n^2;
-  c=2^nq;
-  lut=zeros(c,1);
-  w=reshape(2.^[nq-1:-1:0],n,n);
-  for i=0:c-1
-    idx=bitand(w,i)>0;
-    lut(i+1)= feval(fun, idx, all_va_args);
-  endfor
-endfunction
-
-%!demo
-%! makelut(inline('sum(x(:))>=3','x'), 2)
-%! % Returns '1' if one or more values
-%! % in the input matrix are 1
-
-%!assert(prod(makelut(inline('sum(x(:))==2','x'),2)==makelut(inline('sum(x(:))==a*b*c*d','x','a','b','c','d'),2,2/(3*4*5),3,4,5))); # test multiple params
-%!assert(prod(makelut(inline('x(1,1)==1','x'),2)==[zeros(2^3,1);ones(2^3,1)])==1); # test 2-by-2
-%!assert(prod(makelut(inline('x(1,1)==1','x'),3)==[zeros(2^8,1);ones(2^8,1)])==1); # test 3-by-3
-%!assert(prod(makelut(inline('x(1,1)==1','x'),4)==[zeros(2^15,1);ones(2^15,1)])==1); # test 4-by-4
-%!assert(prod(makelut(inline('x(2,1)==1','x'),3)==[zeros(2^7,1);ones(2^7,1);zeros(2^7,1);ones(2^7,1)])==1); # another test for 3-by-3
-
-
-
deleted file mode 100644
--- a/mat2gray.m
+++ /dev/null
@@ -1,49 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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{I}= mat2gray (@var{M},[min max])
-## converts a matrix to a intensity image
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	22/03/2000
-
-function I = mat2gray (M, scale)
-
-  if (nargin < 1|| nargin > 2)
-    usage ("mat2gray(...) number of arguments must be 1 or 2");
-  endif
-
-  if (!is_matrix (M))
-    usage ("mat2gray(M,...) M must be a matrix");
-  endif
-
-  if (nargin == 1)
-    Mmin = min (min (M));
-    Mmax = max (max (M));
-  else 
-    if (isvector (scale))
-      Mmin = min (scale (1), scale (2));
-      Mmax = max (scale (1), scale (2));
-    endif
-  endif
-
-  I = (M < Mmin) .* 0;
-  I = I + (M >= Mmin & M < Mmax) .* (1 / (Mmax - Mmin) * (M - Mmin));
-  I = I + (M >= Mmax);
-
-endfunction
deleted file mode 100644
--- a/mean2.m
+++ /dev/null
@@ -1,39 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{m}= mean2 (@var{I})
-## returns the mean value for a 2d real type matrix.
-## Uses @code{mean(I(:))}
-## @end deftypefn
-## @seealso{std2,mean}
-
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	01/08/2000
-
-function m = mean2 (I)
-
-  if !(nargin == 1)
-    usage ("mean2(I)");
-  endif
-
-  if !(is_matrix(I) && isreal(I))
-	error("argument must be a real type matrix");
-  endif
-
-  m = mean (I(:));
-endfunction
deleted file mode 100644
--- a/medfilt2.m
+++ /dev/null
@@ -1,68 +0,0 @@
-## 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} {} medfilt2(@var{A}, [@var{domain}, @var{padding}])
-## Two dimensional median filtering.
-##
-## Replaces elements of @var{A} with the median of their neighbours defined 
-## by true elements of logical matrix @var{domain}. The default @var{domain} 
-## is a 3 by 3 matrix with all elements equal to 1. If @var{domain} is 1 by 2
-## row vector, the domain matrix will be 
-## logical(ones(@var{domain}(2), @var{domain}(1))).
-##
-## Optional variable @var{padding} defines the padding used in augmenting 
-## the borders of @var{A}. See impad for details.
-##
-## @end deftypefn
-## @seealso{ordfilt2}
-
-## Author: Teemu Ikonen <tpikonen@pcu.helsinki.fi>
-## Created: 5.5.2000
-## Keywords: image processing median filtering
-
-%!test
-%! b = [0,1,2,3;1,8,12,12;4,20,24,21;7,22,25,18];
-%! assert(medfilt2(b),[0,1,2,0;1,4,12,3;4,12,20,12;0,7,20,0]);
-
-function retval = medfilt2(A, varargin)
-
-padding = "zeros";
-domain = logical(ones(3,3));
-
-for i=1:length(varargin)
-  a = varargin{i};
-  if(ischar(a))
-    padding = a;
-  elseif(isvector(a) && size(a) == [1, 2])
-    domain = logical(ones(a(2), a(1)));
-  elseif(is_matrix(a))
-    domain = logical(a);
-  endif
-endfor
-
-n = sum(sum(domain));
-if((n - 2*floor(n/2)) == 0) % n even - more work
-  nth = floor(n/2);
-  a = ordfilt2(A, nth, domain, padding);
-  b = ordfilt2(A, nth + 1, domain, padding);
-  retval = (a + b)./2;
-else
-  nth = floor(n/2) + 1;
-  retval = ordfilt2(A, nth, domain, padding);
-endif
-
-endfunction
deleted file mode 100644
--- a/nlfilter.m
+++ /dev/null
@@ -1,167 +0,0 @@
-## 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} = } nlfilter (@var{A}, [@var{m},@var{n}], @var{fun})
-## @deftypefnx {Function File} {@var{B} = } nlfilter (@var{A}, [@var{m},@var{n}], @var{fun}, ...)
-## @deftypefnx {Function File} {@var{B} = } nlfilter (@var{A},'indexed', ...)
-## Processes image in sliding blocks using user-supplied function
-##
-## @code{B=nlfilter(A,[m,n],fun)} passes sliding @var{m}-by-@var{n}
-## blocks to user-supplied function @var{fun}. A block is build for
-## every pixel in @var{A}, such as it is centered within the block.
-## @var{fun} must return a scalar, and it is used to create matrix
-## @var{B}. @var{nlfilter} pads the @var{m}-by-@var{n} block at the
-## edges if necessary.
-## 
-## Center of block is taken at ceil([@var{m},@var{n}]/2).
-##
-## @code{B=nlfilter(A,[m,n],fun,...)} behaves as described above but
-## passes extra parameters to function @var{fun}.
-##
-## @code{B=nlfilter(A,'indexed',...)} assumes that @var{A} is an indexed
-## image, so it pads the image using proper value: 0 for uint8 and
-## uint16 images and 1 for double images. Keep in mind that if 'indexed'
-## is not specified padding is always done using 0.
-##
-## @end deftypefn
-## @seealso{colfilt,blkproc,inline}
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function B = nlfilter(A, varargin)
-  if(nargin<3)
-    error("nlfilter: invalid number of parameters.");
-  endif
-  
-  ## check 'indexed' presence
-  indexed=false;
-  p=1;
-  if(ischar(varargin{1}) && strcmp(varargin{1}, "indexed"))
-    indexed=true;
-    p+=1;
-    if(isa(A,"uint8") || isa(A,"uint16"))
-	padval=0;
-    else
-      padval=1; 
-    endif
-  else
-    padval=0;
-  endif
-
-  ## check [m,n]
-  if(!isvector(varargin{p}))
-    error("nlfilter: expected [m,n] but param is not a vector.");
-  endif
-  if(length(varargin{p})!=2)
-    error("nlfilter: expected [m,n] but param has wrong length.");
-  endif
-  sblk=varargin{p}(:);
-  p+=1;
-
-  ## check fun
-  ## TODO: add proper checks for this one
-  if(nargin<p)
-    error("nlfilter: required parameters haven't been supplied.");
-  endif
-  fun=varargin{p};
-  
-  ## remaining params are params to fun
-  ## extra params are p+1:nargin-1
-
-  ## We take an easy approach... feel free to optimize it (coding this
-  ## in C++ would be a great idea).
-  
-  ## Calculate center of block
-  c=ceil(sblk/2);
-  
-  ## Pre-padding
-  prepad=c-ones(2,1);
-  
-  ## Post-padding
-  postpad=sblk-c;
-  
-  ## Save A size
-  as=size(A);
-
-  ## Pad data
-  if(all(prepad==postpad))
-    if(any(prepad>0))
-      A=padarray(A,prepad,padval,'both');
-    endif
-  else
-    if(any(prepad>0))
-      A=padarray(A,prepad,padval,'pre');
-    endif
-    if(any(postpad>0))
-      A=padarray(A,postpad,padval,'post');
-    endif
-  endif
-
-  ## calc end offsets
-  me=postpad(1)+prepad(1);
-  ne=postpad(2)+prepad(2);
-	
-  ## We concatenate everything to preserve fun return type
-  for i=1:as(1)
-    r=feval(fun,A(i:i+me,1:1+ne),varargin{p+1:nargin-1});
-    for j=2:as(2)
-      r=horzcat(r,feval(fun,A(i:i+me,j:j+ne),varargin{p+1:nargin-1}));
-    endfor
-    if(i==1)
-      B=r;
-    else
-      B=vertcat(B,r);
-    endif
-  endfor
-
-endfunction
-
-%!demo
-%! nlfilter(eye(10),[3,3],inline("any(x(:)>0)","x"))
-%! # creates a "wide" diagonal	
-
-%!assert(nlfilter(eye(4),[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
-%!assert(nlfilter(eye(4),'indexed',[2,3],inline("sum(x(:))","x")),[4,2,1,2;3,2,2,3;2,1,2,4;4,3,4,5]);
-%!assert(nlfilter(eye(4),'indexed',[2,3],inline("sum(x(:))==y","x","y"),2),[0,1,0,1;0,1,1,0;1,0,1,0;0,0,0,0]!=0);
-
-% Check uint8 and uint16 padding
-%!assert(nlfilter(uint8(eye(4)),'indexed',[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
-%!assert(nlfilter(uint16(eye(4)),'indexed',[2,3],inline("sum(x(:))","x")),[2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]);
-
-% Check if function class is preserved
-%!assert(nlfilter(uint8(eye(4)),'indexed',[2,3],inline("int8(sum(x(:)))","x")),int8([2,2,1,0;1,2,2,1;0,1,2,2;0,0,1,1]));
-
-
-
-%
-% $Log$
-% Revision 1.5  2005/09/08 02:00:17  pkienzle
-% [for Bill Denney] isstr -> ischar
-%
-% Revision 1.4  2004/11/15 16:04:20  pkienzle
-% Fix tests for functions which return boolean matrices
-%
-% Revision 1.3  2004/09/03 13:28:32  jmones
-% Corrected behaviour for int* and uint* types
-%
-% Revision 1.2  2004/08/15 19:43:11  jmones
-% corrected a typo in doc
-%
-% Revision 1.1  2004/08/15 19:42:14  jmones
-% nlfilter: Processes image in siliding blocks using user-supplied function
-%
-%
deleted file mode 100644
--- a/ordfilt2.m
+++ /dev/null
@@ -1,72 +0,0 @@
-## 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} {} ordfilt2(@var{A}, @var{nth}, @var{domain}, [@var{S}, @var{padding}])
-## Two dimensional ordered filtering.
-##
-## Ordered filter replaces an element of @var{A} with the @var{nth} 
-## element of the sorted set of neighbours defined by the logical 
-## (boolean) matrix @var{domain}.
-## Neighbour elements are selected to the sort if the corresponding 
-## element in the @var{domain} matrix is true.
-## 
-## The optional variable @var{S} is a matrix of size(@var{domain}). 
-## Values of @var{S} corresponding to nonzero values of domain are 
-## added to values obtained from @var{A} when doing the sorting.
-##
-## Optional variable @var{padding} determines how the matrix @var{A} 
-## is padded from the edges. See impad for details.
-## 
-## @end deftypefn
-## @seealso{medfilt2}
-
-
-## Author: Teemu Ikonen <tpikonen@pcu.helsinki.fi>
-## Created: 5.5.2000
-## Keywords: image processing filtering
-
-function retval = ordfilt2(A, nth, domain, varargin)
-
-S = zeros(size(domain));
-padding = "zeros";
-for i=1:length(varargin)
-  a = varargin{:};
-  if(ischar(a))
-    padding = a;
-  elseif(is_matrix(a) && size(a) == size(domain))
-    S = a;
-  endif
-endfor
-
-if(!islogical(domain))
-  %  warning("domain should be a boolean matrix, converting");
-  domain = logical(domain);
-endif;
-
-xpad(1) = floor((size(domain, 2)+1)/2) - 1;
-xpad(2) = size(domain,2) - xpad(1) - 1;
-ypad(1) = floor((size(domain, 1)+1)/2) - 1;
-ypad(2) = size(domain,1) - ypad(1) - 1;
-
-if(ypad(1) >= size(A,1) || xpad(1) >= size(A,2))
-  error("domain matrix too large");
-endif;
-
-A = impad(A, xpad, ypad, padding);
-retval = cordflt2(A, nth, domain, S);
-
-endfunction
deleted file mode 100644
--- a/padarray.m
+++ /dev/null
@@ -1,362 +0,0 @@
-## 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
-
-  ## Assure padsize is a row vector
-  padsize=padsize(:).';
-
-  # 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 (ischar(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,class(A));       ## class(pad) = class(A)
-	else
-	  pad=padval*ones(ps,class(A)); ## class(pad) = class(A)
-	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)]);
-
-% Test padding on 3D array
-%!test
-%! int8(0); % fail for octave <= 2.1.57 without crashing
-%! assert(padarray([1,2,3;4,5,6],[3,2,1]), cat(3, 			\
-%! 	zeros(8,7),							\
-%! 	[zeros(3,7); [zeros(2,2), [1,2,3;4,5,6], zeros(2,2)]; zeros(3,7)], \
-%! 	zeros(8,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 vertical padsize
-%!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));
-
-% Repeat some tests with int* uint* class types
-%!assert(padarray(int8([1;2]),[1]), int8([0;1;2;0]));
-%!assert(padarray(uint8([3,4]),[0,2]), uint8([0,0,3,4,0,0]));
-%!assert(padarray(int16([1;2]),[1],4), int16([4;1;2;4]));
-%!assert(padarray(uint16([1;2]),[1],0), uint16([0;1;2;0]));
-%!assert(padarray(int32([1;2]),[1],int32(4),'pre'), int32([4;1;2]));
-%!assert(padarray(uint32([1;2]),[1],6,'post'), uint32([1;2;6]));
-
-% Test circular padding with int* uint* class types
-%!test
-%! A=int8([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 with int* uint* class types
-%!test
-%! A=uint8([1,2;3,4]);
-%! B=[ones(10,5,"uint8")*1,ones(10,5,"uint8")*2; \
-%!    ones(10,5,"uint8")*3,ones(10,5,"uint8")*4];
-%! 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 with int* uint* class types
-%!test
-%! A=int16([1:3;4:6]);
-%! HA=int16([3:-1:1;6:-1:4]);
-%! VA=int16([4:6;1:3]);
-%! VHA=int16([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.6  2005/09/08 02:00:17  pkienzle
-% [for Bill Denney] isstr -> ischar
-%
-% Revision 1.5  2004/09/03 18:33:11  pkienzle
-% skip tests which use cat(3,X,Y) for octave <= 2.1.57
-%
-% Revision 1.4  2004/09/03 13:37:10  jmones
-% Corrected behaviour for int* and uint* types
-%
-% Revision 1.3  2004/08/15 19:21:50  jmones
-% support column vector padsize
-%
-% Revision 1.2  2004/08/11 15:04:59  pkienzle
-% Convert dos line endings to unix line endings
-%
-% Revision 1.1  2004/08/08 21:20:25  jmones
-% uintlut and padarray functions added
-%
-%
deleted file mode 100644
--- a/pink.m
+++ /dev/null
@@ -1,55 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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} {} pink (@var{n})
-## Create color colormap. 
-## (gives a sephia tone on b/w images)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = pink (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("pink: argument must be a scalar");
-    endif
-  else
-    usage ("pink (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 0];  
-  elseif (number > 1)
-    x = linspace (0, 1, number)';
-    r = (x < 3/8) .* (14/9 * x) + (x >= 3/8) .* (2/3 * x + 1/3);
-    g = (x < 3/8) .* (2/3 * x)\
-      + (x >= 3/8 & x < 3/4) .* (14/9 * x - 1/3)\
-      + (x >= 3/4) .* (2/3 * x + 1/3);
-    b = (x < 3/4) .* (2/3 * x) + (x >= 3/4) .* (2 * x - 1);
-
-    map = sqrt ([r, g, b]);
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/pngcanvas.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *  readpng.h
- *
- *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
- *
- *  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 Library 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.
- */
-
-/*
- * Modified: Stefan van der Walt <stefan@sun.ac.za>
- * Date: 28 January 2005
- * - Fix bugs, restructure
- */
-
-typedef struct
-{
-  int width;
-  int height;
-  int bit_depth;
-  int color_type;
-  unsigned char **row_pointers;
-} canvas;
-
-//////////////Libcanvas///////////
-canvas *new_canvas(int width, int height, int stride)
-{
-  // Default stride if none given
-  if (stride==0) stride=width*4;
-
-  // Clean allocation of canvas structure
-  canvas *can=new(canvas);
-  unsigned char *image_data = new unsigned char[stride*height];
-  unsigned char **row_pointers = new unsigned char *[height];
-  if (can == NULL || image_data == NULL || row_pointers == NULL) 
-    {
-      if (can == NULL) delete can;
-      if (image_data == NULL) delete[] image_data;
-      if (row_pointers == NULL) delete[] row_pointers;
-      return NULL;
-    }
-
-  // Fill in canvas structure
-  can->width=width;
-  can->height=height;
-  can->bit_depth=8;
-  can->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
-  can->row_pointers = row_pointers;
-  for (int i=0; i < height; i++) row_pointers[i] = image_data + i*stride;
-
-  return can;
-}
-
-void delete_canvas(canvas *can)
-{
-  
-  if (can!=NULL)
-    {
-      delete[] can->row_pointers[0]; 
-      delete[] can->row_pointers;
-      delete can;
-    }
-  return;
-}
-
deleted file mode 100644
--- a/pngread.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- *  pngread.cc
- *
- *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
- *
- *  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 Library 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.
- */
-
-/*
-
-Load PNG files to octave using libpng;
-
-       PNG  (Portable  Network  Graphics) is an extensible file format for the
-       lossless, portable, well-compressed storage of raster images. PNG  pro-
-       vides  a patent-free replacement for GIF and can also replace many com-
-       mon uses of TIFF. Indexed-color, grayscale, and  truecolor  images  are
-       supported,  plus  an optional alpha channel. Sample depths range from 1
-       to 16 bits.
-
-*/
-
-/*
- * Modified: Stefan van der Walt <stefan@sun.ac.za>
- * Date: 28 January 2005
- * - Fix bugs, restructure
- */
-
-#include "png.h"
-#include "pngcanvas.h"
-#include <octave/oct.h>
-
-canvas *load_canvas(char *filename);
-
-DEFUN_DLD (pngread, args, nargout ,
-"-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {[@var{I}, @var{alpha}] =} pngread(@var{filename})\n\
-\n\
-Read a PNG file from disk.\n\
-\n\
-The image is returned as a matrix of dimension MxN (for grey-level images)\n\
-or MxNx3 (for colour images).  The numeric type of @var{I} and @var{alpha}\n\
-is @code{uint8} for grey-level and RGB images, or @code{logical} for\n\
-black-and-white images.\n\
-\n\
-@end deftypefn\n\
-@seealso{imread}")
-{
-  octave_value_list retval;
-  int nargin  = args.length();
-  
-  //
-  // We bail out if the input parameters are bad
-  //
-  if (nargin != 1 || !args(0).is_string()) {
-    print_usage ();
-    return retval;
-  }
-  
-  //
-  // Load png file
-  //
-  canvas *pic=load_canvas((char *)args(0).string_value().c_str());
-  if (!pic) return retval;
-
-  dim_vector dim = dim_vector();
-  dim.resize(3);
-  dim(0) = pic->height;
-  dim(1) = pic->width;
-  dim(2) = 3;
-
-  if ( (pic->color_type == PNG_COLOR_TYPE_GRAY) ||
-       (pic->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
-       ((pic->color_type == PNG_COLOR_TYPE_PALETTE) && (pic->bit_depth == 1)) )
-      dim(2) = 1;
-
-  if (pic->bit_depth > 1 && pic->bit_depth < 8)
-      pic->bit_depth = 8;
-
-  NDArray out(dim);
-  
-  dim.resize(2);
-  NDArray alpha(dim);
-   
-  Array<int> coord = Array<int> (3);
-  
-  for (unsigned long j=0; j < pic->height; j++) {
-      coord(0) = j;
-      for (unsigned long i=0; i < pic->width; i++) {
-	  coord(1) = i;
-
-	  for (int c = 0; c < out.dims()(2); c++) {
-	      coord(2) = c;
-	      out(coord) = pic->row_pointers[j][i*4+c];
-	  }
-	  alpha(j,i) = pic->row_pointers[j][i*4+3];
-      }
-  }
-  out = out.squeeze();
-
-  switch (pic->bit_depth) {
-  case 1: 
-     retval.append((boolNDArray)out);
-     retval.append((boolNDArray)alpha);
-     break;
-  case 8:
-     retval.append((uint8NDArray)out);
-     retval.append((uint8NDArray)alpha);
-     break;
-  case 16:
-     retval.append((uint16NDArray)out);
-     retval.append((uint16NDArray)alpha);
-     break;
-  default:
-     retval.append(out);
-     retval.append(alpha);
-  }
-
-  delete_canvas(pic);
-  return retval;
-}
-
-canvas *load_canvas(char *filename)
-{
-  png_structp png_ptr;
-  png_infop info_ptr;
-  
-  FILE *infile = fopen(filename,"r");
-  if (!infile) {
-    error("pngread could not open file %s", filename); 
-    return NULL;
-  }
-  
-  unsigned char sig[8];
-  fread(sig,1,8,infile);
-  if (!png_check_sig(sig,8)) {
-    error("pngread invalid signature in %s", filename); 
-    fclose(infile);
-    return NULL;
-  }
-  
-  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
-  if (!png_ptr) {
-    error("pngread out of memory"); 
-    fclose(infile);
-    return NULL;
-  }
-  
-  info_ptr = png_create_info_struct(png_ptr);
-  if(!info_ptr) { 
-    error("pngread can't generate info");  
-    png_destroy_read_struct(&png_ptr,NULL,NULL); 
-    fclose(infile);
-    return NULL;
-  }
-
-  /* Set error handling */
-  if (setjmp(png_jmpbuf(png_ptr))) {
-      error("pngread: libpng exited abnormally");
-      png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
-      fclose(infile);
-      return NULL;
-  }
-
-  png_init_io(png_ptr, infile);
-  png_set_sig_bytes(png_ptr, 8);
-  png_read_info(png_ptr, info_ptr);
-  
-  png_uint_32 width,height;
-  int color_type, bit_depth;
-  png_get_IHDR(png_ptr,info_ptr,&width,&height,
-	       &bit_depth,&color_type,NULL,NULL,NULL);
-  
-  /* Transform grayscale images with depths < 8-bit to 8-bit, change
-   * paletted images to RGB, and add a full alpha channel if there is
-   * transparency information in a tRNS chunk.
-   */
-  if (color_type == PNG_COLOR_TYPE_PALETTE) {
-      png_set_palette_to_rgb(png_ptr);
-  }
-  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
-      png_set_gray_1_2_4_to_8(png_ptr);
-  }
-  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { //add alpha
-      png_set_tRNS_to_alpha(png_ptr);
-  }
-  
-  // Always transform image to RGB
-  if (color_type == PNG_COLOR_TYPE_GRAY 
-      || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
-      png_set_gray_to_rgb(png_ptr);
-   
-  // If no alpha layer is present, create one
-  if (color_type == PNG_COLOR_TYPE_GRAY
-      || color_type == PNG_COLOR_TYPE_RGB)
-     png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
-
-  if (bit_depth < 8) {
-      png_set_packing(png_ptr);
-  }
-  
-  // For now, use 8-bit only
-  if (bit_depth == 16) {
-      png_set_strip_16(png_ptr);
-  }
-   
-  png_read_update_info(png_ptr,info_ptr);
-
-  // Read the data from the file
-  int stride = png_get_rowbytes(png_ptr, info_ptr);
-  canvas *can = new_canvas(width, height, stride);
-  
-  if (can) {
-    png_read_image(png_ptr, can->row_pointers);
-  } else {
-    error("pngread out of memory");
-  }
-
-  png_read_end(png_ptr,NULL);
-  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
-
-  fclose(infile);
-
-  // Set color type and depth. Used to determine octave output arguments.
-  can->color_type = color_type;  
-  can->bit_depth = bit_depth;
-  return can;
-}
deleted file mode 100644
--- a/pngwrite.cc
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *  pngwrite.cc
- *
- *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
- *
- *  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 Library 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.
- */
-
-/*
-
-Write PNG files to disk from octave
-
-       PNG  (Portable  Network  Graphics) is an extensible file format for the
-       lossless, portable, well-compressed storage of raster images. PNG  pro-
-       vides  a patent-free replacement for GIF and can also replace many com-
-       mon uses of TIFF. Indexed-color, grayscale, and  truecolor  images  are
-       supported,  plus  an optional alpha channel. Sample depths range from 1
-       to 16 bits.
-
-*/
-
-/*
- * Modified: Stefan van der Walt <stefan@sun.ac.za>
- * Date: 28 January 2005
- * - Fix bugs, restructure
- */
-
-#include "png.h"
-#include "pngcanvas.h"
-#include <octave/oct.h>
-
-void save_canvas(canvas *can, char *filename);
-
-DEFUN_DLD (pngwrite, args, ,"\
-pngwrite writes a png file to the disk.\n\
-    pngwrite('filename',R,G,B,A) writes the specified file\n\
-    using the Red, Green, Blue and Alpha matrices.\n\
-    \n\
-    Data must be [0 255] or the high bytes will be lost.")
-{
-   octave_value_list retval;
-   int nargin  = args.length();
-   
-   //
-   // We bail out if the input parameters are bad
-   //
-   if (nargin < 5 || !args(0).is_string() ) {
-     print_usage ();
-     return retval;
-   }
-
-   Matrix red  = args(1).matrix_value();
-   Matrix green= args(2).matrix_value();
-   Matrix blue = args(3).matrix_value();
-   Matrix alpha= args(4).matrix_value();
-   
-   long image_width  = args(1).columns();
-   long image_height = args(1).rows();
-   
-   if ( args(2).columns() != image_width  ||
-	args(3).columns() != image_width  ||
-	args(4).columns() != image_width  ||
-	args(2).rows()    != image_height ||
-	args(3).rows()    != image_height ||
-	args(4).rows()    != image_height )  
-     {
-       error("pngwrite R,G,B,A matrix sizes aren't the same");
-       return retval;
-     }
-   
-   canvas *pic=new_canvas(image_width, image_height, image_width*4);
-   if (!pic) {
-       error("pngwrite out of memory");
-       return retval;
-   }
-
-   for(int i=0; i < pic->width; i++) {
-       for(int j=0; j < pic->height; j++) {
-	   pic->row_pointers[j][i*4+0]=(unsigned char)(red(j,i));
-	   pic->row_pointers[j][i*4+1]=(unsigned char)(green(j,i));
-	   pic->row_pointers[j][i*4+2]=(unsigned char)(blue(j,i));
-	   pic->row_pointers[j][i*4+3]=(unsigned char)(alpha(j,i));
-       }
-   }
-   
-
-   save_canvas(pic,(char *)args(0).string_value().c_str());
-   delete_canvas(pic);
-
-   return retval;
-}
-
-void save_canvas(canvas *can,char *filename)
-{
-  FILE            *fp;
-  png_structp     png_ptr;
-  png_infop       info_ptr;
-  
-  fp = fopen(filename, "wb");
-  if (fp == NULL) {
-    error("pngwrite could not open %s", filename);
-    return;
-  }
-
-  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-  if (!png_ptr) {
-      fclose(fp);
-      error("pngwrite: cannot create write structure");
-      return;
-  }
-
-  info_ptr = png_create_info_struct(png_ptr);
-  if (!info_ptr) {
-      fclose(fp);
-      error("pngwrite: cannot not create image structure");
-      png_destroy_write_struct(&png_ptr, png_infopp_NULL);
-      return;
-  }
-
-  if (setjmp(png_jmpbuf(png_ptr))) {
-      fclose(fp);
-      png_destroy_write_struct(&png_ptr, &info_ptr);
-      error("pngread: libpng exited abnormally");
-      return;
-  }
-
-  png_init_io(png_ptr, fp);
-  png_set_compression_level(png_ptr, 3);
-  
-  png_set_IHDR(png_ptr, info_ptr, can->width, can->height,         
-	       can->bit_depth, can->color_type, PNG_INTERLACE_NONE,
-	       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-  
-  
-  png_set_gAMA(png_ptr, info_ptr, 0.7);
-  
-  time_t          gmt;
-  png_time        mod_time;
-  png_text        text_ptr[2];
-  time(&gmt);
-  png_convert_from_time_t(&mod_time, gmt);
-  png_set_tIME(png_ptr, info_ptr, &mod_time);
-  text_ptr[0].key = "Created by";
-  text_ptr[0].text = "Octave";
-  text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
-  
-  png_set_text(png_ptr, info_ptr, text_ptr, 1);
-  
-  png_write_info(png_ptr, info_ptr);
-  png_write_image(png_ptr, can->row_pointers);
-  png_write_end(png_ptr, info_ptr);                      
-  png_destroy_write_struct(&png_ptr, &info_ptr);          
-  fclose(fp); 
-}
deleted file mode 100644
--- a/poly2mask.m
+++ /dev/null
@@ -1,253 +0,0 @@
-## 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{BW} = } poly2mask (@var{x},@var{y},@var{m},@var{n})
-## Convert a polygon to a region mask
-##
-## BW=poly2mask(x,y,m,n) converts a polygon, specified by a list of
-## vertices in @var{x} and @var{y} and returns in a @var{m}-by-@var{n}
-## logical mask @var{BW} the filled polygon. Region inside the polygon
-## is set to 1, values outside the shape are set to 0.
-##
-## @var{x} and @var{y} should always represent a closed polygon, first
-## and last points should be coincident. If they are not poly2mask will
-## close it for you. If @var{x} or @var{y} are fractional they are
-## nearest integer.
-##
-## If all the polygon or part of it falls outside the masking area
-## (1:m,1:n), it is discarded or clipped.
-##
-## This function uses scan-line polygon filling algorithm as described
-## in http://www.cs.rit.edu/~icss571/filling/ with some minor
-## modifications: capability of clipping and scan order, which can
-## affect the results of the algorithm (algorithm is described not to
-## reach ymax, xmax border when filling to avoid enlarging shapes). In
-## this function we scan the image backwards (we begin at ymax and end
-## at ymin), and we don't reach ymin, xmin, which we believe should be
-## compatible with MATLAB.
-## @end deftypefn
-
-
-## TODO: check how to create a logical BW without any conversion
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function BW = poly2mask(x, y, m, n)
-  if (nargin!=4)
-    usage("BW = poly2mask(x, y, m, n)");
-  endif
-
-  ## check x and y
-  x=round(x(:)');
-  y=round(y(:)');
-  if(length(x)<3)
-    error("poly2mask: polygon must have at least 3 vertices.");
-  endif
-  if(length(x)!=length(y))
-    error("poly2mask: length of x doesn't match length of y.");
-  endif
-
-  ## create output matrix
-  uint8(0); ## This fails for octave < 2.1.58
-  BW=logical(zeros(m,n,"uint8"));
-
-  ## close polygon if needed
-  if((x(1)!=x(length(x)))||(y(1)!=y(length(y))))
-    x=horzcat(x,x(1));
-    y=horzcat(y,y(1));
-  endif
-
-  ## build global edge table
-  ex=[x(1:length(x)-1);x(1,2:length(x))]; ## x values for each edge
-  ey=[y(1:length(y)-1);y(1,2:length(y))]; ## y values for each edge
-  idx=find(ey(1,:)!=ey(2,:));             ## eliminate horizontal edges
-  ex=ex(:,idx);
-  ey=ey(:,idx);
-  eminy=min(ey);                          ## minimum y for each edge
-  emaxy=max(ey);                          ## maximum y for each edge
-  t=ey==[eminy;eminy];                    ## values associated to miny
-  exminy=ex(:)(find(t));                  ## x values associated to min y
-  exmaxy=ex(:)(find(!t));                 ## x values associated to max y
-  emaxy=emaxy';                           ## we want them vertical now...
-  eminy=eminy';
-  m_inv=(exmaxy-exminy)./(emaxy-eminy);   ## calculate inverse slope
-  ge=[emaxy, eminy, exmaxy, m_inv];       ## build global edge table
-  ge=sortrows(ge,[1,3]);                  ## sort on eminy and exminy
-
-  ## we add an extra dummy edge at the end just to avoid checking
-  ## while indexing it
-  ge=[-Inf,-Inf,-Inf,-Inf;ge];
-
-  ## initial parity is even (0)
-  parity=0;
-
-  ## init scan line set to bottom line
-  sl=ge(size(ge,1),1);
-
-  ## init active edge table
-  ## we use a loop because the table is sorted and edge list could be
-  ## huge
-  ae=[];
-  gei=size(ge,1);
-  while sl==ge(gei,1)
-    ae=[ge(gei,2:4);ae];
-    gei-=1;
-  endwhile
-
-  ## calc minimum y to draw
-  miny=min(y);
-  if (miny<1)
-    miny=1;
-  endif
-
-  while sl>=miny
-    ## check vert clipping
-    if(sl<=m)
-      ## draw current scan line
-      ## we have to round because 1/m is fractional
-      ie=round(reshape(ae(:,2),2,size(ae)/2));
-
-      ## this discards left border of image (this differs from version at
-      ## http://www.cs.rit.edu/~icss571/filling/ which discards right
-      ## border) but keeps an exception when the point is a vertex.
-      ie(1,:)+=ie(1,:)!=ie(2,:);
-
-      ## we'll clip too, just in case m,n is not big enough
-      ie(1,find(ie(1,:)<1))=1;
-      ie(2,find(ie(2,:)>n))=n;
-
-      ## we eliminate segments outside window
-      ie=ie(:,find(ie(1,:)<=n));
-      ie=ie(:,find(ie(2,:)>=1));
-      for i=1:columns(ie)
-	BW(sl,ie(1,i):ie(2,i))=true;
-      endfor
-    endif
-
-    ## decrement scan line
-    sl-=1;
-
-    ## eliminate edges that eymax==sl
-    ## this discards ymin border of image (this differs from version at
-    ## http://www.cs.rit.edu/~icss571/filling/ which discards ymax).
-    ae=ae(find(ae(:,1)!=sl),:);
-
-    ## update x (x1=x0-1/m)
-    ae(:,2)-=ae(:,3);
-
-    ## update ae with new values
-    while sl==ge(gei,1)
-      ae=vertcat(ae,ge(gei,2:4));
-      gei-=1;
-    endwhile
-
-    ## order the edges in ae by x value
-    if(rows(ae)>0)
-      ae=sortrows(ae,2);
-    endif
-  endwhile
-endfunction
-
-
-%!demo
-%! s=[0:pi/4:2*pi];
-%! x=cos(s)*90+101;
-%! y=sin(s)*90+101;
-%! bw=poly2mask(x,y,200,200);
-%! imshow(bw);
-%! %Creates a filled octagon
-
-%!demo
-%! s=[0:2*pi/5:pi*4];
-%! s=s([1,3,5,2,4,6]);
-%! x=cos(s)*90+101;
-%! y=sin(s)*90+101;
-%! bw=poly2mask(x,y,200,200);
-%! imshow(bw);
-%! %Creates a 5-vertex star
-
-%!# Convex polygons
-
-%!shared xs, ys, Rs, xt, yt, Rt
-%! xs=[3,3,10,10];
-%! ys=[4,12,12,4];
-%! Rs=zeros(16,14);
-%! Rs(5:12,4:10)=1;
-%! Rs=logical(Rs);
-%! xt=[1,4,7];
-%! yt=[1,4,1];
-%! Rt=[0,0,0,0,0,0,0;
-%!     0,0,1,1,1,1,0;
-%!     0,0,0,1,1,0,0;
-%!     0,0,0,1,0,0,0;
-%!     0,0,0,0,0,0,0];
-%! Rt=logical(Rt);
-
-%!assert(poly2mask(xs,ys,16,14),Rs);          # rectangle
-%!assert(poly2mask(xs,ys,8,7),Rs(1:8,1:7));   # clipped
-%!assert(poly2mask(xs-7,ys-8,8,7),Rs(9:16,8:14)); # more clipping
-
-%!assert(poly2mask(xt,yt,5,7),Rt);            # triangle
-%!assert(poly2mask(xt,yt,3,3),Rt(1:3,1:3));   # clipped
-
-
-%!# Concave polygons
-
-%!test
-%! x=[3,3,5,5,8,8,10,10];
-%! y=[4,12,12,8,8,11,11,4];
-%! R=zeros(16,14);
-%! R(5:12,4:5)=1;
-%! R(5:8,6:8)=1;
-%! R(5:11,9:10)=1;
-%! R=logical(R);
-%! assert(poly2mask(x,y,16,14), R);
-
-%!# Complex polygons
-%!test
-%! x=[1,5,1,5];
-%! y=[1,1,4,4];
-%! R=[0,0,0,0,0,0;
-%!    0,0,1,1,0,0;
-%!    0,0,1,1,0,0;
-%!    0,1,1,1,1,0;
-%!    0,0,0,0,0,0];
-%! R=logical(R);
-%! assert(poly2mask(x,y,5,6), R);
-
-
-
-
-
-%
-% $Log$
-% Revision 1.5  2004/09/07 14:47:50  pkienzle
-% Avoid segfaults on pre-2.1.58 octave.  Invisible whitespace changes.
-%
-% Revision 1.4  2004/09/03 17:12:36  jmones
-% Uses uint8 to save some temporal memory (suggested by David Bateman)
-%
-% Revision 1.3  2004/09/03 13:32:07  jmones
-% Work with logical arrays from BW creation
-%
-% Revision 1.2  2004/08/11 17:39:51  jmones
-% Algorithm url in docs corrected.
-%
-% Revision 1.1  2004/08/11 17:34:11  jmones
-% poly2mask added: creates filled polygon bw mask
-%
-%
deleted file mode 100644
--- a/prism.m
+++ /dev/null
@@ -1,48 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} prism (@var{n})
-## Create color colormap. 
-## (cycling trough red, orange, yellow, green, blue and violet)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = prism (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("prism: argument must be a scalar");
-    endif
-  else
-    usage ("prism (number)");
-  endif
-
-  p = [1, 0, 0; 1, 1/2, 0; 1, 1, 0; 0, 1, 0; 0, 0, 1; 2/3, 0, 1];
-
-  if (rem (number, 6) == 0)
-    map = kron(ones (fix (number / 6), 1), p);
-  else
-    map = [kron(ones (fix (number / 6), 1), p); p(1:rem (number, 6), :)];
-  endif
-
-endfunction
deleted file mode 100644
--- a/qtdecomp.m
+++ /dev/null
@@ -1,328 +0,0 @@
-## 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{S} = } qtdecomp (@var{I})
-## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold})
-## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{mindim})
-## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{threshold},@var{[mindim maxdim]})
-## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun})
-## @deftypefnx {Function File} {@var{S} = } qtdecomp (@var{I},@var{fun},@var{P1},@var{P2},...)
-## Performs quadtree decomposition
-##
-## qtdecomp decomposes a square image @var{I} into four equal-sized
-## blocks. Then it performs some kind of test on each block to decide if
-## it should decompose them further. This process is repeated
-## iteratively until there's no block left to be decomposed.
-##
-## Note that blocks are not decomposed if their dimensions are not even.
-##
-## The output is a sparse matrix whose non-zero elements determine the
-## position of the block (the element is at top-left position in the
-## block) and size of each block (the value of the element determines
-## length of a side of the square-shaped block).
-##
-## S = qtdecomp(I) decomposes an intensity image @var{I} as described
-## above. By default it doesn't split a block if all elements are equal.
-##
-## S = qtdecomp(I, threshold) decomposes an image as decribed, but only
-## splits a block if the maximum value in the block minus the minimum
-## value is greater than @var{threshold}, which is a value between 0 and
-## 1. If @var{I} is of class uint8, @var{threshold} is multiplied by 255
-## before use. Also, if@var{I} is of class uint16, @var{threshold} is 
-## multiplied by 65535.
-##
-## S = qtdecomp(I, threshold, mindim) decomposes an image using the
-## @var{threshold} as just described, but doesn't produce blocks smaller
-## than mindim.
-##
-## S = qtdecomp(I, threshold, [mindim maxdim]) decomposes an image as
-## described, but produces blocks that can't be bigger than maxdim. It
-## decomposes to maxdim even if it isn't needed if only @var{threshold}
-## was considered.
-##
-## S = qtdecomp(I, fun) decomposes an image @var{I} and uses function
-## @var{fun} to decide if a block should be splitted or not. @var{fun}
-## is called with a m-by-m-by-k  array of m-by-m blocks to be
-## considered, and should return a vector of size k, whose elements
-## represent each block in the stacked array. @var{fun} sets the
-## corresponding value to 1 if the block should be split, and 0
-## otherwise.
-##
-## S = qtdecomp(I, fun, ...) behaves as qtdecomp(I, fun) but passes
-## extra parameters to @var{fun}.
-##
-## @end deftypefn
-## @seealso qtgetblk, qtsetblk
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function S = qtdecomp(I, p1, varargin)
-  if (nargin<1)
-    usage("S=qtdecomp(I)");
-  endif
-  
-  if (!ismatrix(I) || size(I,1)!=size(I,2))
-    error("qtdecomp: I should be a square matrix.");
-  endif
-
-  ## current size (assumed to be square)
-  curr_size=size(I,1);
-
-  ## initial mindim to a sensible value
-  mindim=1;
- 
-  ## sensible default maxdim value
-  maxdim=curr_size;
-
-  if (nargin<2)
-    ## Initialize decision method variable
-    ## We could have implemented threshold as a function and use an
-    ## uniform interface (function handle) to decide whether to split or
-    ## not blocks. We have decided not to do so because block
-    ## rearrangement that is needed as a parameter to functions is
-    ## expensive.
-    decision_method=0;
-  elseif (isreal(p1))
-    ## p1 is threshold
-    threshold=p1;
-    decision_method=1;
-
-    if(strcmp(typeinfo(I), 'uint8 matrix'))
-      threshold*=255;
-    elseif(strcmp(typeinfo(I), 'uint16 matrix'))
-      threshold*=65535;
-    endif
-
-    if (nargin>3)
-      usage("S=qtdecomp(I,threshold,mindim),        \
-	  S=qtdecomp(I,threshold,[mindim maxdim])");
-    elseif (nargin==3)
-      dims=varargin{1};
-      if (isvector(dims)&&length(dims)==2)
-	mindim=dims(1);
-	maxdim=dims(2);
-      elseif (isreal(dims))
-	mindim=dims;
-      else
-	error("qtdecomp: third parameter must be 'mindim' or '[mindim maxdim]'");
-      endif
-      ## we won't check if mindim or maxdim are powers of 2. It's too
-      ## restrictive and don't need it at all.
-    endif
-    
-  elseif strcmp(typeinfo(p1),"function handle") ...
-  	  || strcmp(typeinfo(p1),"inline function")
-    ## function handles seem to return true to isscalar
-    fun=p1;
-    decision_method=2;
-  else
-    error("qtdecomp: second parameter must be a integer (threshold) or a function handle (fun).");
-  endif
-  
-  ## initialize results matrices
-  res=[];
-
-  ## bool to flag end
-  finished=false;
-
-  ## array of offsets to blocks to evaluate
-  offsets=[1,1];
-
-  if (maxdim<mindim)
-    error("qtdecomp: mindim must be smaller than maxdim.");
-  endif
-
-  ## See if we have to split a minimum regarless other considerations.
-  if (maxdim<curr_size)
-    initial_splits=ceil(log2(curr_size/maxdim));
-    if(initial_splits>0)
-      divs=2^initial_splits;
-      if (rem(curr_size,divs)!=0)
-	error("qtdecomp: Can't decompose I enough times to fulfill maxdim requirement.");
-      endif
-      ## update curr_size
-      curr_size/=divs;
-      if(curr_size<mindim)
-	error("qtdecomp: maxdim restriction collides with mindim restriction.");
-      endif
-      els=transpose([0:divs-1]*curr_size+1);
-      offsets=[kron(els,ones(divs,1)), kron(ones(divs,1),els)];
-    endif
-  endif
-
-  while(!finished && rows(offsets)>0)
-    ## check other ending conditions:
-    ## is size is odd?
-    ## is splitted size < than mindim?
-    if ((rem(curr_size,2)!=0)||((curr_size/2)<mindim))
-      ## can't continue, lets add current evaluation blocks to results
-      res=[res; offsets, ones(size(offsets,1),1)*curr_size];
-      finished = true;
-    else
-      if (decision_method<2)
-	db=logical(ones(rows(offsets),1));
-	for r=1:rows(offsets)
-	  o=offsets(r,:);
-	  fo=offsets(r,:)+curr_size-1;
-
-	  if(decision_method==0)
-	    ## is everything equal?
-	    if (all(I(o(1),o(2))==I(o(1):fo(1),o(2):fo(2))))
-	      db(r)=0;
-	    endif
-	  else
-	    ## check threshold
-	    t=I(o(1):fo(1),o(2):fo(2));
-	    t=t(:);
-	    if ((max(t)-min(t))<=threshold)
-	      db(r)=0;
-	    endif
-	  endif
-	endfor
-      elseif(decision_method==2)
-	## function handle decision method
-	## build blocks
-	b=zeros(curr_size,curr_size,rows(offsets));
-	rbc=offsets(:,1:2)+curr_size-1;
-	for r=1:rows(offsets)
-	  b(:,:,r)=I(offsets(r,1):rbc(r,1),offsets(r,2):rbc(r,2));
-	endfor
-
-	db=feval(fun, b, varargin{:});
-      else
-	error("qtdecomp: execution shouldn't reach here. Please report this as a bug.");
-      endif
-
-      ## Add blocks that won't divide to results
-      nd=offsets(find(!db),:);
-      res=[res; nd, ones(size(nd,1),1)*curr_size];
-      
-      ## Update curr_size for next iteration
-      curr_size/=2;
-      
-      ## Prepare offsets for next iteration
-      otemp=offsets(find(db),:);
-      hs=ones(rows(otemp),1)*curr_size;
-      zs=zeros(size(hs));
-      offsets=[otemp;otemp+[hs,zs];otemp+[zs,hs];otemp+[hs,hs]];
-    endif
-  endwhile
-
-  S=sparse(res(:,1),res(:,2),res(:,3),size(I,1),size(I,2));
-endfunction
-
-
-%!demo
-%! full(qtdecomp(eye(8)))
-%! %It finds 2 big blocks of 0 and it decomposes further where 0 and 1 are mixed.
-
-
-%!# Test if odd-sized limits split
-%!assert(full(qtdecomp(eye(5))), reshape([5,zeros(1,24)],5,5));
-%!assert(full(qtdecomp(eye(6))), repmat(reshape([3,zeros(1,8)],3,3),2,2));
-
-%!# Test 'equal' method
-%!test
-%! a=ones(2,2);
-%! b=[2,0;0,0];
-%! assert(full(qtdecomp(eye(4))), [a,b;b,a]);
-
-%!shared A, B2, B4
-%! A=[ 1, 4, 2, 5,54,55,61,62;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!    23,42,42,42,99,99,99,99;    
-%!    27,42,42,42,99,99,99,99;    
-%!    23,22,26,25,99,99,99,99;    
-%!    22,22,24,22,99,99,99,99];
-%! B2=[2,0;0,0];
-%! B4=zeros(4); B4(1,1)=4;
-
-%!test
-%! R=[ones(4,8); [ones(2),B2;ones(2,4)], B4];
-%! assert(full(qtdecomp(A)), R);
-%! assert(full(qtdecomp(A,0)), R);
-
-%!# Test 'threshold' method
-%!test
-%! R=[ones(4,8); [ones(2),B2;B2,ones(2)],B4];
-%! assert(full(qtdecomp(A,1)), R);
-
-%!test
-%! R=[[B4,[B2,B2;B2,B2]]; [[ones(2),B2;B2,B2],B4]];
-%! assert(full(qtdecomp(A,10)), R);
-
-%!test
-%! R=[[B4,[B2,B2;B2,B2]]; [[B2,B2;B2,B2],B4]];
-%! assert(full(qtdecomp(A,10,2)), R);
-
-%!assert(full(qtdecomp(A,100,[2, 4])), [B4,B4;B4,B4]);
-
-%!# Test 'fun' method
-%!# Can't define a function inside tests because Octave
-%!# complains about nested functions. If you know how to
-%!# do it please add function handle tests.
-
-%!# inline version
-%!# We use [size(A),1](3) as a trick since size(A,3) fails if A is 2D.
-
-%!# no params
-%!test
-%! first_eq=inline("(A(1,1,:)!=(54*ones(1,1,[size(A),1](3))))(:)","A");
-%! assert(full(qtdecomp(A,first_eq)),[ones(4),B4;ones(4,8)]); 
-
-%!# 1 param
-%!test
-%! first_eq=inline("(A(1,1,:)!=(c*ones(1,1,[size(A),1](3))))(:)","A","c");
-%! assert(full(qtdecomp(A,first_eq,54)),[ones(4),B4;ones(4,8)]); 
-
-%!# 3 params
-%!test
-%! first_eq=inline("(A(1,1,:)!=((c1+c2+c3)*ones(1,1,[size(A),1](3))))(:)","A","c1","c2","c3");
-%! assert(full(qtdecomp(A,first_eq,4,40,10)),[ones(4),B4;ones(4,8)]); 
-
-
-
-%
-% $Log$
-% Revision 1.8  2006/01/03 02:09:15  pkienzle
-% Reorder tests so that shared variables are displayed unless relevant.
-%
-% Revision 1.7  2006/01/02 22:05:06  pkienzle
-% Reduce number of shared variables in tests
-%
-% Revision 1.6  2004/09/09 19:36:35  jmones
-% all_va_args -> varargin{:}. Now works on 2.1.58
-%
-% Revision 1.5  2004/09/08 14:07:22  pkienzle
-% Fix test for 'inline function'
-%
-% Revision 1.4  2004/08/11 19:52:41  jmones
-% qtsetblk added
-%
-% Revision 1.3  2004/08/11 00:05:21  jmones
-% seealso qtgetblk added to doc
-%
-% Revision 1.2  2004/08/10 00:19:42  jmones
-% Corrected misleading comment.
-%
-% Revision 1.1  2004/08/09 01:48:54  jmones
-% Added qtdecomp: quadtree decomposition
-%
-%
-
deleted file mode 100644
--- a/qtgetblk.m
+++ /dev/null
@@ -1,151 +0,0 @@
-## 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{vals}] = } qtgetblk (@var{I},@var{S},@var{dim})
-## @deftypefnx {Function File} {[@var{vals},@var{idx}] = } qtgetblk (@var{I},@var{S},@var{dim})
-## @deftypefnx {Function File} {[@var{vals},@var{r},@var{c}] = } qtgetblk (@var{I},@var{S},@var{dim})
-## Obtain block values from a quadtree decomposition
-##
-## [vals]=qtgetblk(I,S,dim) returns a dim-by-dim-by-k array in
-## @var{vals} which contains the dim-by-dim blocks in the quadtree
-## decomposition (@var{S}, which is returned by qtdecomp) of @var{I}. If
-## there are no blocks, an empty matrix is returned.
-##
-## [vals,idx]=qtgetblk(I,S,dim) returns @var{vals} as described above.
-## In addition, it returns @var{idx}, a vector which contains the linear
-## indices of the upper left corner of each block returned (the same
-## result as find(full(S)==dim)).
-##
-## [vals,r,c]=qtgetblk(I,S,dim) returns @var{vals} as described, and two
-## vectors, @var{r} and @var{c}, which contain the row and column
-## coordinates of the blocks returned.
-##
-## @end deftypefn
-## @seealso qtdecomp, qtsetblk
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function [varargout] = qtgetblk(I, S, dim)
-  if (nargin!=3)
-    usage("[vals,r,c]=qtgetblk(I,S,dim), [vals,idx]=qtgetblk(I,S,dim)");
-  endif
-  if (nargout>3)
-    usage("[vals,r,c]=qtgetblk(I,S,dim), [vals,idx]=qtgetblk(I,S,dim)");
-  endif
-
-  ## get blocks
-  [i,j,v]=spfind(S);
-
-  ## filter the ones which match dim
-  idx=find(v==dim);
-  
-  if(length(idx)==0)
-    for i=1:nargout
-      varargout{i}=[];
-    endfor
-  else
-    r=i(idx);
-    c=j(idx);
-    
-    ## copy to a dim-by-dim-by-k array
-    vals=zeros(dim,dim,length(idx));
-    for i=1:length(idx)
-      vals(:,:,i)=I(r(i):r(i)+dim-1,c(i):c(i)+dim-1);
-    endfor
-    
-    varargout{1}=vals;
-  
-    if(nargout==3)
-      varargout{2}=r;
-      varargout{3}=c;
-    elseif(nargout==2)
-      varargout{2}=(c-1)*rows(I)+r;
-    endif
-  endif
-endfunction
-
-
-%!demo
-%! [vals,r,c]=qtgetblk(eye(4),qtdecomp(eye(4)),2)
-%! % Returns 2 blocks, at [1,3] and [3,1] (2*2 zeros blocks)
-
-%!shared A,S
-%! A=[ 1, 4, 2, 5,54,55,61,62;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!    23,42,42,42,99,99,99,99;    
-%!    27,42,42,42,99,99,99,99;    
-%!    23,22,26,25,99,99,99,99;    
-%!    22,22,24,22,99,99,99,99];
-%! S=qtdecomp(A,10);
-
-%!test
-%! [va]=qtgetblk(A,S,8);
-%! [vb,r,c]=qtgetblk(A,S,8);
-%! [vc,i]=qtgetblk(A,S,8);
-%! assert(va, vb);
-%! assert(va, vc);
-%! assert(i,[]);
-%! assert(r,[]);
-%! assert(c,[]);
-%! R=[];
-%! assert(va,R);
-
-
-%!test
-%! [va]=qtgetblk(A,S,4);
-%! [vb,r,c]=qtgetblk(A,S,4);
-%! [vc,i]=qtgetblk(A,S,4);
-%! assert(va, vb);
-%! assert(va, vc);
-%! assert(i, find(full(S)==4));
-%! assert(r,[1;5]);
-%! assert(c,[1;5]);
-%! R=zeros(4,4,2);
-%! R(:,:,1)=A(1:4,1:4);
-%! R(:,:,2)=A(5:8,5:8);
-%! assert(va,R);
-
-%!test
-%! [va]=qtgetblk(A,S,2);
-%! [vb,r,c]=qtgetblk(A,S,2);
-%! [vc,i]=qtgetblk(A,S,2);
-%! assert(va, vb);
-%! assert(va, vc);
-%! assert(i, find(full(S)==2));
-%! assert(r,[7;5;7;1;3;1;3]);
-%! assert(c,[1;3;3;5;5;7;7]);
-%! R=zeros(2,2,7);
-%! R(:,:,1)=A(7:8,1:2);
-%! R(:,:,2)=A(5:6,3:4);
-%! R(:,:,3)=A(7:8,3:4);
-%! R(:,:,4)=A(1:2,5:6);
-%! R(:,:,5)=A(3:4,5:6);
-%! R(:,:,6)=A(1:2,7:8);
-%! R(:,:,7)=A(3:4,7:8);
-%! assert(va,R);
-
-%
-% $Log$
-% Revision 1.3  2006/01/02 20:53:42  pkienzle
-% Reduce number of shared variables in tests
-%
-% Revision 1.2  2004/08/11 19:52:41  jmones
-% qtsetblk added
-%
-%
deleted file mode 100644
--- a/qtsetblk.m
+++ /dev/null
@@ -1,102 +0,0 @@
-## 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{J} = } qtsetblk (@var{I},@var{S},@var{dim},@var{vals})
-## Set block values in a quadtree decomposition
-##
-## J=qtsetblk(I,S,dim,vals) sets all the @var{dim}-by-@var{dim} blocks
-## in the quadtree decomposition (@var{S} returned by qtdecomp) of
-## @var{I} to @var{dim}-by-@var{dim} blocks in @var{vals}, which is
-## itself a @var{dim}-by-@var{dim}-by-k array. k is the number of
-## @var{dim}-by-@var{dim} blocks in the quadtree decomposition.
-## @end deftypefn
-## @seealso qtdecomp, qtgetblk
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function J = qtsetblk(I, S, dim, vals)
-  if (nargin!=4)
-    usage("J=qtsetblk(I,S,dim,vals)");
-  endif
-
-  ## get blocks
-  [ii,ji,v]=spfind(S);
-
-  ## filter the ones which match dim
-  idx=find(v==dim);
-  if(size(vals,3)<length(idx)) ## we won't complain if k>num blocks
-    error("qtsetblk: k (vals 3rd dimension) is not equal to number of blocks.");
-  endif
-  ii=ii(idx);
-  ji=ji(idx);
-  
-  ## calc end vertex
-  ie=ii+dim-1;
-  je=ji+dim-1;
-
-
-  J=I;
-  for b=1:length(idx)
-    J(ii(b):ie(b),ji(b):je(b))=vals(:,:,b);
-  endfor
-endfunction
-
-
-%!demo
-%! J=qtsetblk(eye(4),qtdecomp(eye(4)),2,ones(2,2,2))
-%! % Sets upper-right and lower-left blocks of 2*2 zeros to ones
-
-%!shared A, S
-%! A=[ 1, 4, 2, 5,54,55,61,62;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!     3, 6, 3, 1,58,53,67,65;
-%!    23,42,42,42,99,99,99,99;    
-%!    27,42,42,42,99,99,99,99;    
-%!    23,22,26,25,99,99,99,99;    
-%!    22,22,24,22,99,99,99,99];
-%! S=qtdecomp(A,10);
-
-%!test
-%! R=A;
-%! vals=zeros(4,4,2);
-%! vals(:,:,1)=reshape([1:16],4,4);
-%! vals(:,:,2)=reshape([21:36],4,4);
-%! R(1:4,1:4)=reshape([1:16],4,4);
-%! R(5:8,5:8)=reshape([21:36],4,4);
-%! assert(qtsetblk(A,S,4,vals),R);
-
-%!test
-%! R=A;
-%! R(1:4,5:8)=1;
-%! R(7:8,1:4)=1;
-%! R(5:6,3:4)=1;
-%! assert(qtsetblk(A,S,2,ones(2,2,7)),R);
-
-%!test
-%! R=A;
-%! R(5:6,1:2)=10;
-%! assert(qtsetblk(A,S,1,ones(1,1,4)*10),R);
-
-
-
-%
-% $Log$
-% Revision 1.1  2004/08/11 19:52:41  jmones
-% qtsetblk added
-%
-%
deleted file mode 100644
--- a/rainbow.m
+++ /dev/null
@@ -1,56 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} rainbow (@var{n})
-## Create color colormap. 
-## (red through orange, yellow, green, blue to violet)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = rainbow (number)
-## this colormap is not part of matlab, it is like the prism
-## colormap map but with a continuous map
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("rainbow: argument must be a scalar");
-    endif
-  else
-    usage ("rainbow (number)");
-  endif
-
-  if (number == 1)
-    map = [1, 0, 0];  
-  elseif (number > 1)
-    x = linspace (0, 1, number)';
-    r = (x < 2/5) + (x >= 2/5 & x < 3/5) .* (-5 * x + 3)\
-      + (x >= 4/5) .* (10/3 * x - 8/3);
-    g = (x < 2/5) .* (5/2 * x) + (x >= 2/5 & x < 3/5)\
-      + (x >= 3/5 & x < 4/5) .* (-5 * x + 4);
-    b = (x >= 3/5 & x < 4/5) .* (5 * x - 3) + (x >= 4/5);
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/rgb2gray.m
+++ /dev/null
@@ -1,47 +0,0 @@
-## Copyright (C) 2000, 2001  Kai Habel
-##
-## 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{I}= rgb2gray (@var{M})
-## converts a color map to a gray map. 
-## The RGB map is converted into the YIQ space of ntsc. The luminance
-## value (Y) is taken to create a gray color map.
-## R = G = B = Y
-## @end deftypefn
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	19. March 2000
-
-function graymap = rgb2gray (rgb)
-
-  if (nargin != 1)
-    usage ("graymap = rgb2gray (map)");
-  endif
-
-  msg = "rgb2gray: argument must be a matrix of size n x 3";
-  if (! is_matrix (rgb))
-    error (msg);
-  endif
-
-  nc = columns (rgb);
-  if (nc != 3)
-    error (msg);
-  endif
-
-  ntscmap = rgb2ntsc (rgb);
-
-  graymap = ntscmap (:, 1) * ones (1, 3);
-endfunction
deleted file mode 100644
--- a/roicolor.m
+++ /dev/null
@@ -1,74 +0,0 @@
-## 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{BW} = } roicolor (@var{A},@var{low},@var{high})
-## @deftypefnx {Function File} {@var{BW} = } roicolor (@var{A},@var{v})
-## Select a Region Of Interest of an image based on color.
-##
-## BW = roicolor(A,low,high) selects a region of interest (ROI) of an
-## image @var{A} returning a black and white image in a logical array (1 for
-## pixels inside ROI and 0 outside ROI), which is formed by all pixels
-## whose values lie within the colormap range specified by [@var{low}
-## @var{high}].
-##
-## BW = roicolor(A,v) selects a region of interest (ROI) formed by all
-## pixels that match values in @var{v}.
-## @end deftypefn
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function BW = roicolor(A, p1, p2)
-  if (nargin < 2 || nargin > 3)
-    usage("BW = roicolor(A, low, high), BW = roicolor(A, v)");
-  endif
-
-  if (nargin == 2)
-    if (!isvector(p1))
-      error("BW = roicolor(A, v): v should be a vector.");
-    endif
-    BW=logical(zeros(size(A)));
-    for c=p1
-      BW|=(A==c);
-    endfor
-  elseif (nargin==3)
-    if (!isscalar(p1) || !isscalar(p2))
-      error("BW = roicolor(A, low, high): low and high must be scalars.");
-    endif
-    BW=logical((A>=p1)&(A<=p2));
-  endif
-endfunction
-
-%!demo
-%! roicolor([1:10],2,4);
-%! % Returns '1' where input values are between 2 and 4 (both included).
-
-%!assert(roicolor([1:10],2,4),logical([0,1,1,1,zeros(1,6)]));
-%!assert(roicolor([1,2;3,4],3,3),logical([0,0;1,0]));
-%!assert(roicolor([1,2;3,4],[1,4]),logical([1,0;0,1]));
-
-%
-% $Log$
-% Revision 1.3  2004/09/15 17:54:59  pkienzle
-% test that data type matches during assert
-%
-% Revision 1.2  2004/08/11 15:04:59  pkienzle
-% Convert dos line endings to unix line endings
-%
-% Revision 1.1  2004/08/08 21:02:44  jmones
-% Add roicolor function (selects ROI based on color)
-%
-%
deleted file mode 100644
--- a/rotate_scale.cc
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * ROTATE_SCALE: rotate and scale a matrix using bilinear interpolation
- * imo= block(im, xregs, yregs);
- *
- * Copyright (C) 2003 Andy Adler
- * This code has no warrany whatsoever.
- * Do what you like with this code as long as you
- *     leave this copyright in place.
- *
- * $Id$
- */
-
-#include <octave/oct.h>
-
-void
-calc_rotation_params(
-              double x0l,double y0l,double x0r,double y0r,
-              double x1l,double y1l,double x1r,double y1r,
-              double* Tx_x, double* Ty_x,
-              double* Tx_y, double* Ty_y,
-              double* Tx_1, double* Ty_1 );
-void
-do_interpolation (
-              double Tx_x, double Ty_x,
-              double Tx_y, double Ty_y,
-              double Tx_1, double Ty_1,
-              int x0max, int y0max,// initial size
-              int x1max, int y1max,// output size
-              const double * img0,
-              double       * img1 );
-
-DEFUN_DLD (rotate_scale, args, ,
-  "ROTATE_SCALE: arbitrary rotation and scaling of an image\n"
-  "              using fast bilinear interpolation\n"
-  "im1 = rotate_scale(im0, lm0, lm1, out_size)\n"
-  "  where:\n"
-  "im0 = input image\n"
-  "lm0 = landmarks of points in original image [ x1,x2;y1,y2 ]\n"
-  "im1 = output image, where size(im1) == out_size\n"
-  "lm1 = landmarks of points in output image [ x1,x2;y1,y2 ]\n"
-  "\n"
-  "   note1: two landmarks must be specified for lm0 and lm1\n"
-  "   note2: all images have a single component\n"
-  "   to use this for colour images, use:\n"
-  "  r_im1= rotate_scale( red_im0, lm0, lm1, out_size)\n"
-  "  g_im1= rotate_scale( grn_im0, lm0, lm1, out_size)\n"
-  "  b_im1= rotate_scale( blu_im0, lm0, lm1, out_size)\n"
-  "\n"
-  "   example:\n"
-  "  im0= zeros(100); im0(25:75,25:75)=1;\n"
-  "  im1= rotate_scale( im0, [40,60;50,50],[60,90;60,90],[120,120]);\n"
-)
-{
-   octave_value_list retval;
-   if (args.length() < 4 ||
-       !args(0).is_matrix_type() ||
-       !args(1).is_matrix_type() ||
-       !args(2).is_matrix_type() ||
-       !args(3).is_matrix_type()
-       ) {
-      print_usage ();
-      return retval;
-   }
-
-   Matrix im0( args(0).matrix_value() );
-   const double * im0p = im0.data();
-   Matrix lm0( args(1).matrix_value() );
-   Matrix lm1( args(2).matrix_value() );
-   ColumnVector out_size( args(3).vector_value() );
-
-   int inp_hig= im0.rows();
-   int inp_wid= im0.cols();
-
-   int out_hig= (int) out_size(0);
-   int out_wid= (int) out_size(1);
-   Matrix im1( out_hig, out_wid);
-   double * im1p = im1.fortran_vec();
-
-   double Tx_x; double Ty_x;
-   double Tx_y; double Ty_y;
-   double Tx_1; double Ty_1;
-   calc_rotation_params(
-          lm0(0,0), lm0(1,0), lm0(0,1), lm0(1,1),
-          lm1(0,0), lm1(1,0), lm1(0,1), lm1(1,1),
-          & Tx_x, & Ty_x,
-          & Tx_y, & Ty_y,
-          & Tx_1, & Ty_1 );
-    
-   do_interpolation( Tx_x, Ty_x, Tx_y, Ty_y, Tx_1, Ty_1,
-                  inp_wid, inp_hig, out_wid, out_hig,
-                  im0p, im1p );
-
-   retval(0) = im1;
-   return retval;
-}
-
-inline double sqr(double a) { return (a)*(a); }
-
-void
-calc_rotation_params(
-              double x1l,double y1l,double x1r,double y1r,
-              double x0l,double y0l,double x0r,double y0r,
-              double* Tx_x, double* Ty_x,
-              double* Tx_y, double* Ty_y,
-              double* Tx_1, double* Ty_1 
-              )
-{
-    double d0= sqrt( sqr(x0l-x0r) + sqr(y0l-y0r) );
-    double d1= sqrt( sqr(x1l-x1r) + sqr(y1l-y1r) );
-    double dr= d1/d0;
-
-    double a0= atan2( y0l-y0r , x0l-x0r );
-    double a1= atan2( y1l-y1r , x1l-x1r );
-    double ad= a1-a0;
-    double dr_cos_ad= dr*cos(ad);
-    double dr_sin_ad= dr*sin(ad);
-
-    double x0m= (x0l+x0r)/2;
-    double y0m= (y0l+y0r)/2;
-    double x1m= (x1l+x1r)/2;
-    double y1m= (y1l+y1r)/2;
-
-    *Tx_x=  dr_cos_ad;
-    *Ty_x=  dr_sin_ad;
-    *Tx_y= -dr_sin_ad;
-    *Ty_y=  dr_cos_ad;
-    *Tx_1=  x1m - dr_cos_ad*x0m + dr_sin_ad*y0m;
-    *Ty_1=  y1m - dr_sin_ad*x0m - dr_cos_ad*y0m;
-}    
-
-
-void
-do_interpolation (
-              double Tx_x, double Ty_x,
-              double Tx_y, double Ty_y,
-              double Tx_1, double Ty_1,
-              int x0max, int y0max,// initial size
-              int x1max, int y1max,// output size
-              const double * img0,
-              double       * img1 
-            )
-{
-
-    for (int i=0; i< x1max; i++) {
-        for (int j=0; j< y1max; j++) {
-            double x0i= Tx_x * i + Tx_y * j + Tx_1;
-            double y0i= Ty_x * i + Ty_y * j + Ty_1;
-
-            if ( x0i < 0       )    x0i= 0;
-            else
-            if (x0i >= x0max-1 )    x0i= x0max - 1.00001; 
-
-            if ( y0i < 0       )    y0i= 0;
-            else
-            if (y0i >= y0max-1 )    y0i= y0max - 1.00001; 
-
-            int x0idx= (int) x0i;
-            int y0idx= (int) y0i;
-
-            double frac_r= x0i- x0idx; 
-            double frac_l= 1 - frac_r;
-            double frac_d= y0i- y0idx; 
-            double frac_u= 1 - frac_d;
-
-            int pix_lu= (y0idx+0) + (x0idx+0) * y0max ;
-            int pix_ru= (y0idx+0) + (x0idx+1) * y0max ;
-            int pix_ld= (y0idx+1) + (x0idx+0) * y0max ;
-            int pix_rd= (y0idx+1) + (x0idx+1) * y0max ;
-               
-            img1[ i*y1max + j ]=
-               frac_l*frac_u* img0[ pix_lu ] +
-               frac_r*frac_u* img0[ pix_ru ] +
-               frac_l*frac_d* img0[ pix_ld ] +
-               frac_r*frac_d* img0[ pix_rd ];
-
-        }
-    }
-}
-
deleted file mode 100644
--- a/spring.m
+++ /dev/null
@@ -1,51 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} spring (@var{n})
-## Create color colormap. 
-## (magenta to yellow)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = spring (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("spring: argument must be a scalar");
-    endif
-  else
-    usage ("spring (number)");
-  endif
-
-  if (number == 1)
-    map = [1, 0, 1];  
-  elseif (number > 1)
-    r = ones (number, 1);
-    g = (0:number - 1)' ./ (number - 1);
-    b = 1 - g;
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
new file mode 100644
--- /dev/null
+++ b/src/Makeconf.add
@@ -0,0 +1,3 @@
+@DEFHAVE_JPEG@
+@DEFHAVE_PNG@
+@DEFHAVE_MAGICKXX@
new file mode 100644
--- /dev/null
+++ b/src/Makeconf.base
@@ -0,0 +1,92 @@
+
+## Makeconf is automatically generated from Makeconf.base and Makeconf.add
+## in the various subdirectories.  To regenerate, use ./autogen.sh to
+## create a new ./Makeconf.in, then use ./configure to generate a new
+## Makeconf.
+
+OCTAVE_FORGE = 1
+
+SHELL = @SHELL@
+
+canonical_host_type = @canonical_host_type@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+libdir = @libdir@
+datadir = @datadir@
+infodir = @infodir@
+includedir = @includedir@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLOCT=octinst.sh
+
+DESTDIR =
+
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+LN_S = @LN_S@
+MKOCTLINK = @MKOCTLINK@
+OCTLINK= @OCTLINK@
+
+AWK = @AWK@
+
+# Most octave programs will be compiled with $(MKOCTFILE).  Those which
+# cannot use mkoctfile directly can request the flags that mkoctfile 
+# would use as follows:
+#    FLAG = $(shell $(MKOCTFILE) -p FLAG)
+# The following flags are for compiling programs that are independent
+# of Octave.  How confusing.
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CPICFLAG = @CPICFLAG@
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CXXPICFLAG = @CXXPICFLAG@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FPICFLAG = @FPICFLAG@
+
+OCTAVE = @OCTAVE@
+OCTAVE_VERSION = @OCTAVE_VERSION@
+MKOCTFILE = @MKOCTFILE@ -DHAVE_OCTAVE_$(ver) -v
+SHLEXT = @SHLEXT@
+
+@DEFHAVE_X@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+
+ver = @ver@
+MPATH = @mpath@
+OPATH = @opath@
+XPATH = @xpath@
+ALTMPATH = @altmpath@
+ALTOPATH = @altopath@
+
+HAVE_DO_FORTRAN_INDEXING = @HAVE_DO_FORTRAN_INDEXING@
+HAVE_PROPAGATE_EMPTY_MATRICES = @HAVE_PROPAGATE_EMPTY_MATRICES@
+HAVE_OK_TO_LOSE_IMAGINARY_PART = @HAVE_OK_TO_LOSE_IMAGINARY_PART@
+HAVE_ND_ARRAYS = @HAVE_ND_ARRAYS@
+TYPEID_HAS_CLASS = @TYPEID_HAS_CLASS@
+CLASS_HAS_LOAD_SAVE = @CLASS_HAS_LOAD_SAVE@
+HAVE_OCTAVE_MAP_INDEX = @HAVE_OCTAVE_MAP_INDEX@
+HAVE_OCTAVE_CONCAT = @HAVE_OCTAVE_CONCAT@
+HAVE_SWAP_BYTES = @HAVE_SWAP_BYTES@
+HAVE_OCTAVE_UPLUS = @HAVE_OCTAVE_UPLUS@
+
+MAKEINFO = @MAKEINFO@
+TEXI2DVI = @TEXI2DVI@
+TEXI2HTML = @TEXI2HTML@
+DVIPDF = @DVIPDF@
+DVIPS = @DVIPS@
+
+MKDOC = @MKDOC@
+MKTEXI = @MKTEXI@
+
+%.o: %.c ; $(MKOCTFILE) -c $<
+%.o: %.f ; $(MKOCTFILE) -c $<
+%.o: %.cc ; $(MKOCTFILE) -c $<
+%.oct: %.cc ; $(MKOCTFILE) $<
new file mode 100644
--- /dev/null
+++ b/src/Makeconf.in
@@ -0,0 +1,95 @@
+
+## Makeconf is automatically generated from Makeconf.base and Makeconf.add
+## in the various subdirectories.  To regenerate, use ./autogen.sh to
+## create a new ./Makeconf.in, then use ./configure to generate a new
+## Makeconf.
+
+OCTAVE_FORGE = 1
+
+SHELL = @SHELL@
+
+canonical_host_type = @canonical_host_type@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+bindir = @bindir@
+mandir = @mandir@
+libdir = @libdir@
+datadir = @datadir@
+infodir = @infodir@
+includedir = @includedir@
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALLOCT=octinst.sh
+
+DESTDIR =
+
+RANLIB = @RANLIB@
+STRIP = @STRIP@
+LN_S = @LN_S@
+MKOCTLINK = @MKOCTLINK@
+OCTLINK= @OCTLINK@
+
+AWK = @AWK@
+
+# Most octave programs will be compiled with $(MKOCTFILE).  Those which
+# cannot use mkoctfile directly can request the flags that mkoctfile 
+# would use as follows:
+#    FLAG = $(shell $(MKOCTFILE) -p FLAG)
+# The following flags are for compiling programs that are independent
+# of Octave.  How confusing.
+CC = @CC@
+CFLAGS = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+CPICFLAG = @CPICFLAG@
+CXX = @CXX@
+CXXFLAGS = @CXXFLAGS@
+CXXPICFLAG = @CXXPICFLAG@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+FPICFLAG = @FPICFLAG@
+
+OCTAVE = @OCTAVE@
+OCTAVE_VERSION = @OCTAVE_VERSION@
+MKOCTFILE = @MKOCTFILE@ -DHAVE_OCTAVE_$(ver) -v
+SHLEXT = @SHLEXT@
+
+@DEFHAVE_X@
+X_CFLAGS = @X_CFLAGS@
+X_LIBS = @X_LIBS@
+
+ver = @ver@
+MPATH = @mpath@
+OPATH = @opath@
+XPATH = @xpath@
+ALTMPATH = @altmpath@
+ALTOPATH = @altopath@
+
+HAVE_DO_FORTRAN_INDEXING = @HAVE_DO_FORTRAN_INDEXING@
+HAVE_PROPAGATE_EMPTY_MATRICES = @HAVE_PROPAGATE_EMPTY_MATRICES@
+HAVE_OK_TO_LOSE_IMAGINARY_PART = @HAVE_OK_TO_LOSE_IMAGINARY_PART@
+HAVE_ND_ARRAYS = @HAVE_ND_ARRAYS@
+TYPEID_HAS_CLASS = @TYPEID_HAS_CLASS@
+CLASS_HAS_LOAD_SAVE = @CLASS_HAS_LOAD_SAVE@
+HAVE_OCTAVE_MAP_INDEX = @HAVE_OCTAVE_MAP_INDEX@
+HAVE_OCTAVE_CONCAT = @HAVE_OCTAVE_CONCAT@
+HAVE_SWAP_BYTES = @HAVE_SWAP_BYTES@
+HAVE_OCTAVE_UPLUS = @HAVE_OCTAVE_UPLUS@
+
+MAKEINFO = @MAKEINFO@
+TEXI2DVI = @TEXI2DVI@
+TEXI2HTML = @TEXI2HTML@
+DVIPDF = @DVIPDF@
+DVIPS = @DVIPS@
+
+MKDOC = @MKDOC@
+MKTEXI = @MKTEXI@
+
+%.o: %.c ; $(MKOCTFILE) -c $<
+%.o: %.f ; $(MKOCTFILE) -c $<
+%.o: %.cc ; $(MKOCTFILE) -c $<
+%.oct: %.cc ; $(MKOCTFILE) $<
+@DEFHAVE_JPEG@
+@DEFHAVE_PNG@
+@DEFHAVE_MAGICKXX@
new file mode 100644
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,37 @@
+sinclude Makeconf
+
+ifdef HAVE_JPEG
+	JPEG=jpgwrite.oct jpgread.oct
+endif
+
+ifdef HAVE_PNG
+	PNG=pngread.oct pngwrite.oct
+endif
+
+ifdef HAVE_MAGICKXX
+	IMAGEMAGICK=__imagemagick__.oct __magick_read__$(OCTLINK)
+endif
+
+all: cordflt2.oct bwlabel.oct bwfill.oct rotate_scale.oct \
+	houghtf.oct graycomatrix.oct \
+	$(JPEG) $(PNG) $(IMAGEMAGICK)
+
+jpgread.oct: jpgread.cc
+	$(MKOCTFILE) $< -ljpeg
+
+jpgwrite.oct: jpgwrite.cc
+	$(MKOCTFILE) $< -ljpeg
+
+pngread.oct: pngread.cc
+	$(MKOCTFILE) $< -lpng
+
+pngwrite.oct: pngwrite.cc
+	$(MKOCTFILE) $< -lpng
+
+__imagemagick__.oct: __imagemagick__.cc
+	$(MKOCTFILE) $< -lMagick++ -lMagick
+
+__magick_read__$(OCTLINK): __imagemagick__.oct
+	$(MKOCTLINK) __imagemagick__.oct $@
+
+clean: ; -$(RM) *.o octave-core core *.oct *~
new file mode 100644
--- /dev/null
+++ b/src/__imagemagick__.cc
@@ -0,0 +1,310 @@
+#include <octave/oct.h>
+#include <Magick++.h>
+#include <iostream>
+using namespace std;
+using namespace Magick;
+
+octave_value_list read_indexed_images(vector<Image> imvec, Array<int> frameidx, bool wantalpha)
+{
+    octave_value_list output;
+    int rows = imvec[0].baseRows();
+    int columns = imvec[0].baseColumns();
+    int nframes = frameidx.length();
+    ImageType type = imvec[0].type();
+    
+    unsigned int mapsize = imvec[0].colorMapSize();
+    int i = mapsize;
+    unsigned int depth = 0;
+    while(i >>= 1) depth++;
+    i = 0;
+    depth--;
+    while(depth >>= 1) i++;
+    depth = 1 << i;
+
+    int x, y, frame;
+    const IndexPacket *pix;
+    switch(depth) {
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+	{
+	    uint8NDArray im = uint8NDArray(dim_vector(rows, columns, nframes));
+	    for(frame=0; frame < nframes; frame++) {
+		imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+		pix = imvec[frameidx(frame)].getConstIndexes();
+		i = 0;      
+		for(y=0; y < rows; y++) {
+		    for(x=0; x < columns; x++) {        
+			im(y, x, frame) = static_cast<octave_uint8>(pix[i++]);
+		    }
+		}
+	    }
+	    im.chop_trailing_singletons();
+	    output(0) = octave_value(im);
+	}
+	    break;
+	case 16:
+	{
+	    uint16NDArray im = uint16NDArray(dim_vector(rows, columns, nframes));
+	    for(frame=0; frame < nframes; frame++) {
+		imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+		pix = imvec[frameidx(frame)].getConstIndexes();		
+		i = 0;      
+		for(y=0; y < rows; y++) {
+		    for(x=0; x < columns; x++) {
+			im(y, x, frame) = static_cast<octave_uint16>(pix[i++]);
+		    }
+		}
+	    }
+	    im.chop_trailing_singletons();
+	    output(0) = octave_value(im);
+	}
+	    break;
+	default:
+	    error("Index depths bigger than 16-bit not supported");
+	    return octave_value_list();
+    }
+
+    ColorRGB c;
+    Matrix map = Matrix(mapsize, 3);
+    Matrix alpha;
+    switch(type) {
+	case PaletteMatteType:
+/*	    warning("palettematte");
+	    map = Matrix(mapsize, 3);
+	    alpha = Matrix(mapsize, 1);
+	    for(i = 0; i < mapsize; i++) {
+		warning("%d", i);
+		c = imvec[0].colorMap(i);
+		map(i, 0) = c.red();
+		map(i, 1) = c.green();
+		map(i, 2) = c.blue();
+		alpha(i, 1) = c.alpha();				
+	    }
+	    break;	    */
+    	case PaletteType:
+	    alpha = Matrix(0,0);
+	    for(i = 0; i < mapsize; i++) {
+		c = imvec[0].colorMap(i);
+		map(i, 0) = c.red();
+		map(i, 1) = c.green();
+		map(i, 2) = c.blue();		
+	    }
+	    break;	    
+	default:
+	    error("Unsupported indexed image type");
+	    return octave_value_list();
+    }
+
+    output(1) = octave_value(map);
+    if(wantalpha) {
+	output(2) = octave_value(alpha);
+    }     
+    return output;
+}
+
+template <class T>
+octave_value_list read_images(vector<Image> imvec, Array<int> frameidx)
+{
+  int i;
+  T im;  
+  int rows = imvec[0].baseRows();
+  int columns = imvec[0].baseColumns();
+  int nframes = frameidx.length();
+  ImageType type = imvec[0].type();
+  
+  int x, y, frame;
+  const PixelPacket *pix;
+  dim_vector idim = dim_vector();
+  idim.resize(4);
+  idim(0) = rows;
+  idim(1) = columns;
+  idim(2) = 1;
+  idim(3) = nframes;
+  Array<int> idx(dim_vector(4));
+  switch(type) {
+      case BilevelType:
+    //    break;
+      case GrayscaleType:
+	  im = T(dim_vector(rows, columns, nframes));
+	  for(frame=0; frame < nframes; frame++) {
+	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+	      i = 0;      
+	      for(y=0; y < rows; y++) {
+		  for(x=0; x < columns; x++) {        
+		      im(y, x, frame) = pix[i++].red;
+		  }
+	      }
+	  }
+	  break;
+      case GrayscaleMatteType:
+	  idim(2) = 2;
+	  im = T(idim);
+	  for(frame=0; frame < nframes; frame++) {
+	      idx(3) = frame;
+	      i = 0;
+	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+	      for(y=0; y < rows; y++) {
+		  idx(0) = y;
+		  for(x=0; x < columns; x++) {
+		      idx(1) = x;
+		      idx(2) = 0;
+		      im(idx) = pix[i].red;
+		      idx(2) = 1;
+		      im(idx) = pix[i].opacity;
+		      i++;
+		  }
+	      }
+	  }    
+	  break;
+      case PaletteType:
+      case TrueColorType:
+	  idim(2) = 3;
+	  im = T(idim);      
+	  for(frame=0; frame < nframes; frame++) {
+	      idx(3) = frame;
+	      i = 0;
+	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+	      for(y=0; y < rows; y++) {
+		  idx(0) = y;
+		  for(x=0; x < columns; x++) {
+		      idx(1) = x;
+		      idx(2) = 0;
+		      im(idx) = pix[i].red;
+		      idx(2) = 1;
+		      im(idx) = pix[i].green;
+		      idx(2) = 2;
+		      im(idx) = pix[i].blue;
+		      i++;
+		  }
+	      }
+	  }      
+	  break;
+      case PaletteMatteType:
+      case TrueColorMatteType:
+      case ColorSeparationType:
+	  idim(2) = 4;
+	  im = T(idim);      	  
+	  for(frame=0; frame < nframes; frame++) {
+	      idx(3) = frame;
+	      i = 0;
+	      pix = imvec[frameidx(frame)].getConstPixels(0,0, columns, rows);
+	      for(y=0; y < rows; y++) {
+		  idx(0) = y;
+		  for(x=0; x < columns; x++) {
+		      idx(1) = x;
+		      idx(2) = 0;
+		      im(idx) = pix[i].red;
+		      idx(2) = 1;
+		      im(idx) = pix[i].green;
+		      idx(2) = 2;
+		      im(idx) = pix[i].blue;
+		      idx(2) = 3;
+		      im(idx) = pix[i].opacity;
+		      i++;
+		  }
+	      }
+	  }      
+	  break;
+      default:
+	  error("Undefined Imagemagick image type");
+	  return octave_value_list();
+  }
+
+  im.chop_trailing_singletons();
+  return octave_value_list(octave_value(im));
+}
+
+// instantiate templates
+template octave_value_list read_images<boolNDArray>(vector<Image>, Array<int>);
+template octave_value_list read_images<uint8NDArray>(vector<Image>, Array<int>);
+template octave_value_list read_images<uint16NDArray>(vector<Image>, Array<int>);
+
+DEFUN_DLD(__magick_read__, args, nargout,
+"function m = __imagemagick_read__(fname[, index])\n\
+function [m, colormap] = __imagemagick_read__(fname[, index])\n\
+function [m, colormap, alpha] = __imagemagick_read__(fname[, index])\n\
+\n\
+Read images with ImageMagick++. User interface in imread.m.\n\
+\n\
+")
+{
+    octave_value_list output;
+    int i;    
+    if(args.length() > 2 || args.length() < 1 || !args(0).is_string() \
+       || nargout > 3) {
+      print_usage ();
+      return octave_value_list();
+    }
+    Array<int> frameidx;
+    if(args.length() == 2 && args(1).is_real_type()) {
+	frameidx = args(1).int_vector_value();
+    } else {
+	frameidx = Array<int>(1);
+	frameidx(0) = 1;
+    }
+
+    vector<Image> imvec;
+    try {
+	// Read a file into vector of image objects
+	readImages(&imvec, args(0).string_value());
+    }
+    catch( Warning &warning_ ) {
+        warning("Magick++ warning: %s", warning_.what());
+    }
+    catch( ErrorCoder &error_) {
+	warning("Magick++ coder error: %s", error_.what());
+    }
+    catch( Exception &error_ ) {
+	error("Magick++ exception: %s", error_.what());
+	imvec.clear();
+	return octave_value_list();	
+    }
+
+    int nframes = imvec.size();
+    for(i = 0; i < frameidx.length(); i++) {
+	frameidx(i) = frameidx(i) - 1;
+	if(frameidx(i) >= nframes || frameidx(i) < 0) {
+	    error("Invalid index vector");
+	    imvec.clear();
+	    return output;
+	}
+    }
+    
+    ClassType klass = imvec[0].classType();
+    if(klass == PseudoClass && nargout > 1) {
+	output = read_indexed_images(imvec, frameidx, (nargout == 3));
+    } else {
+	int depth = imvec[0].modulusDepth();
+	i = 0;
+	while(depth >>= 1) i++;
+	depth = 1 << i;
+	
+	switch(depth) {
+	    case 1:
+		output = read_images<boolNDArray>(imvec, frameidx);
+	    break;
+	    case 2:
+	    case 4:
+	    case 8:
+		output = read_images<uint8NDArray>(imvec, frameidx);		
+	    break;
+	    case 16:
+		output = read_images<uint16NDArray>(imvec, frameidx);		
+	    break;
+	    case 32:
+	    case 64:
+	    default:
+		error("Image depths bigger than 16-bit not supported");
+	}
+	if(nargout > 1) {
+	    output(1) = Matrix(0,0);
+	    if(nargout > 2)
+		output(2) = Matrix(0,0);
+	}
+    }
+    imvec.clear();
+
+    return output;
+}
new file mode 100644
--- /dev/null
+++ b/src/admin/CONTENTS
@@ -0,0 +1,3 @@
+Contains files and scripts used to administer the octave-forge
+website and build the release files.  Nothing in here is needed
+by octave-forge users.
new file mode 100644
--- /dev/null
+++ b/src/admin/OctRe.pm
@@ -0,0 +1,101 @@
+#!/usr/bin/perl -w
+
+=head1 NAME OctRe - Regexes for octave code
+
+Regexpes come in pairs, I<$XYZ_re>,which don't set I<$1, $2, ...>
+and I<$XYZ_rx>, which do.
+
+=over 4
+
+=item I<$var_r[ex]> match an octave variable (sets I<$1>)
+
+=item I<$dot_r[ex]> match an ellipsis (sets I<$1>)
+
+=item I<$vl_r[ex]> match a variable list, as it appears in a function
+call (sets I<$1>). The individual variables in $1  can be retrieved
+with /$var_rx/g. Example : "x, y, z".
+
+=item I<retl_r[xe]> match a return list, as it appears in a function
+declaration (sets I<$1>). The individual variables in $1 can be
+retrieved with /$var_rx/g. Example : "[x]", "[ x, y]", "[x,y,z]",
+"[x,...]".
+
+=item I<retl_r[xe]> match an argument list, as it appears in a
+function declaration (sets I<$1>). The individual variables in $1 can
+be retrieved with /$var_rx/g. Example : "(x)", "( x, y)", "(x,y,z)",
+"(x,...)".
+
+=back
+
+Rem : This is not a true module, as no package is used. It just declares
+some regexes.
+
+=cut
+
+## Variable $1 : variable name
+$var_re = qr{\s*[A-Za-z\_]+\w*\s*} ;
+$var_rx = qr{\s*([A-Za-z\_]+\w*)\s*} ;
+
+## Ellipsis $1 : ellipsis
+$dot_re = qr{\.\.\.} ;
+$dot_rx = qr{(\.\.\.)} ; # qr{(${var_re})(?:\,(${var_re}))*} ;
+
+## Variable list : $1, $2 ... variable names
+$vl_re = qr{${var_re}(?:\,${var_re})*} ;
+$vl_rx = qr{(${var_re})(?:\,(${var_re}))*} ;
+
+## Return list (as in function declaration)
+## $1, $2 ... : variable names (or ellipsis at end)
+$retl_re = qr{(?:\[\s*(?:${vl_re}(?:,$dot_re)?|$dot_re|)\s*\]|${var_re})\s*\=|} ;
+$retl_rx = qr{(?:\[\s*(?:${vl_rx}(?:,$dot_rx)?|$dot_rx|)\s*\]|${var_rx})\s*\=|} ;
+
+# Simple assignment $1 : lhs name
+$sas_re = qr{${var_re}\s*\=} ;
+$sas_rx = qr{${var_rx}\s*\=} ;
+
+## Return list, as in function call. Call it "mas" like multiple
+## assignment.
+# $1, $2, ... : variable names
+$mas_re = qr{(?:\[(?:${vl_re})\]|${var_re})\s*\=} ;
+$mas_rx = qr{(?:\[(?:${vl_rx})\]|${var_rx})\s*\=} ;
+
+## Arg list as in function declaration
+## $1, $2, ... : variable names
+$argl_re = qr{(?:\((?:${vl_re}(?:,$dot_re)?|$dot_re|)\)|)} ;
+$argl_rx = qr{(?:\((?:${vl_rx}(?:,$dot_rx)?|$dot_rx|)\)|)} ;
+
+## $retl_re = qr{(?:\((?:${vl_re}(?:,$dot_re)?|$dot_re|)\)|)} ;
+
+## $argl_re = qr{\((?:${var_re}(?:\,${var_re})*)?\)|} ;
+
+## Function definition
+# $1 : return list; $2 : function name; $3 : arg list.
+$defun_re = qr{^\s*function\s+${retl_re}\s*${var_re}${argl_re}} ;
+$defun_rx = qr{^\s*function\s+(${retl_re})\s*(${var_rx})(${argl_re})} ;
+## Two quoting chars
+$qch2_re = qr{\\\\} ;
+
+## Quotes next character
+$qch_re = qr{\\${qch2_re}*} ;
+
+## String
+$str_re = qr{\'(?:[^'\n]|(?<!\\)${qch2_re}+\')*\'|\"(?:[^"\n]|(?<!\\)${qch2_re}+\")*\"} ;
+$str_rx = qr{(\'(?:[^'\n]|(?<!\\)${qch2_re}+\')*\'|\"(?:[^"\n]|(?<!\\)${qch2_re}+\")*\")} ;
+
+## Parenthesis "
+$oppar = qr{[\(\{\[]};
+$noppar = qr{[^\(\{\[]};
+$opparx = qr{([\(\{\[])};
+
+$mcp = {"("=>")", "["=>"]", "{"=>"}"};
+
+
+## Comments
+## Not perfect, but should catch most cases
+## $com_re = qr{\#((?:[^'"]|(?<!\\)${qch2_re}*['"])*['"]|.*)} ;
+
+$cch_re = qr{[\#%]+};
+$cch_rx = qr{([\#%]+)};
+
+1;
+
new file mode 100644
--- /dev/null
+++ b/src/admin/change_va_arg.pm
@@ -0,0 +1,48 @@
+#!/usr/bin/perl -w -n
+
+## defines function change_line that transforms old-style variable argument
+## lists (...) into new-style varargin. va_arg() etc are also transformed.
+
+BEGIN{
+
+    $va_arg_re = qr!^(\s*function\s*\w*.*?\(.*?)\.\.\.(\s*\).*)$!;
+    
+}
+
+## Does necessary changes inplace on $_[0].
+sub change_line {
+    
+    if ($_[0] !~ /^\s*\#/) {	# Don't do obvious comment lines
+
+				# Transform ... in function decalaration
+
+	$_[0] =~ s{$va_arg_re}{$1varargin$2}og;
+
+				# list(all_va_args) becomes varargin
+
+	$_[0] =~ s!list\s*\(\s*all_va_args\s*\)!varargin!og;
+
+				# all_va_args becomes varargin{:}
+
+	$_[0] =~ s!all_va_args!varargin{:}!og;
+
+				# va_start() can be delicate, so add a
+				# warning. 
+
+				# declare a va_arg_cnt counter
+
+	$_[0] =~ s!(.*\b)va_start\b(\s*\(\s*\)|)(.*)!$1va_arg_cnt = 1$3\nwarn ("va_start should be transformed\\n");\n!g;
+
+				# Use that counter to substitute va_arg by
+				# nth (varargin, va_arg_cnt++)
+
+	$_[0] =~ s!(.*\b)va_arg\b(\s*\(\s*\)|)(.*)!$1nth (varargin, va_arg_cnt++)$3!g;
+    }
+}
+
+## Does it look like an underlined func that is not a function call?
+sub comment_line {
+     0 ?
+	"## Hmmm ... is that a function call?\n" : "";
+}
+1;
new file mode 100755
--- /dev/null
+++ b/src/admin/find_changes
@@ -0,0 +1,172 @@
+#!/usr/bin/perl -w
+
+=head1 NAME find_changes.pl - Find patterns in text files and propose changes.
+
+This script passes lines of text through a perl function with the aim of
+reporting the occurence of patterns and proposing changes to be
+done. L<patch> should be used to actually modify the original files.
+
+=head1 SYNOPSIS
+
+find_changes.pl [options] changes_def file(s).txt ... E<gt> changes_patch
+
+Reads and executes the perl F<changes_def> file, which must contain the
+definition of a function called C<change_line()>, and then reads the
+F<file(s).txt> line by line.
+
+For each line of each file, the function F<change_line()> is called with the
+line as single argument, which can be modified inplace.
+
+If any change is done to the line, it is reported by printing to stdout a
+universal diff patch.
+
+=head2 Modifying files
+
+It is then recommended to inspect and edit the file F<changes_patch>,
+removing lines that should not be changed. Once this is done, the changes
+can be done in the original files by using C<patch -p0 < changes_patch>.
+
+=head2 Commenting on lines
+
+If a function C<comment_line()> is present, each line will be passed to it
+and its output will be shown on standard error.
+
+=head1 OPTIONS
+
+=over 4
+
+=item -p, --patch
+
+Output a patch (default).
+
+=item -d
+
+Use another output format, adapted to some F<do_changes.pl> script.
+
+=item -v, --verbose
+
+Print some info on stderr during execution.
+
+=item -h, --help
+
+Print a help message and exit.
+
+=head1 COPYRIGHT
+
+This file is distributed under the terms of the GNU General Public Licence.
+
+=head1 AUTHOR Etienne Grossmann E<lt>etienne@isr.ist.utl.ptE<gt>
+
+=cut
+
+###
+sub help {system ("perldoc $0|cat")}
+
+$patch = 1;
+$verbose = 0;
+				# Read options
+
+while (@ARGV && ($ARGV[0] =~ /^\-/)) {
+    if    ($ARGV[0] =~ /^\-(h|\-help)$/){ help(); exit 0;}
+    elsif ($ARGV[0] =~ /^\-(v|\-verbose)$/){ $verbose = 1;}
+    elsif ($ARGV[0] =~ /^\-(p|\-patch)$/) { 
+	$patch = 1;
+    } elsif ($ARGV[0] =~ /^\-(d)$/) { 
+	$patch = 0;
+    } else {
+	die "Unknown option '$ARGV[0]'. Try '$0 --help'";
+    }
+    
+    shift @ARGV;
+}
+
+die "No definition file specified" unless @ARGV;
+
+$dfile = shift @ARGV;
+
+				# Read and compile definition file
+print STDERR "Definition file is $dfile\n" if $verbose;
+
+if (!defined (do ($dfile))) {
+    if ($!) {
+	print STDERR "Can't find $dfile : '$!'\n";
+	exit 1;
+    } elsif ($@) {
+	print STDERR "Can't compile $dfile : '$@'\n";
+	exit 1;
+    } else {
+	print STDERR "Problem with $dfile : do returns undefined\n";
+	exit 1;
+    }
+} 
+
+if (!defined (&change_line)) {
+    print STDERR "File '$dfile' does not define a function 'change_line()'\n";
+    exit 1;
+}
+
+$has_comment = defined (&comment_line);
+
+foreach my $f (@ARGV) {
+
+    if (!$patch) {
+	unless (open FF, "<$f") {
+	    print "## Whoa!!! Can't open file '$f'. Skipping";
+	    next;
+	}
+	print STDERR "Scanning file $f\n" if $verbose;
+	
+	
+	local $lnum = 0;
+	while (! eof (FF)) {
+	    
+	    my $line = <FF>;	# Read a line
+	    my $olin = $line;
+	    $lnum++;
+	    
+	    if ($has_comment) {
+		if ($comment = &comment_line ($line)) {
+		    $comment = "## $comment" if $comment !~ /^\s*\#/;
+		    $comment .= "\n" if $comment !~ /\n$/;
+		    print "$f:$.:$comment";
+		}
+	    }
+	    
+	    &change_line ($line);
+	    if ($olin ne $line) {
+		print "$f:$.:$olin";
+	    }
+	}
+	close FF;
+    } else {			# Do a patch. Using diff, what else?
+	my $nf = "$f.new";
+	my $i = 1;
+	while (-e $nf) {	# Find a name for the temp file.
+	    $nf = $f . ".new." . $i ;
+	}
+	unless (open FF, "<$f") {
+	    print STDERR "## Whoa!!! Can't open file '$f'. Skipping\n";
+	}
+	unless (open GG, ">$nf") {
+	    print STDERR "## Whoa!!! Can't open temp file '$nf'. Skipping\n";
+	    next;
+	}
+	print STDERR "## Scanning file $f\n" if $verbose;
+
+	while (! eof (FF)) {	# Create (temp) transformed file
+	    
+	    my $line = <FF>;	# Read a line
+	    
+	    &change_line ($line);
+	    print GG $line;
+	}
+	close FF; close GG;
+				# Call diff and modify slightly the output
+	my $tmp = `diff -u $f $nf`;
+	$tmp =~ s{^\+\+\+ $nf}{+++ $f}m;
+	print $tmp;
+
+	unlink($nf) or print STDERR "## Whoa!!! Can't remove temp file '$nf'\n";
+    }
+}
+
new file mode 100755
--- /dev/null
+++ b/src/admin/get_authors
@@ -0,0 +1,241 @@
+#!/usr/bin/env perl
+#
+# Traverse the directory tree and extract author information from .m
+# files.  Put author information in the file 'AUTHORS'.
+# Understands variations of these entries:
+#
+#   ## Copyright (C)  year(s)  name1   <email>
+#   ## Copyright (C)  year(s)  name2   <email>
+#   ## Author:  name3  <email>
+#   ## Author:  name4  <email>
+#
+# Albert Danial Dec 15 2001
+#               Nov 30 2002 - Attribute to 'Anonymous' any file which has 
+#                             licensing terms (ie, granted to public domain)
+#                             but no author.  Show code and comment line
+#                             counts.
+#               Apr 25 2005 - Added -s option, better logic to identify
+#                             public domain files.
+# Dirk Eddelbuettel 07 Jul 2004  also look at .cc files and // comments
+#                             
+# Usage:  admin/get_authors  [-s <# lines>]                             
+#            Scans .m and .cc files and extracts author and copyright
+#            information.  Creates the AUTHORS file.
+#                       Option:  -s  <n>    Set the size of a "short" program
+#                                           to <n> non-commented lines.  
+#                                           Copyrights aren't needed for short 
+#                                           programs.  Default <n> is 5.
+#                             
+use warnings;
+use strict;
+use vars qw($opt_s );
+use Cwd;
+use Getopt::Std;
+use File::Find;
+
+getopts('s:');
+$opt_s = 5 unless $opt_s;  # set the default value
+my $location = getcwd;
+my $PATH     = "";
+if ($location =~ m{^(.*)/admin$}) {
+    chdir "..";
+    $PATH = "$1/";
+}
+
+my @files = ();       # to contain relative path names of each .m file
+find(\&wanted, ".");  # start here & descend recursively; populate @files
+
+my %file_data = ();
+classify_files(\@files,       # in
+               \%file_data);  # out file_data{file}{'name'} = [ names ]
+                              #                    {'year'} = [ years ]
+                              #                    {'mail'} = [ email addrs ]
+                              #                    {'cpyr'} = [ 'C' or ' '  ]
+                              #                    {'n_code'}    = # lines code
+                              #                    {'n_comment'} = # lines of
+                              #                                    comments
+
+# traverse file_data and extract
+#   - files without copyrights
+#   - files without authors
+#   - files grouped by author
+#   - author to email map
+#   - number of lines of code, number of lines of comments
+my @unattributed_files  = ();
+my @uncopyrighted_files = ();
+my @short_files         = ();
+my @public_domain       = ();
+my %email               = ();   # email{ author name } = email address
+my %files               = ();   # files{ author name } = [ list of files ]
+foreach my $f (sort @files) {
+    # each file can have multiple authors, loop over each author
+    if (!defined @{$file_data{$f}{name}}) {
+	if ($file_data{$f}{n_code} > $opt_s) { # not a short program
+           push @unattributed_files, $f;
+        } else {
+           push @short_files       , $f;
+        }
+        next;
+    }
+    my $copyrighted = 0;
+    for (my $i = 0; $i < scalar @{$file_data{$f}{name}}; $i++) {
+        if (defined $file_data{$f}{mail}[$i]) {
+            $email{ $file_data{$f}{name}[$i] } = $file_data{$f}{mail}[$i];
+        }
+        if (defined $file_data{$f}{cpyr}[$i]) {
+            $copyrighted = 1;
+            push @public_domain, $f if $file_data{$f}{cpyr}[$i] eq "P";
+        }
+        $files{ $file_data{$f}{name}[$i] }{$f} = 1;
+    }
+    next if $copyrighted;
+    if ($file_data{$f}{n_code} > $opt_s) { # then it is not a short program
+        push @uncopyrighted_files, $f;
+    } else {
+        push @short_files        , $f;
+    }
+}
+
+printf "%3d uncopyrighted files:%s lines of code/lines of comments\n", 
+       scalar @uncopyrighted_files, ' ' x 22;
+foreach my $f (sort @uncopyrighted_files) {
+    printf "      %-50s %3d/%3d\n", 
+           $f, $file_data{$f}{n_code}, $file_data{$f}{n_comment};
+}
+
+printf "\n%3d unattributed files:%s lines of code/lines of comments\n", 
+       scalar @unattributed_files, ' ' x 23;
+foreach my $f (sort @unattributed_files) {
+    printf "      %-50s %3d/%3d\n",
+           $f, $file_data{$f}{n_code}, $file_data{$f}{n_comment};
+}
+
+printf "\n%3d public domain files:%s lines of code/lines of comments\n", 
+       scalar @public_domain, ' ' x 22;
+foreach my $f (sort @public_domain) {
+    printf "      %-50s %3d/%3d\n", 
+           $f, $file_data{$f}{n_code}, $file_data{$f}{n_comment};
+}
+
+printf "\n%3d uncopyrighted short (<= %2d lines) files:%s lines of code/lines of comments\n", 
+       scalar @short_files, $opt_s, ' ' x 2;
+foreach my $f (sort @short_files) {
+    printf "      %-50s %3d/%3d\n", 
+           $f, $file_data{$f}{n_code}, $file_data{$f}{n_comment};
+}
+
+my $Auth_file = "AUTHORS";
+open(OUT, ">$Auth_file") or die "Cannot write $Auth_file:  $!\n";
+printf "%3d authors:\n", scalar keys %files;
+foreach my $n (sort keys %files) {
+    printf     "%-28s", $n;
+    printf OUT "%-28s", $n;
+    print     $email{$n} if defined $email{$n};
+    print OUT $email{$n} if defined $email{$n};
+    print     "\n";
+    print OUT "\n";
+    my $i = 0;
+    foreach my $f (sort keys %{$files{$n}}) {
+        printf "%3d. %-50s  %3d/%3d\n",
+               ++$i, $f, $file_data{$f}{n_code}, $file_data{$f}{n_comment};
+    }
+}
+close OUT;
+warn "Wrote ${PATH}${Auth_file}\n";
+
+# # # # # # # 
+
+#sub by_last_name { # {{{1 for sorting on names
+#    (my $A = $a) =~ s/.*?(\w+)$/$1/;
+#    (my $B = $b) =~ s/.*?(\w+)$/$1/;
+#    return lc($A) cmp lc($B);
+#} # 1}}}
+
+# # # # # # # 
+
+sub classify_files { # {{{1
+    my ($ra_files,  # in, list of files
+        $rhha_data, # out,  data{file}{ name | year | cpyr } = [entries]
+       ) = @_;
+    warn "Found ", scalar grep (/\.m$/,  @{$ra_files}), " .m files; ",
+                   scalar grep (/\.cc$/, @{$ra_files}), " .cc files",
+                   "\n";
+    foreach my $f (@{$ra_files}) {
+        open(IN, $f) or die "Cannot read $f: $!\n";
+        my $found_copyright = 0;
+        my $found_author    = 0;
+        $rhha_data->{$f}{n_code}    = 0;
+        $rhha_data->{$f}{n_comment} = 0;
+        while (<IN>) {
+            # find the copyright line and extract author info from it
+            if (/^[#%\/]+/) {           # a comment
+                ++$rhha_data->{$f}{n_comment};
+            } elsif (!/^\s*$/) {        # not a blank line
+                ++$rhha_data->{$f}{n_code};
+            }
+            s/all\s+rights\s+reserved\.?//i;
+            s/\bby\s+//i;
+
+            if (/^\s*[#%\/\*]*          #  one or more leading comment markers
+                  \s*copyright          #  Copyright
+                  \s*(\(c\))?           #  (c)    - optional           $1
+                  \s*(\d[,\- 0-9]+)     #  Year (or years)             $2
+                  \s+(\w.*?)            #  name                        $3
+                  \s*(<.*>)?            #  email  - optional           $4
+                  \s*$/ix) {
+                $found_copyright = 1;
+                $found_author    = 1;
+                my $year  = $2;
+                my $name  = $3;
+                   $name  = "John W. Eaton" if $name eq "jwe";
+                   $name  =~ s/\.\s*$//; # strip trailing period
+                my $email = "" || $4;
+                $name =~ s/^\s+//;  # strip leading  whitespace
+                $name =~ s/\s+$//;  # strip trailing whitespace
+                push @{$rhha_data->{$f}{name}}, $name;
+                push @{$rhha_data->{$f}{year}}, $year;
+                push @{$rhha_data->{$f}{mail}}, $email;
+                push @{$rhha_data->{$f}{cpyr}}, 'C';
+                # don't exit w/last because there could be multiple copyrights
+            } elsif (
+                /^\s*[#%\/\*]*            # one or more leading comment markers
+                    \s*author\s*:?        #  Author    
+                    \s+(\w.*?)            #  name                        $1
+                    \s*(<.*>)?            #  email  - optional           $2
+                    \s*$/ix) {
+                my $name  = $1;
+                   $name  =~ s/\.\s*$//; # strip trailing period
+                   $name  = "John W. Eaton" if $name eq "jwe";
+                my $email = "" || $2;
+                push @{$rhha_data->{$f}{name}}, $name;
+                push @{$rhha_data->{$f}{year}}, "";
+                push @{$rhha_data->{$f}{mail}}, $email;
+                $found_author = 1;
+            } elsif (
+                /^\s*[#%\/\*]*            # one or more leading comment markers
+                  .*?                     #  some leading text
+                  \b(grant(ed)?|place(d)?|give(n)?|is)(\s+this)?
+                  (\s+(file|program|script|code|algorithm))?(\s+(in|to))?
+                  (\s+the)?
+                  \s+public\s+domain
+                /ix) {
+                push @{$rhha_data->{$f}{cpyr}}, 'P';
+                $found_copyright = 1;
+            }
+        }
+        if ($found_copyright and !$found_author) {
+            push @{$rhha_data->{$f}{name}}, "Anonymous";
+            push @{$rhha_data->{$f}{year}}, "";
+            push @{$rhha_data->{$f}{mail}}, "";
+            push @{$rhha_data->{$f}{cpyr}}, 'C';
+        }
+        close IN;
+    }
+} # 1}}}
+
+# # # # # # # 
+
+sub wanted { # {{{1 populates global array @files
+    return unless -f and /\.(m|cc)$/;  # only want .m files (for now)
+    push @files, "$File::Find::name";
+} # 1}}}
new file mode 100755
--- /dev/null
+++ b/src/admin/get_contents
@@ -0,0 +1,181 @@
+#!/usr/bin/env perl
+#
+# Traverse the directory tree and look for files called 'CONTENTS'.
+# Insert the text from these files into octave-forge documentation
+# files such as the top-level README, and the developer's guide.
+# Issues:
+#   - Entries in the README appear in the sort order of
+#     the directory names the CONTENTS files are in.  This
+#     isn't necessarily the best sequence since some directories
+#     such as main/ should appear first.
+#   - At the moment the text in the CONTENTS files should be plain
+#     text.  Planning to allow texinfo for layout control in .html
+#     files.
+#
+# Albert Danial Jan 2 2002
+
+use strict;
+use File::Find;
+
+my $location = `pwd`;
+my $PATH     = "";
+if ($location =~ m{^(.*)/admin$}) {
+    chdir "..";
+    $PATH = "$1/";
+}
+
+my @files = ();       # to contain relative path names of each CONTENTS file
+find(\&wanted, ".");  # start here & descend recursively; populate @files
+
+fill_README(@files);         # creates 'README' from 'template.readme'
+fill_developer_html(@files); # creates 'new_developer.html' from 'template.ndev'
+
+# # # # # # # 
+
+sub fill_README {  # {{{1
+    my (@files, ) = @_;
+    my $template = "admin/template.readme";    # -> reads
+    my $RM       = "README";                   # -> writes
+    if (!-r $template) {
+        warn "Unable to read the file '$template'; cannot make README\n";
+        return;
+    }
+    open(IN,  $template) or die "Unable to read $template: $!\n";
+    my @template_data = <IN>;  # slurp the entire file
+    close IN;
+
+    my $added_contents = 0;
+    my $top_of_file    = 1;
+    open(README, ">$RM")    or die "Unable to write $RM: $!\n";
+    foreach my $t (@template_data) {
+        if      ($top_of_file) {      # skip over warning lines in
+            next if $t =~ /^-> /;     # template starting with '->'
+            $top_of_file = 0;
+        } elsif ($added_contents) {
+            print README $t;
+            next;
+        } elsif ($t =~ /^Project organization/) {
+            print README "$t\n";
+            foreach (sort @files) {
+                open(CONTENTS, $_) or die "Cannot read $_: $!\n";
+                my @c = <CONTENTS>;
+                close CONTENTS;
+                m{^(.*)/(.*?)$}; # match directory and file's basename
+                my $dir  = $1;
+                my $file = $2;
+                $dir     =~ s{^\./}{};  # strip leading  ./
+                print README "$dir/\n";
+                foreach my $line (@c) {
+                    print README "\t$line";
+                }
+                print README "\n";
+            }
+            $added_contents = 1;
+        } else {
+            print README $t;
+        }
+    }
+    close README;
+    warn "Use 'cvs diff ${PATH}${RM}' to determine if updates are needed.\n";
+    warn "Use 'cvs commit ${PATH}${RM}' to update README.\n";
+}  # 1}}}
+
+# # # # # # # 
+
+sub fill_developer_html {  # {{{1
+    my (@files, ) = @_;
+    my $template = "admin/template.ndev";          # <- reads
+    my $RM       = "doc/new_developer.html";       # <- writes
+    if (!-r $template) {
+        warn "Unable to read the file '$template'; cannot make README\n";
+        return;
+    }
+    open(IN,  $template) or die "Unable to read $template: $!\n";
+    my @template_data = <IN>;  # slurp the entire file
+    close IN;
+
+    my $added_contents = 0;
+    my $top_of_file    = 1;
+    open(README, ">$RM")    or die "Unable to write $RM: $!\n";
+    foreach my $t (@template_data) {
+        if      ($top_of_file) {      # skip over warning lines in
+            next if $t =~ /^-> /;     # template starting with '->'
+            $top_of_file = 0;
+        } elsif ($added_contents) {
+            print README $t;
+            next;
+        } elsif ($t =~ /^>>>INSERT CONTENTS HERE<<</) {
+            foreach (sort @files) {
+                open(CONTENTS, $_) or die "Cannot read $_: $!\n";
+                my @c = <CONTENTS>;
+                close CONTENTS;
+                text_bullet_list_to_HTML(\@c);
+                m{^(.*)/(.*?)$}; # match directory and file's basename
+                my $dir  = $1;
+                my $file = $2;
+                $dir     =~ s{^\./}{};  # strip leading  ./
+                print README "\t<li> <b><tt>$dir/</tt></b><br>\n";
+                foreach my $line (@c) {
+                    # use fixed font for words that end with /
+                    # (ie, directory names).
+                    $line =~ s{\s(\S+/)([.,\s])}{ <tt>$1</tt>$2}g;
+                    print README "\t$line";
+                }
+                print README "\n";
+            }
+            $added_contents = 1;
+        } else {
+            print README $t;
+        }
+    }
+    close README;
+    warn "Use 'scp ${PATH}${RM} \$OFHOME' to update the web.\n";
+}  # 1}}}
+
+# # # # # # # 
+
+sub text_bullet_list_to_HTML { # {{{1
+    # Takes an array of plain text lines and embeds <ul>, <li>, and </ul>
+    # tags as appropriate to turn a text bullet list (denoted by *) into
+    # an html equivalent.
+    # Can only handle a single bullet list.
+    my ($ra_contents, ) = @_;
+    my $found_list = 0;
+    foreach my $l (@{$ra_contents}) {
+        if ($l =~ /^\s*\*/) {
+            $found_list = 1;
+            last;
+        }
+    }
+    return unless $found_list; # bail if no list found
+
+    # find the first and last lines of the bullet list
+    my $start_line = 0;
+    for (my $i = 0; $i < scalar @{$ra_contents}; $i++) {
+        if ($ra_contents->[$i] =~ /^\s*\*/) {
+            $start_line = $i;
+            last;
+        }
+    }
+    my $end_line   = 0;
+    for (my $i = scalar @{$ra_contents} - 1; $i >= 0; $i--) {
+        if ($ra_contents->[$i] =~ /^\s*\*/) {
+            $end_line   = $i;
+            last;
+        }
+    }
+
+    # finally, insert the HTML
+    for (my $i = 0; $i < scalar @{$ra_contents}; $i++) {
+        $ra_contents->[$i] =~ s{^(\s*)\*}{$1 <li>};
+        $ra_contents->[$i] = "<ul> " . $ra_contents->[$i] if $i == $start_line;
+        $ra_contents->[$i] = $ra_contents->[$i] . "</ul>" if $i == $end_line;
+    }
+} # 1}}}
+
+# # # # # # # 
+
+sub wanted { # populates global array @files
+    return unless -f and /^CONTENTS$/;
+    push @files, "$File::Find::dir/$_";
+}
new file mode 100755
--- /dev/null
+++ b/src/admin/make_index
@@ -0,0 +1,1148 @@
+#!/usr/bin/env perl
+#
+# Albert Danial Mar 21 2002
+#
+# Creates .html files documenting all the functions in octave and
+# octave-forge.
+
+use strict;
+use File::Find;
+use File::Basename;
+use Text::Wrap;
+use FileHandle;
+use IPC::Open3;
+use POSIX ":sys_wait_h";
+
+## Local configuration; the OCTAVE directory should contain
+# src/DOCSTRINGS (which is a build product) and scripts/.
+my $OCTAVE  = "../octave";
+my $tmpdir = "/tmp";   # temp directory
+my $catdir = "index";  # output directory
+
+## Commands to grab the last few defs from octave
+## Use the first def if you want to extract from
+## a locally compiled version, or the second if you
+## want to use the installed version.
+#my $OCTAVECMD = "LD_LIBRARY_PATH=$OCTAVE/src/:$OCTAVE/liboctave:$OCTAVE/libcruft $OCTAVE/src/octave -q";
+#my $OCTAVEINIT = "path='.:$OCTAVE/src//:$OCTAVE/scripts//'; suppress_verbose_help_message = 1;";
+my $OCTAVECMD = "octave -q";
+my $OCTAVEINIT = "suppress_verbose_help_message = 1;";
+
+# Links to octave/octave-forge web CVS
+my $OCTAVECVS = "http://www.octave.org/cgi-bin/viewcvs.cgi/~checkout~/octave";
+my $FORGECVS = "http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/*checkout*/octave/octave-forge/";
+
+#my $script  = basename($0);
+
+my $forgebar = qq~<center>
+<A href="http://octave.sourceforge.net">Home</A> |
+<A href="http://sourceforge.net/projects/octave/">Summary</A> |
+<A href="http://sourceforge.net/forum/?group_id=2888">Forums</A> |
+<A href="http://sourceforge.net/bugs/?group_id=2888">Bugs</A> |
+<A href="http://sourceforge.net/support/?group_id=2888">Support</A> |
+<A href="http://sourceforge.net/patch/?group_id=2888">Patches</A> |
+<A href="http://sourceforge.net/mail/?group_id=2888">Lists</A> |
+<A href="http://sourceforge.net/pm/?group_id=2888">Tasks</A> |
+<A href="http://sourceforge.net/docman/?group_id=2888">Docs</A> |
+<A href="http://sourceforge.net/survey/?group_id=2888">Surveys</A> |
+<A href="http://sourceforge.net/news/?group_id=2888">News</A> |
+<A href="http://sourceforge.net/cvs/?group_id=2888">CVS</A> | 
+<A href="http://sourceforge.net/project/showfiles.php?group_id=2888">Files</A> 
+</center>
+    ~;
+
+my $forgelink = qq~
+<hr><center>
+<small>Hosted by</small> <a  href="http://sourceforge.net"><img  src="http://sourceforge.net/sflogo.php?group_id=2888&amp;type=4"  width="125" height="37" border="0" alt="SourceForge.net Logo"  /></a>
+</center>
+    ~;
+
+# initialize the indexing variables
+my %index_by_TB_cat   = (); # i_TB_cat{toolbox}{category} = list of functions
+my %index_by_function = (); # i_function{function} =[ [toolbox_1,category_1],
+#                         [toolbox_2,category_2],..]
+my %TB_description    = ();
+my %index_notes = (); # index_notes{function} = comment
+
+# find and load all indices
+my @index_files = ();
+find(\&index_files, ".");
+sub index_files { # {{{1 populates global array @files
+    return unless -f and /INDEX$/;  # INDEX files
+    my $path = "$File::Find::dir/$_";
+    $path =~ s|^[.]/||;
+    push @index_files, $path; 
+} # 1}}}
+foreach my $f ( @index_files ) {
+    load_index($f,
+	       \%index_by_TB_cat,
+	       \%TB_description,
+	       \%index_by_function);
+}
+
+# XXX FIXME XXX should die if the index is empty
+# die "No INDEX in current directory" if !-e "INDEX";
+my $summary = !-e "admin/make_index";  # if not in the root, just summarize
+my $include_octave = !$summary;        # only include octave if not summarizing
+
+# locate all C++ and m-files in octave-forge, and all m-files in octave
+# don't need C++ files from octave because we have DOCSTRINGS
+my @m_files = ();
+my @C_files = ();
+find(\&cc_and_m_files, "$OCTAVE/scripts") if $include_octave; 
+find(\&cc_and_m_files, "$OCTAVE/src") if $include_octave; 
+        # or just use $OCTAVE/{src,scripts}/DOCSTRINGS ....
+find(\&cc_and_m_files, ".");
+sub cc_and_m_files { # {{{1 populates global array @files
+    return unless -f and /\.(m|cc|l|y)$/;  # .m and .cc files (lex & yacc too!)
+    my $path = "$File::Find::dir/$_";
+    $path =~ s|^[.]/||;
+    if (/\.m$/) {
+        push @m_files, $path;
+    } else {
+        push @C_files, $path;
+    }
+} # 1}}}
+
+my %function_description  = ();
+my %octave_forge_function = ();
+my @uncategorized = ();
+my @skipped = ();
+my %n_appearances = ();
+my $n_functions = 0;
+my @shadow_paths = ('FIXES', 'extra/NaN', 'extra/Windows', 'extra/ver20'); 
+my @shadowed = ();
+
+# grab help from C++ files
+foreach my $f ( @C_files ) {
+    if ( open(IN,$f) ) {
+	while (<IN>) {
+	    # skip to the next function
+	    next unless /^\s*DEF(UN[ (]|UN_MAPPER|UN_DLD|CMD|VAR|CONST)/;
+
+	    # print "looking at $_";
+	    # extract function name to pattern space
+	    /\((\w*)\s*,/;
+	    # remember function name
+	    my $function = $1;
+	    # print "  found function $function\n";
+
+	    # skip to second , to skip default string options of DEFVAR
+	    # comment if third or higher arg
+	    # XXX FIXME XXX What about if the string arg includes ,
+	    # XXX FIXME XXX What if second , is not on first line!!
+	    # Special cases
+	    #  * for DEFCONST (I, Complex (0., 1.),
+	    s/\(\w*\s*,\s*Complex\s*\(\s*[0-9.]*\s*,\s*[0-9.]*\s*\),//;
+	    #  * for macro containing DEFUN_DLD
+	    s/\w*\s*\(\w*\s*,\s*"/"/;
+	    # Main case
+	    s/\(\w*\s*,.*?,//;
+
+	    # If we have nothing but a newline, skip
+	    $_ = <IN> if /^\s*DEF(UN[ (]|UN_MAPPER|UN_DLD|CMD|VAR|CONST)\s*,*\s*\n/;
+
+	    # if line contains \w+_DOC_STRING we have a macro for the
+	    # help text
+	    my $desc;
+	    if (/\w+_DOC_STRING/) {
+	      my $macro = $_;
+	      $macro =~ s/^.*?\s*(\w*_DOC_STRING).*$/$1/;
+	      $macro =~ s/\n//;
+
+	      my $line;
+	      if ( open(IN2, $f) ) {
+		while ($line = <IN2>) {
+		  next unless $line =~ /^\#\s*define\s+$macro\s+\"/;
+		  $desc = $line;
+		  $desc =~ s/^\#\s*define\s+$macro\s+\"(.*\n)$/$1/;
+		  while ($desc !~ /[^\\]\"/ && $desc !~ /^\"/) {
+		    $desc =~ s/\\\s*\n//;
+		    # join with the next line
+		    $desc .= <IN2>;
+		  }
+		  $desc = "" if $desc =~ /^\"/; # chop everything if it was ""
+		  $desc =~ s/\\n/\n/g;          # insert fake line ends
+		  $desc =~ s/([^\"])\".*$/$1/;  # chop everything after final '"'
+		  $desc =~ s/\\\"/\"/;          # convert \"; XXX FIXME XXX \\"
+		  last;
+		}
+		close (IN2);
+	      } else {
+		print STDERR "Could not open file ($f): $!\n";
+	      }
+	    } else {
+	      # skip to next line if comment doesn't start on this line
+	      # XXX FIXME XXX maybe we want a loop here?
+	      $_ = <IN> unless /\"/;
+	      # skip to the beginning of the comment string by
+	      # chopping everything up to opening "
+	      $desc = $_;
+	      $desc =~ s/^[^\"]*\"//;
+
+	      # join lines until you get the end of the comment string
+	      # plus a bit more.  You need the "plus a bit more" because
+	      # C compilers allow implicitly concatenated string constants
+	      # "A" "B" ==> "AB".
+	      while ($desc !~ /[^\\]\"\s*[\,\)]/ && $desc !~ /^\"/) {
+		# if line ends in '\', chop it and the following '\n'
+		$desc =~ s/\\\s*\n//;
+		# join with the next line
+		$desc .= <IN>;
+		# eliminate consecutive quotes, being careful to ignore
+		# preceding slashes. XXX FIXME XXX what about \\" ?
+		$desc =~ s/([^\\])\"\s*\"/$1/;
+	      }
+	      $desc = "" if $desc =~ /^\"/; # chop everything if it was ""
+
+	      # Now check for text included in help messages as macros
+	      # XXX FIXME XXX These macros are often compile dependent, so
+	      # how to we get the correct version of the macro in this case
+	      # without actually compiling the code???
+	      while ($desc =~ /[^\\]\"\s*\S+\s*[^\\]\"/) {
+		my $macro = $desc;
+		# Deal with issues of multiple macros...
+		# $macro =~ s/^.*[^\\]\"\s*(\S+?)\s*[^\\]\".*$/$1/;
+		($macro) =   ($macro =~ /[^\\]\"\s*(\S+?)\s*\".*$/);
+		$macro =~ s/\n//;
+		my $macro_defn;
+		my $line;
+		if ( open(IN2, $f) ) {
+		  while ($line = <IN2>) {
+		    next unless $line =~ /^\#\s*define\s+$macro\s+\"/;
+		    $macro_defn = $line;
+		    $macro_defn =~ s/^\#\s*define\s+$macro\s+\"(.*)\n$/$1/;
+		    while ($macro_defn !~ /[^\\]\"/ && $macro_defn !~ /^\"/) {
+		      $macro_defn =~ s/\\\s*\n//;
+		      # join with the next line
+		      $macro_defn .= <IN2>;
+		    }
+		    $macro_defn = "" if $macro_defn =~ /^\"/; # chop everything if it was ""
+		    $macro_defn =~ s/\\n/\n/g;          # insert fake line ends
+		    $macro_defn =~ s/([^\"])\".*$/$1/;  # chop everything after final '"'
+		    $macro_defn =~ s/\\\"/\"/;          # convert \"; XXX FIXME XXX \\"
+		    last;
+		  }
+		  close (IN2);
+		} else {
+		  print STDERR "Could not open file ($f): $!\n";
+		}
+		$desc =~ s/\"\s*$macro\s*\"/$macro_defn/;
+	      }
+	    }
+
+	    $desc =~ s/\\n/\n/g;          # insert fake line ends
+	    $desc =~ s/([^\"])\".*$/$1/;  # chop everything after final '"'
+	    $desc =~ s/\\\"/\"/;          # convert \"; XXX FIXME XXX \\"
+#	    print " description: $desc";
+
+	    # register the function with a brief description
+	    register_function($function,$desc,$f,0);
+	}
+	close (IN);
+    } else {
+	print STDERR "Could not open file ($f): $!\n";
+    }
+}
+
+# grab help from m-files (octave-forge and octave)
+foreach my $f ( @m_files ) {
+    my $desc     = extract_description($f);
+    my $function = basename($f, ('.m'));
+    die "Null function?? [$f]\n" unless $function;
+    register_function($function,$desc,$f,0);
+}
+
+# grab help from octave's DOCSTRINGS
+if ( !$include_octave ) {
+  # skip DOCSTRINGS if just summary
+}
+else {
+
+  if (open (IN,"$OCTAVE/src/DOCSTRINGS")) {
+    process_docstrings();
+  } else {
+    print STDERR "could not open $OCTAVE/src/DOCSTRINGS !\n";
+  }
+  if (open (IN,"$OCTAVE/scripts/DOCSTRINGS")) {
+    process_docstrings();
+  } else {
+    print STDERR "could not open $OCTAVE/scripts/DOCSTRINGS !\n";
+  }
+}
+
+# Desperate last measure. Try help <func> within octave. Good for getting
+# keyword and operator descriptions
+print "Perl hacker: please make the following faster\n";
+# XXX FIXME XXX, we shouldn't respawn a new octave process each time !!!
+foreach my $TB ( toolbox_list()) {
+  foreach my $cat ( cat_list($TB) ) {
+    foreach my $func ( cat_funcs($TB,$cat) ) {
+      if (! defined $function_description{$func}[1] && ! defined $index_notes{$func} ) {
+	open3(*Writer, *Reader, *Errer, $OCTAVECMD) or die "Could not run octave";
+	print Writer $OCTAVEINIT;
+        print Writer "help $func; 1"; close(Writer);
+	my @lines = <Reader>; close(Reader);
+	my @err = <Errer>; close(Errer);
+	waitpid(-1,&WNOHANG);
+
+	# Display errors, if any
+	if (@err) {
+	  print "help $func\n>>> @err";
+	} else {
+	  my $body = join("",@lines);
+	  if ($body =~ /help: `(.*)' not found/ || $body =~ /help: sorry,/) {
+	    # do nothing
+	  } else {
+	    print "help $func\n";
+
+	    my $start;
+	    if ($body =~ /^\n\*\*\*/) {
+	      # clipping assuming ops/keywords only
+	      $start = index($body,"$func") + 1 + length($func);
+	    } else {
+	      # first lines till \n\n will be octave tell us the type
+	      # of variable/funtion and where it is found
+	      $start = index($body,"\n\n") + 2;
+	    }
+	    my $stop = index($body,"ans =");
+	    $body = substr($body,$start,$stop-$start);
+	    register_function($func,$body,$OCTAVE,0);
+	  }
+	}
+      }
+    }
+  }
+}
+
+# print a summary table rather than generating the html
+if ( $summary ) {
+    write_ascii("% ");
+}
+else {
+    write_html();
+}
+
+
+if (@skipped) {
+    print "skipped ", scalar(@skipped), " functions ";
+    my $rs = $,; $, = "\n  ";
+    print "  ", sort(@skipped); $, = $rs;
+    print "\n";
+}
+
+print_missing();
+
+if (@uncategorized) {
+    print scalar(@uncategorized), " uncategorized functions ";
+    print "(out of ", $n_functions, " total)";
+    my $rs = $,; $, = "\n  ";
+    print "  ", sort(@uncategorized); $, = $rs;
+    print "\n";
+#    print wrap("\t", "\t", join(" ", sort @uncategorized)), "\n";
+}
+
+if (@shadowed) {
+    print "unexpected shadowing of ", scalar(@shadowed), " Octave functions";
+    my $rs = $,; $, = "\n  ";
+    print "  ", sort(@shadowed); $, = $rs;
+    print "\n";
+#    print wrap("\t", "\t", join(" ", sort @shadowed)), "\n";
+}
+
+sub process_docstrings {
+  my $function = "";
+  my $desc = "";
+  while (<IN>) {
+    if (/^\037/) {
+	register_function($function,$desc,$OCTAVE,1) unless $function eq "";
+	$function = $_;
+	$function =~ s/^\037//;
+	$function =~ s/\n$//;
+        $desc = "";
+    } else {
+      $desc .= $_;
+    }
+  }
+  register_function($function,$desc,$OCTAVE,1) unless $function eq "";
+  close(IN);
+}
+
+sub first_sentence { # {{{1
+# grab the first real sentence from the function documentation
+    my ($desc) = @_;
+    my $retval = '';
+    my $line;
+    my $next;
+    my @lines;
+
+    my $trace = 0;
+    # $trace = 1 if $desc =~ /Levenberg/;
+    return "" unless defined $desc;
+    if ($desc =~ /^\s*-[*]- texinfo -[*]-/) {
+
+	# help text contains texinfo.  Strip the indicator and run it
+	# through makeinfo. (XXX FIXME XXX this needs to be a function)
+	$desc =~ s/^\s*-[*]- texinfo -[*]-\s*//;
+	my $cmd = "makeinfo --fill-column 1600 --no-warn --no-validate --no-headers --force --ifinfo";
+	open3(*Writer, *Reader, *Errer, $cmd) or die "Could not run info";
+	print Writer "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n";
+	print Writer "$desc"; close(Writer);
+	@lines = <Reader>; close(Reader);
+	my @err = <Errer>; close(Errer);
+	waitpid(-1,&WNOHANG);
+
+	# Display source and errors, if any
+	if (@err) {
+	    my $n = 1;
+	    foreach $line ( split(/\n/,$desc) ) {
+		printf "%2d: %s\n",$n++,$line;
+	    }
+	    print ">>> @err";
+	}
+
+	# Print trace showing formatted output
+#	print "<texinfo--------------------------------\n";
+#	print @lines;
+#	print "--------------------------------texinfo>\n";
+
+	# Skip prototype and blank lines
+	while (1) {
+	    return "" unless @lines;
+	    $line = shift @lines;
+	    next if $line =~ /^\s*-/;
+	    next if $line =~ /^\s*$/;
+	    last;
+	}
+
+    } else {
+
+#	print "<plain--------------------------------\n";
+#	print $desc;
+#	print "--------------------------------plain>\n";
+
+	# Skip prototype and blank lines
+	@lines = split(/\n/,$desc);
+	while (1) {
+	    return "" if ($#lines < 0);
+	    $line = shift @lines;
+	    next if $line =~ /^\s*[Uu][Ss][Aa][Gg][Ee]/; # skip " usage "
+	    next if $line =~ /^\s*-/;           # skip " -- blah"
+
+	    $line =~ s/^\s*\w+\s*://;             # chop " blah : "
+	    print "strip blah: $line\n" if $trace;
+	    $line =~ s/^\s*[Ff]unction\s+//;      # chop " function "
+	    print "strip function $line\n" if $trace;
+	    $line =~ s/^\s*\[.*\]\s*=\s*//;       # chop " [a,b] = "
+	    print "strip []= $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s*=\s*//;          # chop " a = "
+	    print "strip a= $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s*\([^\)]*\)\s*//; # chop " f(x) "
+	    print "strip f(x) $line\n" if $trace;
+	    $line =~ s/^\s*[;:]\s*//;                # chop " ; "
+	    print "strip ; $line\n" if $trace;
+
+	    $line =~ s/^\s*[[:upper:]][[:upper:]0-9_]+//; # chop " BLAH"
+	    print "strip BLAH $line\n" if $trace;
+	    $line =~ s/^\s*\w*\s*[-]+\s+//;        # chop " blah --- "
+	    print "strip blah --- $line\n" if $trace;
+	    $line =~ s/^\s*\w+ *\t\s*//;          # chop " blah <TAB> "
+	    print "strip blah <TAB> $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s\s+//;            # chop " blah  "
+	    print "strip blah <NL> $line\n" if $trace;
+
+#	    next if $line =~ /^\s*\[/;           # skip  [a,b] = f(x)
+#	    next if $line =~ /^\s*\w+\s*(=|\()/; # skip a = f(x) OR f(x)
+	    next if $line =~ /^\s*or\s*$/;      # skip blah \n or \n blah
+	    next if $line =~ /^\s*$/;            # skip blank line
+	    next if $line =~ /^\s?!\//;          # skip # !/usr/bin/octave
+	    # XXX FIXME XXX should be testing for unmatched () in proto
+	    # before going to the next line!
+	    last;
+	}
+    }
+
+    # Try to make a complete sentence, including the '.'
+    if ( "$line " !~ /[^.][.]\s/ && $#lines >= 0) {
+	my $next = $lines[0];
+	$line =~ s/\s*$//;  # trim trailing blanks on last
+	$next =~ s/^\s*//;    # trim leading blanks on next
+	$line .= " $next" if "$next " =~ /[^.][.]\s/; # ends the sentence
+    }
+
+    # Tidy up the sentence.
+    chomp $line;          # trim trailing newline, if there is one
+    $line =~ s/^\s*//;    # trim leading blanks on line
+    $line =~ s/([^.][.])\s.*$/$1/; # trim everything after the sentence
+    print "Skipping:\n$desc---\n" if $line eq "";
+
+    # And return it.
+    return $line;
+
+} # 1}}}
+sub shadow_path { # {{{1
+# shadow_path($f) returns true if $f is on a known Octave shadow path
+    my ($file) = @_;
+    $file =~ s|/[^/]*$||;
+    my @matches = grep(/^$file$/,@shadow_paths);
+#    print "looking for $file in @shadow_paths\n";
+#    print "returns ",@matches,"\n";
+    return scalar(@matches) > 0 || $file =~ /alternatives$/;
+    
+} # 1}}}
+sub register_function { # {{{1
+# register the function and its one-line description
+    my ($function,      # in   $index{toolbox}{category} = [functions]
+        $desc,          # in   $toolbox_desc{toolbox} = description
+	$file,
+	$replace_shadow,
+       )      = @_;
+    ++$n_appearances{$function};
+    if ($n_appearances{$function} > 1) {
+      if ($replace_shadow != 0) {
+	push @shadowed, "$file:$function" if $file =~ /^$OCTAVE/ 
+	  and !shadow_path($function_description{$function}[0]);
+	        # print "$file:$function appeared previously\n";
+      }
+    } else {
+        ++$n_functions;
+    }
+
+    $octave_forge_function{$function} = 1 unless $file =~ /^$OCTAVE/;
+    if (!defined $index_by_function{$function}) {
+	my $entry = $file;
+	$entry = "$file: $function" if $file !~ /[.]m$/;
+	if ($function =~ /__/ || $file =~ /test/ 
+	    || $function =~ /^[Cc]ontents?$/) {
+	    push @skipped, $entry;
+	} else {
+	    push @uncategorized, $entry;
+	}
+    }
+
+    my $oneline = first_sentence($desc);
+    #printf "%30s %s\n", $function, $oneline;
+    if ($replace_shadow == 0 && defined @function_description{$function}) {
+      @function_description{$function} = [ $function_description{$function}[0], $oneline, $desc ];
+    } elsif (!defined @function_description{$function}) {
+      @function_description{$function} = [ $file, $oneline, $desc ];
+    }
+#    push @function_description{$function}}, "$file\n$oneline\n$desc";
+    #printf "%-12s %-20s %s\n", $function,
+    #                           $index_by_function{$function}[0],
+    #                           $index_by_function{$function}[1];
+} # 1}}}
+sub extract_description { # {{{1
+# grab the entire documentation comment from an m-file
+    my ($file) = @_;
+    my $retval = '';
+
+    if( open( IN, "$file")) {
+	# skip leading blank lines
+	while (<IN>) {
+	    last if /\S/;
+	}
+	if( m/\s*[%\#][\s\#%]* Copyright/) {
+	    # next block is copyright statement, skip it
+	    while (<IN>) {
+		last unless /^\s*[%\#]/;
+	    }
+	}
+	# Skip everything until the next comment block
+	while ( !/^\s*[\#%]/ ) {
+	    $_ = <IN>;
+	    last if not defined $_;
+	}
+        # Return the next comment block as the documentation
+        while (/^\s*[\#%]/) {
+	    s/^[\s%\#]*//;    # strip leading comment characters
+            s/[\cM\s]*$//;   # strip trailing spaces.
+	    $retval .= "$_\n";
+	    $_ = <IN>;
+	    last if not defined $_;
+	}
+        close(IN);
+	return $retval;
+    }
+    else {
+	print STDERR "Could not open file ($file): $!\n";
+    }
+} # 1}}}
+sub load_index { # {{{1
+    my ($file) = @_;             # in
+    my $toolbox     = "extra";
+    my $category    = "";
+    my $description = "";
+    my $function    = "";
+    open(IN, $file) or die "Cannot read $file:  $!\n";
+    my %map;   # simple macros for use in notes
+    while (<IN>) {
+        next if /^\s*$/; # skip blank lines
+	next if /^\s*\#/; # skip comment lines
+        chomp;
+        if      (/^(.*?)\s*>>\s*(.*?)$/) {
+	    # toolbox lines contain "word >> description"
+            $toolbox     = $1;
+            $description = $2;
+            $category    = "";
+            $TB_description{$toolbox} = $description;
+	} elsif (/^\s*\$(\w+)\s*=\s*(\S.*\S)\s*$/) {
+	    # define a variable as "$var = expansion"
+	    $map{$1} = $2;
+        } elsif (/^(\w.*?)\s*$/) {
+	    # category lines start in the left most column
+            $category    = $1;
+        } elsif (/^\s+(\S.*[^=~!><])=\s*(\S.*\S)\s*$/) {
+	    # Process "function = notes" explicit descriptions
+	    $function = $1;
+	    $description = $2;
+
+	    # We used ...(\S.*)=... rather than (\S.*\S)\s*= to allow for
+	    # single character function names, but that means we may have
+	    # to trim some extra spaces of the function name.  Single
+	    # character descriptions get the treatment they deserve.
+	    $function =~ s/\s+$//;
+
+	    # expand all $var in the description
+	    my @parts = split('\$', $description);
+	    foreach my $i ( 1 .. $#parts ) {
+		$parts[$i] =~ /^(\w+)(\W.*)$/ or $parts[$i] =~ /^(\w+)()$/;
+		$parts[$i] = "$map{$1}$2";
+	    }
+	    $description = join("",@parts);
+
+	    # record the function->description mapping
+	    $index_notes{$function} = $description;
+	    die "Function $function (line $.) has no category" unless $category;
+	    push @{$index_by_TB_cat{$toolbox}{$category}}, $function;
+	    push @{$index_by_function{$function}}, [$toolbox, $category];
+	} else {
+            s/^\s+//;
+            my @list = split /\s+/;
+            while ($#list >= 0) {
+                $function    = shift @list;
+                die "Function $function (line $.) has no category" unless $category;
+                push @{$index_by_TB_cat{$toolbox}{$category}}, $function;
+                push @{$index_by_function{$function}}, [$toolbox, $category];
+
+            }
+        }
+    }
+    close(IN);
+} # 1}}}
+sub write_html { # {{{1
+    # make empty html directories
+    unlink <$catdir/*.html>;
+    unlink <$catdir/f/*.html>;
+    mkdir "$catdir";
+    mkdir "$catdir/f";
+
+    write_main();
+    write_forgebar();
+    write_intro();
+    write_alphabetic_navbar();
+    write_TBnavbar();
+    foreach ( toolbox_list() ) {
+	write_TBnavbar($_);
+	write_TBdetails($_);
+    }
+
+    # Write one file for each letter.
+    #
+
+    my $Letter = chr(0);
+    foreach my $func ( indexed_funcs() ) {
+	# The source file
+
+	my $body = long_desc($func);
+	if ($body ne "") {
+	    # XXX FIXME XXX this will die if the punctuation is too wild
+	    open FUNC, ">$catdir/f/$func.html" or die "Could not open $func.html";
+	    print FUNC "<html><head><title>$func</title></head>\n";
+	    print FUNC "<body>\n";
+	    print FUNC "<table width=100%><tr><td align=left><b>$func</b>\n";
+	    # The toolboxes to which it belongs
+	    foreach my $pair ( @{$index_by_function{$func}} ) {
+		my ( $TB, $cat ) = @{$pair};
+		print FUNC "    ", cat_ref_up($TB, $cat, "[$TB]"), "\n";
+	    }
+	    print FUNC "    <td align=right>", download_ref($func), "</table>\n";
+	    print FUNC "$body\n";
+	    print FUNC "$forgelink\n</body></html>";
+            close FUNC;
+	}
+
+	# Check if need to go to the next letter
+	# This is particularly complicated because we
+	# want to include all punctuation in the 
+	my $next = uc(substr($func, 0, 1));
+	if ($next ne $Letter) {
+	    if ($Letter =~ /[A-Y]/) {
+		print OUT "</dl>\n$forgelink\n</body></html>\n";
+		close OUT;
+	    } else {
+		print OUT "</dl>\n";
+	    }
+	    if ($Letter =~ /[\0A-Y]/) {
+		my $head = "";
+		if ( $next =~ /[A-Z]/ ) {
+		    $head = $next;
+		} elsif ( $next lt "A" ) {
+		    $head = "A";
+		} else {
+		    $head = "Z";
+		}
+		my $file = ">$catdir/$head.html";
+		open(OUT, $file) or die "Cannot write $file";
+		print OUT "<html><head>\n";
+		print OUT "<title>Octave Functions: $head</title>\n";
+		print OUT "<meta name=\"keywords\" content=\"\"></head>\n";
+		print OUT "<body>\n";
+	    }
+	    $Letter = $next;
+	    print OUT "<h1><a name=\"$Letter\">$Letter</a></h1>";
+	    print OUT "<dl>\n";
+	}
+
+	# Function reference
+	print OUT "<dt><table width=100%><tr><td align=left><b>",func_ref($func,$func),"</b>\n";
+	# The toolboxes to which it belongs
+	foreach my $pair ( @{$index_by_function{$func}} ) {
+	    my ( $TB, $cat ) = @{$pair};
+	    print OUT "    ", cat_ref($TB, $cat, "[$TB]"), "\n";
+	}
+	print OUT "    <td align=right>", download_ref($func), "</table>\n";
+
+
+	# column 3:  the function description
+	# XXX FIXME XXX multiple functions???
+	print OUT "    <dd>",html_desc($func),"\n";
+    }
+
+    print OUT "</dl>\n$forgelink\n</body></html>\n";
+    close(OUT);
+} # 1}}}
+sub writenav { # 1{{{
+    my ($cat) = @_;
+
+} # 1}}}
+sub write_main { # {{{1
+    open(OUT,">$catdir/index.html") or die "Could not open $catdir/index.html";
+    print OUT <<EOF;
+<HTML><HEAD>
+<TITLE>Octave-forge combined index</TITLE>
+</HEAD>
+<FRAMESET rows="50, *">
+  <FRAME src="forgebar.html" noresize frameborder="0">
+  <FRAMESET cols="33%, 67%">
+    <FRAME name=navbar src="categorical.html">
+    <FRAMESET rows="50, *">
+      <FRAME src="alphabetic.html">
+      <FRAME name=content src="intro.html">
+    </FRAMESET>
+  </FRAMESET>
+<NOFRAMES>
+$forgebar
+<H1>Octave-Forge Combined Index</H1>
+<ul>
+<li><A HREF="categorical.html">Categorical index</a>
+<li><A HREF="alphabetic.html">Alphabetic index</a>
+</ul>
+</NOFRAMES>
+</FRAMESET>
+</HTML>
+EOF
+    close OUT;
+} # 1}}}
+sub write_forgebar {
+    open(OUT,">$catdir/forgebar.html") or die "Could not open index/forgebar.html";
+    print OUT <<EOF;
+<html><title>Octave Forge site navigator</title>
+<base target=_top>
+<body>
+$forgebar
+</body></html>
+EOF
+}
+sub download_ref { 
+# download_ref($func,$desc) returns a link to download $func described by $desc
+    my ($func) = @_;
+
+    my $path = $function_description{$func}[0];
+    if ($path ne "" && $path !~ /^$OCTAVE/) {
+	return "[<a href=\"$FORGECVS$path\?rev=HEAD\&content-type=text/plain\">octave-forge/$path</a>]";
+    } elsif ($path =~ /^$OCTAVE/) {
+	$path =~ s/^$OCTAVE//;
+	return "[<a href=\"$OCTAVECVS$path\?rev=HEAD\&content-type=text/plain\">octave$path</a>]";
+    } else {
+	return "";
+    }
+}
+sub write_intro { # 1{{{
+    open(OUT,">$catdir/intro.html") or die "Could not open $catdir/intro.html";
+    print OUT <<EOF;
+<HTML><HEAD><TITLE>Octave-forge index intro</TITLE></HEAD>
+<BODY>
+<H1>Welcome to Octave-forge</H1>
+$forgelink
+</BODY></HTML>
+EOF
+    close OUT;
+} # 1}}}
+sub write_TBnavbar { # 1{{{
+    my $openTB = shift;
+    my $file = "categorical";
+    $file = "nav$openTB" if $openTB ne "";
+    open(OUT,">$catdir/$file.html") or die "Could not open $catdir/$file.html";
+    print OUT <<EOF;
+<html><head><title>Octave-forge categorical index</title></head>
+<body>
+What\'s available:
+<ol>
+EOF
+    foreach my $TB (toolbox_list()) {
+#	print OUT "<li><a href=\"$TB.html\" target=content><a href=\"nav$TB.html#$TB\" target=navbar>$TB_description{$TB}</a></a>";
+	print OUT "<li>";
+	if ($openTB eq $TB) {
+	    print OUT "<a name=\"$TB\"><a href=\"categorical.html#$TB\" target=navbar>
+$TB_description{$TB}</a></a>";
+	    print OUT "<ul>\n";
+	    foreach my $cat ( cat_list($TB) ) {
+		my $anchor = cat_anchor($cat);
+		print OUT "    <li><a href=\"$TB.html#$anchor\" target=content>$cat</a></li>\n";
+	    }
+	    print OUT "</ul>\n";
+	} else {
+	    print OUT "<a name=\"$TB\"><a href=\"nav$TB.html#$TB\" target=navbar>$TB_description{$TB}</a></a>";
+	}
+    }
+    print OUT "</ol>\n</body></html>";
+    close OUT;
+} # 1}}}
+sub write_TBdetails { # 1{{{
+    my $TB = shift;
+    my $file   = "$catdir/$TB.html";
+    
+    open(OUT, ">$file") or die "Cannot write $file:  $!\n";
+    print OUT <<EOF;
+<html><head>
+<title>$TB</title>
+<meta name=\"keywords\" content=\"\">
+</head>
+<body>
+<h1>$TB_description{$TB}</h1>
+EOF
+
+    # summary list of categories
+    print OUT "<ul>\n";
+    foreach my $cat ( cat_list($TB) ) {
+	my $anchor = cat_anchor($cat);
+	print OUT "    <li><a href=\"#$anchor\">$cat</a></li>\n";
+    }
+    print OUT "</ul>\n";
+    
+    # Each category has a table of its functions and their descriptions.
+    foreach my $cat ( cat_list($TB) ) {
+	my $anchor = cat_anchor($cat);
+	print OUT "<h2><a name=\"$anchor\">$cat</a></h2>\n";
+	print OUT "<dl>\n";
+	foreach my $func ( cat_funcs($TB,$cat) ) {
+	    
+	    # column 1:  the function (x-ref to full description in
+	    #                          cvs-tree's html file)
+	    print OUT "<dt><table width=100%><tr><td align=left><b>",func_ref($func,$func),"</b>\n";
+	    print OUT "    <td align=right>", download_ref($func), "</table>\n";
+	    
+	    # column 2: the description, if it exists
+	    #
+	    print OUT "<dd>",html_desc($func),"\n";
+	}
+	print OUT "</dl>\n";
+    }
+    print OUT "$forgelink\n</body></html>\n";
+    close(OUT);
+} # 1}}}
+sub write_alphabetic_navbar { # 1{{{
+    open(OUT,">$catdir/alphabetic.html") or die "Could not open $catdir/alphabetic.html";
+    print OUT <<EOF;
+<html><head><title>Octave-Forge alphabetic list</title></head>
+<base target=content>
+<body>
+EOF
+    my $A_to_Z     = "";
+    foreach (first_letters (indexed_funcs())) {
+        $A_to_Z .= letter_ref($_) . "|";
+    }
+    $A_to_Z         =~ s/\s*\|\s*$//;  # strip last pipe separator
+    print OUT "<center>$A_to_Z</center>\n</body></html>\n";
+    close OUT;
+} # 1}}}
+sub oldnavbar { # 1{{{
+    my $max_TB_across_top = 7;
+    my $all_toolboxes = "<center>\n";
+    my $n = 0;
+
+    foreach my $TB (toolbox_list()) {
+        ++$n;
+        if ($n > $max_TB_across_top) {
+            $n = 0;
+            $all_toolboxes .= "<a href=\"$TB.html\">$TB</a> <br> ";
+        } else {
+            $all_toolboxes .= "<a href=\"$TB.html\">$TB</a> | ";
+        }
+    }
+    $all_toolboxes =~ s/\s+\|\s*$//;  # strip last pipe separator
+    $all_toolboxes .= "<br><br>";
+    my $A_to_Z     = "";
+    foreach (first_letters (indexed_funcs())) {
+        $A_to_Z .= letter_ref($_);
+	$A_to_Z .= " | ";
+    }
+    $A_to_Z         =~ s/\s+\|\s*$//;  # strip last pipe separator
+    my $all_toolboxes_A_Z = $all_toolboxes . "$A_to_Z </center>\n";
+    $all_toolboxes .= "</center>\n";
+
+} # 1}}}
+sub print_missing {
+    my $printmissing = 1;
+    foreach my $TB ( toolbox_list() ) {
+	my $printTB = 1;
+	foreach my $cat ( cat_list($TB) ) {
+            my $printcat = 1;
+            foreach my $func ( cat_funcs($TB,$cat) ) {
+                if (! defined $function_description{$func}[1] && ! defined $index_notes{$func} ) {
+		     print "missing functions:" if $printmissing;
+		     print "\n  [$TB]" if $printTB;
+		     print "\n  $cat\n  >" if $printcat;
+	             print " $func";
+	             $printTB = 0;
+		     $printcat = 0;
+		     $printmissing = 0;
+                }
+            }
+        }
+    }
+    print "\n" unless $printmissing;
+}
+sub write_ascii { # 1{{{
+# output all toolboxes as a contents.m file
+    my ($prefix) = @_;
+    my $indent = 16 - 3 - length($prefix);
+
+    # XXX FIXME XXX add an option to spit out contents.m
+    # XXX FIXME XXX what if there is no toolbox?
+    # XXX FIXME XXX preserve category order
+    foreach my $TB ( toolbox_list() ) {
+	print wrap($prefix,$prefix,$TB_description{$TB}),"\n$prefix\n";
+	foreach my $cat ( cat_list($TB) ) {
+	    print wrap($prefix,$prefix,$cat), "\n";
+	    foreach my $func ( cat_funcs($TB,$cat) ) {
+		my $entry = sprintf("%-*s %s",$indent,$func,ascii_desc($func));
+		print wrap("$prefix","$prefix\t\t","  $entry"), "\n";
+	    }
+	    print "$prefix\n";
+	}
+    } 
+} # 1}}}
+sub cat_ref { # 1{{{
+# cat_ref($TB,$cat,$ref) returns an html link to $cat described by $ref
+    my ($TB,$cat,$ref) = @_;
+    my $anchor = cat_anchor($cat);
+    return "<a href=\"$TB.html#$anchor\">$ref</a>";
+} # 1}}}
+sub cat_ref_up { # 1{{{
+# cat_ref($TB,$cat,$ref) returns an html link to $cat described by $ref
+    my ($TB,$cat,$ref) = @_;
+    my $anchor = cat_anchor($cat);
+    return "<a href=\"../$TB.html#$anchor\">$ref</a>";
+} # 1}}}
+sub cat_anchor { # 1{{{
+# cat_anchor($cat) returns the anchor word generated for category $cat
+    my ($cat) = @_;
+    $cat =~ s/\W+//g;
+    return $cat;
+} # 1}}}
+sub func_ref { # 1{{{
+# func_ref($func) returns an html link to $func described by $ref
+    my ($func,$ref) = @_;
+    if ( defined $function_description{$func}[2] &&
+	 $function_description{$func}[2] ne "") {
+	return "<a href=\"f/$func.html\">$ref</a>";
+    } elsif ( $ref ne $func ) {
+	# XXX FIXME XXX do we want "$ref ($func)"? Check how it is called.
+	return $ref;
+    } else {
+	return $ref;
+    }
+} # 1}}}
+sub split_long_name { # 1{{{
+# html magic to break long variable/function names
+    # XXX FIXME XXX this function is probably not used
+    my ( $nicefunc ) = @_;
+    # $nicefunc =~ s/([^_])_([^_])/$1_ $2/g;
+    return $nicefunc;
+} # 1}}}
+sub first_letters { # 1{{{
+# return a list of all first letters in the arguments
+# The argument list must come sorted with a case-insensitive sort.
+    my $Letter = chr(0);
+    my @ret = ();
+    foreach my $name ( @_ ) {
+	# Check if need to go to the next letter
+	if (uc(substr($name, 0, 1)) ne $Letter) {
+	    $Letter = uc(substr($name, 0, 1));
+	    push @ret, $Letter;
+	}
+    } 
+    return @ret;
+} # 1}}}
+sub letter_file { # 1{{{
+    return "$_.html" if /[A-Z]/;
+    return "A.html" if $_ lt "A";
+    return "Z.html";
+} # 1}}}
+sub letter_ref { # 1{{{
+# letter_ref($letter) returns a link to the letter
+    return "<a href=\"" . letter_file($_) . "#$_\">$_</a>";
+} # 1}}}
+sub ascii_desc { # 1{{{
+# ascii_desc($func) returns a decription of $func using ascii markup
+    my ( $func ) = @_;
+    if (! defined $function_description{$func}[1] ) {
+	my $notes = $index_notes{$func};
+	$notes = "<missing>" if $notes eq "";
+	# convert "<a link>desc</a>" to "desc (link)"
+	$notes =~ s|<a href=\"?([^>]*)\"?>([^<]*)</a>|$2 ($1)|g;
+	# strip all remaining html formatting
+	$notes =~ s|<[^>]*>||g;
+	return $notes;	    
+    } else {
+	my $desc = $function_description{$func}[1];
+	if ($desc eq "") {
+	    return "<no description>";
+	} else {
+	    return $desc;
+	}
+    }
+} #}}}
+sub html_desc { # 1{{{
+# html_desc($func) returns a description of $func using html markup
+    my ( $func ) = @_;
+    my $notes = $index_notes{$func};
+    if (! defined $function_description{$func}[1] ) {
+	$notes = "not implemented" if $notes eq "";
+	# shut of the bold italics during "code" formatting
+	$notes =~ s|<code>|</i><code>|g;
+	$notes =~ s|</code>|</code><i>|g;
+	$notes =~ s|<f>(\w+)</f>|</i><code><a href="f/$1.html">$1</a></code><i>|g;
+	return "<i>$notes</i>";
+    } else {
+	print "ignoring $func = $notes\n" if $notes ne "";
+	my $desc = $function_description{$func}[1];
+	if ($desc eq "") {
+	    return "<i>no description</i>";
+	} else {
+	    return $desc;
+	}
+    }
+} # 1}}}
+sub long_desc {
+    my ( $func ) = @_;
+    my $body = $function_description{$func}[2];
+    if ($body =~ /^\s*-[*]- texinfo -[*]-/) {
+	$body = info2html($func, $body);
+    } elsif ($body ne "") {
+	$body = "<pre>$body</pre>";
+    }
+    return $body
+} # 1}}}
+sub info2html_texi2html { # 1{{{
+# run body through texi2html to produce html
+    my ( $func, $body ) = @_;
+    $body =~ s/^\s*-[*]- texinfo -[*]-//;
+    open(SRC, ">$func.texi");
+    print SRC "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n";
+    print SRC "BEGINCUT $body ENDCUT";
+    close SRC;
+    system ("texi2html -expand info $tmpdir/$func.texi");
+    open(SRC, "<$func.html");
+    my @lines = <SRC>;
+    close SRC;
+    $body = join("",@lines);
+    my $start = index($body,"BEGINCUT") + 8;
+    my $stop = index($body,"ENDCUT");
+    $body = substr($body,$start,$stop-$start);
+    unlink "$func.texi", "$func.html";
+} # 1}}}
+sub info2html { # 1{{{
+# run body through makeinfo to produce html
+    my ( $func, $body ) = @_;
+    $body =~ s/^\s*-[*]- texinfo -[*]-//;
+    my $cmd = "makeinfo --fill-column 80 --no-warn --no-validate --force --html --ifinfo -o -";
+    open3(*Writer, *Reader, *Errer, $cmd) or die "Could not run info";
+    print Writer "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n";
+    # I have no idea why but makeinfo is introducing some weirdness with <p>
+    # at the front of the document.  The following works for my particular
+    # version but I have little hope for it working in general
+    print Writer "-CUT HERE $body"; close(Writer);
+    my @lines = <Reader>; close(Reader);
+    my @err = <Errer>; close(Errer);
+    waitpid(-1,&WNOHANG);
+    # strip everything before <body> and after </body>
+    $body = join("",@lines);
+    my $start = index($body,"CUT HERE") + 8;
+    my $stop = index($body,"</body");
+    $body = substr($body,$start,$stop-$start);
+    $body =~ s|\@var\{([^\}]*)\}|<var>$1</var>|g;
+    return $body;
+} # 1}}}
+sub toolbox_list { # 1{{{
+# toolbox_list() returns an ordered list of toolboxes.
+    return sort { uc($a) cmp uc($b) } keys %index_by_TB_cat;
+} # 1}}}
+sub cat_list { # 1{{{
+# cat_list($TB) returns an ordered list of categories in a toolbox $TB.
+    my ($TB) = @_;
+    return sort keys %{$index_by_TB_cat{$TB}};
+} # 1}}}
+sub cat_funcs { # 1{{{
+# cat_funcs($TB,$cat) returns an ordered list of functions in $TB,$cat
+    my ($TB,$cat) = @_;
+    return sort { uc($a) cmp uc($b) } @{$index_by_TB_cat{$TB}{$cat}}
+} # 1}}}
+sub indexed_funcs { # 1{{{
+# indexed_funcs() returns an ordered list of all functions in the index
+    return sort { uc($a) cmp uc($b) } keys %index_by_function;
+} # 1}}}
+sub forge_funcs { # 1{{{
+# forge_funcs() returns an ordered list of functions only found in octave forge
+    return sort { uc($a) cmp uc($b) } keys %octave_forge_function;
+} # 1}}}
+sub scanned_funcs { # 1{{{
+# scanned_funcs() returns an ordered list of all functions found in m-files and oct-files
+    return sort { uc($a) cmp uc($b) } %function_description;
+} # 1}}}
+__END__
+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
+This program is granted to the public domain.
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
new file mode 100755
--- /dev/null
+++ b/src/admin/mkdoc
@@ -0,0 +1,137 @@
+#!/usr/bin/env perl
+#
+# David Bateman Feb 02 2003
+# 
+# Extracts the help in texinfo format from *.cc and *.m files for use
+# in documentation. Based on make_index script from octave_forge.
+
+use strict;
+use File::Find;
+use File::Basename;
+use FileHandle;
+
+my $docdir = ".";
+if (@ARGV) {
+  $docdir = @ARGV[0];
+}
+
+# locate all C++ and m-files in current directory
+my @m_files = ();
+my @C_files = ();
+find(\&cc_and_m_files, $docdir);
+
+sub cc_and_m_files { # {{{1 populates global array @files
+    return unless -f and /\.(m|cc)$/;  # .m and .cc files
+    my $path = "$File::Find::dir/$_";
+    $path =~ s|^[.]/||;
+    if (/\.m$/) {
+        push @m_files, $path;
+    } else {
+        push @C_files, $path;
+    }
+} # 1}}}
+
+# grab help from C++ files
+foreach my $f ( @C_files ) {
+  # XXX FIXME XXX. Should run the preprocessor over the file first, since 
+  # the help might include defines that are compile dependent.
+    if ( open(IN,$f) ) {
+	while (<IN>) {
+	    # skip to the next function
+	    next unless /^DEFUN_DLD/;
+
+	    # extract function name to pattern space
+	    /\((\w*)\s*,/;
+	    # remember function name
+	    my $function = $1;
+	    # skip to next line if comment doesn't start on this line
+	    # XXX FIXME XXX maybe we want a loop here?
+	    $_ = <IN> unless /\"/;
+	    # skip to the beginning of the comment string by
+	    # chopping everything up to opening "
+	    my $desc = $_;
+            $desc =~ s/^[^\"]*\"//;
+	    # join lines until you get the end of the comment string
+	    # plus a bit more.  You need the "plus a bit more" because
+	    # C compilers allow implicitly concatenated string constants
+	    # "A" "B" ==> "AB".
+	    while ($desc !~ /[^\\]\"\s*\S/ && $desc !~ /^\"/) {
+		# if line ends in '\', chop it and the following '\n'
+		$desc =~ s/\\\s*\n//;
+		# join with the next line
+		$desc .= <IN>;
+		# eliminate consecutive quotes, being careful to ignore
+		# preceding slashes. XXX FIXME XXX what about \\" ?
+		$desc =~ s/([^\\])\"\s*\"/$1/;
+	    }
+	    $desc = "" if $desc =~ /^\"/; # chop everything if it was ""
+	    $desc =~ s/\\n/\n/g;          # insert fake line ends
+	    $desc =~ s/([^\"])\".*$/$1/;  # chop everything after final '"'
+	    $desc =~ s/\\\"/\"/;          # convert \"; XXX FIXME XXX \\"
+	    $desc =~ s/$//g;		  # chop trailing ...
+
+	    if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) {
+		my $err = sprintf("Function %s, does not contain texinfo help\n",
+				$function);
+		print STDERR "$err";
+	    }
+	    my $entry = sprintf("\037%s\n%s", $function, $desc);
+	    print "$entry", "\n";
+	}
+	close (IN);
+    } else {
+	print STDERR "Could not open file ($f): $!\n";
+    }
+}
+
+# grab help from m-files
+foreach my $f ( @m_files ) {
+    my $desc     = extract_description($f);
+    my $function = basename($f, ('.m'));
+    die "Null function?? [$f]\n" unless $function;
+    if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) {
+	my $err = sprintf("Function %s, does not contain texinfo help\n",
+				$function);
+	print STDERR "$err";
+    }
+    my $entry = sprintf("\037%s\n%s", $function, $desc);
+    print "$entry", "\n";
+}
+
+sub extract_description { # {{{1
+# grab the entire documentation comment from an m-file
+    my ($file) = @_;
+    my $retval = '';
+
+    if( open( IN, "$file")) {
+	# skip leading blank lines
+	while (<IN>) {
+	    last if /\S/;
+	}
+	if( m/\s*[%\#][\s\#%]* Copyright/) {
+	    # next block is copyright statement, skip it
+	    while (<IN>) {
+		last unless /^\s*[%\#]/;
+	    }
+	}
+	# Skip everything until the next comment block
+	while ( !/^\s*[\#%]/ ) {
+	    $_ = <IN>;
+	    last if not defined $_;
+	}
+        # Return the next comment block as the documentation
+        while (/^\s*[\#%]/) {
+	    s/^[\s%\#]*//;    # strip leading comment characters
+            s/[\cM\s]*$//;   # strip trailing spaces.
+	    s/[\.*]$//;
+	    $retval .= "$_\n";
+	    $_ = <IN>;
+	    last if not defined $_;
+	}
+        close(IN);
+	return $retval;
+    }
+    else {
+	print STDERR "Could not open file ($file): $!\n";
+    }
+} # 1}}}
new file mode 100755
--- /dev/null
+++ b/src/admin/mkpkgadd
@@ -0,0 +1,27 @@
+#! /bin/sh
+
+if test $# -eq 1; then
+  dir="$1"
+else
+  echo "usage: mkpkgadd directory" 1>&2
+  exit 1
+fi
+
+cd $dir
+
+m_files=`echo *.m`
+cxx_files=`echo *.cc`
+ln_files=`echo *.octlink`
+
+if test "$m_files" != "*.m"; then
+  sed -n 's/^[#%][#%]* *PKG_ADD: *//p' $m_files
+fi
+
+if test "$cxx_files" != "*.cc"; then
+  sed -n -e 's,^//* *PKG_ADD: *,,p' \
+         -e 's,^/\** *PKG_ADD: *\(.*\) \*/$,\1,p' $cxx_files
+fi
+
+if test "$ln_files" != "*.octlink" ; then
+  cat $ln_files
+fi
new file mode 100755
--- /dev/null
+++ b/src/admin/mktests.sh
@@ -0,0 +1,73 @@
+#! /bin/sh
+
+# Where to find mkpkgadd
+MKPKGADD=$1
+
+# Create a new fntests.m file
+echo "fid=fopen('fntests.log','wt');" > fntests.m
+echo "if fid<0,error('could not open fntests.log for writing');end" >>fntests.m
+echo "test('','explain',fid);" >> fntests.m
+echo "passes=0; tests=0;" >>fntests.m
+
+# Find all toplevel non-cvs directories
+DIRS="`find FIXES main/* extra/* nonfree/* -type d ! -name CVS -prune`"
+
+# Find the tests in that directory
+for dir in $DIRS; do
+    dir=`echo $dir | sed -e "s-^\./--" `
+
+    # skip the NOINSTALL directories
+    if test -f "$dir/NOINSTALL"; then continue; fi
+
+    # Create local copy of PKG_ADD for in place testing
+    if test -e "$dir/PKG_ADD" ; then rm -f $dir/PKG_ADD; fi
+    $MKPKGADD $dir > $dir/PKG_ADD
+    if test -z "`cat $dir/PKG_ADD`" ; then rm -f $dir/PKG_ADD;  fi
+ 
+    # Build a list of possible test files
+    FILES=""
+
+    # Find all successfully compiled .cc files
+    cxx_files=`echo $dir/*.cc`
+    if test "$cxx_files" != "$dir/*.cc"; then 
+	for file in $cxx_files; do
+      	    obj=`echo "$file" | sed -e 's-\.cc$-.o-'`
+	    if test -f "$obj" ; then FILES="$FILES $file"; fi
+	done
+    fi
+
+    # Find all m-files
+    m_files=`echo $dir/*.m`
+    if test "$m_files" != "$dir/*.m"; then FILES="$FILES $m_files"; fi
+
+    # No C++ of m-files, so no testing
+    if test -z "$FILES" ; then continue; fi
+
+    # Find all files with %!test or %!assert in them
+    # XXX FIXME XXX is there a system independent way of doing (test|assert)
+    TESTS=`grep -l -E '^%![ta][es]s' $FILES`
+
+    NUMFILES=`echo $FILES | wc -w`
+    NUMTESTS=`echo $TESTS | wc -w`
+    prompt="$dir [tests $NUMTESTS of $NUMFILES files]"
+
+    # if no files have tests in them, skip
+    echo "printf('%s','$prompt'); disp('');" >>fntests.m
+    if test -z "$TESTS" ; then
+	echo "printf('%-40s ---> success','');disp('');" >>fntests.m
+    else 
+	echo "dp=dn=0;" >>fntests.m
+	for file in $TESTS ; do
+            echo "[p,n] = test('$file','quiet',fid);" >>fntests.m
+            echo "dp += p; dn += n;" >>fntests.m
+	done
+	echo "if dp==dn, printf('%-40s ---> success',''); else" >>fntests.m
+        echo "printf('%-40s ---> passes %d out of %d tests','',dp,dn); end" >>fntests.m
+        echo "disp(''); passes += dp; tests += dn;" >>fntests.m
+    fi
+
+done
+
+echo "printf('passes %d out of %d tests',passes,tests);disp('');" >> fntests.m
+echo "printf('see fntests.log for details');disp('');" >> fntests.m
+echo "fclose(fid);" >> fntests.m
new file mode 100755
--- /dev/null
+++ b/src/admin/mktexi
@@ -0,0 +1,433 @@
+#!/usr/bin/env perl
+#
+# David Bateman Feb 02 2003
+# 
+# Extracts the help in texinfo format for particular function for use
+# in documentation. Based on make_index script from octave_forge.
+
+use strict;
+use File::Find;
+use File::Basename;
+use Text::Wrap;
+use FileHandle;
+use IPC::Open3;
+use POSIX ":sys_wait_h";
+
+my $file = shift @ARGV;
+my $docfile = shift @ARGV;
+my $indexfile = shift @ARGV;
+my $line;
+
+if ( open(IN,$file) ) {
+  $line = <IN>;
+  my $tex = 0;
+  while ($line) {
+    if ($line =~ /^\@DOCSTRING/) {
+      my $found = 0;
+      my $func = $line;
+      $func =~ s/\@DOCSTRING\(//;
+      $func =~ s/\)[\n\r]+//;
+      my $func0 = $func;
+      my $func1 = $func;
+      $func0 =~ s/,.*$//;
+      $func1 =~ s/^.*,//;
+      if ( open(DOC,$docfile) ) {
+	while (<DOC>) {
+	  next unless /\037/;
+	  my $function = $_;
+	  $function =~ s/\037//;
+	  $function =~ s/[\n\r]+//;
+	  if ($function =~ /^$func0$/) {
+	    my $desc = "";
+	    my $docline;
+	    my $doctex = 0;
+	    while (($docline = <DOC>) && ($docline !~ /^\037/)) {
+	      $docline =~ s/^\s*-[*]- texinfo -[*]-\s*//;
+	      if ($docline =~ /\@tex/) {
+		$doctex = 1;
+	      }
+	      if ($doctex) {
+		$docline =~ s/\\\\/\\/g;
+	      }
+	      if ($docline =~ /\@end tex/) {
+		$doctex = 0;
+	      }
+	      $desc .= $docline;
+	    }
+	    $desc =~ s/$func0/$func1/g;
+	    $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g;
+	    print "$desc", "\n";
+	    $found = 1;
+	    last;
+	  }
+        }
+	close (DOC);
+	if (! $found) {
+	  print "\@emph{Not implemented}\n";
+	}
+      } else {
+	print STDERR "Could not open file $docfile\n";
+	exit 1;
+      }
+    } elsif ($line =~ /^\@REFERENCE_SECTION/) {
+      my $secfound = 0;
+      my $sec = $line;
+      $sec =~ s/\@REFERENCE_SECTION\(//;
+      $sec =~ s/\)[\n\r]+//;
+      my @listfunc = ();
+      my $nfunc = 0;
+      my $seccat = 0;
+
+      if ( open(IND,$indexfile) ) {
+	while (<IND>) {
+	  next unless /^[^ ]/;
+	  my $section = $_;
+	  $section =~ s/[\n\r]+//;
+	  if ($section =~ /^(.*?)\s*>>\s*(.*?)$/) {
+	    $section =~ s/.*>>(.*)/\1/;
+	    $seccat = 1;
+	  }
+	  $section =~ s/^ *//;
+	  $section =~ s/ *$//;
+	  if ($section =~ /^$sec$/) {
+	    if ($seccat) {
+	      print "\@iftex\n";
+	      print "\@section Functions by Category\n";
+	      # Get the list of categories to index
+	      my $firstcat = 1;
+	      my $category;
+	      while (<IND>) {
+		last if />>/;
+		if (/^[^ ]/) {	
+		  if (! $firstcat) {
+		    print "\@end table\n";
+		  } else {
+		    $firstcat = 0;
+		  }
+		  $category = $_;
+		  $category =~ s/[\n\r]+//;
+		  print "\@subsection $category\n";
+		  print "\@table \@asis\n";
+		} elsif (/^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) {
+		  my $func = $1;
+		  my $desc = $2;
+		  print "\@item $func\n";
+		  print "$desc\n";
+		  print "\n";
+		} else {
+		  if ($firstcat) {
+		    print STDERR "Error parsing index file\n";
+		    exit 1;
+		  }
+		  s/^\s+//;
+		  my @funcs = split /\s+/;
+		  while ($#funcs >= 0) {
+		    my $func = shift @funcs;
+		    $func =~ s/^ *//;
+		    $func =~ s/[\n\r]+//;
+		    push @listfunc, $func;
+		    $nfunc = $nfunc + 1;
+		    print "\@item $func\n";
+		    print func_summary($func, $docfile);
+		    print "\n";
+		  }
+		}
+	      }
+	      if (! $firstcat) {
+	        print "\@end table\n";
+	      }
+	      print "\n\@section Functions Alphabetically\n";
+	      print "\@end iftex\n\n";
+	    } else {
+	      # Get the list of functions to index
+	      my $indline;
+	      while (($indline = <IND>) && ($indline =~ /^ /)) {
+		if ($indline =~ /^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) {
+		  next;
+		}
+		$indline =~ s/^\s+//;
+		my @funcs = split(/\s+/,$indline);
+		while ($#funcs >= 0) {
+		  my $func = shift @funcs;
+		  $func =~ s/^ *//;
+		  $func =~ s/[\n\r]+//;
+		  push @listfunc, $func;
+		  $nfunc = $nfunc + 1;
+		}
+	      }
+	    }
+	    $secfound = 1;
+	    last;
+	  }
+	}
+	close (IND);
+	if (! $secfound) {
+	  print STDERR "Did not find section $sec\n";
+	}
+      } else {
+	print STDERR "Could not open file $indexfile\n";
+	exit 1;
+      }
+
+      @listfunc = sort(@listfunc);
+      my @listfunc2 = ();
+      my $indent = 16 - 3;
+      print "\@menu\n";
+      foreach my $func (@listfunc) {
+	if ( open(DOC,$docfile) ) {
+	  my $found = 0;
+	  while (<DOC>) {
+	    next unless /\037/;
+	    my $function = $_;
+	    $function =~ s/\037//;
+	    $function =~ s/[\n\r]+//;
+	    if ($function =~ /^$func$/) {
+	      $found = 1;
+	      last;
+	    }
+	  }
+	  close (DOC);
+	  if ($found) {
+	    push @listfunc2, $func;
+	    my $func0 = "${func}::";
+	    my $entry = sprintf("* %-*s %s",$indent,$func0,func_summary($func,$docfile));
+	    print wrap("","\t\t","$entry"), "\n";
+	  }
+	} else {
+	  print STDERR "Could not open file $indexfile\n";
+	  exit 1;
+	}
+      }
+      print "\@end menu\n";
+
+      my $up = "Function Reference";
+      my $next;
+      my $prev;
+      my $mfunc = 1;
+      foreach my $func (@listfunc2) {
+	if ($mfunc == $nfunc) {
+	  $next = "";
+	} else {
+	  $next = @listfunc2[$mfunc];
+	  $mfunc = $mfunc + 1;
+	}
+	print "\n\@node $func, $next, $prev, $up\n";
+	if ($seccat) {
+	  print "\@subsection $func\n\n";
+	} else {
+	  print "\@section $func\n\n";
+	}
+	$prev = $func;
+	my $found = 0;
+	my $desc = "";
+	if ( open(DOC,$docfile) ) {
+	  while (<DOC>) {
+	    next unless /\037/;
+	    my $function = $_;
+	    $function =~ s/\037//;
+	    $function =~ s/[\n\r]+//;
+	    if ($function =~ /^$func$/) {
+	      my $docline;
+	      my $doctex = 0;
+	      while (($docline = <DOC>) && ($docline !~ /^\037/)) {
+		$docline =~ s/^\s*-[*]- texinfo -[*]-\s*//;
+		if ($docline =~ /\@tex/) {
+		  $doctex = 1;
+		}
+		if ($doctex) {
+		  $docline =~ s/\\\\/\\/g;
+		}
+		if ($docline =~ /\@end tex/) {
+		  $doctex = 0;
+		}
+		$desc .= $docline;
+	      }
+	      $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g;
+	      print "$desc", "\n";
+	      $found = 1;
+	      last;
+	    }
+	  }
+	  close (DOC);
+	  if (! $found) {
+	    print "\@emph{Not implemented}\n";
+	  }
+        } else {
+	  print STDERR "Could not open file $docfile\n";
+	  exit 1;
+	}
+      }
+    } else {
+      if ($line =~ /\@tex/) {
+	$tex = 1;
+      }
+      if ($tex) {
+	$line =~ s/\\\\/\\/g;
+      }
+      print "$line";
+      if ($line =~ /\@end tex/) {
+	$tex = 0;
+      }
+    }
+    $line = <IN>;
+  }
+} else {
+    print STDERR "Could not open file $file\n";
+    exit 1;
+}
+
+sub func_summary { # {{{1
+  my ($func,		# in function name
+      $docfile		# in DOCSTRINGS
+      )       = @_;
+
+  my $desc = "";
+  my $found = 0;
+  if ( open(DOC,$docfile) ) {
+    while (<DOC>) {
+      next unless /\037/;
+      my $function = $_;
+      $function =~ s/\037//;
+      $function =~ s/[\n\r]+//;
+      if ($function =~ /^$func$/) {
+	my $docline;
+	my $doctex = 0;
+	while (($docline = <DOC>) && ($docline !~ /^\037/)) {
+	  if ($docline =~ /\@tex/) {
+	    $doctex = 1;
+	  }
+	  if ($doctex) {
+	    $docline =~ s/\\\\/\\/g;
+	  }
+	  if ($docline =~ /\@end tex/) {
+	    $doctex = 0;
+	  }
+	  $desc .= $docline;
+	}
+	$desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g;
+        $found = 1;
+        last;
+      }
+    }
+    close (DOC);
+    if (! $found) {
+      $desc = "\@emph{Not implemented}";
+    }
+  } else {
+    print STDERR "Could not open file $docfile\n";
+    exit 1;
+  }
+  return first_sentence($desc);
+}   # 1}}}
+
+
+sub first_sentence { # {{{1
+# grab the first real sentence from the function documentation
+    my ($desc) = @_;
+    my $retval = '';
+    my $line;
+    my $next;
+    my @lines;
+
+    my $trace = 0;
+    # $trace = 1 if $desc =~ /Levenberg/;
+    return "" unless defined $desc;
+    if ($desc =~ /^\s*-[*]- texinfo -[*]-/) {
+	# help text contains texinfo.  Strip the indicator and run it
+	# through makeinfo. (XXX FIXME XXX this needs to be a function)
+	$desc =~ s/^\s*-[*]- texinfo -[*]-\s*//;
+	my $cmd = "makeinfo --fill-column 1600 --no-warn --no-validate --no-headers --force --ifinfo";
+	open3(*Writer, *Reader, *Errer, $cmd) or die "Could not run info";
+	print Writer "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n";
+	print Writer "$desc"; close(Writer);
+	@lines = <Reader>; close(Reader);
+	my @err = <Errer>; close(Errer);
+	waitpid(-1,&WNOHANG);
+
+	# Display source and errors, if any
+	if (@err) {
+	    my $n = 1;
+	    foreach $line ( split(/\n/,$desc) ) {
+		printf "%2d: %s\n",$n++,$line;
+	    }
+	    print ">>> @err";
+	}
+
+	# Print trace showing formatted output
+#	print "<texinfo--------------------------------\n";
+#	print @lines;
+#	print "--------------------------------texinfo>\n";
+
+	# Skip prototype and blank lines
+	while (1) {
+	    return "" unless @lines;
+	    $line = shift @lines;
+	    next if $line =~ /^\s*-/;
+	    next if $line =~ /^\s*$/;
+	    last;
+	}
+
+    } else {
+
+#	print "<plain--------------------------------\n";
+#	print $desc;
+#	print "--------------------------------plain>\n";
+
+	# Skip prototype and blank lines
+	@lines = split(/\n/,$desc);
+	while (1) {
+	    return "" if ($#lines < 0);
+	    $line = shift @lines;
+	    next if $line =~ /^\s*[Uu][Ss][Aa][Gg][Ee]/; # skip " usage "
+
+	    $line =~ s/^\s*\w+\s*://;             # chop " blah : "
+	    print "strip blah: $line\n" if $trace;
+	    $line =~ s/^\s*[Ff]unction\s+//;      # chop " function "
+	    print "strip function $line\n" if $trace;
+	    $line =~ s/^\s*\[.*\]\s*=\s*//;       # chop " [a,b] = "
+	    print "strip []= $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s*=\s*//;          # chop " a = "
+	    print "strip a= $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s*\([^\)]*\)\s*//; # chop " f(x) "
+	    print "strip f(x) $line\n" if $trace;
+	    $line =~ s/^\s*[;:]\s*//;                # chop " ; "
+	    print "strip ; $line\n" if $trace;
+
+	    $line =~ s/^\s*[[:upper:]][[:upper:]0-9_]+//; # chop " BLAH"
+	    print "strip BLAH $line\n" if $trace;
+	    $line =~ s/^\s*\w*\s*[-]+\s+//;        # chop " blah --- "
+	    print "strip blah --- $line\n" if $trace;
+	    $line =~ s/^\s*\w+ *\t\s*//;          # chop " blah <TAB> "
+	    print "strip blah <TAB> $line\n" if $trace;
+	    $line =~ s/^\s*\w+\s\s+//;            # chop " blah  "
+	    print "strip blah <NL> $line\n" if $trace;
+
+#	    next if $line =~ /^\s*\[/;           # skip  [a,b] = f(x)
+#	    next if $line =~ /^\s*\w+\s*(=|\()/; # skip a = f(x) OR f(x)
+	    next if $line =~ /^\s*or\s*$/;      # skip blah \n or \n blah
+	    next if $line =~ /^\s*$/;            # skip blank line
+	    next if $line =~ /^\s?!\//;          # skip # !/usr/bin/octave
+	    # XXX FIXME XXX should be testing for unmatched () in proto
+	    # before going to the next line!
+	    last;
+	}
+    }
+
+    # Try to make a complete sentence, including the '.'
+    if ( "$line " !~ /[^.][.]\s/ && $#lines >= 0) {
+	my $next = $lines[0];
+	$line =~ s/\s*$//;  # trim trailing blanks on last
+	$next =~ s/^\s*//;    # trim leading blanks on next
+	$line .= " $next" if "$next " =~ /[^.][.]\s/; # ends the sentence
+    }
+
+    # Tidy up the sentence.
+    chomp $line;          # trim trailing newline, if there is one
+    $line =~ s/^\s*//;    # trim leading blanks on line
+    $line =~ s/([^.][.])\s.*$/$1/; # trim everything after the sentence
+    print "Skipping:\n$desc---\n" if $line eq "";
+
+    # And return it.
+    return $line;
+
+} # 1}}}
new file mode 100644
--- /dev/null
+++ b/src/admin/no_vr_val.pm
@@ -0,0 +1,45 @@
+#!/usr/bin/perl -w -n
+
+## Catches vr_val (x) transforms it into varargout(i++) = x;
+## 
+
+use OctRe;
+
+BEGIN {
+    $first = "vr_val_cnt = 1; ";
+
+}
+
+## Does necessary changes inplace on $_[0].
+sub change_line {
+    
+    if ($_[0] !~ /^\s*\#/) {	# Don't do obvious comment lines
+
+				# Change function declaration
+	if ($_[0] =~ /$defun_rx/) {
+	    $_[0] =~ s/\.\.\.(\s*\]\s*\=)/varargout$1/g;
+	}
+				# Change vr_val()
+
+				# BTW, if 1st vr_val() occurs in a loop,
+				# this will NOT WORK!
+
+	if ($_[0] =~ 
+	    s{vr_val\s*\(([^;]*)\)(\s*;)}
+	    {"$first" . "varargout\{vr_val_cnt++\} = $1$2"}eg) {
+
+	    $first = "";
+	}
+				# Did I miss anything?
+	if ($_[0] =~ /vr_val\s*\(/) {
+	    $_[0] .= "## TODO : Remove this vr_val\n";
+	}
+
+    }
+    $first = "vr_val_cnt = 1; " if $. == 1;
+}
+
+sub comment_line {
+    ""
+}
+1;
new file mode 100755
--- /dev/null
+++ b/src/admin/octlink.sh
@@ -0,0 +1,6 @@
+#! /bin/sh
+
+FN2=`echo $2 | sed -e's/.octlink//'`
+FN1=`echo $1 | sed -e's/.oct//'`
+if test -e $2 ; then /bin/rm $2; fi
+echo "autoload (\"$FN2\", which (\"$FN1\"));" > $2
new file mode 100755
--- /dev/null
+++ b/src/admin/run_forge
@@ -0,0 +1,58 @@
+#! /bin/sh
+
+# Walk the octave-forge tree (starting in the root) searching for 
+# all the directories that are supposed to be installed.
+# Add each directory and any data subdirectories to the LOADPATH for octave.
+# Add any bin directories to the EXEC_PATH.
+# Add any DLL directories to the system PATH.
+# Set LD_LIBRARY_PATH and DYLD_LIBRARY_PATH for any .so and .dylib files found.
+#
+# You must call this from the root of the octave-forge tree, using, e.g.,
+# 	admin/run_forge octave --norc -q
+#
+# Normally this is called for you, using the run target from make:
+#       make run
+
+ROOT=`pwd`
+BINPATH="$PATH"
+LDPATH="$LD_LIBRARY_PATH"
+DYLDPATH="$DYLD_LIBRARY_PATH"
+OCTPATH="$OCTAVE_PATH"
+# XXX FIXME XXX strictly speaking, the default octave bin directories
+# should be in the middle of EXECPATH and PATH, but it should be safe
+# to put them at the end since octave probably isn't overriding anything
+# on the system.  We may also want to pick up the OCTAVE_EXEC_PATH if
+# there is one.
+EXECPATH="$PATH:"
+for f in FIXES main/* extra/* nonfree/*; do
+    # exclude CVS directories, only include directories, skip NOINSTALL
+    case "$f" in
+      */CVS) ;;
+      *)
+    if test -d $f -a ! -f $f/NOINSTALL; then 
+	OCTPATH="$ROOT/$f:$OCTPATH"
+
+	# if there is install data, include in on the path
+	if test -d "$f/data"; then OCTPATH="$ROOT/$f/data:$OCTPATH"; fi
+
+	# make sure we can find supporting binaries
+	if test -d "$f/bin"; then EXECPATH="$ROOT/$f/bin:$EXECPATH"; fi
+	if test -d "$f/scripts"; then EXECPATH="$ROOT/$f/scripts:$EXECPATH"; fi
+
+	# supporting libraries need to be available as well
+	check=`echo $f/*.dll`
+	if test "$check" != "$f/*.dll"; then BINPATH="$ROOT/$f:$BINPATH"; fi
+	check=`echo $f/*.so`
+	if test "$check" != "$f/*.so"; then LDPATH="$ROOT/$f:$LDPATH"; fi
+	check=`echo $f/*.dylib`
+	if test "$check" != "$f/*.dylib"; then DYLDPATH="$ROOT/$f:$DYLDPATH"; fi
+    fi
+    esac
+done
+LD_LIBRARY_PATH="$LDPATH" 
+DYLD_LIBRARY_PATH="$DYLDPATH" 
+PATH="$BINPATH" 
+OCTAVE_PATH="$OCTPATH"
+OCTAVE_EXEC_PATH="$EXECPATH"
+export LD_LIBRARY_PATH DYLD_LIBRARY_PATH PATH OCTAVE_PATH OCTAVE_EXEC_PATH
+$*
new file mode 100644
--- /dev/null
+++ b/src/admin/template.ndev
@@ -0,0 +1,405 @@
+->  Note:  this file is a template used by the Perl script 'get_contents'.
+->         get_contents reads this file and the CONTENTS files in each 
+->         subdirectory then creates the new_developer.html file by
+->         populating the "Where does your code belong" section.
+->         Albert Danial Jan 2 2002
+
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!-- 
+      The file new_developer.html is generated dynamically by the Perl 
+      program 'get_contents'.  Edit admin/template.ndev to make permanent 
+      changes to new_developer.html.
+      Albert Danial Jan 2 2002
+  -->
+<html>
+<head>
+<title>Octave-Forge Developer's Notes</title>
+   <meta name="keywords" content="instruction,octave,developer,contribute">
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- top table {{{1 -->
+<table align="center" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="95%" BGCOLOR="#444444" >
+<tr>
+<td>
+<table BORDER=0 cellspacing=1 CELLPADDING=3 WIDTH="100%" >
+<tr>
+<td ALIGN=CENTER VALIGN=CENTER BGCOLOR="#FFFFFF">
+	<font face="Arial, Helvetica, Sans Serif" size=+2 color="#0000CC">
+		GNU Octave Repository	
+	</font>
+</td>
+</tr>
+</table>
+</td>
+</tr>
+</table>
+<p align="center">
+<font size="-1">
+<A href="http://octave.sourceforge.net">Home</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/projects/octave/">Summary</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/forum/?group_id=2888">Forums</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/bugs/?group_id=2888">Bugs</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/support/?group_id=2888">Support</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/patch/?group_id=2888">Patches</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/mail/?group_id=2888">Lists</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/pm/?group_id=2888">Tasks</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/docman/?group_id=2888">Docs</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/survey/?group_id=2888">Surveys</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/news/?group_id=2888">News</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/cvs/?group_id=2888">CVS</A>&nbsp;|&nbsp;
+<A href="http://sourceforge.net/project/showfiles.php?group_id=2888">Files</A>
+</font>
+</p>
+
+
+<!-- 1}}} end top table -->
+
+<p>
+<center>
+<h2>Contributing Code to the Gnu Octave Repository</h2>
+</center>
+
+
+<h3>Requirements</h3>
+To contribute your .m files, C++, C, or Fortran code to the GNU Octave
+Repository (octave-forge) you need to
+<ul>
+    <li> have an account on SourceForge,
+    <li> be registered as an octave-forge developer,
+    <li> have <a href="http://www.cvshome.org/">CVS</a>
+        installed on the computer from which you
+        will submit contributions, and
+    <li> have the secure shell,
+         <a href="http://www.openssh.com/"><tt>ssh</tt></a>, installed
+         on your computer.
+</ul>
+The first two requirements are easy but may take a few days.  
+If you don't already have one, request a SourceForge (SF) account
+<a href="http://sourceforge.net/account/register.php"> here</a>.
+To register as a developer send a request 
+to the octave-forge mailing list 
+<a href="mailto:octave-dev@lists.sf.net">octave-dev@lists.sf.net</a>.
+Include a bit of information about the code
+you plan to submit. 
+Finally, if your computer runs linux or
+FreeBSD, chances are good that both <tt>ssh</tt> and CVS are already 
+installed on your system. 
+If they aren't, 
+you will need to find prebuilt packages for them or download their
+source codes and build them.
+
+<h3>Create a SF home directory</h3>
+<p>
+If you've never submitted code to a SourceForge project before,
+create your home directory by
+logging onto the octave-forge account with <tt>ssh</tt>:
+<pre>
+   $ ssh -l <FONT COLOR="#800000"><i>sflogin</i></FONT>  octave.cvs.sourceforge.net
+   Password:  <FONT COLOR="#800000"><i>your SF password</i></FONT>
+</pre>
+Although SF will only show you a message-of-the-day screen then log
+you out, this process has the useful side effect of creating a home
+directory for you if one doesn't already exist.  Some CVS commands will fail
+if you do not have a home directory on SF.
+
+<h3>Download the latest octave-forge distribution</h3>
+CVS expects the 
+code you plan to submit to reside in a directory within the existing
+octave-forge directory structure.
+You will therefore need to download a copy of the latest octave-forge
+distribution to work in.  Change directories to a place you want
+to put the code, then issue the CVS <i>checkout</i>
+(abreviated as 'co') command:
+<pre>
+   $ cd <FONT COLOR="#800000"><i>working_directory</i></FONT>
+   $ export CVS_RSH=ssh
+   $ cvs -d:ext:<FONT COLOR="#800000"><i>sflogin</i></FONT>@octave.cvs.sourceforge.net:/cvsroot/octave co octave-forge
+</pre>
+
+<h3>Where does your code belong?</h3>
+
+Put your file(s) in a subdirectory under the <tt>octave-forge/</tt>
+directory.  Here are some guidelines to help you decide where your
+code belongs:
+<ul>
+>>>INSERT CONTENTS HERE<<<
+</ul>
+
+<h3>Add a copyright notice</h3>
+<p>
+Each file in octave-forge must contain a copyright notice.  
+If you wish to release your
+code under the 
+GNU <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>
+, insert the following text at the top of your file:
+<pre>
+## Copyright (C) <FONT COLOR="#800000"><i>year</i></FONT>   <FONT COLOR="#800000"><i>Your Name</i></FONT>   &lt;<FONT COLOR="#800000"><i>your@preferred.email</i></FONT>&gt;
+##
+## 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
+</pre>
+
+Here are other popular open source licenses:
+<ul>
+    <li> <a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser GPL</a>
+    <li> <a href="http://www.gnu.org/licenses/fdl.html">GNU Free Documentation License</a>
+    <li> <a href="http://www.opensource.org/licenses/artistic-license.html">Artistic License</a>
+    <li> <a href="http://www.opensource.org/licenses/bsd-license.html">BSD License</a>
+</ul>
+Consult 
+<a href="http://www.opensource.org/licenses/index.html">opensource.org</a>.
+for a comprehensive list of Open Source licenses.
+
+<h3>Package structure</h3>
+<dl>
+<dt>package/NOINSTALL
+<dd>	don't install this package; the user can rename or delete this
+	file if they want the package installed anyway.
+<dt>package/*.m 
+<dd>	m-files for the package; these will be installed in
+	site/mfiles/octave-forge/package
+<dt>package/data/*
+<dd>	datafiles to be installed with the mfiles.  You can accesses
+	them from your m-files with x = file_in_load_path("a").
+<dt>package/Makefile 
+<dd>	Makefile with a default target to build anything that needs
+	building, an optional "install" target in case you need to
+	install something other than m-files, oct-files, data files or
+	octave binaries, and a "clean" target to remove everything that
+	has been built.  See below for details.
+<dt>package/configure.add, package/Makeconf.add
+<dd>	Additional configuration-time commands to run in order to 
+	find all the components that your package requires.  You 
+	can look for anything you want in configure.add and note 
+	what you need in Makeconf.add.  The definitions in 
+	Makeconf.add will be available when you include ../../Makeconf 
+	in your Makefile.  See main/symbolic for an example.
+<dt>package/*.oct
+<dd>	oct-files built by Makefile. These will be installed all 
+	together in site-oct-files/octave-forge.  You may assume that
+	HAVE_OCTAVE_20 is defined for 2.0.x series mkoctfile, and
+	HAVE_OCTAVE_21 is defined for 2.1.x series mkoctfile.
+<dt>package/bin/*
+<dd>	executable files built by Makefile.  These will be 
+	installed in Octave's EXEC_PATH, so they will be available 
+	from Octave but not from the shell. You have two options
+	regarding this directory.  The better one would be to make
+	sure that the directory exists before you try building the
+	binary.  The other option is to have a hidden bin/.keepdir
+	so that CVS won't delete it for you automatically.
+</dl>
+
+<h3>Adding a Makefile</h3>
+
+If your package has something other than m-files you will need a 
+Makefile in your directory.  This could be as short as three lines:
+<pre>
+include ../../Makeconf
+all: f1.oct
+clean: ; -$(RM) *.o core octave-core *.oct *~
+</pre><p>
+
+If you define multiple DEFUN_DLD's in a file, you may need to
+use symbolic links in order for Octave to find them:
+<pre>
+include ../../Makeconf
+
+# extra functions defined in fn.oct
+fn_LINKS=fn2.oct fn3.oct
+
+# all compiled functions
+PROGS=fn.oct $(fn_LINKS) gn.oct
+
+all: $(PROGS)
+
+$(PROGS): Makefile
+
+$(fn_LINKS):
+	-$(RM) $@
+	$(LN_S) fn.oct $@
+
+clean: ; -$(RM) *.o core octave-core *.oct *~
+</pre><p>
+
+The "include ../../Makeconf" line above includes all of the definitions 
+that were created during configuration.  This includes things like MKOCTFILE,
+as well as implicit rules for compiling oct-files.  See Makeconf.base 
+for a list of predefined variables and rules.  Sometimes you will see
+"sinclude ../../Makeconf".  This is for packages which can be compiled
+independently of Octave-forge.  If Octave-forge is configured, then the
+variable OCTAVE_FORGE will be defined.<p>
+
+Even more complicated makefiles are sometimes necessary, particularly when
+the package depends on external libraries.  See main/symbolic/Makefile
+for an example.  The external libraries must be found during configure
+so main/symbolic/configure.add provides detection rules.  The results 
+are posted in main/symbolic/Makeconf.add, and will be available during make.<p>
+
+Please try to keep compatibility with older versions of Octave.  The main
+configure script tests for features that have changed since octave-2.1.36.
+The tests are done in such a way that conditions are only defined if you
+are using an older version of octave.  That way if the tests are not performed
+and the conditions are not defined, support defaults to the newer version
+of octave.  The following conditions are defined in configure.base:
+<dl>
+<dt>HAVE_SLLIST_H
+<dd>subsref changed from using SLList to using std::list.
+To support older versions of octave, use:<pre><code>
+#ifdef HAVE_SLLIST_H
+#define LIST SLList
+#define LISTSIZE length
+#define SUBSREF_STRREF
+#else
+#include &lt;list&gt;
+#define LIST std::list
+#define LISTSIZE size
+#define SUBSREF_STRREF &amp;
+#endif
+...
+  octave_value subsref (const std::string SUBSREF_STRREF type,
+                        const LIST&lt;octave_value_list&gt;&amp; idx) {
+	...
+  }
+  octave_value_list subsref (const std::string SUBSREF_STRREF type,
+                             const LIST&lt;octave_value_list&gt;&amp; idx,
+                             int nargout) {
+        ...
+
+     if (idx.LISTSIZE () > 1)
+        ...
+  }
+</code></pre>
+<dt>NEED_OCTAVE_QUIT
+<dd>signal handling changed from longjump to C++ exceptions. To support 
+older versions of octave, use:<pre><code>
+#ifdef NEED_OCTAVE_QUIT
+#define OCTAVE_QUIT do {} while (0)
+#define BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE
+#define END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE
+#define octave_throw_bad_alloc() \
+   do { jump_to_top_level(); panic_impossible(); } while (0)
+#else
+#include &lt;octave/quit.h&gt;
+#endif
+</code></pre>
+<dt>USE_OCTAVE_NAN
+<dd>octave_NaN and octave_Inf constants were converted to functions.  
+To support older versions of octave, use:<pre><code>
+#ifdef USE_OCTAVE_NAN
+#define lo_ieee_nan_value() octave_NaN
+#define lo_ieee_inf_value() octave_Inf
+#endif
+</code></pre>
+</dl>
+<p>m-file support across multiple versions
+is tricky.  Sometimes try/catch will help, but for syntax
+changes you will need some sort of preprocessor, such as
+awk or sed.
+</p>
+
+<h3>Submit your code!</h3>
+You are now ready to upload your code to the Gnu Octave Repository.
+Do this with two CVS commands--one to add a new
+entry for your file in the octave-forge catalog, and a second command
+to actually upload the file:
+<pre>
+   $ cvs add <FONT COLOR="#800000"><i>files</i></FONT>
+   $ cvs commit <FONT COLOR="#800000"><i>files</i></FONT>
+</pre>
+
+After hitting the carriage return at the end of the commit command,
+CVS will open your default editor so that you can enter comments about
+the commit. The first time you commit a file the comment might be
+something as simple as `Initial commit into CVS.' However, for all
+subsequent commits please add meaningful comments that explain why
+changes were made to the file since all comments will appear in the
+changelog.  Try to gather related changes into one commit command.
+<p>
+Aside:  the default editor can be defined like so:
+<pre>
+   $ export EDITOR=<FONT COLOR="#800000">vim</FONT>
+</pre>
+<p>
+
+If you are uploading an entire package, then put your directory into the
+octave-forge tree and do the following:
+<pre>
+   $ cd octave-forge/main
+   $ cvs add <FONT COLOR="#800000"><i>package</i></FONT>
+   $ cvs commit <FONT COLOR="#800000"><i>package</i></FONT>
+   $ cd <FONT COLOR="#800000"><i>package</i></FONT>
+   $ cvs add *
+   $ cvs commit *
+</pre>
+
+You may find it easier to use the import command, especially if your
+package contains subdirectories.  In this case, you should not put
+your directory into the octave-forge tree.  Instead, change to the
+root of your package tree and enter the following:
+<pre>
+   $ cd <FONT COLOR="#800000"><i>package</i></FONT>
+   $ cvs -d:ext:<FONT COLOR="#800000"><i>sflogin</i></FONT>@octave.cvs.sourceforge.net:/cvsroot/octave import -m "<FONT COLOR="#800000"><i>package name</i></FONT>" octave-forge/<FONT COLOR="#800000"><i>main/package</i></FONT> <FONT COLOR="#800000"><i>sflogin</i></FONT> start
+</pre>
+
+You can then fetch the new package from octave-forge as follows:
+<pre>
+   $ cd octave-forge
+   $ cvs -q update -d
+</pre>
+
+<p>
+From time to time, you will need to synchronize with CVS:
+<pre>
+   $ cd octave-forge
+   $ cvs -q update -d
+</pre>
+Each file will be listed with one of the following codes:
+<ul>
+<li> `?' for files you created didn't add and commit.
+<li> `M' for files you modified but didn't commit.
+<li> `C' for files which have unresolvable conflicts.  Look inside the file to
+see what it was that couldn't be resolved.  It will be clearly marked, or you
+can do a cvs diff on the file to highlight the conflict.
+<li> `U' for files you haven't touched but are modified on the server.
+<li> `P' for files you have modified in a way consistent with the modifications
+on the server (?), e.g., because you submitted a patch for someone else to apply.
+</ul>
+
+<h3>Learn more about CVS</h3>
+The few CVS commands shown here just scratch the surface of this
+powerful versioning package.  If you become an active contributor
+you will benefit from learning more CVS commands and understanding 
+how CVS works.
+The
+<a href="http://cvsbook.red-bean.com/cvsbook.html">
+CVS Book</a> is a great place to begin your exploration.
+
+<h3>Join the developers' mailing list</h3>
+Finally, consider joining the octave-forge developer's 
+<a href="http://lists.sourceforge.net/lists/listinfo/octave-dev">
+mailing list</a>.  It is very low traffic.  It is used to announce
+pending releases of octave-forge and discuss issues related to
+working with octave-forge.  Discussion of the functions in
+octave-forge mostly occurs on the primary octave mailing lists.
+
+<hr noshade size=1>
+
+<center>
+<p>
+<small>Hosted by</small>
+<br><a  href="http://sourceforge.net"><img  src="http://sourceforge.net/sflogo.php?group_id=2888&amp;type=4"  width="125" height="37" border="0" alt="SourceForge.net Logo"  /></a>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/src/admin/template.readme
@@ -0,0 +1,137 @@
+->  Note:  this is not the true README file.  Create the correct top-level
+->         README by running the Perl script 'get_contents'.  get_contents 
+->         reads this file and the CONTENTS files in each subdirectory then 
+->         creates the README by populating the "Project organization" 
+->         section below with the information found in the CONTENTS files.
+->         Albert Danial Jan 2 2002
+
+*** README is automatically generated from admin/template.readme ***
+
+The octave-forge project contains functions for Octave which are not in
+the main distribution.  While the main Octave distribution is
+conservative about accepting new functions and changes, octave-forge is
+very open.  As a result, be prepared for some lower quality code and
+more rapidly changing interfaces to the functions in octave-forge.
+
+The collection is in the public domain, but the individual functions
+vary.  See COPYING for details.  See INSTALL for installation
+instructions.
+
+Octave needs your support!  Please donate to the University of
+Wisconsin Foundation:
+
+    http://www.uwfoundation.wisc.edu/index.html
+
+designated as follows:
+
+   I/we wish to support ongoing development of the Octave modelling
+   language, under the supervision of Professor James B. Rawlings and
+   Dr. John W. Eaton of the Department of Chemical and Biological 
+   Engineering at the University of Wisconsin-Madison.
+
+Donations are tax deductible in the United States.  A donation of $10/user
+per year at current estimates of the user base would support two developers.
+Adjust as appropriate for the percentage of users that you think will donate.
+
+
+=====================================================================
+Project organization
+======================================================================
+Package organization
+
+package/NOINSTALL
+	don't install this package; rename or delete this
+	file if you want the package installed anyway.
+package/INDEX
+	a functions in the directory organized into categories.  See
+	octave-forge/INDEX for a description of the format.
+package/*.m 
+	m-files for the package.  These will be installed in
+	site/mfiles/octave-forge/package
+package/data/*
+	datafiles to be installed with the mfiles.  You can accesses
+	them from your m-files with x = file_in_load_path("a").
+package/Makefile 
+	Makefile with a default target to build anything that needs
+	building, an "install" target to install anything that needs
+	installing (other than oct-files and m-files---they are handled
+	automatically), and a "clean" target to delete everything that
+	was built.
+package/configure.add
+package/Makeconf.add
+	Additional configuration-time commands to run in order to 
+	find all the components that the package requires.
+package/*.oct
+	oct-files built by Makefile. These will be installed all 
+	together in site-oct-files/octave-forge.
+package/bin/*
+	executable files built by Makefile.  These will be 
+	installed in Octave's EXEC_PATH, so they will be available 
+	from Octave but not from the shell.  
+
+==========================================================================
+Administrative files
+
+autogen.sh
+	Generates ./configure and Makeconf.in
+
+configure.base
+Makeconf.base
+	Basic configuration checks, such as locating the install paths,
+	and the associated variables to be put into Makeconf.  Each 
+	package can append checks by including configure.add in the 
+	package directory.
+
+octinst.sh.in
+	Install program for packages, with pieces to be filed in by
+	./configure
+
+install-sh
+	intall program to use if /usr/bin/install does not work
+
+COPYING
+	License for the collection, plus an out-of-date list of functions 
+	in the collection and their licenses.
+
+COPYING.GPL
+	The text of the GPL license
+
+cvs-tree
+	Generate web listing of m-files in the tree
+
+README
+	This file
+
+TODO
+	Things that could/should be done
+
+INSTALL
+	Installation instructions
+
+Makefile
+	Top level makefile
+
+release.sh
+	Generates release tarball
+
+cvsdir.sh
+	Save/restore CVS adminstration files.  You need this to install
+	directly from the CVS tree rather than an exported tarball.  E.g.,
+	   $ cvsdir.sh save
+	   $ make install
+	   $ cvsdir.sh restore
+
+==========================================================================
+Compatibility Issues
+
+Issue the following command:
+	$ grep -d skip "XXX COMPATIBILITY XXX" */* */*/*
+for a list of compatibility issues in various functions.  As of this
+writing, mu2lin is a likely cause of problems when porting audio
+packages.
+
+
+==========================================================================
+Paul Kienzle
+pkienzle@users.sf.net
+March 17, 2002
new file mode 100755
--- /dev/null
+++ b/src/autogen.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+## Generate ./configure
+rm -f configure.in
+echo "dnl --- DO NOT EDIT --- Automatically generated by autogen.sh" > configure.in
+cat configure.base >> configure.in
+files=`find . -name configure.add -print`
+if test ! -z "$files" ; then
+  cat $files >> configure.in
+fi
+cat <<EOF >> configure.in
+  AC_OUTPUT(\$CONFIGURE_OUTPUTS)
+  dnl XXX FIXME XXX chmod is not in autoconf's list of portable functions
+  chmod 0771 octinst.sh
+  echo " "
+  echo "  \"\\\$prefix\" is \$prefix"
+  echo "  \"\\\$exec_prefix\" is \$exec_prefix"
+  AC_MSG_RESULT([\$STATUS_MSG
+
+find . -name NOINSTALL -print    # shows which toolboxes won't be installed
+])
+EOF
+
+autoconf && rm -f configure.in
+
+## Generate ./Makeconf.in
+rm -f Makeconf.in
+cp Makeconf.base Makeconf.in
+files=`find . -name Makeconf.add -print`
+if test ! -z "$files" ; then
+  cat $files >> Makeconf.in
+fi
+
new file mode 100644
--- /dev/null
+++ b/src/bwfill.cc
@@ -0,0 +1,241 @@
+/*
+ * BWFILL: fill a bw image starting at points
+ * imo= block(im, xregs, yregs);
+ *
+ * Copyright (C) 1999 Andy Adler
+ * This code has no warrany whatsoever.
+ * Do what you like with this code as long as you
+ *     leave this copyright in place.
+ *
+ * $Id$
+ */
+
+#include <octave/oct.h>
+
+#ifndef OCTAVE_LOCAL_BUFFER
+#include <vector>
+#define OCTAVE_LOCAL_BUFFER(T, buf, size) \
+  std::vector<T> buf ## _vector (size); \
+  T *buf = &(buf ## _vector[0])
+#endif
+
+#define   ptUP     (-1)
+#define   ptDN     (+1)
+#define   ptRT     (+ioM)
+#define   ptLF     (-ioM)
+
+/*
+ * check if the point needs to be filled, if so
+ * fill it and change the appropriate variables
+ */
+void checkpoint( int pt,
+      unsigned char* imo,
+               int * ptstack,
+               int * npoints ) {
+// printf("filling %d np=%d fill=%d\n",pt,*npoints, *(imo+pt)==0 );
+   if( *(imo+pt) != 0 ) return;
+
+   *(imo+pt) = 2;
+   *(ptstack + (*npoints))= pt;
+   (*npoints)++;
+}
+
+DEFUN_DLD (bwfill, args, ,
+  "[...] = bwfill (...)\n\
+   [BW2,IDX] = BWFILL(BW1,Y,X,N) performs a flood-fill on BW1\n\
+\n\
+       (X(k), Y(k)) are rows and columns of seed points\n\
+\n\
+   [BW2,IDX] = BWFILL(BW1,'holes',N) fills interior holes in BW1\n\
+\n\
+       N = 4 or 8(default) for neighborhood connectedness\n\
+\n\
+       IDX is the indices of the filled pixels")
+{
+   octave_value_list retval;
+   octave_value tmp;
+   ColumnVector xseed, yseed ;
+   int nargin = args.length ();
+
+   if (nargin < 2 ) {
+      print_usage ();
+      return retval;
+   }
+
+   Matrix       im=    args(0).matrix_value();
+   int          imM=   im.rows();
+   int          imN=   im.columns();
+
+   int          nb=    8;
+   int          npoints= 0;
+   bool         fillmode= false;
+   if (args(1).is_string() && args(1).string_value() == "holes" ) {
+      fillmode= true;
+
+      npoints= 2*( imM + imN - 4 ); // don't start fill from corners
+
+      xseed= ColumnVector( npoints );
+      yseed= ColumnVector( npoints );
+      int idx= 0;
+      for (int j=2; j<= imN-1; j++) {
+         xseed( idx )= j;   yseed( idx++)= 1;   
+         xseed( idx )= j;   yseed( idx++)= imM;   
+      }
+
+      for (int i=2; i<= imM-1; i++) {
+         yseed( idx )= i;   xseed( idx++)= 1;   
+         yseed( idx )= i;   xseed( idx++)= imN;   
+      }
+
+      if (nargin >= 4 ) 
+         nb= (int) args(2).double_value();
+   } // holes mode? 
+   else {
+      {
+         ColumnVector tmp( args(2).vector_value() );
+         xseed= tmp;
+      }
+      {
+         ColumnVector tmp( args(1).vector_value() );
+         yseed= tmp;
+      }
+      npoints= xseed.length();
+      if (nargin >= 4 ) 
+         nb= (int) args(3).double_value();
+   } // holes mode? 
+
+/*
+ * put a one pixel thick boundary around the image
+ *  so that we can be more efficient in the main loop
+ */
+   int           ioM=   imM+2;
+   OCTAVE_LOCAL_BUFFER(unsigned char, imo, (imM+2) * (imN+2));
+
+   for (int i=0; i<imM; i++) 
+      for (int j=0; j<imN; j++)
+         imo[(i+1) + ioM*(j+1)]= ( im(i,j) > 0 ) ;
+
+   for (int i=0; i<ioM; i++) 
+      imo[i]= imo[i + ioM*(imN+1)] = 3;
+
+   for (int j=1; j<imN+1; j++)
+      imo[ioM*j]= imo[imM+1 + ioM*j] = 3;
+
+// This is obviously big enough for the point stack, but I'm
+// sure it can be smaller. 
+   OCTAVE_LOCAL_BUFFER(int, ptstack, ioM*imN );
+
+   int seedidx= npoints; 
+   npoints= 0;
+   while ( (--seedidx) >= 0 ) {
+// no need to add 1 to convert indexing style because we're adding a boundary
+      int pt= (int) xseed( seedidx )*ioM + (int) yseed( seedidx ); 
+      checkpoint( pt , imo, ptstack, &npoints );
+   }
+
+   while ( npoints > 0 ) {
+      npoints--;
+      int pt= ptstack[ npoints ];
+      
+      checkpoint( pt + ptLF, imo, ptstack, &npoints );
+      checkpoint( pt + ptRT, imo, ptstack, &npoints );
+      checkpoint( pt + ptUP, imo, ptstack, &npoints );
+      checkpoint( pt + ptDN, imo, ptstack, &npoints );
+      
+      if (nb==8) {
+         checkpoint( pt + ptLF + ptUP, imo, ptstack, &npoints );
+         checkpoint( pt + ptRT + ptUP, imo, ptstack, &npoints );
+         checkpoint( pt + ptLF + ptDN, imo, ptstack, &npoints );
+         checkpoint( pt + ptRT + ptDN, imo, ptstack, &npoints );
+      }
+   } // while ( npoints
+
+   Matrix       imout( imM, imN );
+   ColumnVector idxout (imM*imN );
+   int idx=0;
+
+   int notvalidpt= 0;
+   int idxpoint=   2;
+   if ( fillmode ) {
+      notvalidpt= 2;
+      idxpoint=   0;
+   }
+
+   for (int i=0; i<imM; i++) 
+      for (int j=0; j<imN; j++) {
+         imout(i,j) =    (double) ( imo[(i+1) + ioM*(j+1)] != notvalidpt );
+         if ( imo[(i+1) + ioM*(j+1)] == idxpoint )
+            idxout(idx++) = (double) (i + j*imM + 1);
+      }
+
+   /*
+   Matrix imout( imM+2, imN+2 );
+   for (int i=0; i<imM+2; i++) 
+      for (int j=0; j<imN+2; j++)
+         imout(i,j) = (double) imo[i + ioM*j];
+    */
+
+   retval(0)= imout;
+// we need to do this to be able to return a proper empty vector
+   if (idx > 0) 
+      retval(1)= idxout.extract(0, idx-1);
+   else
+      retval(1)= ColumnVector ( 0 );
+   return retval;
+}
+
+
+/*
+ * $Log$
+ * Revision 1.1  2006/08/20 12:59:36  hauberg
+ * Changed the structure to match the package system
+ *
+ * Revision 1.7  2006/05/19 06:58:50  jwe
+ * *** empty log message ***
+ *
+ * Revision 1.5  2003/05/15 21:25:40  pkienzle
+ * OCTAVE_LOCAL_BUFFER now requires #include <memory>
+ *
+ * Revision 1.4  2003/03/05 15:31:52  pkienzle
+ * Backport to octave-2.1.36
+ *
+ * Revision 1.3  2003/02/20 23:03:57  pkienzle
+ * Use of "T x[n]" where n is not constant is a g++ extension so replace it with
+ * OCTAVE_LOCAL_BUFFER(T,x,n), and other things to keep the picky MipsPRO CC
+ * compiler happy.
+ *
+ * Revision 1.2  2002/11/02 10:39:36  pkienzle
+ * gcc 3.2 wants \n\ for multi-line strings.
+ *
+ * Revision 1.1  2002/03/17 02:38:51  aadler
+ * fill and edge detection operators
+ *
+ * Revision 1.9  2000/06/16 20:22:47  aadler
+ * mods for 2.1/2.0 compat
+ *
+ * Revision 1.8  2000/06/13 17:27:24  aadler
+ * mods for 2.1.30
+ *
+ * Revision 1.7  1999/06/10 19:42:12  aadler
+ * minor verbose fix
+ *
+ * Revision 1.6  1999/06/08 16:30:30  aadler
+ * bug fix. reversed r,c input arguments
+ *
+ * Revision 1.5  1999/06/08 15:41:02  aadler
+ * now fills in holes
+ *
+ * Revision 1.4  1999/06/08 15:21:02  aadler
+ * fixed bug that so specified points are only used if they can fill
+ *
+ * Revision 1.3  1999/06/08 15:05:08  aadler
+ * now returns 1 and gives index output
+ *
+ * Revision 1.2  1999/06/04 21:58:57  aadler
+ * fixed 8 vs 4 neighborhood
+ *
+ * Revision 1.1  1999/06/04 21:43:20  aadler
+ * Initial revision
+ *
+ *
+ */
new file mode 100644
--- /dev/null
+++ b/src/bwlabel.cc
@@ -0,0 +1,238 @@
+/* ---------------------------------------------------------------------
+
+    bwimage.cc - octave module to label componenets of a binary image
+
+    copyright 2002 Jeffrey E. Boyd
+
+    - uses 4, 6, or 8 connectedness
+    - See BKP Horn, Robot Vision, MIT Press, 1986, p 66 - 71 
+
+    labeling scheme
+
+        +-+-+-+
+        |D|C|E|
+        +-+-+-+
+        |B|A| |
+        +-+-+-+
+        | | | |
+        +-+-+-+
+                
+    A is the center pixel of a neighborhood.  In the 3 versions of
+    connectedness:
+    
+    4:  A connects to B and C
+    6:  A connects to B, C, and D
+    8:  A connects to B, C, D, and E
+    
+    
+--------------------------------------------------------------------- */
+
+
+
+#include <oct.h>
+#ifndef OCTAVE_LOCAL_BUFFER
+#include <vector>
+#define OCTAVE_LOCAL_BUFFER(T, buf, size) \
+  std::vector<T> buf ## _vector (size); \
+  T *buf = &(buf ## _vector[0])
+#endif
+
+
+
+#define     NO_OBJECT       0
+#define     MIN(x, y)       (((x) < (y)) ? (x) : (y))
+
+
+
+static int find( int *, int );
+
+static bool any_bad_argument( const octave_value_list& );
+
+
+/*
+%!assert(bwlabel([0 1 0; 0 0 0; 1 0 1]),[0 1 0; 0 0 0; 2 0 3]);
+*/
+DEFUN_DLD(bwlabel, args, ,
+"\n\
+[l,num] = bwlabel( bw, n ) - label foreground components of boolean image\n\
+\n\
+    bw  -   boolean image array\n\
+    n   -   neighborhood connectedness (4, 6,or 8)\n\
+\n\
+    l   -   label image array\n\
+    num -   number of components labeled\n\
+\n\
+    The algorithm is derived from  BKP Horn, Robot Vision, MIT Press,\n\
+    1986, p 65 - 89 \n" )
+{
+    if ( any_bad_argument(args) )
+        return octave_value_list();
+    
+    // input arguments
+    Matrix BW = args(0).matrix_value();     // the input binary image
+    int n;
+    if ( args.length() < 2 ) n = 6;         // n-hood connectivity
+    else n = args(1).int_value(); 
+    int nr = args(0).rows();
+    int nc = args(0).columns();
+    
+    // results
+    Matrix L( nr, nc );     // the label image
+    int nobj;                               // number of objects found in image
+    
+    // other variables
+    int ntable;                             // number of elements in the component table/tree
+    
+    OCTAVE_LOCAL_BUFFER(int, lset, nr * nc);   // label table/tree
+    ntable = 0;
+    lset[0] = 0;
+    
+    for( int r = 0; r < nr; r++ ) {
+        for( int c = 0; c < nc; c++ ) {            
+            if ( BW.elem(r,c) ) {               // if A is an object
+                // get the neighboring pixels B, C, D, and E
+                int B, C, D, E;
+                if ( c == 0 ) B = 0; else B = find( lset, (int)L.elem(r,c-1) );
+                if ( r == 0 ) C = 0; else C = find( lset, (int)L.elem(r-1,c) );
+                if ( r == 0 || c == 0 ) D = 0; else D = find( lset, (int)L.elem(r-1,c-1) );
+                if ( r == 0 || c == nc - 1 ) E = 0;
+                    else E = find( lset, (int)L.elem(r-1,c+1) );
+                    
+                if ( n == 4 ) {
+                    // apply 4 connectedness
+                    if ( B && C ) {        // B and C are labeled
+                        if ( B == C )
+                            L.elem(r,c) = B;
+                        else {
+                            lset[C] = B;
+                            L.elem(r,c) = B;
+                        }
+                    } else if ( B )             // B is object but C is not
+                        L.elem(r,c) = B;
+                    else if ( C )               // C is object but B is not
+                        L.elem(r,c) = C;
+                    else {                      // B, C, D not object - new object
+                        //   label and put into table
+                        ntable++;
+                        L.elem(r,c) = lset[ ntable ] = ntable;
+                    }
+                } else if ( n == 6 ) {
+                    // apply 6 connected ness
+                    if ( D )                    // D object, copy label and move on
+                        L.elem(r,c) = D;
+                    else if ( B && C ) {        // B and C are labeled
+                        if ( B == C )
+                            L.elem(r,c) = B;
+                        else {
+                            int tlabel = MIN(B,C);
+                            lset[B] = tlabel;
+                            lset[C] = tlabel;
+                            L.elem(r,c) = tlabel;
+                        }
+                    } else if ( B )             // B is object but C is not
+                        L.elem(r,c) = B;
+                    else if ( C )               // C is object but B is not
+                        L.elem(r,c) = C;
+                    else {                      // B, C, D not object - new object
+                        //   label and put into table
+                        ntable++;
+                        L.elem(r,c) = lset[ ntable ] = ntable;
+                    }
+                } else if ( n == 8 ) {
+                    // apply 8 connectedness
+                    if ( B || C || D || E ) {
+                        int tlabel = B;
+                        if ( B ) tlabel = B;
+                        else if ( C ) tlabel = C;
+                        else if ( D ) tlabel = D;
+                        else if ( E ) tlabel = E;
+                        L.elem(r,c) = tlabel;
+                        if ( B && B != tlabel ) lset[B] = tlabel;
+                        if ( C && C != tlabel ) lset[C] = tlabel;
+                        if ( D && D != tlabel ) lset[D] = tlabel;
+                        if ( E && E != tlabel ) lset[E] = tlabel;
+                    } else {
+                        //   label and put into table
+                        ntable++;
+                        L.elem(r,c) = lset[ ntable ] = ntable;
+                    }
+                }
+            } else {
+                L.elem(r,c) = NO_OBJECT;      // A is not an object so leave it
+            }
+        }
+    }
+    
+    // consolidate component table
+    for( int i = 0; i <= ntable; i++ )
+        lset[i] = find( lset, i );
+
+    // run image through the look-up table
+    for( int r = 0; r < nr; r++ )
+        for( int c = 0; c < nc; c++ )
+            L.elem(r,c) = lset[ (int)L.elem(r,c) ];
+    
+    // count up the objects in the image
+    for( int i = 0; i <= ntable; i++ )
+        lset[i] = 0;
+
+    for( int r = 0; r < nr; r++ )
+        for( int c = 0; c < nc; c++ )
+            lset[ (int)L.elem(r,c) ]++;
+
+    // number the objects from 1 through n objects
+    nobj = 0;
+    lset[0] = 0;
+    for( int i = 1; i <= ntable; i++ )
+        if ( lset[i] > 0 )
+            lset[i] = ++nobj;
+
+    // run through the look-up table again
+    for( int r = 0; r < nr; r++ )
+        for( int c = 0; c < nc; c++ )
+            L.elem(r,c) = lset[ (int)L.elem(r,c) ];
+
+    octave_value_list rval;
+    rval(0) = L;
+    rval(1) = (double)nobj;
+    return rval;
+}
+
+
+static bool any_bad_argument( const octave_value_list& args )
+{
+    if ( args.length() < 1 || args.length() > 2 ) {
+        error( "bwlabel: number of arguments - expecting bwlabel(bw) or bwlabel(bw,n)" );
+        return true;
+    }
+    
+    if ( !args(0).is_matrix_type() ) {
+        error( "bwlabel: matrix expected for first argument" );
+        return true;
+    }
+    
+    if ( args.length() == 2 ) {
+        if ( !args(1).is_real_scalar() ) {
+            error( "bwlabel: expecting real scalar for second argument" );
+            return true;
+        }
+        int n = args(1).int_value();
+        if ( n != 4 && n != 6 && n != 8 ) {
+            error( "bwlabel: in bwlabel(BW,n) n must be in {4,6,8}" );
+            return true;
+        }
+    }
+    
+    return false;
+    
+}
+
+
+static int find( int set[], int x )
+{
+    int r = x;
+    while ( set[r] != r )
+        r = set[r];
+    return r;
+}
+
new file mode 100644
--- /dev/null
+++ b/src/configure.add
@@ -0,0 +1,56 @@
+
+if test -e main/image/NOINSTALL ; then
+
+	dnl Not installing so don't test for libjpeg/libpng/libMagick++.
+	STATUS=none
+
+else
+
+	AC_DEFINE(have_jpeg)
+	AC_CHECK_HEADER(jpeglib.h, have_jpeg=yes, have_jpeg=no)
+	if test $have_jpeg = yes ; then
+	    OF_CHECK_LIB(jpeg, jpeg_std_error, have_jpeg=yes, have_jpeg=no)
+	    if test $have_jpeg = no ; then
+		STATUS="libjpeg not found"
+	    else
+		STATUS="jpeg"
+		AC_SUBST(DEFHAVE_JPEG)
+		DEFHAVE_JPEG="HAVE_JPEG=1"
+	    fi
+	else
+	    STATUS="jpeglib.h not found"
+	fi
+
+	AC_DEFINE(have_png)
+	AC_CHECK_HEADER(png.h, have_png=yes, have_png=no)
+	if test $have_png = yes ; then
+	    OF_CHECK_LIB(png, png_set_sig_bytes, have_png=yes, have_png=no)
+	    if test $have_png = no ; then
+		STATUS="$STATUS, libpng not found"
+	    else
+		STATUS="$STATUS, png"
+		AC_SUBST(DEFHAVE_PNG)
+		DEFHAVE_PNG="HAVE_PNG=1"
+	    fi
+	else
+	    STATUS="$STATUS, png.h not found"
+	fi
+
+	AC_CHECK_PROG(HAVE_MAGICKXX, Magick++-config, yes)
+	if test $HAVE_MAGICKXX ; then
+		STATUS="$STATUS, ImageMagick++"
+		AC_SUBST(DEFHAVE_MAGICKXX)		
+		DEFHAVE_MAGICKXX="HAVE_MAGICKXX=1"	
+	else
+	    STATUS="$STATUS, ImageMagick++ not found"
+	fi
+
+
+fi
+
+dnl Append the status message to the global status message.  This will
+dnl be displayed at the end of configuration so that the user doesn't
+dnl have to scan the list for critical details.
+
+STATUS_MSG="$STATUS_MSG
+   read/write image formats: $STATUS"
new file mode 100644
--- /dev/null
+++ b/src/configure.base
@@ -0,0 +1,520 @@
+dnl The configure script is generated by autogen.sh from configure.base 
+dnl and the various configure.add files in the source tree.  Edit 
+dnl configure.base and reprocess rather than modifying ./configure.
+
+dnl autoconf 2.13 certainly doesn't work! What is the minimum requirement?
+AC_PREREQ(2.2)
+
+AC_INIT(configure.base)
+
+PACKAGE=octave-forge
+MAJOR_VERSION=0
+MINOR_VERSION=1
+PATCH_LEVEL=0
+
+dnl Kill caching --- this ought to be the default
+define([AC_CACHE_LOAD], )dnl
+define([AC_CACHE_SAVE], )dnl
+
+dnl uncomment to put support files in another directory
+dnl AC_CONFIG_AUX_DIR(admin)
+
+VERSION=$MAJOR_VERSION.$MINOR_VERSION.$PATCH_LEVEL
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+
+dnl need to find admin files, so keep track of the top dir.
+TOPDIR=`pwd`
+AC_SUBST(TOPDIR)
+
+dnl if mkoctfile doesn't work, then we need the following:
+dnl AC_PROG_CXX
+dnl AC_PROG_F77
+
+dnl Need C compiler regardless so define it in a way that
+dnl makes autoconf happy and we can override whatever we
+dnl need with mkoctfile -p.
+dnl XXX FIXME XXX should use mkoctfile to get CC and CFLAGS
+AC_PROG_CC
+
+dnl XXX FIXME XXX need tests for -p -c -s in mkoctfile.
+
+dnl *******************************************************************
+dnl Sort out mkoctfile version number and install paths
+
+dnl XXX FIXME XXX latest octave has octave-config so we don't
+dnl need to discover things here.  Doesn't have --exe-site-dir
+dnl but defines --oct-site-dir and --m-site-dir
+
+dnl Check for mkoctfile
+AC_CHECK_PROG(MKOCTFILE,mkoctfile,mkoctfile)
+test -z "$MKOCTFILE" &&	AC_MSG_WARN([no mkoctfile found on path])
+
+AC_SUBST(ver)
+AC_SUBST(subver)
+AC_SUBST(mpath)
+AC_SUBST(opath)
+AC_SUBST(xpath)
+AC_SUBST(altpath)
+AC_SUBST(altmpath)
+AC_SUBST(altopath)
+
+AC_ARG_WITH(path, 
+	[  --with-path             install path prefix],
+	[ path=$withval ])
+AC_ARG_WITH(mpath,
+	[  --with-mpath            override path for m-files],
+	[mpath=$withval])
+AC_ARG_WITH(opath,
+	[  --with-opath            override path for oct-files],
+	[opath=$withval])
+AC_ARG_WITH(xpath,
+	[  --with-xpath            override path for executables],
+	[xpath=$withval])
+AC_ARG_WITH(altpath, 
+	[  --with-altpath          alternative functions install path prefix],
+	[ altpath=$withval ])
+AC_ARG_WITH(altmpath,
+	[  --with-altmpath         override path for alternative m-files],
+	[altmpath=$withval])
+AC_ARG_WITH(altopath,
+	[  --with-altopath         override path for alternative oct-files],
+	[altopath=$withval])	
+
+if test -n "$path" ; then
+   test -z "$mpath" && mpath=$path 
+   test -z "$opath" && opath=$path/oct 
+   test -z "$xpath" && xpath=$path/bin
+   test -z "$altpath" && altpath=$path-alternatives
+fi
+
+if test -n "$altpath" ; then
+   test -z "$altmpath" && altmpath=$altpath 
+   test -z "$altopath" && altopath=$altpath/oct 
+fi
+
+dnl Don't query if path/ver are given in the configure environment
+#if test -z "$mpath" || test -z "$opath" || test -z "$xpath" || test -z "$altmpath" || test -z "$altopath" || test -z "$ver" ; then
+if test -z "$mpath" || test -z "$opath" || test -z "$xpath" || test -z "$ver" ; then
+   dnl Construct program to get mkoctfile version and local install paths
+   cat > conftest.cc <<EOF
+#include <octave/config.h>
+#include <octave/version.h>
+#include <octave/defaults.h>
+
+#define INFOV "\nINFOV=" OCTAVE_VERSION "\n"
+
+#define INFOH "\nINFOH=" OCTAVE_CANONICAL_HOST_TYPE "\n"
+
+#ifdef OCTAVE_LOCALVERFCNFILEDIR
+# define INFOM "\nINFOM=" OCTAVE_LOCALVERFCNFILEDIR "\n"
+#else
+# define INFOM "\nINFOM=" OCTAVE_LOCALFCNFILEPATH "\n"
+#endif
+
+#ifdef OCTAVE_LOCALVEROCTFILEDIR
+# define INFOO "\nINFOO=" OCTAVE_LOCALVEROCTFILEDIR "\n"
+#else
+# define INFOO "\nINFOO=" OCTAVE_LOCALOCTFILEPATH  "\n"
+#endif
+
+#ifdef OCTAVE_LOCALVERARCHLIBDIR
+# define INFOX "\nINFOX=" OCTAVE_LOCALVERARCHLIBDIR  "\n"
+#else
+# define INFOX "\nINFOX=" OCTAVE_LOCALARCHLIBDIR  "\n"
+#endif
+
+const char *infom = INFOM;
+const char *infoo = INFOO;
+const char *infox = INFOX;
+const char *infoh = INFOH;
+const char *infov = INFOV;
+EOF
+
+   dnl Compile program perhaps with a special version of mkoctfile
+   $MKOCTFILE conftest.cc || AC_MSG_ERROR(Could not run $MKOCTFILE)
+
+   dnl Strip the config info from the compiled file
+   eval `strings conftest.o | grep "^INFO.=" | sed -e "s,//.*$,,"`
+   rm -rf conftest*
+
+   dnl set the appropriate variables if they are not already set
+   ver=`echo $INFOV | sed -e "s/\.//" -e "s/\..*$//"`
+   subver=`echo $INFOV | sed -e "[s/^[^.]*[.][^.]*[.]//]"`
+   alt_mbase=`echo $INFOM | sed -e "[s,\/[^\/]*$,,]"`
+   alt_obase=`echo $INFOO | sed -e "[s,/site.*$,/site,]"`
+   test -z "$mpath" && mpath=$INFOM/octave-forge
+   test -z "$opath" && opath=$INFOO/octave-forge
+   test -z "$xpath" && xpath=$INFOX
+   test -z "$altmpath" && altmpath=$alt_mbase/octave-forge-alternatives/m
+   test -z "$altopath" && altopath=$alt_obase/octave-forge-alternatives/oct/$INFOH
+fi
+
+dnl *******************************************************************
+
+dnl XXX FIXME XXX Should we allow the user to override these?
+dnl Do we even need them?  The individual makefiles can call mkoctfile -p
+dnl themselves, so the only reason to keep them is for configure, and
+dnl for those things which are not built using mkoctfile (e.g., aurecord)
+dnl but it is not clear we should be using octave compile flags for those.
+
+dnl C compiler and flags
+AC_MSG_RESULT([retrieving compile and link flags from $MKOCTFILE])
+CC=`$MKOCTFILE -p CC`
+CFLAGS=`$MKOCTFILE -p CFLAGS`
+CPPFLAGS=`$MKOCTFILE -p CPPFLAGS`
+CPICFLAG=`$MKOCTFILE -p CPICFLAG`
+LDFLAGS=`$MKOCTFILE -p LDFLAGS`
+LIBS=`$MKOCTFILE -p LIBS`
+AC_SUBST(CC)
+AC_SUBST(CFLAGS)
+AC_SUBST(CPPFLAGS)
+AC_SUBST(CPICFLAG)
+
+dnl Fortran compiler and flags
+F77=`$MKOCTFILE -p F77`
+FFLAGS=`$MKOCTFILE -p FFLAGS`
+FPICFLAG=`$MKOCTFILE -p FPICFLAG`
+AC_SUBST(F77)
+AC_SUBST(FFLAGS)
+AC_SUBST(FPICFLAG)
+
+dnl C++ compiler and flags
+CXX=`$MKOCTFILE -p CXX`
+CXXFLAGS=`$MKOCTFILE -p CXXFLAGS`
+CXXPICFLAG=`$MKOCTFILE -p CXXPICFLAG`
+AC_SUBST(CXX)
+AC_SUBST(CXXFLAGS)
+AC_SUBST(CXXPICFLAG)
+
+dnl *******************************************************************
+
+dnl Check for features of your version of mkoctfile.
+dnl All checks should be designed so that the default
+dnl action if the tests are not performed is to do whatever
+dnl is appropriate for the most recent version of Octave.
+
+dnl Define the following macro:
+dnl    OF_CHECK_LIB(lib,fn,true,false,helpers)
+dnl This is just like AC_CHECK_LIB, but it doesn't update LIBS
+AC_DEFUN(OF_CHECK_LIB,
+[save_LIBS="$LIBS"
+AC_CHECK_LIB($1,$2,$3,$4,$5)
+LIBS="$save_LIBS"
+])
+
+dnl Define the following macro:
+dnl    TRY_MKOCTFILE(msg,program,action_if_true,action_if_false)
+dnl
+AC_DEFUN(TRY_MKOCTFILE,
+[AC_MSG_CHECKING($1)
+cat > conftest.cc << EOF
+#include <octave/config.h>
+$2
+EOF
+ac_try="$MKOCTFILE -c conftest.cc"
+if AC_TRY_EVAL(ac_try) ; then
+   AC_MSG_RESULT(yes)
+   $3
+else
+   AC_MSG_RESULT(no)
+   $4
+fi
+])
+
+dnl
+dnl Check if F77_FUNC works with MKOCTFILE
+dnl
+TRY_MKOCTFILE([for F77_FUNC],
+[int F77_FUNC (hello, HELLO) (const int &n);],,
+[MKOCTFILE="$MKOCTFILE -DF77_FUNC=F77_FCN"])
+
+dnl
+dnl Check if octave still uses SLList.h
+dnl
+TRY_MKOCTFILE([for SLList.h],[#include <octave/SLList.h>],
+[MKOCTFILE="$MKOCTFILE -DHAVE_SLLIST_H"],)
+
+dnl
+dnl Check if octave has lo_ieee_nan_value
+dnl
+TRY_MKOCTFILE([for lo_ieee_nan_value],
+[ #include <octave/lo-ieee.h>
+int test(void) { lo_ieee_nan_value(); }],,
+[MKOCTFILE="$MKOCTFILE -DUSE_OCTAVE_NAN"])
+
+dnl
+dnl Check if octave is needs octave_idx_type
+dnl
+TRY_MKOCTFILE([for octave_idx_type],
+[#include <octave/oct-types.h>
+octave_idx_type test(void) { octave_idx_type idx = 1; return idx; }],,
+[MKOCTFILE="$MKOCTFILE -Doctave_idx_type=int"])
+
+dnl
+dnl Check if octave uses quit.h
+dnl
+TRY_MKOCTFILE([for quit.h],[#include <octave/quit.h>],,
+[MKOCTFILE="$MKOCTFILE -DNEED_OCTAVE_QUIT"])
+
+dnl **********************************************************
+
+dnl Evaluate an expression in octave
+dnl
+dnl OCTAVE_EVAL(expr,var) -> var=expr
+dnl
+AC_DEFUN(OCTAVE_EVAL,
+[AC_MSG_CHECKING([for $1 in Octave])
+$2=`echo "disp($1)" | $OCTAVE -qf`
+AC_MSG_RESULT($$2)
+AC_SUBST($2)
+])
+
+dnl Check status of an octave variable
+dnl
+dnl OCTAVE_CHECK_EXIST(variable,action_if_true,action_if_false)
+dnl
+AC_DEFUN(OCTAVE_CHECK_EXIST,
+[AC_MSG_CHECKING([for $1 in Octave])
+if test `echo 'disp(exist("$1"))' | $OCTAVE -qf`X != 0X ; then
+   AC_MSG_RESULT(yes)
+   $2
+else
+   AC_MSG_RESULT(no)
+   $3
+fi
+])
+
+dnl should check that $(OCTAVE) --version matches $(MKOCTFILE) --version
+AC_CHECK_PROG(OCTAVE,octave,octave)
+OCTAVE_EVAL(OCTAVE_VERSION,OCTAVE_VERSION)
+
+dnl grab canonical host type so we can write system specific install stuff
+OCTAVE_EVAL(octave_config_info('canonical_host_type'),canonical_host_type)
+
+dnl grab SHLEXT from octave config
+OCTAVE_EVAL(octave_config_info('SHLEXT'),SHLEXT)
+
+AC_PROG_LN_S
+AC_PROG_INSTALL
+AC_PROG_RANLIB
+
+dnl Use $(COPY_FLAGS) to set options for cp when installing .oct files.
+COPY_FLAGS="-Rfp"
+case "$canonical_host_type" in
+    *-*-linux*)
+        COPY_FLAGS="-fdp"
+    ;;
+esac
+AC_SUBST(COPY_FLAGS)
+
+dnl Use $(STRIP) in the makefile to strip executables.  If not found, 
+dnl STRIP expands to ':', which in the makefile does nothing.
+dnl Don't need this for .oct files since mkoctfile handles them directly
+STRIP=${STRIP-strip}
+AC_CHECK_PROG(STRIP,$STRIP,$STRIP,:)
+
+dnl Strip on windows, don't strip on Mac OS/X or IRIX
+dnl For the rest, you can force strip using MKOCTFILE="mkoctfile -s"
+dnl or avoid strip using STRIP=: before ./configure
+case "$canonical_host_type" in
+    powerpc-apple-darwin*|*-sgi-*)
+	STRIP=:
+    ;;
+    *-cygwin-*|*-mingw-*) 
+	MKOCTFILE="$MKOCTFILE -s" 
+    ;;
+esac
+
+dnl Things needed to link to X11 programs
+dnl defines X_CFLAGS, X_LIBS
+AC_SUBST(DEFHAVE_X)
+AC_SUBST(X_LIBS)
+AC_SUBST(X_CFLAGS)
+AC_PATH_XTRA
+if test "$no_x" = yes ; then
+	DEFHAVE_X=
+	XSTATUS="no (plot/g{input,text,zoom,rab} will not work)"
+else
+	DEFHAVE_X="HAVE_X=1"
+	X_LIBS="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+	XSTATUS="yes"
+fi
+
+OCTAVE_CHECK_EXIST(autoload,[
+	HAVE_AUTOLOAD="yes"
+	OCTLINK=.octlink
+	MKOCTLINK=$TOPDIR/admin/octlink.sh
+],[
+	HAVE_AUTOLOAD="no"
+	OCTLINK=.oct
+	MKOCTLINK=$LN_S
+])
+AC_SUBST(HAVE_AUTOLOAD)
+AC_SUBST(OCTLINK)
+AC_SUBST(MKOCTLINK)
+
+OCTAVE_CHECK_EXIST(do_fortran_indexing,
+	[HAVE_DO_FORTRAN_INDEXING="-DHAVE_DO_FORTRAN_INDEXING"],)
+AC_SUBST(HAVE_DO_FORTRAN_INDEXING)
+
+OCTAVE_CHECK_EXIST(propagate_empty_matrices,
+	[PROPAGATE_EMPTY_MATRICES="-DHAVE_PROPAGATE_EMPTY_MATRICES"],)
+AC_SUBST(HAVE_PROPAGATE_EMPTY_MATRICES)
+
+OCTAVE_CHECK_EXIST(ok_to_lose_imaginary_part,
+  [HAVE_OK_TO_LOSE_IMAGINARY_PART="-DHAVE_OK_TO_LOSE_IMAGINARY_PART"],)
+AC_SUBST(HAVE_OK_TO_LOSE_IMAGINARY_PART)
+
+dnl Test for N-dimensional Arrays
+TRY_MKOCTFILE([for N-dim arrays],
+[#include <octave/dim-vector.h>],
+[HAVE_ND_ARRAYS="-DHAVE_ND_ARRAYS"],)
+AC_SUBST(HAVE_ND_ARRAYS)
+
+OCTAVE_CHECK_EXIST(class,[TYPEID_HAS_CLASS="-DTYPEID_HAS_CLASS"],)
+AC_SUBST(TYPEID_HAS_CLASS)
+
+dnl Test for load/save functions in class
+TRY_MKOCTFILE([for load/save functions in class],
+[#include <octave/ov-scalar.h>
+int main (void) { octave_scalar a; a.load_ascii(std::cin); }],
+[CLASS_HAS_LOAD_SAVE="-DCLASS_HAS_LOAD_SAVE"],)
+AC_SUBST(CLASS_HAS_LOAD_SAVE)
+
+TRY_MKOCTFILE([for Octave_map indexing],
+[#include <octave/oct-map.h>
+int main(void) { Octave_map a; a[["key"]]; }],
+[HAVE_OCTAVE_MAP_INDEX="-DHAVE_OCTAVE_MAP_INDEX"],)
+AC_SUBST(HAVE_OCTAVE_MAP_INDEX)
+
+TRY_MKOCTFILE([for old Octave concatenation],
+[#include <octave/dNDArray.h>
+int main(void) { NDArray a(dim_vector(1,1)); Array<int> idx(2,0); a=concat(a,a,idx); }],
+[HAVE_OCTAVE_CONCAT="-DHAVE_OLD_OCTAVE_CONCAT"],)
+
+TRY_MKOCTFILE([for Octave concatenation],
+[#include <octave/dNDArray.h>
+int main(void) { NDArray a(dim_vector(1,1)); Array<int> idx(2,0); a=a.concat(a,idx); }],
+[HAVE_OCTAVE_CONCAT="-DHAVE_OCTAVE_CONCAT"],)
+AC_SUBST(HAVE_OCTAVE_CONCAT)
+
+TRY_MKOCTFILE([for swap_8_bytes],
+[#include <sys/types.h>
+#include <octave/config.h>
+#include <octave/byte-swap.h>
+int main(void) {long long a = 1; swap_8_bytes (&a,1);}],,
+[HAVE_SWAP_BYTES="-DHAVE_SWAP_BYTES"])
+AC_SUBST(HAVE_SWAP_BYTES)
+
+TRY_MKOCTFILE([for op_uplus],
+[#include <octave/config.h>
+#include <octave/ov.h>
+int main(void) {int i = octave_value::op_uplus;}],
+[HAVE_OCTAVE_UPLUS="-DHAVE_OCTAVE_UPLUS"],)
+AC_SUBST(HAVE_OCTAVE_UPLUS)
+
+dnl Test for the makeinfo program
+AC_CHECK_PROG(MAKEINFO,makeinfo,makeinfo)
+if [ test -n "$MAKEINFO" ]; then
+	dnl Check whether the makeinfo command accepts the 
+	dnl "--no-split" option
+	touch conftest.texi
+	AC_MSG_CHECKING([for makeinfo --no-split])
+	ac_try="$MAKEINFO --no-split conftest.texi"
+	if AC_TRY_EVAL(ac_try) ; then
+		MAKEINFO="$MAKEINFO --no-split"
+		AC_MSG_RESULT(yes)
+	else
+		AC_MSG_RESULT(no)
+	fi
+	rm -f conftest.*
+fi
+
+dnl Test for the texi2dvi program
+AC_CHECK_PROG(TEXI2DVI,texi2dvi,texi2dvi)
+if [ test -n "$TEXI2DVI" ]; then
+	dnl Check whether the texi2dvi command accepts the 
+	dnl "--clean" option
+	cat > conftest.texi <<EOF
+\input texinfo
+@bye
+EOF
+	AC_MSG_CHECKING([that texi2dvi runs])
+	ac_try="$TEXI2DVI conftest.texi > /dev/null"
+	if AC_TRY_EVAL(ac_try) ; then
+	    AC_MSG_RESULT(yes)
+	    AC_MSG_CHECKING([for texi2dvi --clean])
+	    ac_try="$TEXI2DVI --clean conftest.texi > /dev/null"
+	    if AC_TRY_EVAL(ac_try) ; then
+		TEXI2DVI="$TEXI2DVI --clean"
+		AC_MSG_RESULT(yes)
+	    else
+		AC_MSG_RESULT(no)
+	    fi
+	else
+	    TEXI2DVI=""
+	    AC_MSG_RESULT(no)
+	fi
+	rm -f conftest.*
+fi
+
+dnl Test for the texi2html program
+AC_CHECK_PROG(TEXI2HTML,texi2html,texi2html)
+if [ test -n "$TEXI2HTML" ]; then
+	STATUS="yes"
+	dnl Check whether the texi2html command accepts the 
+	dnl "-split_chapter -number" option
+	touch conftest.texi
+	AC_MSG_CHECKING([for texi2html --clean])
+	ac_try="$TEXI2HTML -split_chapter -number conftest.texi"
+	if AC_TRY_EVAL(ac_try) ; then
+		TEXI2HTML="$TEXI2HTML -split_chapter -number"
+		AC_MSG_RESULT(yes)
+	else
+		AC_MSG_RESULT(no)
+	fi
+	rm -f conftest.*
+        dnl TeTex 3.0 on Suse is leaving a conftest directory
+	rm -rf conftest
+fi
+
+dnl Test for the dvipdf program
+AC_CHECK_PROG(DVIPDF,dvipdf,dvipdf)
+
+dnl Test for the dvips program
+AC_CHECK_PROG(DVIPS,dvips,dvips)
+
+MKDOC=$TOPDIR/admin/mkdoc
+AC_SUBST(MKDOC)
+
+MKTEXI=$TOPDIR/admin/mktexi
+AC_SUBST(MKTEXI)
+
+CONFIGURE_OUTPUTS="Makeconf octinst.sh"
+STATUS_MSG="
+octave commands will install into the following directories:
+   m-files:   $mpath
+   oct-files: $opath
+   binaries:  $xpath
+alternatives:
+   m-files:   $altmpath
+   oct-files: $altopath
+
+shell commands will install into the following directories:
+   binaries:  $bindir
+   man pages: $mandir
+   libraries: $libdir
+   headers:   $includedir
+
+octave-forge is configured with
+   octave:      $OCTAVE (version $OCTAVE_VERSION)
+   mkoctfile:	$MKOCTFILE for Octave $subver
+   X11 support:	$XSTATUS
+   makeinfo:    $MAKEINFO
+   texi2dvi:    $TEXI2DVI
+   texi2html:   $TEXI2HTML
+   mkdoc:       $MKDOC
+   mktexi:      $MKTEXI
+   dvips:       $DVIPS
+   dvipdf:      $DVIPDF"
new file mode 100644
--- /dev/null
+++ b/src/cordflt2.cc
@@ -0,0 +1,214 @@
+// 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.
+
+#include <octave/oct.h>
+
+#ifdef HAVE_OCTAVE_20
+typedef Matrix boolMatrix;
+#define bool_matrix_value matrix_value
+#endif
+
+#define SWAP(a, b) { SWAP_temp = (a); (a)=(b); (b) = SWAP_temp; }
+
+// Template function for comparison
+// ET is the type of the matrix element
+template <class ET>
+inline bool compare(const ET a, const ET b)
+{
+    if(a > b)
+      return 1;
+    else
+      return 0;
+}
+
+// Explicit template function for complex compare
+template <> inline bool compare<Complex>(const Complex a, const Complex b)
+{
+    double anorm2 = a.real() * a.real() + a.imag() * a.imag();
+    double bnorm2 = b.real() * b.real() + b.imag() * b.imag();
+        
+    if( anorm2 > bnorm2 ) {
+      return 1;
+    } else {
+      return 0;
+    }
+}
+
+// select nth largest member from the array values
+// Partitioning algorithm, see Numerical recipes chap. 8.5
+template <class ET>
+ET selnth(ET *vals, int len, int nth)
+{
+    ET SWAP_temp;
+    ET hinge;
+    int l, r, mid, i, j;
+
+    l = 0;
+    r = len - 1;
+    for(;;) {
+	// if partition size is 1 or two, then sort and return
+	if(r <= l+1) {
+	    if(r == l+1 && compare<ET>(vals[l], vals[r])) {
+		SWAP(vals[l], vals[r]);
+	    }
+	    return vals[nth];
+	} else {
+	    mid = (l+r) >> 1;
+	    SWAP(vals[mid], vals[l+1]);
+	    // choose median of l, mid, r to be the hinge element
+	    // and set up sentinels in the borders (order l, l+1 and r)
+	    if(compare<ET>(vals[l], vals[r])) {
+		SWAP(vals[l], vals[r]);
+	    }
+	    if(compare<ET>(vals[l+1], vals[r])) {
+		SWAP(vals[l+1], vals[r]);
+	    }
+	    if(compare<ET>(vals[l], vals[l+1])) {
+		SWAP(vals[l], vals[l+1]);
+	    }
+	    i = l+1;
+	    j = r;
+	    hinge = vals[l+1];
+	    for(;;) {
+		do i++; while(compare<ET>(hinge, vals[i]));
+		do j--; while(compare<ET>(vals[j], hinge));
+		if(i > j) 
+		    break;
+		SWAP(vals[i], vals[j]);
+	    }
+	    vals[l+1] = vals[j];
+	    vals[j] = hinge;
+	    if(j >= nth)
+		r = j - 1;
+	    if(j <= nth)
+		l = i;
+	}
+    }
+}
+
+// Template function for doing the actual filtering
+// MT is the type of the matrix to be filtered (Matrix or ComplexMatrix)
+// ET is the type of the element of the matrix (double or Complex)
+template <class MT, class ET> 
+octave_value_list do_filtering(MT A, int nth, boolMatrix dom, MT S)
+{
+    int i, j, c, d;
+    
+    int len = 0;
+    for(j = 0; j < dom.columns(); j++) {
+	for(i = 0; i < dom.rows(); i++) {
+	    if(dom.elem(i,j)) 
+	      len++;
+	}
+    }
+    if(nth > len - 1) {
+	warning("nth should be less than number of non-zero values in domain");
+	warning("setting nth to largest possible value\n");
+	nth = len - 1;
+    }
+    if(nth < 0) {
+	warning("nth should be non-negative, setting to 1\n");
+	nth = 0; // nth is a c-index
+    }
+                
+    int rowoffset = (dom.columns() + 1)/2 - 1;
+    int coloffset = (dom.rows() + 1)/2 - 1;
+
+    //outputs
+    octave_value_list out;
+    const int origx = A.columns() - dom.columns()+1;
+    const int origy = A.rows() - dom.rows()+1;
+    MT retval = MT(origy, origx);
+
+    int *offsets = new int[len];
+    ET *values = new ET[len];
+    ET *adds = new ET[len];
+    
+    c = 0;
+    d = A.rows();
+    for(j = 0; j < dom.columns(); j++) {
+	for(i = 0; i < dom.rows(); i++) {
+	    if(dom.elem(i,j)) {
+		offsets[c] = (i - coloffset) + (j - rowoffset)*d;
+		adds[c] = S.elem(i,j);
+		c++;
+	    }
+	}
+    }
+    
+    ET *data = A.fortran_vec();
+    int base = coloffset + A.rows()*rowoffset;
+    for(j = 0; j < retval.columns(); j++) {
+	for(i = 0; i < retval.rows(); i++) {
+	    for(c = 0; c < len; c++) {
+		values[c] = data[base + offsets[c]] + adds[c];
+	    }
+	    base++;
+	    retval(i, j) = selnth(values, len, nth);
+	}
+	base += dom.rows() - 1;
+    }
+
+    out(0) = octave_value(retval);
+    
+    return out;
+}
+
+// instantiate template functions
+template bool compare<double>(const double, const double);
+template double selnth(double *, int, int);
+template Complex selnth(Complex *, int, int);
+template octave_value_list do_filtering<Matrix, double>(Matrix, int, boolMatrix, Matrix);
+// g++ is broken, explicit instantiation of specialized template function
+// confuses the compiler.
+//template int compare<Complex>(const Complex, const Complex);
+template octave_value_list do_filtering<ComplexMatrix, Complex>(ComplexMatrix, int, boolMatrix, ComplexMatrix);
+
+DEFUN_DLD(cordflt2, args, ,
+"function retval = cordflt2(A, nth, domain, S)\n\
+\n\
+ Implementation of two-dimensional ordered filtering. User interface\n\
+ in ordfilt2.m")
+{
+    if(args.length() != 4) {
+	print_usage ();
+	return octave_value_list();
+    }
+    
+    // nth is an index to an array, thus - 1
+    int nth = (int) (args(1).vector_value())(0) - 1;
+    boolMatrix dom = args(2).bool_matrix_value();
+
+    octave_value_list retval;
+    
+    if(args(0).is_real_matrix()) {
+	Matrix A = args(0).matrix_value();
+	Matrix S = args(3).matrix_value();
+	retval = do_filtering<Matrix, double>(A, nth, dom, S);
+    } 
+    else if(args(0).is_complex_matrix()) {
+	ComplexMatrix A = args(0).complex_matrix_value();
+	ComplexMatrix S = args(3).complex_matrix_value();
+	retval = do_filtering<ComplexMatrix, Complex>(A, nth, dom, S);
+    } 
+    else {
+	error("A should be real or complex matrix\n");
+	return octave_value_list();
+    }
+    
+    return retval;
+     
+}
new file mode 100644
--- /dev/null
+++ b/src/graycomatrix.cc
@@ -0,0 +1,148 @@
+/* Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#include <octave/oct.h>
+
+DEFUN_DLD(graycomatrix, args, , "\
+\
+usage: P = graycomatrix(I, levels, distances, angles)\n\
+\n\
+  Calculate the gray-level co-occurrence matrix P = f(i,j,d,theta)\n\
+  of a gray-level image.\n\
+\n\
+  P is a 4-dimensional matrix (histogram). The value P(i,j,d,theta)\n\
+  is the number of times that gray-level j occurs at a distance 'd' and\n\
+  at an angle 'theta' from gray-level j.\n\
+\n\
+  'I' is the input image which should contain integers in [0, levels-1],\n\
+  where 'levels' indicate the number of gray-levels counted (typically\n\
+  256 for an 8-bit image).  'distances' and 'angles' are vectors of\n\
+  the different distances and angles to use.\n" ) {
+
+    // 4-dimensional histogram
+    // P = f(i, j, d, theta) where i and j are gray levels
+    // See Pattern Recognition Engineering (Morton Nadler & Eric P. Smith)
+
+    octave_value_list retval;
+
+    if (args.length() != 4) {
+	print_usage ();
+	// 'I' must be integer values [0, nr_of_levels-1]
+
+	return retval;
+    }
+
+    // Input arguments
+    Matrix I = args(0).matrix_value();
+    int L = args(1).int_value();
+    ColumnVector d = ColumnVector(args(2).vector_value());
+    ColumnVector th = ColumnVector(args(3).vector_value());
+
+    if (error_state) {
+	print_usage ();
+	return retval;
+    }
+
+    // Create output NDArray, P
+    dim_vector dim = dim_vector();
+    dim.resize(4);
+    dim(0) = L; dim(1) = L; dim(2) = d.length(); dim(3) = th.length();
+    NDArray P = NDArray(dim, 0);
+
+    // Run through image
+    int d_max = (int)ceil(d.max());
+    int cnt = 0;
+
+    for (int r = 0; r < I.rows(); r++) {
+	for (int c = 0; c < I.columns(); c++) {
+	    int i = (int)I(r,c);
+
+	    for (int d_idx = 0; d_idx < d.length(); d_idx++) {
+		int d_val = (int)d(d_idx);
+		for (int th_idx = 0; th_idx < th.length(); th_idx++) {
+		    
+		    double angle = th(th_idx);
+		    
+		    int row = r + (int)floor(cos(angle) * d_val + 0.5);
+		    int col = c - (int)floor(sin(angle) * d_val + 0.5);
+
+		    if ( ( row >= 0 ) && ( row < I.rows() ) &&
+			 ( col >= 0 ) && ( col < I.cols() ) ) {
+
+			int j = (int)I(row, col);
+
+			if (i >= 0 && i < L && j >= 0 && j < L) {
+			    Array<int> coord = Array<int> (4);
+			    coord(0) = i;
+			    coord(1) = j;
+			    coord(2) = d_idx;
+			    coord(3) = th_idx;
+			    
+			    P(coord)++;			    
+			} else {
+			    warning("Image contains invalid gray-level! (%d, %d)", i, j);
+			} 
+		    }
+
+		}
+	    }
+
+	}
+    }
+
+    return octave_value(P);
+    
+}
+
+/*
+
+%!shared a
+%!test
+%!  a = [0 0 0 1 2;
+%!       1 1 0 1 1;
+%!       2 2 1 0 0;
+%!       1 1 0 2 0;
+%!       0 0 1 0 1];
+%!  squeeze(graycomatrix(a, 3, 1, -pi/4)) == [4 2 0;
+%!                                     2 3 2;
+%!                                     1 2 0];
+%!
+%!assert(size(graycomatrix(a, 3, 1:5, [0:3]*-pi/4)), [3, 3, 5, 4])
+
+%!demo
+%!
+%!  # Pattern Recognition Engineering (Nadler & Smith)
+%!  # Digital Image Processing (Gonzales & Woods), p. 668
+%!
+%!  a = [0 0 0 1 2;
+%!       1 1 0 1 1;
+%!       2 2 1 0 0;
+%!       1 1 0 2 0;
+%!       0 0 1 0 1];
+%!
+%!  graycomatrix(a, 3, 1, [0 1]*-pi/4)
+%!
+
+
+*/
new file mode 100644
--- /dev/null
+++ b/src/houghtf.cc
@@ -0,0 +1,129 @@
+/* Copyright (C) 2004 Stefan van der Walt <stefan@sun.ac.za>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions are
+   met:
+
+   1. Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+
+#include <octave/oct.h>
+
+DEFUN_DLD(houghtf, args, , "\
+\
+usage: [H, R]  = houghtf(I[, angles])\n\
+\n\
+  Calculate the straight line Hough transform of an image.\n\
+\n\
+  The image, I, should be a binary image in [0,1].  The angles are given\n\
+  in degrees and defaults to -90..90.\n\
+\n\
+  H is the resulting transform, R the radial distances.\n\
+\n\
+  See also: Digital Image Processing by Gonzales & Woods (2nd ed., p. 587)\n") {
+
+    octave_value_list retval;
+    bool DEF_THETA = false;
+
+    if (args.length() == 1) {
+	DEF_THETA = true;
+    } else if (args.length() != 2) {
+	print_usage ();
+	return retval;
+    } 
+
+    Matrix I = args(0).matrix_value();
+
+    ColumnVector thetas = ColumnVector();
+    if (!DEF_THETA) {
+    	thetas = ColumnVector(args(1).vector_value());
+    } else {
+        thetas = ColumnVector(Range(-90,90).matrix_value());
+    }
+
+    if (error_state) {
+	print_usage ();
+	return retval;
+    }
+
+    thetas = thetas / 180 * M_PI;
+
+    int r = I.rows();
+    int c = I.columns();
+
+    Matrix xMesh = Matrix(r, c);
+    Matrix yMesh = Matrix(r, c);
+    for (int m = 0; m < r; m++) {
+	for (int n = 0; n < c; n++) {
+	    xMesh(m, n) = n+1;
+	    yMesh(m, n) = m+1;
+	}
+    }
+
+    Matrix size = Matrix(1, 2);
+    size(0) = r; size(1) = c;
+    double diag_length = sqrt( size.sumsq()(0) );
+    int nr_bins = 2 * (int)ceil(diag_length) - 1;
+    RowVector bins = RowVector( Range(1, nr_bins).matrix_value() ) - ceil(nr_bins/2.);
+
+    Matrix J = Matrix(bins.length(), 0);
+
+    for (int i = 0; i < thetas.length(); i++) {
+	double theta = thetas(i);
+	ColumnVector rho_count = ColumnVector(bins.length(), 0);
+
+	double cT = cos(theta); double sT = sin(theta);
+	for (int x = 0; x < r; x++) {
+	    for (int y = 0; y < c; y++) {
+		if ( I(x, y) == 1 ) {
+		    int rho = (int)floor( cT*x + sT*y + 0.5 );
+		    int bin = (int)(rho - bins(0));
+		    if ( (bin > 0) && (bin < bins.length()) ) {
+			rho_count( bin )++;
+		    }
+		}
+	    }
+	}
+
+	J = J.append( rho_count );
+    }
+
+    retval.append(J);
+    retval.append(bins);
+    return retval;
+
+}
+
+/*
+%!test
+%! I = zeros(100, 100);
+%! I(1,1) = 1; I(100,100) = 1; I(1,100) = 1; I(100, 1) = 1; I(50,50) = 1;
+%! [J, R] = houghtf(I); J = J / max(J(:));
+%! assert(size(J) == [length(R) 181]);
+%!
+
+%!demo
+%! I = zeros(100, 150);
+%! I(30,:) = 1; I(:, 65) = 1; I(35:45, 35:50) = 1;
+%! for i = 1:90, I(i,i) = 1;endfor
+%! I = imnoise(I, 'salt & pepper');
+%! imshow(I);
+%! J = houghtf(I); J = J / max(J(:));
+%! imshow(J, bone(128), 'truesize');
+
+*/
new file mode 100755
--- /dev/null
+++ b/src/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission.  M.I.T. makes no representations about the
+# suitability of this software for any purpose.  It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.  It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+	-c) instcmd="$cpprog"
+	    shift
+	    continue;;
+
+	-d) dir_arg=true
+	    shift
+	    continue;;
+
+	-m) chmodcmd="$chmodprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-o) chowncmd="$chownprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-g) chgrpcmd="$chgrpprog $2"
+	    shift
+	    shift
+	    continue;;
+
+	-s) stripcmd="$stripprog"
+	    shift
+	    continue;;
+
+	-t=*) transformarg=`echo $1 | sed 's/-t=//'`
+	    shift
+	    continue;;
+
+	-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+	    shift
+	    continue;;
+
+	*)  if [ x"$src" = x ]
+	    then
+		src=$1
+	    else
+		# this colon is to work around a 386BSD /bin/sh bug
+		:
+		dst=$1
+	    fi
+	    shift
+	    continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+	echo "install:	no input file specified"
+	exit 1
+else
+	true
+fi
+
+if [ x"$dir_arg" != x ]; then
+	dst=$src
+	src=""
+	
+	if [ -d $dst ]; then
+		instcmd=:
+		chmodcmd=""
+	else
+		instcmd=mkdir
+	fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad 
+# if $src (and thus $dsttmp) contains '*'.
+
+	if [ -f $src -o -d $src ]
+	then
+		true
+	else
+		echo "install:  $src does not exist"
+		exit 1
+	fi
+	
+	if [ x"$dst" = x ]
+	then
+		echo "install:	no destination specified"
+		exit 1
+	else
+		true
+	fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+	if [ -d $dst ]
+	then
+		dst="$dst"/`basename $src`
+	else
+		true
+	fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='	
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+	pathcomp="${pathcomp}${1}"
+	shift
+
+	if [ ! -d "${pathcomp}" ] ;
+        then
+		$mkdirprog "${pathcomp}"
+	else
+		true
+	fi
+
+	pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+	$doit $instcmd $dst &&
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+	if [ x"$transformarg" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		dstfile=`basename $dst $transformbasename | 
+			sed $transformarg`$transformbasename
+	fi
+
+# don't allow the sed command to completely eliminate the filename
+
+	if [ x"$dstfile" = x ] 
+	then
+		dstfile=`basename $dst`
+	else
+		true
+	fi
+
+# Make a temp file name in the proper directory.
+
+	dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+	$doit $instcmd $src $dsttmp &&
+
+	trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing.  If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+	if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+	if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+	if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+	if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+	$doit $rmcmd -f $dstdir/$dstfile &&
+	$doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
new file mode 100644
--- /dev/null
+++ b/src/jpgread.cc
@@ -0,0 +1,181 @@
+ //
+ // This is a hack into octave 
+ //   based on jpgread.c by jpgread by Drea Thomas, The Mathworks and the
+ //        examples in the IJG distribution. 
+ //
+ // (C) 1998 Andy Adler. This code is in the public domain
+ // USE THIS CODE AT YOUR OWN RISK 
+ //
+ // $Id$                                     
+ //
+
+/* Modified: Stefan van der Walt <stefan@sun.ac.za>
+ * Date: 27 January 2004
+ * - Manual error handler to prevent segfaults in Octave.
+ * - Use uint8NDArray for output.
+ */
+
+/*
+ * Compilation:
+ * First, try
+ *   mkoctfile jpgread.cc -ljpeg
+ *
+ * If this doesn't work, install the jpeg library which is part of
+ * "The Independent JPEG Group's JPEG software" collection.
+ *
+ * The jpeg library came from
+ *
+ * ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6.tar.gz
+ *
+ * Extract and build the library:
+ * tar xvfz jpegsrc.v6.tar.gz
+ * cd jpeg-6b
+ * ./configure
+ * make
+ * make test
+ *
+ * Compile this file using:
+ * mkoctfile jpgread.cc -I<jpeg-6b include dir> -L<jpeg-6b lib dir> -ljpeg
+ */
+
+#include <octave/oct.h>
+#include <iostream>
+#include <csetjmp>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "jpeglib.h"
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+struct oct_error_mgr {
+    struct jpeg_error_mgr pub;    /* "public" fields */
+    jmp_buf setjmp_buffer;        /* for return to caller */
+};
+
+typedef struct oct_error_mgr * oct_error_ptr;
+
+METHODDEF(void)
+oct_error_exit (j_common_ptr cinfo)
+{
+    /* cinfo->err really points to an oct_error_mgr struct, so coerce pointer */
+    oct_error_ptr octerr = (oct_error_ptr) cinfo->err;
+    
+    /* Format error message and send to interpreter */
+    char errmsg[JMSG_LENGTH_MAX];
+    (octerr->pub.format_message)(cinfo, errmsg);
+    error("jpgread: %s", errmsg);
+    
+    /* Return control to the setjmp point */
+    longjmp(octerr->setjmp_buffer, 1);
+}
+
+DEFUN_DLD (jpgread, args, nargout ,
+"usage: I = jpgread('filename')\n\
+\n\
+  Read a JPEG file from disk.\n\
+\n\
+  For a grey-level image, the output is an MxN matrix. For a\n\
+  colour image, three such matrices are returned (MxNx3),\n\
+  representing the red, green and blue components. The output\n\
+  is of class 'uint8'.\n\
+\n\
+  See also: imread, im2double, im2gray, im2rgb.")
+{ 
+    octave_value_list retval;
+    int nargin  = args.length();
+    
+    FILE * infile;
+    
+    JSAMPARRAY buffer;
+    long row_stride;
+    struct jpeg_decompress_struct cinfo;
+    struct oct_error_mgr jerr;
+
+    //
+    // We bail out if the input parameters are bad
+    //
+    if ((nargin != 1) || !args(0).is_string() || (nargout != 1)) {
+	print_usage ();
+	return retval;
+    }    
+    
+    //
+    // Open jpg file
+    //
+    std::string filename = args(0).string_value();
+    if ((infile = fopen(filename.c_str(), "rb")) == NULL) {
+	error("jpgread: couldn't open file %s", filename.c_str());
+	return retval;
+    }
+    
+    //
+    // Initialize the jpeg library
+    //
+    cinfo.err = jpeg_std_error(&jerr.pub);
+    jerr.pub.error_exit = oct_error_exit;
+    if (setjmp(jerr.setjmp_buffer)) {
+	/* If we get here, the JPEG code has signaled an error.
+	 * We need to clean up the JPEG object, close the input file, and return.
+	 */
+	jpeg_destroy_decompress(&cinfo);
+	fclose(infile);
+	return retval;
+    }
+    
+    jpeg_create_decompress(&cinfo);
+    
+    //
+    // Read the jpg header to get info about size and color depth
+    //
+    jpeg_stdio_src(&cinfo, infile);
+    jpeg_read_header(&cinfo, TRUE);
+    jpeg_start_decompress(&cinfo);
+    
+    //
+    // Allocate buffer for one scan line
+    //
+    row_stride = cinfo.output_width * cinfo.output_components;
+    buffer = (*cinfo.mem->alloc_sarray)
+	((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+    
+    //
+    // Create an NDArray for the output.  Loop through each of the
+    // scanlines and copy the image data from the buffer.
+    //
+    
+    dim_vector dim = dim_vector();
+    dim.resize(3);
+    dim(0) = cinfo.output_height;
+    dim(1) = cinfo.output_width;
+    dim(2) = cinfo.output_components;
+    uint8NDArray out = uint8NDArray(dim, 0);
+    
+    Array<int> coord = Array<int> (3);
+    for (unsigned long j=0; cinfo.output_scanline < cinfo.output_height; j++) {
+	jpeg_read_scanlines(&cinfo, buffer, 1);
+	
+	coord(0) = j;
+	for (unsigned long i=0; i<cinfo.output_width; i++) {
+	    coord(1) = i;
+	    for (unsigned int c = 0; c < cinfo.output_components; c++) {
+		coord(2) = c;
+		out(coord) = buffer[0][i*cinfo.output_components+c];
+	    }
+	}
+    }
+    retval.append(out.squeeze());
+    
+    //
+    // Clean up
+    //
+    jpeg_finish_decompress(&cinfo);
+    jpeg_destroy_decompress(&cinfo);
+    fclose(infile);
+    
+    return retval;
+}
new file mode 100644
--- /dev/null
+++ b/src/jpgwrite.cc
@@ -0,0 +1,221 @@
+ // This is a hack into octave
+ //   based on jpgwrite.c by jpgread by Drea Thomas, The Mathworks, and the
+ //        examples in the IJG distribution.
+ //
+ // (C) 1998 Andy Adler. This code is in the public domain
+ //  USE THIS CODE AT YOUR OWN RISK 
+ //
+ // $Id$                                     
+ //                                                       
+
+#include <octave/oct.h>
+#include <iostream>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "jpeglib.h"
+
+#ifdef __cplusplus
+} //extern "C"
+#endif
+
+#define GRAYIMAGES
+
+/*
+ * Simple jpeg writing MEX-file. 
+ *
+ * Synopsis:
+ *   jpgwrite(filename,r,g,b,quality)
+ *
+ * Compilation:
+ * First, try
+ *   mkoctfile jpgwrite.cc -ljpeg
+ *
+ * If this doesn't work, then do
+ *
+ * Calls the jpeg library which is part of 
+ * "The Independent JPEG Group's JPEG software" collection.
+ *
+ * The jpeg library came from,
+ *
+ * ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6.tar.gz
+ */
+
+DEFUN_DLD (jpgwrite, args, ,
+"JPGWRITE Write a JPEG file to disk.\n\
+   jpgwrite('filename',R,G,B,quality) writes the specified file\n\
+   using the Red, Green, and Blue intensity matrices, at the given quality.\n\
+   \n\
+   jpgwrite('filename',M,quality) writes a grey-scale image.\n\
+   \n\
+   Data must be [0 255] or the high bytes will be lost\n\
+   \n\
+   If specified, quality should be in the range 1-100 and will default to \n\
+   75 if not specified.  100 is best quality, 1 is best compression.\n\
+   \n\
+   See also JPGREAD")
+{
+   octave_value_list retval;
+   int nargin  = args.length();
+
+   FILE * outfile;
+
+   JSAMPARRAY buffer;
+   struct jpeg_compress_struct cinfo;
+   struct jpeg_error_mgr jerr;
+   int quality=75; //default value
+
+//
+// We bail out if the input parameters are bad
+//
+   if (nargin < 2 || !args(0).is_string() ) {
+      print_usage ();
+      return retval;
+   }
+
+
+//
+// Open jpg file
+//
+   std::string filename = args(0).string_value();
+   if ((outfile = fopen(filename.c_str(), "wb")) == NULL) {
+      error("Couldn't open file");
+      return retval;
+   }
+
+//
+// Set Jpeg parameters
+//
+   if (nargin == 3) {
+      quality= (int) args(2).double_value();
+   } else if (nargin == 5) {
+      quality= (int) args(4).double_value();
+   }
+  
+//
+// Initialize the jpeg library
+// Read the jpg header to get info about size and color depth 
+//
+   cinfo.err = jpeg_std_error(&jerr);
+   jpeg_create_compress(&cinfo);
+   jpeg_stdio_dest(&cinfo, outfile);
+
+
+//
+// set parameters for compression
+//
+      
+   if ( nargin <= 3 ) {
+//
+// we're here because only one matrix of grey scale values was provided
+//
+      Matrix avg= args(1).matrix_value();
+      long image_width  = args(1).columns();
+      long image_height = args(1).rows();
+
+
+      cinfo.image_width = image_width; 	/* image width and height, in pixels */
+      cinfo.image_height = image_height;
+#ifdef GRAYIMAGES
+      cinfo.input_components = 1;
+      cinfo.input_components = JCS_GRAYSCALE;
+#else
+      cinfo.input_components = 3;
+      cinfo.in_color_space = JCS_RGB;
+#endif
+      jpeg_set_defaults(&cinfo);
+      jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */);
+//
+//  start compressor
+//
+      jpeg_start_compress(&cinfo, TRUE);
+
+//
+// Allocate buffer for one scan line
+//
+      long row_stride = image_width * cinfo.input_components ;
+      buffer = (*cinfo.mem->alloc_sarray)
+      		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+//
+// Now, loop thru each of the scanlines. For each, copy the image
+// data from the buffer, data must be [0 255]
+//
+      for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
+         for(unsigned long i=0; i<cinfo.image_width; i++) {
+#ifdef GRAYIMAGES
+            buffer[0][i] = (unsigned char) avg(j,i);
+#else
+            buffer[0][i*3+0] = (unsigned char) avg(j,i);
+            buffer[0][i*3+1] = (unsigned char) avg(j,i);
+            buffer[0][i*3+2] = (unsigned char) avg(j,i);
+#endif
+         }
+         jpeg_write_scanlines(&cinfo, buffer,1);
+      }
+
+   } // if nargin <= 3
+   else {
+//
+// we're here because red green and blue matrices were provided
+//  we assume that they're the same size
+//
+      Matrix red  = args(1).matrix_value();
+      Matrix green= args(2).matrix_value();
+      Matrix blue = args(3).matrix_value();
+      long image_width  = args(1).columns();
+      long image_height = args(1).rows();
+
+      if ( args(2).columns() != image_width  ||
+           args(3).columns() != image_width  ||
+           args(2).rows()    != image_height ||
+           args(3).rows()    != image_height ) {
+         error("R,G,B matrix sizes aren't the same");
+         return retval;
+      }
+
+      cinfo.image_width = image_width; 	/* image width and height, in pixels */
+      cinfo.image_height = image_height;
+      cinfo.input_components = 3;		/* # of color components per pixel */
+      cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */
+      jpeg_set_defaults(&cinfo);
+      jpeg_set_quality(&cinfo, quality, TRUE );
+//
+//  start compressor
+//
+      jpeg_start_compress(&cinfo, TRUE);
+
+//
+// Allocate buffer for one scan line
+//
+      long row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */
+      buffer = (*cinfo.mem->alloc_sarray)
+      		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
+//
+// Now, loop thru each of the scanlines. For each, copy the image
+// data from the buffer, data must be [0 255]
+//
+      for( long j=0; cinfo.next_scanline < cinfo.image_height; j++) {
+         for(unsigned long i=0; i<cinfo.image_width; i++) {
+            buffer[0][i*3+0] = (unsigned char) red(j,i);
+            buffer[0][i*3+1] = (unsigned char) green(j,i);
+            buffer[0][i*3+2] = (unsigned char) blue(j,i);
+         }
+         jpeg_write_scanlines(&cinfo, buffer,1);
+      }
+
+   } // else nargin > 3
+
+//
+// Clean up
+//
+
+   jpeg_finish_compress(&cinfo);
+   fclose(outfile);
+   jpeg_destroy_compress(&cinfo);
+
+
+   return retval;
+
+}
new file mode 100755
--- /dev/null
+++ b/src/octinst.sh.in
@@ -0,0 +1,93 @@
+#! /bin/sh
+
+# octinst.sh source mpath opath xpath [altmpath altopath]
+
+# Copies all m-files and oct-files from the source directory to the
+# mpath and opath respectively.  Preserves links.  Files in
+# source/data are copied to mpath.  Files in the source/bin are copied
+# to xpath. m-files and oct-files in source/alternatives are copied to 
+# altmpath and altopath respectively
+
+if test $# -lt 4 ; then
+    echo 'Not enough arguments'
+    exit 1
+fi
+
+# interpret input parameters
+source=$1; shift
+mpath=$1; shift
+opath=$1; shift
+xpath=$1; shift
+if test $# -ge 1; then altmpath=$1; shift; fi
+if test $# -ge 1; then altopath=$1; shift; fi
+INSTALL="@INSTALL@"
+INSTALL_DATA="@INSTALL_DATA@"
+INSTALL_PROGRAM="@INSTALL_PROGRAM@"
+INSTALL_SCRIPT="@INSTALL_SCRIPT@"
+MKPKGADD="@TOPDIR@/admin/mkpkgadd"
+COPY_FLAGS="@COPY_FLAGS@"
+
+# grab the m-files
+files=`echo $source/*.m`
+if test "$files" != "$source/*.m" ; then
+    $INSTALL -d $mpath
+    $INSTALL_DATA $files $mpath
+fi
+
+# grab the oct-files
+files=`echo $source/*.oct`
+if test "$files" != "$source/*.oct" ; then
+    $INSTALL -d $opath
+## Grrr... install doesn't preserve links.  Hope this works.
+    cp $COPY_FLAGS $files $opath
+fi
+
+# install alternatives
+if test -d "$source/alternatives" ; then
+    # m-files
+    files=`echo $source/alternatives/*.m`
+    if test "$files" != "$source/alternatives/*.m" ; then
+        $INSTALL -d $altmpath
+	$INSTALL_DATA $files $altmpath
+    fi
+    # oct-files
+    files=`echo $source/alternatives/*.oct`
+    if test "$files" != "$source/alternatives/*.oct" ; then
+        $INSTALL -d $altopath
+	$INSTALL_DATA $files $altopath
+    fi
+fi
+
+# Create PKG_ADD, and destroy it immediately if it is empty
+# XXX FIXME XXX no PKG_ADD created if only oct-files and no m-files.
+if test -d "$mpath" ; then
+    $MKPKGADD $source > $mpath/PKG_ADD
+    if test -z "`cat $mpath/PKG_ADD`" ; then rm -f $mpath/PKG_ADD;  fi
+fi
+# PKG_ADD for alternatives
+if test -d "$source/alternatives" -a -d "$altmpath" ; then
+    $MKPKGADD $source/alternatives > $altmpath/PKG_ADD
+    if test -z "`cat $altmpath/PKG_ADD`" ; then rm $altmpath/PKG_ADD; fi
+fi
+
+# grab the data files, skipping the CVS directory
+files=`echo $source/data/* | sed -e "s/[^ ]*CVS//"`
+if test -n "$files" -a "$files" != "$source/data/*" ; then
+    $INSTALL -d $mpath
+    $INSTALL_DATA $files $mpath
+fi
+
+# grab the executable files, skipping the CVS directory
+files=`echo $source/bin/* | sed -e "s/[^ ]*CVS//"`
+if test -n "$files" -a "$files" != "$source/bin/*" ; then
+    $INSTALL -d $xpath
+    $INSTALL_PROGRAM $files $xpath
+fi
+
+# grab the script files, skipping the CVS directory
+files=`echo $source/scripts/* | sed -e "s/[^ ]*CVS//"`
+if test -n "$files" -a "$files" != "$source/scripts/*" ; then
+    $INSTALL -d $xpath
+    $INSTALL_SCRIPT $files $xpath
+fi
+
new file mode 100644
--- /dev/null
+++ b/src/pngcanvas.h
@@ -0,0 +1,76 @@
+/*
+ *  readpng.h
+ *
+ *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
+ *
+ *  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 Library 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.
+ */
+
+/*
+ * Modified: Stefan van der Walt <stefan@sun.ac.za>
+ * Date: 28 January 2005
+ * - Fix bugs, restructure
+ */
+
+typedef struct
+{
+  int width;
+  int height;
+  int bit_depth;
+  int color_type;
+  unsigned char **row_pointers;
+} canvas;
+
+//////////////Libcanvas///////////
+canvas *new_canvas(int width, int height, int stride)
+{
+  // Default stride if none given
+  if (stride==0) stride=width*4;
+
+  // Clean allocation of canvas structure
+  canvas *can=new(canvas);
+  unsigned char *image_data = new unsigned char[stride*height];
+  unsigned char **row_pointers = new unsigned char *[height];
+  if (can == NULL || image_data == NULL || row_pointers == NULL) 
+    {
+      if (can == NULL) delete can;
+      if (image_data == NULL) delete[] image_data;
+      if (row_pointers == NULL) delete[] row_pointers;
+      return NULL;
+    }
+
+  // Fill in canvas structure
+  can->width=width;
+  can->height=height;
+  can->bit_depth=8;
+  can->color_type=PNG_COLOR_TYPE_RGB_ALPHA;
+  can->row_pointers = row_pointers;
+  for (int i=0; i < height; i++) row_pointers[i] = image_data + i*stride;
+
+  return can;
+}
+
+void delete_canvas(canvas *can)
+{
+  
+  if (can!=NULL)
+    {
+      delete[] can->row_pointers[0]; 
+      delete[] can->row_pointers;
+      delete can;
+    }
+  return;
+}
+
new file mode 100644
--- /dev/null
+++ b/src/pngread.cc
@@ -0,0 +1,239 @@
+/*
+ *  pngread.cc
+ *
+ *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
+ *
+ *  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 Library 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.
+ */
+
+/*
+
+Load PNG files to octave using libpng;
+
+       PNG  (Portable  Network  Graphics) is an extensible file format for the
+       lossless, portable, well-compressed storage of raster images. PNG  pro-
+       vides  a patent-free replacement for GIF and can also replace many com-
+       mon uses of TIFF. Indexed-color, grayscale, and  truecolor  images  are
+       supported,  plus  an optional alpha channel. Sample depths range from 1
+       to 16 bits.
+
+*/
+
+/*
+ * Modified: Stefan van der Walt <stefan@sun.ac.za>
+ * Date: 28 January 2005
+ * - Fix bugs, restructure
+ */
+
+#include "png.h"
+#include "pngcanvas.h"
+#include <octave/oct.h>
+
+canvas *load_canvas(char *filename);
+
+DEFUN_DLD (pngread, args, nargout ,
+"-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {[@var{I}, @var{alpha}] =} pngread(@var{filename})\n\
+\n\
+Read a PNG file from disk.\n\
+\n\
+The image is returned as a matrix of dimension MxN (for grey-level images)\n\
+or MxNx3 (for colour images).  The numeric type of @var{I} and @var{alpha}\n\
+is @code{uint8} for grey-level and RGB images, or @code{logical} for\n\
+black-and-white images.\n\
+\n\
+@end deftypefn\n\
+@seealso{imread}")
+{
+  octave_value_list retval;
+  int nargin  = args.length();
+  
+  //
+  // We bail out if the input parameters are bad
+  //
+  if (nargin != 1 || !args(0).is_string()) {
+    print_usage ();
+    return retval;
+  }
+  
+  //
+  // Load png file
+  //
+  canvas *pic=load_canvas((char *)args(0).string_value().c_str());
+  if (!pic) return retval;
+
+  dim_vector dim = dim_vector();
+  dim.resize(3);
+  dim(0) = pic->height;
+  dim(1) = pic->width;
+  dim(2) = 3;
+
+  if ( (pic->color_type == PNG_COLOR_TYPE_GRAY) ||
+       (pic->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
+       ((pic->color_type == PNG_COLOR_TYPE_PALETTE) && (pic->bit_depth == 1)) )
+      dim(2) = 1;
+
+  if (pic->bit_depth > 1 && pic->bit_depth < 8)
+      pic->bit_depth = 8;
+
+  NDArray out(dim);
+  
+  dim.resize(2);
+  NDArray alpha(dim);
+   
+  Array<int> coord = Array<int> (3);
+  
+  for (unsigned long j=0; j < pic->height; j++) {
+      coord(0) = j;
+      for (unsigned long i=0; i < pic->width; i++) {
+	  coord(1) = i;
+
+	  for (int c = 0; c < out.dims()(2); c++) {
+	      coord(2) = c;
+	      out(coord) = pic->row_pointers[j][i*4+c];
+	  }
+	  alpha(j,i) = pic->row_pointers[j][i*4+3];
+      }
+  }
+  out = out.squeeze();
+
+  switch (pic->bit_depth) {
+  case 1: 
+     retval.append((boolNDArray)out);
+     retval.append((boolNDArray)alpha);
+     break;
+  case 8:
+     retval.append((uint8NDArray)out);
+     retval.append((uint8NDArray)alpha);
+     break;
+  case 16:
+     retval.append((uint16NDArray)out);
+     retval.append((uint16NDArray)alpha);
+     break;
+  default:
+     retval.append(out);
+     retval.append(alpha);
+  }
+
+  delete_canvas(pic);
+  return retval;
+}
+
+canvas *load_canvas(char *filename)
+{
+  png_structp png_ptr;
+  png_infop info_ptr;
+  
+  FILE *infile = fopen(filename,"r");
+  if (!infile) {
+    error("pngread could not open file %s", filename); 
+    return NULL;
+  }
+  
+  unsigned char sig[8];
+  fread(sig,1,8,infile);
+  if (!png_check_sig(sig,8)) {
+    error("pngread invalid signature in %s", filename); 
+    fclose(infile);
+    return NULL;
+  }
+  
+  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
+  if (!png_ptr) {
+    error("pngread out of memory"); 
+    fclose(infile);
+    return NULL;
+  }
+  
+  info_ptr = png_create_info_struct(png_ptr);
+  if(!info_ptr) { 
+    error("pngread can't generate info");  
+    png_destroy_read_struct(&png_ptr,NULL,NULL); 
+    fclose(infile);
+    return NULL;
+  }
+
+  /* Set error handling */
+  if (setjmp(png_jmpbuf(png_ptr))) {
+      error("pngread: libpng exited abnormally");
+      png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
+      fclose(infile);
+      return NULL;
+  }
+
+  png_init_io(png_ptr, infile);
+  png_set_sig_bytes(png_ptr, 8);
+  png_read_info(png_ptr, info_ptr);
+  
+  png_uint_32 width,height;
+  int color_type, bit_depth;
+  png_get_IHDR(png_ptr,info_ptr,&width,&height,
+	       &bit_depth,&color_type,NULL,NULL,NULL);
+  
+  /* Transform grayscale images with depths < 8-bit to 8-bit, change
+   * paletted images to RGB, and add a full alpha channel if there is
+   * transparency information in a tRNS chunk.
+   */
+  if (color_type == PNG_COLOR_TYPE_PALETTE) {
+      png_set_palette_to_rgb(png_ptr);
+  }
+  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
+      png_set_gray_1_2_4_to_8(png_ptr);
+  }
+  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { //add alpha
+      png_set_tRNS_to_alpha(png_ptr);
+  }
+  
+  // Always transform image to RGB
+  if (color_type == PNG_COLOR_TYPE_GRAY 
+      || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) 
+      png_set_gray_to_rgb(png_ptr);
+   
+  // If no alpha layer is present, create one
+  if (color_type == PNG_COLOR_TYPE_GRAY
+      || color_type == PNG_COLOR_TYPE_RGB)
+     png_set_add_alpha(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+  if (bit_depth < 8) {
+      png_set_packing(png_ptr);
+  }
+  
+  // For now, use 8-bit only
+  if (bit_depth == 16) {
+      png_set_strip_16(png_ptr);
+  }
+   
+  png_read_update_info(png_ptr,info_ptr);
+
+  // Read the data from the file
+  int stride = png_get_rowbytes(png_ptr, info_ptr);
+  canvas *can = new_canvas(width, height, stride);
+  
+  if (can) {
+    png_read_image(png_ptr, can->row_pointers);
+  } else {
+    error("pngread out of memory");
+  }
+
+  png_read_end(png_ptr,NULL);
+  png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+  fclose(infile);
+
+  // Set color type and depth. Used to determine octave output arguments.
+  can->color_type = color_type;  
+  can->bit_depth = bit_depth;
+  return can;
+}
new file mode 100644
--- /dev/null
+++ b/src/pngwrite.cc
@@ -0,0 +1,166 @@
+/*
+ *  pngwrite.cc
+ *
+ *  Copyright (C) 2003 Nadav Rotem <nadav256@hotmail.com>
+ *
+ *  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 Library 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.
+ */
+
+/*
+
+Write PNG files to disk from octave
+
+       PNG  (Portable  Network  Graphics) is an extensible file format for the
+       lossless, portable, well-compressed storage of raster images. PNG  pro-
+       vides  a patent-free replacement for GIF and can also replace many com-
+       mon uses of TIFF. Indexed-color, grayscale, and  truecolor  images  are
+       supported,  plus  an optional alpha channel. Sample depths range from 1
+       to 16 bits.
+
+*/
+
+/*
+ * Modified: Stefan van der Walt <stefan@sun.ac.za>
+ * Date: 28 January 2005
+ * - Fix bugs, restructure
+ */
+
+#include "png.h"
+#include "pngcanvas.h"
+#include <octave/oct.h>
+
+void save_canvas(canvas *can, char *filename);
+
+DEFUN_DLD (pngwrite, args, ,"\
+pngwrite writes a png file to the disk.\n\
+    pngwrite('filename',R,G,B,A) writes the specified file\n\
+    using the Red, Green, Blue and Alpha matrices.\n\
+    \n\
+    Data must be [0 255] or the high bytes will be lost.")
+{
+   octave_value_list retval;
+   int nargin  = args.length();
+   
+   //
+   // We bail out if the input parameters are bad
+   //
+   if (nargin < 5 || !args(0).is_string() ) {
+     print_usage ();
+     return retval;
+   }
+
+   Matrix red  = args(1).matrix_value();
+   Matrix green= args(2).matrix_value();
+   Matrix blue = args(3).matrix_value();
+   Matrix alpha= args(4).matrix_value();
+   
+   long image_width  = args(1).columns();
+   long image_height = args(1).rows();
+   
+   if ( args(2).columns() != image_width  ||
+	args(3).columns() != image_width  ||
+	args(4).columns() != image_width  ||
+	args(2).rows()    != image_height ||
+	args(3).rows()    != image_height ||
+	args(4).rows()    != image_height )  
+     {
+       error("pngwrite R,G,B,A matrix sizes aren't the same");
+       return retval;
+     }
+   
+   canvas *pic=new_canvas(image_width, image_height, image_width*4);
+   if (!pic) {
+       error("pngwrite out of memory");
+       return retval;
+   }
+
+   for(int i=0; i < pic->width; i++) {
+       for(int j=0; j < pic->height; j++) {
+	   pic->row_pointers[j][i*4+0]=(unsigned char)(red(j,i));
+	   pic->row_pointers[j][i*4+1]=(unsigned char)(green(j,i));
+	   pic->row_pointers[j][i*4+2]=(unsigned char)(blue(j,i));
+	   pic->row_pointers[j][i*4+3]=(unsigned char)(alpha(j,i));
+       }
+   }
+   
+
+   save_canvas(pic,(char *)args(0).string_value().c_str());
+   delete_canvas(pic);
+
+   return retval;
+}
+
+void save_canvas(canvas *can,char *filename)
+{
+  FILE            *fp;
+  png_structp     png_ptr;
+  png_infop       info_ptr;
+  
+  fp = fopen(filename, "wb");
+  if (fp == NULL) {
+    error("pngwrite could not open %s", filename);
+    return;
+  }
+
+  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+  if (!png_ptr) {
+      fclose(fp);
+      error("pngwrite: cannot create write structure");
+      return;
+  }
+
+  info_ptr = png_create_info_struct(png_ptr);
+  if (!info_ptr) {
+      fclose(fp);
+      error("pngwrite: cannot not create image structure");
+      png_destroy_write_struct(&png_ptr, png_infopp_NULL);
+      return;
+  }
+
+  if (setjmp(png_jmpbuf(png_ptr))) {
+      fclose(fp);
+      png_destroy_write_struct(&png_ptr, &info_ptr);
+      error("pngread: libpng exited abnormally");
+      return;
+  }
+
+  png_init_io(png_ptr, fp);
+  png_set_compression_level(png_ptr, 3);
+  
+  png_set_IHDR(png_ptr, info_ptr, can->width, can->height,         
+	       can->bit_depth, can->color_type, PNG_INTERLACE_NONE,
+	       PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+  
+  
+  png_set_gAMA(png_ptr, info_ptr, 0.7);
+  
+  time_t          gmt;
+  png_time        mod_time;
+  png_text        text_ptr[2];
+  time(&gmt);
+  png_convert_from_time_t(&mod_time, gmt);
+  png_set_tIME(png_ptr, info_ptr, &mod_time);
+  text_ptr[0].key = "Created by";
+  text_ptr[0].text = "Octave";
+  text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
+  
+  png_set_text(png_ptr, info_ptr, text_ptr, 1);
+  
+  png_write_info(png_ptr, info_ptr);
+  png_write_image(png_ptr, can->row_pointers);
+  png_write_end(png_ptr, info_ptr);                      
+  png_destroy_write_struct(&png_ptr, &info_ptr);          
+  fclose(fp); 
+}
new file mode 100644
--- /dev/null
+++ b/src/rotate_scale.cc
@@ -0,0 +1,179 @@
+/*
+ * ROTATE_SCALE: rotate and scale a matrix using bilinear interpolation
+ * imo= block(im, xregs, yregs);
+ *
+ * Copyright (C) 2003 Andy Adler
+ * This code has no warrany whatsoever.
+ * Do what you like with this code as long as you
+ *     leave this copyright in place.
+ *
+ * $Id$
+ */
+
+#include <octave/oct.h>
+
+void
+calc_rotation_params(
+              double x0l,double y0l,double x0r,double y0r,
+              double x1l,double y1l,double x1r,double y1r,
+              double* Tx_x, double* Ty_x,
+              double* Tx_y, double* Ty_y,
+              double* Tx_1, double* Ty_1 );
+void
+do_interpolation (
+              double Tx_x, double Ty_x,
+              double Tx_y, double Ty_y,
+              double Tx_1, double Ty_1,
+              int x0max, int y0max,// initial size
+              int x1max, int y1max,// output size
+              const double * img0,
+              double       * img1 );
+
+DEFUN_DLD (rotate_scale, args, ,
+  "ROTATE_SCALE: arbitrary rotation and scaling of an image\n"
+  "              using fast bilinear interpolation\n"
+  "im1 = rotate_scale(im0, lm0, lm1, out_size)\n"
+  "  where:\n"
+  "im0 = input image\n"
+  "lm0 = landmarks of points in original image [ x1,x2;y1,y2 ]\n"
+  "im1 = output image, where size(im1) == out_size\n"
+  "lm1 = landmarks of points in output image [ x1,x2;y1,y2 ]\n"
+  "\n"
+  "   note1: two landmarks must be specified for lm0 and lm1\n"
+  "   note2: all images have a single component\n"
+  "   to use this for colour images, use:\n"
+  "  r_im1= rotate_scale( red_im0, lm0, lm1, out_size)\n"
+  "  g_im1= rotate_scale( grn_im0, lm0, lm1, out_size)\n"
+  "  b_im1= rotate_scale( blu_im0, lm0, lm1, out_size)\n"
+  "\n"
+  "   example:\n"
+  "  im0= zeros(100); im0(25:75,25:75)=1;\n"
+  "  im1= rotate_scale( im0, [40,60;50,50],[60,90;60,90],[120,120]);\n"
+)
+{
+   octave_value_list retval;
+   if (args.length() < 4 ||
+       !args(0).is_matrix_type() ||
+       !args(1).is_matrix_type() ||
+       !args(2).is_matrix_type() ||
+       !args(3).is_matrix_type()
+       ) {
+      print_usage ();
+      return retval;
+   }
+
+   Matrix im0( args(0).matrix_value() );
+   const double * im0p = im0.data();
+   Matrix lm0( args(1).matrix_value() );
+   Matrix lm1( args(2).matrix_value() );
+   ColumnVector out_size( args(3).vector_value() );
+
+   int inp_hig= im0.rows();
+   int inp_wid= im0.cols();
+
+   int out_hig= (int) out_size(0);
+   int out_wid= (int) out_size(1);
+   Matrix im1( out_hig, out_wid);
+   double * im1p = im1.fortran_vec();
+
+   double Tx_x; double Ty_x;
+   double Tx_y; double Ty_y;
+   double Tx_1; double Ty_1;
+   calc_rotation_params(
+          lm0(0,0), lm0(1,0), lm0(0,1), lm0(1,1),
+          lm1(0,0), lm1(1,0), lm1(0,1), lm1(1,1),
+          & Tx_x, & Ty_x,
+          & Tx_y, & Ty_y,
+          & Tx_1, & Ty_1 );
+    
+   do_interpolation( Tx_x, Ty_x, Tx_y, Ty_y, Tx_1, Ty_1,
+                  inp_wid, inp_hig, out_wid, out_hig,
+                  im0p, im1p );
+
+   retval(0) = im1;
+   return retval;
+}
+
+inline double sqr(double a) { return (a)*(a); }
+
+void
+calc_rotation_params(
+              double x1l,double y1l,double x1r,double y1r,
+              double x0l,double y0l,double x0r,double y0r,
+              double* Tx_x, double* Ty_x,
+              double* Tx_y, double* Ty_y,
+              double* Tx_1, double* Ty_1 
+              )
+{
+    double d0= sqrt( sqr(x0l-x0r) + sqr(y0l-y0r) );
+    double d1= sqrt( sqr(x1l-x1r) + sqr(y1l-y1r) );
+    double dr= d1/d0;
+
+    double a0= atan2( y0l-y0r , x0l-x0r );
+    double a1= atan2( y1l-y1r , x1l-x1r );
+    double ad= a1-a0;
+    double dr_cos_ad= dr*cos(ad);
+    double dr_sin_ad= dr*sin(ad);
+
+    double x0m= (x0l+x0r)/2;
+    double y0m= (y0l+y0r)/2;
+    double x1m= (x1l+x1r)/2;
+    double y1m= (y1l+y1r)/2;
+
+    *Tx_x=  dr_cos_ad;
+    *Ty_x=  dr_sin_ad;
+    *Tx_y= -dr_sin_ad;
+    *Ty_y=  dr_cos_ad;
+    *Tx_1=  x1m - dr_cos_ad*x0m + dr_sin_ad*y0m;
+    *Ty_1=  y1m - dr_sin_ad*x0m - dr_cos_ad*y0m;
+}    
+
+
+void
+do_interpolation (
+              double Tx_x, double Ty_x,
+              double Tx_y, double Ty_y,
+              double Tx_1, double Ty_1,
+              int x0max, int y0max,// initial size
+              int x1max, int y1max,// output size
+              const double * img0,
+              double       * img1 
+            )
+{
+
+    for (int i=0; i< x1max; i++) {
+        for (int j=0; j< y1max; j++) {
+            double x0i= Tx_x * i + Tx_y * j + Tx_1;
+            double y0i= Ty_x * i + Ty_y * j + Ty_1;
+
+            if ( x0i < 0       )    x0i= 0;
+            else
+            if (x0i >= x0max-1 )    x0i= x0max - 1.00001; 
+
+            if ( y0i < 0       )    y0i= 0;
+            else
+            if (y0i >= y0max-1 )    y0i= y0max - 1.00001; 
+
+            int x0idx= (int) x0i;
+            int y0idx= (int) y0i;
+
+            double frac_r= x0i- x0idx; 
+            double frac_l= 1 - frac_r;
+            double frac_d= y0i- y0idx; 
+            double frac_u= 1 - frac_d;
+
+            int pix_lu= (y0idx+0) + (x0idx+0) * y0max ;
+            int pix_ru= (y0idx+0) + (x0idx+1) * y0max ;
+            int pix_ld= (y0idx+1) + (x0idx+0) * y0max ;
+            int pix_rd= (y0idx+1) + (x0idx+1) * y0max ;
+               
+            img1[ i*y1max + j ]=
+               frac_l*frac_u* img0[ pix_lu ] +
+               frac_r*frac_u* img0[ pix_ru ] +
+               frac_l*frac_d* img0[ pix_ld ] +
+               frac_r*frac_d* img0[ pix_rd ];
+
+        }
+    }
+}
+
deleted file mode 100644
--- a/std2.m
+++ /dev/null
@@ -1,38 +0,0 @@
-## Copyright (C) 2000  Kai Habel
-##
-## 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{s}= std2 (@var{I})
-## returns the standard deviation for a 2d real type matrix.
-## Uses @code{std (I(:))}
-## @end deftypefn
-## @seealso{mean2,std}
-
-## Author:	Kai Habel <kai.habel@gmx.de>
-## Date:	01/08/2000
-
-function s = std2 (I)
-
-  if !(nargin == 1)
-    usage ("std2(I)");
-  endif
-
-  if !(is_matrix(I) && isreal(I))
-	error("argument must be a real type matrix");
-  endif
-
-  s = std (I(:));
-endfunction
deleted file mode 100644
--- a/stretchlim.m
+++ /dev/null
@@ -1,209 +0,0 @@
-## 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{LOW_HIGH} = } stretchlim (@var{I},@var{TOL})
-## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{I})
-## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{RGB},@var{TOL})
-## @deftypefnx {Function File} {@var{LOW_HIGH} = } stretchlim (@var{RGB})
-## Finds limits to contrast stretch an image
-##
-## @code{LOW_HIGH=stretchlim(I,TOL)} returns a vector @var{LOW_HIGH}
-## which contains a pair of intensities which can be used in
-## @code{imadjust} to stretch the contrast of an image, first of them
-## will be lower value (@code{imadjust} would assign 0 to it) and second
-## is the upper bound. @var{TOL} specifies the fraction of the image to
-## saturate at lower and upper limits. It can be a vector of length 2:
-## @code{[LOW_FRACT, HIGH_FRACT]}, or it can be a scalar, in that case
-## @code{[LOW_FRACT, HIGH_FRACT]=[TOL, 1-TOL]}.
-##
-## @var{TOL} can't be larger than 0.50 and for TOL=0 then
-## @code{LOW_HIGH=[min(I(:)), max(I(:))]}.
-##
-## @code{LOW_HIGH=stretchlim(I)} behaves as described but defaults
-## @var{TOL} to @code{[0.01, 0.99]}.
-##
-## @code{LOW_HIGH=stretchlim(RGB,TOL)} returns a 2-by-3 matrix in
-## @var{LOW_HIGH} of lower and upper values to saturate for each plane
-## of the RGB image in M-by-N-by-3 array @var{RGB}. @var{TOL} is a
-## vector or a scalar, as described above, and the same fractions are
-## applied for each plane.
-##
-## @code{LOW_HIGH=stretchlim(RGB)} uses @code{[0.01, 0.99]} as default
-## value for @var{TOL}.
-##
-## @strong{Notes:}
-##
-## Values in @var{LOW_HIGH} are of type double and comprised between 0
-## and 1 regardless class of input image.
-##
-## @strong{Compatibility notes:}
-##
-## @itemize @bullet
-## @item
-## int* and uint* types are still not implemented (waiting for support
-## in Octave 2.1.58).
-## @item
-## This function tries to find limits that are nearer to saturate
-## requested interval. So, for instance, if you requested a 5% and it
-## has to choose between discarding a 1% and a 7%, it will choose the
-## later despite being more than requested. This should be test against
-## MATLAB behaviour.
-## @end itemize
-##
-## @end deftypefn
-## @seealso imadjust
-
-## Author:  Josep Mones i Teixidor <jmones@puntbarra.com>
-
-function LOW_HIGH = stretchlim(image, TOL)
-  if (nargin<1 || nargin>2)
-    usage("LOW_HIGH=stretchlim(I [, TOL]), LOW_HIGH=stretchlim(RGB [, TOL])");
-  endif
-  
-  if(!ismatrix(image))
-    error("stretchlim: image should be a matrix");
-  endif
-  
-  ## Prepare limits
-  if(nargin==1)
-    low_count=0.01;
-    high_count=0.01;                ## we use this definition in __stretchlim_plane__
-  else
-    if(isscalar(TOL))
-      if(TOL<0 || TOL>=0.5)
-	error("stretchlim: TOL out of bounds. Expected: 0<=TOL<0.5");
-      endif
-      low_count=TOL;
-      high_count=TOL;               ## as before...
-    elseif(isvector(TOL))
-      if(length(TOL)!=2)
-	error("stretchlim: TOL length must be 2.");
-      endif
-      low_count=TOL(1);
-      high_count=1-TOL(2);          ## as before...
-    else
-      error("stretchlim: TOL contains an invalid value.");
-    endif
-  endif
-
-  ## well use size of image several times...
-  simage=size(image);
-
-  ## Convert fractions to pixels
-  psimage=prod(simage(1:2));
-  low_count*=psimage;
-  high_count*=psimage;
-	 
-  if(length(simage)<=2)
-    ## intensity
-    LOW_HIGH=__stretchlim_plane__(image, low_count, high_count);
-  elseif(length(simage)==3 && simage(3)==3)
-    ## RGB
-    LOW_HIGH=zeros(2,3);
-    for i=1:3
-      LOW_HIGH(:,i)=__stretchlim_plane__(image(:,:,i), low_count, \
-					 high_count);
-    endfor
-  else
-    error("stretchlim: invalid image.");
-  endif
-endfunction
-
-
-## Processes a plane
-## high_count is defined so that high_count=elements is the same as
-## low_count=elements (and not total_elements-elements)
-function LOW_HIGH = __stretchlim_plane__(plane, low_count, high_count)
-  ## check exceptions
-  if(low_count==0 && high_count==0)
-    LOW_HIGH=[min(plane(:)); max(plane(:))];
-  else
-
-    ## we sort values
-    sorted=sort(plane(:));
-    
-    low=sorted(round(low_count+1));
-    pos=find(sorted>low);
-    if(length(pos)>0)
-      low2=sorted(pos(1));
-      d1=low_count-sum(sorted<low);
-      d2=sum(sorted<low2)-low_count;
-      if(d2<d1)
-	low=low2;
-      endif
-    endif
-      
-    high=sorted(end-round(high_count));
-    pos=find(sorted<high);
-    if(length(pos)>0)
-      high2=sorted(pos(end));
-      d1=high_count-sum(sorted>high);
-      d2=sum(sorted>high2)-high_count;
-      if(d2<d1)
-	high=high2;
-      endif
-    endif
-
-    ## set result variable
-    LOW_HIGH=[low;high];
-  endif
-endfunction
-
-%!demo
-%! stretchlim([1:100])
-%! # This discards 1% of data from each end, 1 and 100.
-%! # So result should be [2;99]
-
-%!# some invalid params
-%!error(stretchlim());
-%!error(stretchlim("bad parameter"));
-%!error(stretchlim(zeros(10,10,4)));
-%!error(stretchlim(zeros(10,10,3,2)));
-%!error(stretchlim(zeros(10,10),"bad parameter"));
-%!error(stretchlim(zeros(10,10),0.01,2));
-
-
-%!# default param
-%!assert(stretchlim([1:100]),[2;99]);
-
-%!# scalar TOL
-%!assert(stretchlim([1:100],0.01),[2;99]);
-
-%!# vector TOL
-%!assert(stretchlim([1:100],[0.01,0.98]),[2;98]);
-
-%!# TOL=0
-%!assert(stretchlim([1:100],0),[1;100]);
-
-%!# non uniform histogram tests
-%!assert(stretchlim([1,ones(1,90)*2,92:100],0.05),[2;95]);
-%!assert(stretchlim([1,ones(1,4)*2,6:100],0.05),[6;95]);
-
-%!# test limit rounding...
-%!assert(stretchlim([1,ones(1,5)*2,7:100],0.05),[7;95]); # 6% lost 
-%!assert(stretchlim([1,ones(1,6)*2,8:100],0.05),[8;95]); # 7% lost
-%!assert(stretchlim([1,ones(1,7)*2,9:100],0.05),[9;95]); # 8% lost
-%!assert(stretchlim([1,ones(1,8)*2,10:100],0.05),[2;95]); # now he limit at 2 => 1% lost
-
-%!# test RGB
-%!test
-%! RGB=zeros(100,1,3);
-%! RGB(:,:,1)=[1:100];
-%! RGB(:,:,2)=[2:2:200];
-%! RGB(:,:,3)=[4:4:400];
-%! assert(stretchlim(RGB),[2,4,8;99,198,396]);
-
deleted file mode 100644
--- a/summer.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} summer (@var{n})
-## Create color colormap. 
-## (green to yellow)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-## Date:  06/03/2000
-function map = summer (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("summer: argument must be a scalar");
-    endif
-  else
-    usage ("summer (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0.5, 0.4];  
-  elseif (number > 1)
-    r = (0:number - 1)' ./ (number - 1);
-    g = 0.5 + r ./ 2;
-    b = 0.4 * ones (number, 1);
-
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/testimio.m
+++ /dev/null
@@ -1,56 +0,0 @@
-## This program is public domain.
-
-## build image for image r/w tests
-x=linspace(-8,8,200);
-[xx,yy]=meshgrid(x,x);
-r=sqrt(xx.^2+yy.^2) + eps;
-map=colormap(hsv);
-A=sin(r)./r;
-minval = min(A(:));
-maxval = max(A(:));
-z = round ((A-minval)/(maxval - minval) * (rows(colormap) - 1)) + 1;
-Rw=Gw=Bw=z;
-Rw(:)=fix(255*map(z,1));
-Gw(:)=fix(255*map(z,2));
-Bw(:)=fix(255*map(z,3));
-Aw=fix(255*(1-r/max(r(:)))); ## Fade to nothing at the corners
-
-if exist("jpgwrite")
-  disp(">jpgwrite"); 
-  jpgwrite('test.jpg',Rw,Gw,Bw);
-  stats=stat("test.jpg");
-  assert(stats.size,6423);
-  disp(">jpgread");
-  im = jpgread('test.jpg');
-  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
-  assert(all(Rw(:)-double(Rr(:))<35));
-  assert(all(Gw(:)-double(Gr(:))<35));
-  assert(all(Bw(:)-double(Br(:))<35));
-  unlink('test.jpg');
-else
-  disp(">jpgread ... not available");
-  disp(">jpgwrite ... not available");
-endif
-
-if exist("pngwrite")
-  disp(">pngwrite"); 
-  pngwrite('test.png',Rw,Gw,Bw,Aw);
-  stats=stat("test.png");
-  assert(stats.size,24738);
-  disp(">pngread");
-  im = pngread('test.png');
-  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
-  assert(all(double(Rr(:))==Rw(:)));
-  assert(all(double(Gr(:))==Gw(:)));
-  assert(all(double(Br(:))==Bw(:)));
-  [im,Ar] = pngread('test.png');
-  Rr = im(:,:,1); Gr = im(:,:,2); Br = im(:,:,3);
-  assert(all(double(Rr(:))==Rw(:)));
-  assert(all(double(Gr(:))==Gw(:)));
-  assert(all(double(Br(:))==Bw(:)));
-  assert(all(double(Ar(:))==Aw(:)));
-  unlink('test.png');
-else
-  disp(">pngread ... not available");
-  disp(">pngwrite ... not available");
-endif
deleted file mode 100644
--- a/uintlut.m
+++ /dev/null
@@ -1,57 +0,0 @@
-## 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.2  2004/08/11 15:04:59  pkienzle
-% Convert dos line endings to unix line endings
-%
-% Revision 1.1  2004/08/08 21:20:25  jmones
-% uintlut and padarray functions added
-%
-%
deleted file mode 100644
--- a/white.m
+++ /dev/null
@@ -1,46 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} white (@var{n})
-## Create color colormap. 
-## (completly white)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = white (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("white: argument must be a scalar");
-    endif
-  else
-    usage ("white (number)");
-  endif
-
-  if (number > 0)
-    map = ones (number, 3);
-  else
-    map = [];
-  endif
-
-endfunction
deleted file mode 100644
--- a/winter.m
+++ /dev/null
@@ -1,52 +0,0 @@
-## Copyright (C) 1999,2000  Kai Habel
-##
-## 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} {} winter (@var{n})
-## Create color colormap. 
-## (blue to green)
-## The argument @var{n} should be a scalar.  If it
-## is omitted, the length of the current colormap or 64 is assumed.
-## @end deftypefn
-## @seealso{colormap}
-
-## Author:  Kai Habel <kai.habel@gmx.de>
-
-function map = winter (number)
-
-  if (nargin == 0)
-    number = rows (colormap);
-  elseif (nargin == 1)
-    if (! is_scalar (number))
-      error ("winter: argument must be a scalar");
-    endif
-  else
-    usage ("winter (number)");
-  endif
-
-  if (number == 1)
-    map = [0, 0, 1];  
-  elseif (number > 1)
-    r = zeros (number, 1);
-    g = (0:number - 1)' ./ (number - 1);
-    b = 1 - g ./ 2;
-
-    map = [r, g, b];
-  else
-    map = [];
-  endif
-
-endfunction