changeset 10964:ea3c41a1fe67 octave-forge

image: fix dos line ending style
author carandraug
date Thu, 27 Sep 2012 13:18:13 +0000
parents 63a610f342b0
children f557ef28f224
files main/image/NEWS main/image/inst/bwhitmiss.m main/image/inst/graythresh.m main/image/inst/imbothat.m main/image/inst/imclose.m main/image/inst/imdilate.m main/image/inst/imerode.m main/image/inst/imopen.m main/image/inst/imtophat.m main/image/inst/rgbplot.m main/image/inst/wavelength2rgb.m
diffstat 11 files changed, 1317 insertions(+), 1315 deletions(-) [+]
line wrap: on
line diff
--- a/main/image/NEWS	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/NEWS	Thu Sep 27 13:18:13 2012 +0000
@@ -50,7 +50,7 @@
       minimum
       MinError
       moments
-      otsu
+      Otsu
       percentile
 
  ** The following functions have been deprecated (see their help text
--- a/main/image/inst/bwhitmiss.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/bwhitmiss.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,67 +1,67 @@
-## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
-##
-## 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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{bw2} = bwhitmiss (@var{bw1}, @var{se1}, @var{se1})
-## @deftypefnx{Function File} @var{bw2} = bwhitmiss (@var{bw1}, @var{interval})
-## Perform the binary hit-miss operation.
-##
-## If two structuring elements @var{se1} and @var{se1} are given, the hit-miss
-## operation is defined as
-## @example
-## bw2 = erode(bw1, se1) & erode(!bw1, se2);
-## @end example
-## If instead an 'interval' array is given, two structuring elements are computed
-## as
-## @example
-## se1 = (interval ==  1)
-## se2 = (interval == -1)
-## @end example
-## and then the operation is defined as previously.
-## @seealso{bwmorph}
-## @end deftypefn
-
-function bw = bwhitmiss(im, varargin)
-  ## Checkinput
-  if (nargin != 2 && nargin != 3)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("bwhitmiss: first input argument must be a real matrix");
-  endif
-
-  ## Get structuring elements
-  if (nargin == 2) # bwhitmiss (im, interval)
-    interval = varargin{1};
-    if (!isreal(interval))
-      error("bwhitmiss: second input argument must be a real matrix");
-    endif
-    if (!all( (interval(:) == 1) | (interval(:) == 0) | (interval(:) == -1) ))
-      error("bwhitmiss: second input argument can only contain the values -1, 0, and 1");
-    endif
-    se1 = (interval ==  1);
-    se2 = (interval == -1);
-  else # bwhitmiss (im, se1, se2)
-    se1 = varargin{1};
-    se2 = varargin{2};
-    if (!all((se1(:) == 1) | (se1(:) == 0)) || !all((se2(:) == 1) | (se2(:) == 0)))
-      error("bwhitmiss: structuring elements can only contain zeros and ones.");
-    endif
-  endif
-  
-  ## Perform filtering
-  bw = erode(im, se1) & erode(!im, se2);
-
-endfunction
+## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
+##
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{bw2} = bwhitmiss (@var{bw1}, @var{se1}, @var{se1})
+## @deftypefnx{Function File} @var{bw2} = bwhitmiss (@var{bw1}, @var{interval})
+## Perform the binary hit-miss operation.
+##
+## If two structuring elements @var{se1} and @var{se1} are given, the hit-miss
+## operation is defined as
+## @example
+## bw2 = erode(bw1, se1) & erode(!bw1, se2);
+## @end example
+## If instead an 'interval' array is given, two structuring elements are computed
+## as
+## @example
+## se1 = (interval ==  1)
+## se2 = (interval == -1)
+## @end example
+## and then the operation is defined as previously.
+## @seealso{bwmorph}
+## @end deftypefn
+
+function bw = bwhitmiss(im, varargin)
+  ## Checkinput
+  if (nargin != 2 && nargin != 3)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("bwhitmiss: first input argument must be a real matrix");
+  endif
+
+  ## Get structuring elements
+  if (nargin == 2) # bwhitmiss (im, interval)
+    interval = varargin{1};
+    if (!isreal(interval))
+      error("bwhitmiss: second input argument must be a real matrix");
+    endif
+    if (!all( (interval(:) == 1) | (interval(:) == 0) | (interval(:) == -1) ))
+      error("bwhitmiss: second input argument can only contain the values -1, 0, and 1");
+    endif
+    se1 = (interval ==  1);
+    se2 = (interval == -1);
+  else # bwhitmiss (im, se1, se2)
+    se1 = varargin{1};
+    se2 = varargin{2};
+    if (!all((se1(:) == 1) | (se1(:) == 0)) || !all((se2(:) == 1) | (se2(:) == 0)))
+      error("bwhitmiss: structuring elements can only contain zeros and ones.");
+    endif
+  endif
+  
+  ## Perform filtering
+  bw = erode(im, se1) & erode(!im, se2);
+
+endfunction
--- a/main/image/inst/graythresh.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/graythresh.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,726 +1,728 @@
-## Copyright (C) 2004 Antti Niemistö <antti.niemisto@tut.fi>
-## Copyright (C) 2005 Barre-Piquot
-## Copyright (C) 2007 Søren Hauberg
-## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img})
-## @deftypefnx {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img}, @var{algo})
-## @deftypefnx {Function File} {[@var{level}] =} graythresh (@var{img}, "percentile", @var{fraction})
-## Compute global image threshold.
-##
-## Given an image @var{img} finds the optimal threshold value @var{level} for
-## conversion to a binary image with @code{im2bw}. Color images are converted
-## to grayscale before @var{level} is computed.
-##
-## The optional argument @var{method} is the algorithm to be used (default's to
-## Otsu). The available algorithms are:
-##
-## @table @asis
-## @item Otsu (default)
-## Implements Otsu's method as described in @cite{Nobuyuki Otsu (1979). "A
-## threshold selection method from gray-level histograms", IEEE Trans. Sys.,
-## Man., Cyber. 9 (1): 62-66}. This algorithm chooses the threshold to minimize
-## the intraclass variance of the black and white pixels. The second output,
-## @var{sep} represents the ``goodness'' (or separability) of the threshold at
-## @var{level}.
-##
-## @item concavity
-## Find a global threshold for a grayscale image by choosing the threshold to
-## be in the shoulder of the histogram @cite{A. Rosenfeld, and P. De La Torre
-## (1983). "Histogram concavity analysis as an aid in threshold selection", IEEE
-## Transactions on Systems, Man, and Cybernetics, 13: 231-235}.
-##
-## @item Huang
-## Not yet implemented.
-##
-## @item ImageJ
-## A variation of the intermeans algorithm, this is the default for ImageJ.
-## Not yet implemented.
-##
-## @item intermodes
-## This assumes a bimodal histogram and chooses the threshold to be the mean of
-## the two peaks of the bimodal histogram @cite{J. M. S. Prewitt, and M. L.
-## Mendelsohn (1966). "The analysis of cell images", Annals of the New York
-## Academy of Sciences, 128: 1035-1053}.
-##
-## Images with histograms having extremely unequal peaks or a broad and flat
-## valley are unsuitable for this method.
-##
-## @item intermeans
-## Iterative procedure based on the iterative intermeans algorithm of @cite{T.
-## Ridler, and S. Calvard (1978). "Picture thresholding using an iterative
-## selection method", IEEE Transactions on Systems, Man, and Cybernetics, 8: 630-632}
-## and @cite{H. J. Trussell (1979). "Comments on 'Picture thresholding using an
-## iterative selection method'", IEEE Transactions on Systems, Man, and Cybernetics,
-## 9: 311}.
-##
-## Note that several implementations of this method exist. See the source code
-## for details.
-##
-## @item Li
-## Not yet implemented.
-##
-## @item MaxEntropy
-## Implements Kapur-Sahoo-Wong (Maximum Entropy) thresholding method based on the
-## entropy of the image histogram @cite{J. N. Kapur, P. K. Sahoo, and A. C. K. Wong
-## (1985). "A new method for gray-level picture thresholding using the entropy
-## of the histogram", Graphical Models and Image Processing, 29(3): 273-285}.
-##
-## @item MaxLikelihood
-## Find a global threshold for a grayscale image using the maximum likelihood
-## via expectation maximization method @cite{A. P. Dempster, N. M. Laird, and D. B.
-## Rubin (1977). "Maximum likelihood from incomplete data via the EM algorithm",
-## Journal of the Royal Statistical Society, Series B, 39:1-38}.
-##
-## @item mean
-## The mean intensity value. It is mostly used by other methods as a first guess
-## threshold.
-##
-## @item MinError
-## An iterative implementation of Kittler and Illingworth's Minimum Error
-## thresholding @cite{J. Kittler, and J. Illingworth (1986). "Minimum error
-## thresholding", Pattern recognition, 19: 41-47}.
-##
-## This implementation seems to converge more often than the original.
-## Nevertheless, sometimes the algorithm does not converge to a solution. In
-## that case a warning is displayed and defaults to the initial estimate of the
-## mean method.
-##
-## @item minimum
-## This assumes a bimodal histogram and chooses the threshold to be in the
-## valley of the bimodal histogram.  This method is also known as the mode
-## method @cite{J. M. S. Prewitt, and M. L. Mendelsohn (1966). "The analysis of
-## cell images", Annals of the New York Academy of Sciences, 128: 1035-1053}.
-##
-## Images with histograms having extremely unequal peaks or a broad and flat
-## valley are unsuitable for this method.
-##
-## @item moments
-## Find a global threshold for a grayscale image using moment preserving
-## thresholding method @cite{W. Tsai (1985). "Moment-preserving thresholding:
-## a new approach", Computer Vision, Graphics, and Image Processing, 29: 377-393}
-##
-## @item percentile
-## Assumes a specific @var{fraction} of pixels to be background.  If no value is
-## given, assumes a value of 0.5 (equal distribution of background and foreground)
-## @cite{W Doyle (1962). "Operation useful for similarity-invariant pattern
-## recognition", Journal of the Association for Computing Machinery 9: 259-267}
-##
-## @item RenyiEntropy
-## Not yet implemented.
-##
-## @item Shanbhag
-## Not yet implemented.
-##
-## @item triangle
-## Not yet implemented.
-##
-## @item Yen
-## Not yet implemented.
-## @end table
-##
-## @seealso{im2bw}
-## @end deftypefn
-
-## Notes:
-##  * Otsu's method is a function taken from
-##    http://www.irit.fr/~Philippe.Joly/Teaching/M2IRR/IRR05/ Søren Hauberg
-##    added texinfo documentation, error checking and sanitised the code.
-##  * The following methods were adapted from http://www.cs.tut.fi/~ant/histthresh/
-##      intermodes    percentile      minimum
-##      MaxEntropy    MaxLikelihood   intermeans
-##      moments       minerror        concavity
-
-
-function [level, good] = graythresh (img, algo = "otsu", varargin)
-  ## Input checking
-  if (nargin < 1 || nargin > 3)
-    print_usage();
-  elseif (!isgray (img) && !isrgb (img))
-    error ("graythresh: input must be an image");
-  endif
-
-  ## If the image is RGB convert it to grayscale
-  if (isrgb (img))
-    img = rgb2gray (img);
-  endif
-
-  switch tolower (algo)
-    case {"concavity"},     [level]       = concavity (img);
-    case {"intermeans"},    [level]       = intermeans (img);
-    case {"intermodes"},    [level]       = intermodes (img);
-    case {"maxlikelihood"}, [level]       = maxlikelihood (img);
-    case {"maxentropy"},    [level]       = maxentropy (img);
-    case {"mean"},          [level]       = mean (img(:));
-    case {"minimum"},       [level]       = minimum (img);
-    case {"minerror"},      [level]       = minerror_iter (img);
-    case {"moments"},       [level]       = moments (img);
-    case {"otsu"},          [level, good] = otsu (img);
-    case {"percentile"},    [level]       = percentile (img, varargin{1});
-    otherwise, error ("graythresh: unknown method '%s'", algo);
-  endswitch
-endfunction
-
-function [level, good] = otsu (img)
-  ## Calculation of the normalized histogram
-  n = double (intmax (class (img))) + 1;
-  h = hist (img(:), 1:n);
-  h = h / (length (img(:)) + 1);
-
-  ## Calculation of the cumulated histogram and the mean values
-  w  = cumsum (h);
-  mu = zeros (n, 1);
-  mu(1) = h(1);
-  for i = 2:n
-
-    mu(i) = mu(i-1) + i * h(i);
-  endfor
-
-  ## Initialisation of the values used for the threshold calculation
-  level = find (h > 0, 1);
-  w0  = w(level);
-  w1  = 1 - w0;
-  mu0 = mu(level) / w0;
-  mu1 = (mu(end) - mu(level)) / w1;
-  good = w0 * w1 * (mu1 - mu0) * (mu1 - mu0);
-
-  ## For each step of the histogram, calculation of the threshold
-  ## and storing of the maximum
-  for i = find (h > 0)
-    w0 = w(i);
-    w1 = 1 - w0;
-    mu0 = mu(i) / w0;
-    mu1 = (mu(end) - mu(i)) / w1;
-    s = w0 * w1 * (mu1 - mu0) * (mu1 - mu0);
-    if (s > good)
-      good  = s;
-      level = i;
-    endif
-  endfor
-
-  ## Normalisation of the threshold
-  level /= n;
-endfunction
-
-#{
-  ##The following is another implementation of Otsu's method from the HistThresh
-  ##toolbox
-  if nargin == 1
-    n = 255;
-  end
-
-  % This algorithm is implemented in the Image Processing Toolbox.
-  %I = uint8(I);
-  %T = n*graythresh(I);
-
-  % The implementation below uses the notations from the paper, but is
-  % significantly slower.
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  warning off MATLAB:divideByZero
-  for j = 0:n
-    mu = partial_sumB(y,j)/partial_sumA(y,j);
-    nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j));
-    vec(j+1) = partial_sumA(y,j)*(partial_sumA(y,n)-partial_sumA(y,j))*(mu-nu)^2;
-  end
-  warning on MATLAB:divideByZero
-
-  [maximum,ind] = max(vec);
-  T = ind-1;
-#}
-
-function level = moments (I, n)
-
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist (I(:), 0:n);
-
-  % The threshold is chosen such that partial_sumA(y,t)/partial_sumA(y,n) is closest to x0.
-  Avec = zeros (1, n+1);
-
-  for t = 0:n
-    Avec(t+1) = partial_sumA (y, t) / partial_sumA (y, n);
-  end
-
-  % The following finds x0.
-  x2 = (partial_sumB(y,n)*partial_sumC(y,n) - partial_sumA(y,n)*partial_sumD(y,n)) / (partial_sumA(y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2);
-  x1 = (partial_sumB(y,n)*partial_sumD(y,n) - partial_sumC(y,n)^2) / (partial_sumA (y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2);
-  x0 = .5 - (partial_sumB(y,n)/partial_sumA(y,n) + x2/2) / sqrt (x2^2 - 4*x1);
-
-  % And finally the threshold.
-  [minimum, ind] = min (abs (Avec-x0));
-  level = ind-1;
-
-  ## Normalisation of the threshold
-  level /= n;
-endfunction
-
-function T = maxentropy(I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  warning off
-  % The threshold is chosen such that the following expression is minimized.
-  for j = 0:n
-    vec(j+1) = negativeE(y,j)/partial_sumA(y,j) - log10(partial_sumA(y,j)) + ...
-        (negativeE(y,n)-negativeE(y,j))/(partial_sumA(y,n)-partial_sumA(y,j)) - log10(partial_sumA(y,n)-partial_sumA(y,j));
-  end
-  warning on
-
-  [minimum,ind] = min(vec);
-  T = ind-1;
-endfunction
-
-function [T] = intermodes (I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % Smooth the histogram by iterative three point mean filtering.
-  iter = 0;
-  while ~bimodtest(y)
-    h = ones(1,3)/3;
-    y = conv2(y,h,'same');
-    iter = iter+1;
-    % If the histogram turns out not to be bimodal, set T to zero.
-    if iter > 10000;
-      T = 0;
-      return
-    end
-  end
-
-  % The threshold is the mean of the two peaks of the histogram.
-  ind = 0;
-  for k = 2:n
-    if y(k-1) < y(k) && y(k+1) < y(k)
-      ind = ind+1;
-      TT(ind) = k-1;
-    end
-  end
-  T = floor(mean(TT));
-endfunction
-
-function [T] = percentile (I, p, n)
-  if nargin == 1
-    p = 0.5;
-    n = 255;
-  elseif nargin == 2
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % The threshold is chosen such that 50% of pixels lie in each category.
-  Avec = zeros(1,n+1);
-  for t = 0:n
-    Avec(t+1) = partial_sumA(y,t)/partial_sumA(y,n);
-  end
-
-  [minimum,ind] = min(abs(Avec-p));
-  T = ind-1;
-endfunction
-
-
-function T = minimum(I,n);
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % Smooth the histogram by iterative three point mean filtering.
-  iter = 0;
-  while ~bimodtest(y)
-    h = ones(1,3)/3;
-    y = conv2(y,h,'same');
-    iter = iter+1;
-    % If the histogram turns out not to be bimodal, set T to zero.
-    if iter > 10000;
-      T = 0;
-      return
-    end
-  end
-
-  % The threshold is the minimum between the two peaks.
-  for k = 2:n
-    if y(k-1) > y(k) && y(k+1) > y(k)
-      T = k-1;
-    end
-  end
-endfunction
-
-function [T] = minerror_iter (I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % The initial estimate for the threshold is found with the MEAN algorithm.
-  T = floor (mean (I, img(:)));
-  Tprev = NaN;
-
-  while T ~= Tprev
-
-    % Calculate some statistics.
-    mu = partial_sumB(y,T)/partial_sumA(y,T);
-    nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
-    p = partial_sumA(y,T)/partial_sumA(y,n);
-    q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n);
-    sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2;
-    tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2;
-
-    % The terms of the quadratic equation to be solved.
-    w0 = 1/sigma2-1/tau2;
-    w1 = mu/sigma2-nu/tau2;
-    w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2));
-
-    % If the next threshold would be imaginary, return with the current one.
-    sqterm = w1^2-w0*w2;
-    if sqterm < 0
-      warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.')
-      return
-    end
-
-    % The updated threshold is the integer part of the solution of the
-    % quadratic equation.
-    Tprev = T;
-    T = floor((w1+sqrt(sqterm))/w0);
-
-    % If the threshold turns out to be NaN, return with the previous threshold.
-    if isnan(T)
-      warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.')
-      T = Tprev;
-    end
-
-  end
-endfunction
-#{
-  ## this was not an implementatino of the original minerror algorithm but seems
-  ## to converg more often than the original. The original is (also from the
-  ## HistThresh toolbox
-  function T = th_minerror(I,n)
-    if nargin == 1
-      n = 255;
-    end
-
-    I = double(I);
-
-    % Calculate the histogram.
-    y = hist(I(:),0:n);
-
-    warning off
-    % The threshold is chosen such that the following expression is minimized.
-    for j = 0:n
-      mu = partial_sumB(y,j)/partial_sumA(y,j);
-      nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j));
-      p = partial_sumA(y,j)/partial_sumA(y,n);
-      q = (partial_sumA(y,n)-partial_sumA(y,j)) / partial_sumA(y,n);
-      sigma2 = partial_sumC(y,j)/partial_sumA(y,j)-mu^2;
-      tau2 = (partial_sumC(y,n)-partial_sumC(y,j)) / (partial_sumA(y,n)-partial_sumA(y,j)) - nu^2;
-      vec(j+1) = p*log10(sqrt(sigma2)/p) + q*log10(sqrt(tau2)/q);
-    end
-    warning on
-
-    vec(vec==-inf) = NaN;
-    [minimum,ind] = min(vec);
-    T = ind-1;
-  endfunction
-#}
-
-function T = maxlikelihood (I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % The initial estimate for the threshold is found with the MINIMUM
-  % algorithm.
-  T = th_minimum(I,n);
-
-  % Calculate initial values for the statistics.
-  mu = partial_sumB(y,T)/partial_sumA(y,T);
-  nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
-  p = partial_sumA(y,T)/partial_sumA(y,n);
-  q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n);
-  sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2;
-  tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2;
-
-  mu_prev = NaN;
-  nu_prev = NaN;
-  p_prev = NaN;
-  q_prev = NaN;
-  sigma2_prev = NaN;
-  tau2_prev = NaN;
-
-  while abs(mu-mu_prev) > eps || abs(nu-nu_prev) > eps || ...
-        abs(p-p_prev) > eps || abs(q-q_prev) > eps || ...
-        abs(sigma2-sigma2_prev) > eps || abs(tau2-tau2_prev) > eps
-    for i = 0:n
-      phi(i+1) = p/q * exp(-((i-mu)^2) / (2*sigma2)) / ...
-          (p/sqrt(sigma2) * exp(-((i-mu)^2) / (2*sigma2)) + ...
-           (q/sqrt(tau2)) * exp(-((i-nu)^2) / (2*tau2)));
-    end
-    ind = 0:n;
-    gamma = 1-phi;
-    F = phi*y';
-    G = gamma*y';
-    p_prev = p;
-    q_prev = q;
-    mu_prev = mu;
-    nu_prev = nu;
-    sigma2_prev = nu;
-    tau2_prev = nu;
-    p = F/partial_sumA(y,n);
-    q = G/partial_sumA(y,n);
-    mu = ind.*phi*y'/F;
-    nu = ind.*gamma*y'/G;
-    sigma2 = ind.^2.*phi*y'/F - mu^2;
-    tau2 = ind.^2.*gamma*y'/G - nu^2;
-  end
-
-  % The terms of the quadratic equation to be solved.
-  w0 = 1/sigma2-1/tau2;
-  w1 = mu/sigma2-nu/tau2;
-  w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2));
-
-  % If the threshold would be imaginary, return with threshold set to zero.
-  sqterm = w1^2-w0*w2;
-  if sqterm < 0;
-    T = 0;
-    return
-  end
-
-  % The threshold is the integer part of the solution of the quadratic
-  % equation.
-  T = floor((w1+sqrt(sqterm))/w0);
-endfunction
-
-function T = intermeans (I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram.
-  y = hist(I(:),0:n);
-
-  % The initial estimate for the threshold is found with the MEAN algorithm.
-  T = floor (mean (I, img(:)));
-  Tprev = NaN;
-
-  % The threshold is found iteratively. In each iteration, the means of the
-  % pixels below (mu) the threshold and above (nu) it are found. The
-  % updated threshold is the mean of mu and nu.
-  while T ~= Tprev
-    mu = partial_sumB(y,T)/partial_sumA(y,T);
-    nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
-    Tprev = T;
-    T = floor((mu+nu)/2);
-  end
-endfunction
-
-function T = concavity (I,n)
-  if nargin == 1
-    n = 255;
-  end
-
-  I = double(I);
-
-  % Calculate the histogram and its convex hull.
-  h = hist(I(:),0:n);
-  H = hconvhull(h);
-
-  % Find the local maxima of the difference H-h.
-  lmax = flocmax(H-h);
-
-  % Find the histogram balance around each index.
-  for k = 0:n
-    E(k+1) = hbalance(h,k);
-  end
-
-  % The threshold is the local maximum with highest balance.
-  E = E.*lmax;
-  [dummy ind] = max(E);
-  T = ind-1;
-endfunction
-
-################################################################################
-## Auxiliary functions from HistThresh toolbox http://www.cs.tut.fi/~ant/histthresh/
-################################################################################
-
-## partial sums from C. A. Glasbey, "An analysis of histogram-based thresholding
-## algorithms," CVGIP: Graphical Models and Image Processing, vol. 55, pp. 532-537, 1993.
-function x = partial_sumA (y, j)
-  x = sum (y(1:j+1));
-endfunction
-function x = partial_sumB (y, j)
-  ind = 0:j;
-  x   = ind*y(1:j+1)';
-endfunction
-function x = partial_sumC (y, j)
-  ind = 0:j;
-  x = ind.^2*y(1:j+1)';
-endfunction
-function x = partial_sumD (y, j)
-  ind = 0:j;
-  x = ind.^3*y(1:j+1)';
-endfunction
-
-## Test if a histogram is bimodal.
-function b = bimodtest(y)
-  len = length(y);
-  b = false;
-  modes = 0;
-
-  % Count the number of modes of the histogram in a loop. If the number
-  % exceeds 2, return with boolean return value false.
-  for k = 2:len-1
-    if y(k-1) < y(k) && y(k+1) < y(k)
-      modes = modes+1;
-      if modes > 2
-        return
-      end
-    end
-  end
-
-  % The number of modes could be less than two here
-  if modes == 2
-    b = true;
-  end
-endfunction
-
-## Find the local maxima of a vector using a three point neighborhood.
-function y = flocmax(x)
-%  y    binary vector with maxima of x marked as ones
-
-  len = length(x);
-  y = zeros(1,len);
-
-  for k = 2:len-1
-    [dummy,ind] = max(x(k-1:k+1));
-    if ind == 2
-      y(k) = 1;
-    end
-  end
-endfunction
-
-## Calculate the balance measure of the histogram around a histogram index.
-function E = hbalance(y,ind)
-%  y    histogram
-%  ind  index about which balance is calculated
-%
-% Out:
-%  E    balance measure
-%
-% References:
-%
-% A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid
-% in threhold selection," IEEE Transactions on Systems, Man, and
-% Cybernetics, vol. 13, pp. 231-235, 1983.
-%
-% P. K. Sahoo, S. Soltani, and A. K. C. Wong, "A survey of thresholding
-% techniques," Computer Vision, Graphics, and Image Processing, vol. 41,
-% pp. 233-260, 1988.
-
-  n = length(y)-1;
-  E = partial_sumA(y,ind)*(partial_sumA(y,n)-partial_sumA(y,ind));
-endfunction
-
-## Find the convex hull of a histogram.
-function H = hconvhull(h)
-  % In:
-  %  h    histogram
-  %
-  % Out:
-  %  H    convex hull of histogram
-  %
-  % References:
-  %
-  % A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid
-  % in threhold selection," IEEE Transactions on Systems, Man, and
-  % Cybernetics, vol. 13, pp. 231-235, 1983.
-
-  len = length(h);
-  K(1) = 1;
-  k = 1;
-
-  % The vector K gives the locations of the vertices of the convex hull.
-  while K(k)~=len
-
-    theta = zeros(1,len-K(k));
-    for i = K(k)+1:len
-      x = i-K(k);
-      y = h(i)-h(K(k));
-      theta(i-K(k)) = atan2(y,x);
-    end
-
-    maximum = max(theta);
-    maxloc = find(theta==maximum);
-    k = k+1;
-    K(k) = maxloc(end)+K(k-1);
-
-  end
-
-  % Form the convex hull.
-  H = zeros(1,len);
-  for i = 2:length(K)
-    H(K(i-1):K(i)) = h(K(i-1))+(h(K(i))-h(K(i-1)))/(K(i)-K(i-1))*(0:K(i)-K(i-1));
-  end
-endfunction
-
-## Entroy function. Note that the function returns the negative of entropy.
-function x = negativeE(y,j)
-  ## used by the maxentropy method only
-  y = y(1:j+1);
-  y = y(y~=0);
-  x = sum(y.*log10(y));
-endfunction
+## Copyright (C) 2004 Antti Niemistö <antti.niemisto@tut.fi>
+## Copyright (C) 2005 Barre-Piquot
+## Copyright (C) 2007 Søren Hauberg
+## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img})
+## @deftypefnx {Function File} {[@var{level}, @var{sep}] =} graythresh (@var{img}, @var{algo})
+## @deftypefnx {Function File} {[@var{level}] =} graythresh (@var{img}, "percentile", @var{fraction})
+## Compute global image threshold.
+##
+## Given an image @var{img} finds the optimal threshold value @var{level} for
+## conversion to a binary image with @code{im2bw}. Color images are converted
+## to grayscale before @var{level} is computed.
+##
+## The optional argument @var{method} is the algorithm to be used (default's to
+## Otsu). The available algorithms are:
+##
+## @table @asis
+## @item Otsu (default)
+## Implements Otsu's method as described in @cite{Nobuyuki Otsu (1979). "A
+## threshold selection method from gray-level histograms", IEEE Trans. Sys.,
+## Man., Cyber. 9 (1): 62-66}. This algorithm chooses the threshold to minimize
+## the intraclass variance of the black and white pixels. The second output,
+## @var{sep} represents the ``goodness'' (or separability) of the threshold at
+## @var{level}.
+##
+## @item concavity
+## Find a global threshold for a grayscale image by choosing the threshold to
+## be in the shoulder of the histogram @cite{A. Rosenfeld, and P. De La Torre
+## (1983). "Histogram concavity analysis as an aid in threshold selection", IEEE
+## Transactions on Systems, Man, and Cybernetics, 13: 231-235}.
+##
+## @item Huang
+## Not yet implemented.
+##
+## @item ImageJ
+## A variation of the intermeans algorithm, this is the default for ImageJ.
+## Not yet implemented.
+##
+## @item intermodes
+## This assumes a bimodal histogram and chooses the threshold to be the mean of
+## the two peaks of the bimodal histogram @cite{J. M. S. Prewitt, and M. L.
+## Mendelsohn (1966). "The analysis of cell images", Annals of the New York
+## Academy of Sciences, 128: 1035-1053}.
+##
+## Images with histograms having extremely unequal peaks or a broad and flat
+## valley are unsuitable for this method.
+##
+## @item intermeans
+## Iterative procedure based on the iterative intermeans algorithm of @cite{T.
+## Ridler, and S. Calvard (1978). "Picture thresholding using an iterative
+## selection method", IEEE Transactions on Systems, Man, and Cybernetics, 8: 630-632}
+## and @cite{H. J. Trussell (1979). "Comments on 'Picture thresholding using an
+## iterative selection method'", IEEE Transactions on Systems, Man, and Cybernetics,
+## 9: 311}.
+##
+## Note that several implementations of this method exist. See the source code
+## for details.
+##
+## @item Li
+## Not yet implemented.
+##
+## @item MaxEntropy
+## Implements Kapur-Sahoo-Wong (Maximum Entropy) thresholding method based on the
+## entropy of the image histogram @cite{J. N. Kapur, P. K. Sahoo, and A. C. K. Wong
+## (1985). "A new method for gray-level picture thresholding using the entropy
+## of the histogram", Graphical Models and Image Processing, 29(3): 273-285}.
+##
+## @item MaxLikelihood
+## Find a global threshold for a grayscale image using the maximum likelihood
+## via expectation maximization method @cite{A. P. Dempster, N. M. Laird, and D. B.
+## Rubin (1977). "Maximum likelihood from incomplete data via the EM algorithm",
+## Journal of the Royal Statistical Society, Series B, 39:1-38}.
+##
+## @item mean
+## The mean intensity value. It is mostly used by other methods as a first guess
+## threshold.
+##
+## @item MinError
+## An iterative implementation of Kittler and Illingworth's Minimum Error
+## thresholding @cite{J. Kittler, and J. Illingworth (1986). "Minimum error
+## thresholding", Pattern recognition, 19: 41-47}.
+##
+## This implementation seems to converge more often than the original.
+## Nevertheless, sometimes the algorithm does not converge to a solution. In
+## that case a warning is displayed and defaults to the initial estimate of the
+## mean method.
+##
+## @item minimum
+## This assumes a bimodal histogram and chooses the threshold to be in the
+## valley of the bimodal histogram.  This method is also known as the mode
+## method @cite{J. M. S. Prewitt, and M. L. Mendelsohn (1966). "The analysis of
+## cell images", Annals of the New York Academy of Sciences, 128: 1035-1053}.
+##
+## Images with histograms having extremely unequal peaks or a broad and flat
+## valley are unsuitable for this method.
+##
+## @item moments
+## Find a global threshold for a grayscale image using moment preserving
+## thresholding method @cite{W. Tsai (1985). "Moment-preserving thresholding:
+## a new approach", Computer Vision, Graphics, and Image Processing, 29: 377-393}
+##
+## @item percentile
+## Assumes a specific @var{fraction} of pixels to be background.  If no value is
+## given, assumes a value of 0.5 (equal distribution of background and foreground)
+## @cite{W Doyle (1962). "Operation useful for similarity-invariant pattern
+## recognition", Journal of the Association for Computing Machinery 9: 259-267}
+##
+## @item RenyiEntropy
+## Not yet implemented.
+##
+## @item Shanbhag
+## Not yet implemented.
+##
+## @item triangle
+## Not yet implemented.
+##
+## @item Yen
+## Not yet implemented.
+## @end table
+##
+## @seealso{im2bw}
+## @end deftypefn
+
+## Notes:
+##  * Otsu's method is a function taken from
+##    http://www.irit.fr/~Philippe.Joly/Teaching/M2IRR/IRR05/ Søren Hauberg
+##    added texinfo documentation, error checking and sanitised the code.
+##  * The following methods were adapted from http://www.cs.tut.fi/~ant/histthresh/
+##      intermodes    percentile      minimum
+##      MaxEntropy    MaxLikelihood   intermeans
+##      moments       minerror        concavity
+
+
+function [level, good] = graythresh (img, algo = "otsu", varargin)
+  ## Input checking
+  if (nargin < 1 || nargin > 3)
+    print_usage();
+  elseif (nargin > 2 && !any (strcmpi (varargin{1}, {"percentile"})))
+    error ("graythresh: algorithm `%s' does not accept any options.", algo);
+  elseif (!isgray (img) && !isrgb (img))
+    error ("graythresh: input must be an image");
+  endif
+
+  ## If the image is RGB convert it to grayscale
+  if (isrgb (img))
+    img = rgb2gray (img);
+  endif
+
+  switch tolower (algo)
+    case {"concavity"},     [level]       = concavity (img);
+    case {"intermeans"},    [level]       = intermeans (img);
+    case {"intermodes"},    [level]       = intermodes (img);
+    case {"maxlikelihood"}, [level]       = maxlikelihood (img);
+    case {"maxentropy"},    [level]       = maxentropy (img);
+    case {"mean"},          [level]       = mean (img(:));
+    case {"minimum"},       [level]       = minimum (img);
+    case {"minerror"},      [level]       = minerror_iter (img);
+    case {"moments"},       [level]       = moments (img);
+    case {"otsu"},          [level, good] = otsu (img);
+    case {"percentile"},    [level]       = percentile (img, varargin{1});
+    otherwise, error ("graythresh: unknown method '%s'", algo);
+  endswitch
+endfunction
+
+function [level, good] = otsu (img)
+  ## Calculation of the normalized histogram
+  n = double (intmax (class (img))) + 1;
+  h = hist (img(:), 1:n);
+  h = h / (length (img(:)) + 1);
+
+  ## Calculation of the cumulated histogram and the mean values
+  w  = cumsum (h);
+  mu = zeros (n, 1);
+  mu(1) = h(1);
+  for i = 2:n
+
+    mu(i) = mu(i-1) + i * h(i);
+  endfor
+
+  ## Initialisation of the values used for the threshold calculation
+  level = find (h > 0, 1);
+  w0  = w(level);
+  w1  = 1 - w0;
+  mu0 = mu(level) / w0;
+  mu1 = (mu(end) - mu(level)) / w1;
+  good = w0 * w1 * (mu1 - mu0) * (mu1 - mu0);
+
+  ## For each step of the histogram, calculation of the threshold
+  ## and storing of the maximum
+  for i = find (h > 0)
+    w0 = w(i);
+    w1 = 1 - w0;
+    mu0 = mu(i) / w0;
+    mu1 = (mu(end) - mu(i)) / w1;
+    s = w0 * w1 * (mu1 - mu0) * (mu1 - mu0);
+    if (s > good)
+      good  = s;
+      level = i;
+    endif
+  endfor
+
+  ## Normalisation of the threshold
+  level /= n;
+endfunction
+
+#{
+  ##The following is another implementation of Otsu's method from the HistThresh
+  ##toolbox
+  if nargin == 1
+    n = 255;
+  end
+
+  % This algorithm is implemented in the Image Processing Toolbox.
+  %I = uint8(I);
+  %T = n*graythresh(I);
+
+  % The implementation below uses the notations from the paper, but is
+  % significantly slower.
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  warning off MATLAB:divideByZero
+  for j = 0:n
+    mu = partial_sumB(y,j)/partial_sumA(y,j);
+    nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j));
+    vec(j+1) = partial_sumA(y,j)*(partial_sumA(y,n)-partial_sumA(y,j))*(mu-nu)^2;
+  end
+  warning on MATLAB:divideByZero
+
+  [maximum,ind] = max(vec);
+  T = ind-1;
+#}
+
+function level = moments (I, n)
+
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist (I(:), 0:n);
+
+  % The threshold is chosen such that partial_sumA(y,t)/partial_sumA(y,n) is closest to x0.
+  Avec = zeros (1, n+1);
+
+  for t = 0:n
+    Avec(t+1) = partial_sumA (y, t) / partial_sumA (y, n);
+  end
+
+  % The following finds x0.
+  x2 = (partial_sumB(y,n)*partial_sumC(y,n) - partial_sumA(y,n)*partial_sumD(y,n)) / (partial_sumA(y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2);
+  x1 = (partial_sumB(y,n)*partial_sumD(y,n) - partial_sumC(y,n)^2) / (partial_sumA (y,n)*partial_sumC(y,n) - partial_sumB(y,n)^2);
+  x0 = .5 - (partial_sumB(y,n)/partial_sumA(y,n) + x2/2) / sqrt (x2^2 - 4*x1);
+
+  % And finally the threshold.
+  [minimum, ind] = min (abs (Avec-x0));
+  level = ind-1;
+
+  ## Normalisation of the threshold
+  level /= n;
+endfunction
+
+function T = maxentropy(I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  warning off
+  % The threshold is chosen such that the following expression is minimized.
+  for j = 0:n
+    vec(j+1) = negativeE(y,j)/partial_sumA(y,j) - log10(partial_sumA(y,j)) + ...
+        (negativeE(y,n)-negativeE(y,j))/(partial_sumA(y,n)-partial_sumA(y,j)) - log10(partial_sumA(y,n)-partial_sumA(y,j));
+  end
+  warning on
+
+  [minimum,ind] = min(vec);
+  T = ind-1;
+endfunction
+
+function [T] = intermodes (I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % Smooth the histogram by iterative three point mean filtering.
+  iter = 0;
+  while ~bimodtest(y)
+    h = ones(1,3)/3;
+    y = conv2(y,h,'same');
+    iter = iter+1;
+    % If the histogram turns out not to be bimodal, set T to zero.
+    if iter > 10000;
+      T = 0;
+      return
+    end
+  end
+
+  % The threshold is the mean of the two peaks of the histogram.
+  ind = 0;
+  for k = 2:n
+    if y(k-1) < y(k) && y(k+1) < y(k)
+      ind = ind+1;
+      TT(ind) = k-1;
+    end
+  end
+  T = floor(mean(TT));
+endfunction
+
+function [T] = percentile (I, p, n)
+  if nargin == 1
+    p = 0.5;
+    n = 255;
+  elseif nargin == 2
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % The threshold is chosen such that 50% of pixels lie in each category.
+  Avec = zeros(1,n+1);
+  for t = 0:n
+    Avec(t+1) = partial_sumA(y,t)/partial_sumA(y,n);
+  end
+
+  [minimum,ind] = min(abs(Avec-p));
+  T = ind-1;
+endfunction
+
+
+function T = minimum(I,n);
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % Smooth the histogram by iterative three point mean filtering.
+  iter = 0;
+  while ~bimodtest(y)
+    h = ones(1,3)/3;
+    y = conv2(y,h,'same');
+    iter = iter+1;
+    % If the histogram turns out not to be bimodal, set T to zero.
+    if iter > 10000;
+      T = 0;
+      return
+    end
+  end
+
+  % The threshold is the minimum between the two peaks.
+  for k = 2:n
+    if y(k-1) > y(k) && y(k+1) > y(k)
+      T = k-1;
+    end
+  end
+endfunction
+
+function [T] = minerror_iter (I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % The initial estimate for the threshold is found with the MEAN algorithm.
+  T = floor (mean (I, img(:)));
+  Tprev = NaN;
+
+  while T ~= Tprev
+
+    % Calculate some statistics.
+    mu = partial_sumB(y,T)/partial_sumA(y,T);
+    nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
+    p = partial_sumA(y,T)/partial_sumA(y,n);
+    q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n);
+    sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2;
+    tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2;
+
+    % The terms of the quadratic equation to be solved.
+    w0 = 1/sigma2-1/tau2;
+    w1 = mu/sigma2-nu/tau2;
+    w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2));
+
+    % If the next threshold would be imaginary, return with the current one.
+    sqterm = w1^2-w0*w2;
+    if sqterm < 0
+      warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.')
+      return
+    end
+
+    % The updated threshold is the integer part of the solution of the
+    % quadratic equation.
+    Tprev = T;
+    T = floor((w1+sqrt(sqterm))/w0);
+
+    % If the threshold turns out to be NaN, return with the previous threshold.
+    if isnan(T)
+      warning('MINERROR:NaN','Warning: th_minerror_iter did not converge.')
+      T = Tprev;
+    end
+
+  end
+endfunction
+#{
+  ## this was not an implementatino of the original minerror algorithm but seems
+  ## to converg more often than the original. The original is (also from the
+  ## HistThresh toolbox
+  function T = th_minerror(I,n)
+    if nargin == 1
+      n = 255;
+    end
+
+    I = double(I);
+
+    % Calculate the histogram.
+    y = hist(I(:),0:n);
+
+    warning off
+    % The threshold is chosen such that the following expression is minimized.
+    for j = 0:n
+      mu = partial_sumB(y,j)/partial_sumA(y,j);
+      nu = (partial_sumB(y,n)-partial_sumB(y,j))/(partial_sumA(y,n)-partial_sumA(y,j));
+      p = partial_sumA(y,j)/partial_sumA(y,n);
+      q = (partial_sumA(y,n)-partial_sumA(y,j)) / partial_sumA(y,n);
+      sigma2 = partial_sumC(y,j)/partial_sumA(y,j)-mu^2;
+      tau2 = (partial_sumC(y,n)-partial_sumC(y,j)) / (partial_sumA(y,n)-partial_sumA(y,j)) - nu^2;
+      vec(j+1) = p*log10(sqrt(sigma2)/p) + q*log10(sqrt(tau2)/q);
+    end
+    warning on
+
+    vec(vec==-inf) = NaN;
+    [minimum,ind] = min(vec);
+    T = ind-1;
+  endfunction
+#}
+
+function T = maxlikelihood (I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % The initial estimate for the threshold is found with the MINIMUM
+  % algorithm.
+  T = th_minimum(I,n);
+
+  % Calculate initial values for the statistics.
+  mu = partial_sumB(y,T)/partial_sumA(y,T);
+  nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
+  p = partial_sumA(y,T)/partial_sumA(y,n);
+  q = (partial_sumA(y,n)-partial_sumA(y,T)) / partial_sumA(y,n);
+  sigma2 = partial_sumC(y,T)/partial_sumA(y,T)-mu^2;
+  tau2 = (partial_sumC(y,n)-partial_sumC(y,T)) / (partial_sumA(y,n)-partial_sumA(y,T)) - nu^2;
+
+  mu_prev = NaN;
+  nu_prev = NaN;
+  p_prev = NaN;
+  q_prev = NaN;
+  sigma2_prev = NaN;
+  tau2_prev = NaN;
+
+  while abs(mu-mu_prev) > eps || abs(nu-nu_prev) > eps || ...
+        abs(p-p_prev) > eps || abs(q-q_prev) > eps || ...
+        abs(sigma2-sigma2_prev) > eps || abs(tau2-tau2_prev) > eps
+    for i = 0:n
+      phi(i+1) = p/q * exp(-((i-mu)^2) / (2*sigma2)) / ...
+          (p/sqrt(sigma2) * exp(-((i-mu)^2) / (2*sigma2)) + ...
+           (q/sqrt(tau2)) * exp(-((i-nu)^2) / (2*tau2)));
+    end
+    ind = 0:n;
+    gamma = 1-phi;
+    F = phi*y';
+    G = gamma*y';
+    p_prev = p;
+    q_prev = q;
+    mu_prev = mu;
+    nu_prev = nu;
+    sigma2_prev = nu;
+    tau2_prev = nu;
+    p = F/partial_sumA(y,n);
+    q = G/partial_sumA(y,n);
+    mu = ind.*phi*y'/F;
+    nu = ind.*gamma*y'/G;
+    sigma2 = ind.^2.*phi*y'/F - mu^2;
+    tau2 = ind.^2.*gamma*y'/G - nu^2;
+  end
+
+  % The terms of the quadratic equation to be solved.
+  w0 = 1/sigma2-1/tau2;
+  w1 = mu/sigma2-nu/tau2;
+  w2 = mu^2/sigma2 - nu^2/tau2 + log10((sigma2*q^2)/(tau2*p^2));
+
+  % If the threshold would be imaginary, return with threshold set to zero.
+  sqterm = w1^2-w0*w2;
+  if sqterm < 0;
+    T = 0;
+    return
+  end
+
+  % The threshold is the integer part of the solution of the quadratic
+  % equation.
+  T = floor((w1+sqrt(sqterm))/w0);
+endfunction
+
+function T = intermeans (I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram.
+  y = hist(I(:),0:n);
+
+  % The initial estimate for the threshold is found with the MEAN algorithm.
+  T = floor (mean (I, img(:)));
+  Tprev = NaN;
+
+  % The threshold is found iteratively. In each iteration, the means of the
+  % pixels below (mu) the threshold and above (nu) it are found. The
+  % updated threshold is the mean of mu and nu.
+  while T ~= Tprev
+    mu = partial_sumB(y,T)/partial_sumA(y,T);
+    nu = (partial_sumB(y,n)-partial_sumB(y,T))/(partial_sumA(y,n)-partial_sumA(y,T));
+    Tprev = T;
+    T = floor((mu+nu)/2);
+  end
+endfunction
+
+function T = concavity (I,n)
+  if nargin == 1
+    n = 255;
+  end
+
+  I = double(I);
+
+  % Calculate the histogram and its convex hull.
+  h = hist(I(:),0:n);
+  H = hconvhull(h);
+
+  % Find the local maxima of the difference H-h.
+  lmax = flocmax(H-h);
+
+  % Find the histogram balance around each index.
+  for k = 0:n
+    E(k+1) = hbalance(h,k);
+  end
+
+  % The threshold is the local maximum with highest balance.
+  E = E.*lmax;
+  [dummy ind] = max(E);
+  T = ind-1;
+endfunction
+
+################################################################################
+## Auxiliary functions from HistThresh toolbox http://www.cs.tut.fi/~ant/histthresh/
+################################################################################
+
+## partial sums from C. A. Glasbey, "An analysis of histogram-based thresholding
+## algorithms," CVGIP: Graphical Models and Image Processing, vol. 55, pp. 532-537, 1993.
+function x = partial_sumA (y, j)
+  x = sum (y(1:j+1));
+endfunction
+function x = partial_sumB (y, j)
+  ind = 0:j;
+  x   = ind*y(1:j+1)';
+endfunction
+function x = partial_sumC (y, j)
+  ind = 0:j;
+  x = ind.^2*y(1:j+1)';
+endfunction
+function x = partial_sumD (y, j)
+  ind = 0:j;
+  x = ind.^3*y(1:j+1)';
+endfunction
+
+## Test if a histogram is bimodal.
+function b = bimodtest(y)
+  len = length(y);
+  b = false;
+  modes = 0;
+
+  % Count the number of modes of the histogram in a loop. If the number
+  % exceeds 2, return with boolean return value false.
+  for k = 2:len-1
+    if y(k-1) < y(k) && y(k+1) < y(k)
+      modes = modes+1;
+      if modes > 2
+        return
+      end
+    end
+  end
+
+  % The number of modes could be less than two here
+  if modes == 2
+    b = true;
+  end
+endfunction
+
+## Find the local maxima of a vector using a three point neighborhood.
+function y = flocmax(x)
+%  y    binary vector with maxima of x marked as ones
+
+  len = length(x);
+  y = zeros(1,len);
+
+  for k = 2:len-1
+    [dummy,ind] = max(x(k-1:k+1));
+    if ind == 2
+      y(k) = 1;
+    end
+  end
+endfunction
+
+## Calculate the balance measure of the histogram around a histogram index.
+function E = hbalance(y,ind)
+%  y    histogram
+%  ind  index about which balance is calculated
+%
+% Out:
+%  E    balance measure
+%
+% References:
+%
+% A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid
+% in threhold selection," IEEE Transactions on Systems, Man, and
+% Cybernetics, vol. 13, pp. 231-235, 1983.
+%
+% P. K. Sahoo, S. Soltani, and A. K. C. Wong, "A survey of thresholding
+% techniques," Computer Vision, Graphics, and Image Processing, vol. 41,
+% pp. 233-260, 1988.
+
+  n = length(y)-1;
+  E = partial_sumA(y,ind)*(partial_sumA(y,n)-partial_sumA(y,ind));
+endfunction
+
+## Find the convex hull of a histogram.
+function H = hconvhull(h)
+  % In:
+  %  h    histogram
+  %
+  % Out:
+  %  H    convex hull of histogram
+  %
+  % References:
+  %
+  % A. Rosenfeld and P. De La Torre, "Histogram concavity analysis as an aid
+  % in threhold selection," IEEE Transactions on Systems, Man, and
+  % Cybernetics, vol. 13, pp. 231-235, 1983.
+
+  len = length(h);
+  K(1) = 1;
+  k = 1;
+
+  % The vector K gives the locations of the vertices of the convex hull.
+  while K(k)~=len
+
+    theta = zeros(1,len-K(k));
+    for i = K(k)+1:len
+      x = i-K(k);
+      y = h(i)-h(K(k));
+      theta(i-K(k)) = atan2(y,x);
+    end
+
+    maximum = max(theta);
+    maxloc = find(theta==maximum);
+    k = k+1;
+    K(k) = maxloc(end)+K(k-1);
+
+  end
+
+  % Form the convex hull.
+  H = zeros(1,len);
+  for i = 2:length(K)
+    H(K(i-1):K(i)) = h(K(i-1))+(h(K(i))-h(K(i-1)))/(K(i)-K(i-1))*(0:K(i)-K(i-1));
+  end
+endfunction
+
+## Entroy function. Note that the function returns the negative of entropy.
+function x = negativeE(y,j)
+  ## used by the maxentropy method only
+  y = y(1:j+1);
+  y = y(y~=0);
+  x = sum(y.*log10(y));
+endfunction
--- a/main/image/inst/imbothat.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imbothat.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,55 +1,55 @@
-## Copyright (C) 2005  Carvalho-Mariel
-## Copyright (C) 2010-2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{B} = imbothat (@var{A}, @var{se})
-## Perform morphological bottom hat filtering.
-##
-## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
-## structuring element. Both must have the same class, e.g., if @var{A} is a
-## logical matrix, @var{se} must also be logical.
-##
-## A bottom-hat transform is also known as 'black', or 'closing', top-hat
-## transform.
-##
-## @seealso{imerode, imdilate, imopen, imclose, imtophat, mmgradm}
-## @end deftypefn
-
-function retval = imbothat (im, se)
-
-  ## Checkinput
-  if (nargin != 2)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imbothat: first input argument must be a real matrix");
-  elseif (!ismatrix(se) || !isreal(se))
-    error("imbothat: second input argument must be a real matrix");
-  elseif ( !strcmp(class(im), class(se)) )
-    error("imbothat: image and structuring element must have the same class");
-  endif
-
-  ## Perform filtering
-  ## Note that in case that the transform is to applied to a logical image,
-  ## subtraction must be handled in a different way (x & !y) instead of (x - y)
-  ## or it will return a double precision matrix
-  if (islogical(im))
-    retval = imclose(im, se) & !im;
-  else
-    retval = imclose(im, se) - im;
-  endif
-
-endfunction
+## Copyright (C) 2005  Carvalho-Mariel
+## Copyright (C) 2010-2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{B} = imbothat (@var{A}, @var{se})
+## Perform morphological bottom hat filtering.
+##
+## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
+## structuring element. Both must have the same class, e.g., if @var{A} is a
+## logical matrix, @var{se} must also be logical.
+##
+## A bottom-hat transform is also known as 'black', or 'closing', top-hat
+## transform.
+##
+## @seealso{imerode, imdilate, imopen, imclose, imtophat, mmgradm}
+## @end deftypefn
+
+function retval = imbothat (im, se)
+
+  ## Checkinput
+  if (nargin != 2)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imbothat: first input argument must be a real matrix");
+  elseif (!ismatrix(se) || !isreal(se))
+    error("imbothat: second input argument must be a real matrix");
+  elseif ( !strcmp(class(im), class(se)) )
+    error("imbothat: image and structuring element must have the same class");
+  endif
+
+  ## Perform filtering
+  ## Note that in case that the transform is to applied to a logical image,
+  ## subtraction must be handled in a different way (x & !y) instead of (x - y)
+  ## or it will return a double precision matrix
+  if (islogical(im))
+    retval = imclose(im, se) & !im;
+  else
+    retval = imclose(im, se) - im;
+  endif
+
+endfunction
--- a/main/image/inst/imclose.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imclose.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,44 +1,44 @@
-## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
-##
-## 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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{B} = imclose (@var{A}, @var{se})
-## Perform morphological closing on a given image.
-## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
-## structuring element.
-##
-## The closing corresponds to a dilation followed by an erosion of the image, i.e.
-## @example
-## B = imerode(imdilate(A, se), se);
-## @end example
-## @seealso{imdilate, imerode, imclose}
-## @end deftypefn
-
-function retval = imclose (im, se)
-  ## Checkinput
-  if (nargin != 2)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imclose: first input argument must be a real matrix");
-  endif
-  if (!ismatrix(se) || !isreal(se))
-    error("imclose: second input argument must be a real matrix");
-  endif
-  
-  ## Perform filtering
-  retval = imerode(imdilate(im, se), se);
-
-endfunction
+## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
+##
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{B} = imclose (@var{A}, @var{se})
+## Perform morphological closing on a given image.
+## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
+## structuring element.
+##
+## The closing corresponds to a dilation followed by an erosion of the image, i.e.
+## @example
+## B = imerode(imdilate(A, se), se);
+## @end example
+## @seealso{imdilate, imerode, imclose}
+## @end deftypefn
+
+function retval = imclose (im, se)
+  ## Checkinput
+  if (nargin != 2)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imclose: first input argument must be a real matrix");
+  endif
+  if (!ismatrix(se) || !isreal(se))
+    error("imclose: second input argument must be a real matrix");
+  endif
+  
+  ## Perform filtering
+  retval = imerode(imdilate(im, se), se);
+
+endfunction
--- a/main/image/inst/imdilate.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imdilate.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,69 +1,69 @@
-## Copyright (C) 2004 Josep Mones i Teixidor <jmones@puntbarra.com>
-## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
-## Copyright (C) 2010 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{B} =} imdilate (@var{A}, @var{se})
-## Perform morphological dilation on a given image.
-##
-## The image @var{A} must be a grayscale or binary image, and @var{se} a
-## structuring element. Both must have the same class, e.g., if @var{A} is a
-## logical matrix, @var{se} must also be logical. Note that the erosion
-## algorithm is different for each class, being much faster for logical
-## matrices. As such, if you have a binary matrix, you should use @code{logical}
-## first. This will also reduce the memory usage of your code.
-##
-## The center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
-##
-## Pixels outside the image are considered to be 0.
-##
-## @seealso{imerode, imopen, imclose}
-## @end deftypefn
-
-function retval = imdilate(im, se)
-  ## Checkinput
-  if (nargin != 2)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imdilate: first input argument must be a real matrix");
-  elseif (!ismatrix(se) || !isreal(se))
-    error("imdilate: second input argument must be a real matrix");
-  elseif ( !strcmp(class(im), class(se)) )
-    error("imdilate: image and structuring element must have the same class");
-  endif
-
-  ## Perform filtering
-  ## Filtering must be done with the reflection of the structuring element (they
-  ## are not always symmetrical)
-  se      = imrotate(se, 180);
-
-  ## If image is binary/logical, try to use filter2 (much faster)
-  if (islogical(im))
-    retval  = filter2(se,im)>0;
-  else
-    retval  = ordfiltn(im, sum(se(:)!=0), se, 0);
-  endif
-
-endfunction
-
-%!demo
-%! imdilate(eye(5),ones(2,2))
-%! % returns a thick diagonal.
-
-%!assert(imdilate(eye(3),[1])==eye(3));                     # using [1] as a mask returns the same value
-%!assert(imdilate(eye(3),[1,0,0])==[0,0,0;1,0,0;0,1,0]);    # check if it works with non-symmetric SE
-%!assert(imdilate(eye(5),[1,0,0,0])==[0,0,0,0,0;1,0,0,0,0;0,1,0,0,0;0,0,1,0,0;0,0,0,1,0]); # test if center is correctly calculated on even masks
+## Copyright (C) 2004 Josep Mones i Teixidor <jmones@puntbarra.com>
+## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
+## Copyright (C) 2010 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{B} =} imdilate (@var{A}, @var{se})
+## Perform morphological dilation on a given image.
+##
+## The image @var{A} must be a grayscale or binary image, and @var{se} a
+## structuring element. Both must have the same class, e.g., if @var{A} is a
+## logical matrix, @var{se} must also be logical. Note that the erosion
+## algorithm is different for each class, being much faster for logical
+## matrices. As such, if you have a binary matrix, you should use @code{logical}
+## first. This will also reduce the memory usage of your code.
+##
+## The center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
+##
+## Pixels outside the image are considered to be 0.
+##
+## @seealso{imerode, imopen, imclose}
+## @end deftypefn
+
+function retval = imdilate(im, se)
+  ## Checkinput
+  if (nargin != 2)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imdilate: first input argument must be a real matrix");
+  elseif (!ismatrix(se) || !isreal(se))
+    error("imdilate: second input argument must be a real matrix");
+  elseif ( !strcmp(class(im), class(se)) )
+    error("imdilate: image and structuring element must have the same class");
+  endif
+
+  ## Perform filtering
+  ## Filtering must be done with the reflection of the structuring element (they
+  ## are not always symmetrical)
+  se      = imrotate(se, 180);
+
+  ## If image is binary/logical, try to use filter2 (much faster)
+  if (islogical(im))
+    retval  = filter2(se,im)>0;
+  else
+    retval  = ordfiltn(im, sum(se(:)!=0), se, 0);
+  endif
+
+endfunction
+
+%!demo
+%! imdilate(eye(5),ones(2,2))
+%! % returns a thick diagonal.
+
+%!assert(imdilate(eye(3),[1])==eye(3));                     # using [1] as a mask returns the same value
+%!assert(imdilate(eye(3),[1,0,0])==[0,0,0;1,0,0;0,1,0]);    # check if it works with non-symmetric SE
+%!assert(imdilate(eye(5),[1,0,0,0])==[0,0,0,0,0;1,0,0,0,0;0,1,0,0,0;0,0,1,0,0;0,0,0,1,0]); # test if center is correctly calculated on even masks
--- a/main/image/inst/imerode.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imerode.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,65 +1,65 @@
-## Copyright (C) 2004 Josep Mones i Teixidor <jmones@puntbarra.com>
-## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
-## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{B} =} imerode (@var{A}, @var{se})
-## Perform morphological erosion on a given image.
-##
-## The image @var{A} must be a grayscale or binary image, and @var{se} a
-## structuring element. Both must have the same class, e.g., if @var{A} is a
-## logical matrix, @var{se} must also be logical. Note that the erosion
-## algorithm is different for each class, being much faster for logical
-## matrices. As such, if you have a binary matrix, you should use @code{logical}
-## first. This will also reduce the memory usage of your code.
-##
-## The center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
-##
-## Pixels outside the image are considered to be 0.
-##
-## @seealso{imdilate, imopen, imclose}
-## @end deftypefn
-
-function retval = imerode(im, se)
-  ## Checkinput
-  if (nargin != 2)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imerode: first input argument must be a real matrix");
-  elseif (!ismatrix(se) || !isreal(se))
-    error("imerode: second input argument must be a real matrix");
-  elseif ( !strcmp(class(im), class(se)) )
-    error("imerode: image and structuring element must have the same class");
-  endif
-
-  ## Perform filtering
-  ## If image is binary/logical, try to use filter2 (much faster)
-  if (islogical(im))
-    thr     = sum(se(:));
-    retval  = filter2(se,im) == thr;
-  else
-    retval  = ordfiltn(im, 1, se, 0);
-  endif
-
-endfunction
-
-%!demo
-%! imerode(ones(5,5),ones(3,3))
-%! % creates a zeros border around ones.
-
-%!assert(imerode(eye(3),[1])==eye(3));                                           # using [1] as a mask returns the same value
-%!assert(imerode([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]); # check if it works with non-symmetric SE
+## Copyright (C) 2004 Josep Mones i Teixidor <jmones@puntbarra.com>
+## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
+## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{B} =} imerode (@var{A}, @var{se})
+## Perform morphological erosion on a given image.
+##
+## The image @var{A} must be a grayscale or binary image, and @var{se} a
+## structuring element. Both must have the same class, e.g., if @var{A} is a
+## logical matrix, @var{se} must also be logical. Note that the erosion
+## algorithm is different for each class, being much faster for logical
+## matrices. As such, if you have a binary matrix, you should use @code{logical}
+## first. This will also reduce the memory usage of your code.
+##
+## The center of @var{SE} is calculated using floor((size(@var{SE})+1)/2).
+##
+## Pixels outside the image are considered to be 0.
+##
+## @seealso{imdilate, imopen, imclose}
+## @end deftypefn
+
+function retval = imerode(im, se)
+  ## Checkinput
+  if (nargin != 2)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imerode: first input argument must be a real matrix");
+  elseif (!ismatrix(se) || !isreal(se))
+    error("imerode: second input argument must be a real matrix");
+  elseif ( !strcmp(class(im), class(se)) )
+    error("imerode: image and structuring element must have the same class");
+  endif
+
+  ## Perform filtering
+  ## If image is binary/logical, try to use filter2 (much faster)
+  if (islogical(im))
+    thr     = sum(se(:));
+    retval  = filter2(se,im) == thr;
+  else
+    retval  = ordfiltn(im, 1, se, 0);
+  endif
+
+endfunction
+
+%!demo
+%! imerode(ones(5,5),ones(3,3))
+%! % creates a zeros border around ones.
+
+%!assert(imerode(eye(3),[1])==eye(3));                                           # using [1] as a mask returns the same value
+%!assert(imerode([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]); # check if it works with non-symmetric SE
--- a/main/image/inst/imopen.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imopen.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,44 +1,44 @@
-## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
-##
-## 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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{B} = imopen (@var{A}, @var{se})
-## Perform morphological opening on a given image.
-## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
-## structuring element.
-##
-## The opening corresponds to an erosion followed by a dilation of the image, i.e.
-## @example
-## B = imdilate(imerode(A, se), se);
-## @end example
-## @seealso{imdilate, imerode, imclose}
-## @end deftypefn
-
-function retval = imopen(im, se)
-  ## Checkinput
-  if (nargin != 2)
-    print_usage();
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imopen: first input argument must be a real matrix");
-  endif
-  if (!ismatrix(se) || !isreal(se))
-    error("imopen: second input argument must be a real matrix");
-  endif
-  
-  ## Perform filtering
-  retval = imdilate(imerode(im, se), se);
-
-endfunction
+## Copyright (C) 2008 Soren Hauberg <soren@hauberg.org>
+##
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{B} = imopen (@var{A}, @var{se})
+## Perform morphological opening on a given image.
+## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
+## structuring element.
+##
+## The opening corresponds to an erosion followed by a dilation of the image, i.e.
+## @example
+## B = imdilate(imerode(A, se), se);
+## @end example
+## @seealso{imdilate, imerode, imclose}
+## @end deftypefn
+
+function retval = imopen(im, se)
+  ## Checkinput
+  if (nargin != 2)
+    print_usage();
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imopen: first input argument must be a real matrix");
+  endif
+  if (!ismatrix(se) || !isreal(se))
+    error("imopen: second input argument must be a real matrix");
+  endif
+  
+  ## Perform filtering
+  retval = imdilate(imerode(im, se), se);
+
+endfunction
--- a/main/image/inst/imtophat.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/imtophat.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,78 +1,78 @@
-## Copyright (C) 2005 Carvalho-Mariel
-## Copyright (C) 2010, 2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} @var{B} = imtophat (@var{A}, @var{se})
-## Perform morphological top hat filtering.
-##
-## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
-## structuring element. Both must have the same class, e.g., if @var{A} is a
-## logical matrix, @var{se} must also be logical.
-##
-## A 'black', or 'closing', top-hat transform is also known as bottom-hat
-## transform and so that is the same @code{imbothat}.
-##
-## @seealso{imerode, imdilate, imopen, imclose, imbothat, mmgradm}
-## @end deftypefn
-
-function retval = imtophat (im, se, trans)
-
-  ## Checkinput
-  if (nargin < 2 || nargin > 3)
-    print_usage();
-  elseif (nargin == 2)
-    trans = "white";
-  elseif (nargin == 3 && ischar (trans))
-    warning ("Use of the 'trans' argument in imtophat to specify a closing or opening top-hat transform has been deprecated in favor of using the functions 'imtophat' or 'imbothat'. This option will be removed from future versions of the 'imtophat' function");
-  endif
-  if (!ismatrix(im) || !isreal(im))
-    error("imtophat: first input argument must be a real matrix");
-  elseif (!ismatrix(se) || !isreal(se))
-    error("imtophat: second input argument must be a real matrix");
-  elseif ( !strcmp(class(im), class(se)) )
-    error("imtophat: image and structuring element must have the same class");
-  elseif (!ischar (trans))
-    error("imtophat: third input argument must be a string with 'white', 'open, 'black', or 'close'");
-  endif
-
-  ## Perform filtering
-  ## Note that in case that the transform is to applied to a logical image,
-  ## subtraction must be handled in a different way (x & !y) instead of (x - y)
-  ## or it will return a double precision matrix
-  if ( strcmpi(trans, "white") || strcmpi(trans, "open") )
-    if (islogical(im))
-      retval = im & !imopen(im,se);
-    else
-      retval = im - imopen(im, se);
-    endif
-  elseif ( strcmpi(trans, "black") || strcmpi(trans, "close") )
-    retval = imbothat (im, se);
-  else
-    error ("Unexpected type of top-hat transform");
-  endif
-
-endfunction
-
-%!test
-%! I = [1 1 1; 1 1 1; 1 1 1;];
-%! se = [1 1; 0 1;];
-%! ## class of input should be the same as the output
-%! result = imtophat(logical(I), logical(se));
-%! expected = 0.5 < [0 0 1; 0 0 1; 1 1 1];
-%! assert(expected, result);
-%! result = imtophat((I), (se));
-%! expected = [0 0 1; 0 0 1; 1 1 1];
-%! assert(expected, result);
+## Copyright (C) 2005 Carvalho-Mariel
+## Copyright (C) 2010, 2011 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} @var{B} = imtophat (@var{A}, @var{se})
+## Perform morphological top hat filtering.
+##
+## The image @var{A} must be a grayscale or binary image, and @var{se} must be a
+## structuring element. Both must have the same class, e.g., if @var{A} is a
+## logical matrix, @var{se} must also be logical.
+##
+## A 'black', or 'closing', top-hat transform is also known as bottom-hat
+## transform and so that is the same @code{imbothat}.
+##
+## @seealso{imerode, imdilate, imopen, imclose, imbothat, mmgradm}
+## @end deftypefn
+
+function retval = imtophat (im, se, trans)
+
+  ## Checkinput
+  if (nargin < 2 || nargin > 3)
+    print_usage();
+  elseif (nargin == 2)
+    trans = "white";
+  elseif (nargin == 3 && ischar (trans))
+    warning ("Use of the 'trans' argument in imtophat to specify a closing or opening top-hat transform has been deprecated in favor of using the functions 'imtophat' or 'imbothat'. This option will be removed from future versions of the 'imtophat' function");
+  endif
+  if (!ismatrix(im) || !isreal(im))
+    error("imtophat: first input argument must be a real matrix");
+  elseif (!ismatrix(se) || !isreal(se))
+    error("imtophat: second input argument must be a real matrix");
+  elseif ( !strcmp(class(im), class(se)) )
+    error("imtophat: image and structuring element must have the same class");
+  elseif (!ischar (trans))
+    error("imtophat: third input argument must be a string with 'white', 'open, 'black', or 'close'");
+  endif
+
+  ## Perform filtering
+  ## Note that in case that the transform is to applied to a logical image,
+  ## subtraction must be handled in a different way (x & !y) instead of (x - y)
+  ## or it will return a double precision matrix
+  if ( strcmpi(trans, "white") || strcmpi(trans, "open") )
+    if (islogical(im))
+      retval = im & !imopen(im,se);
+    else
+      retval = im - imopen(im, se);
+    endif
+  elseif ( strcmpi(trans, "black") || strcmpi(trans, "close") )
+    retval = imbothat (im, se);
+  else
+    error ("Unexpected type of top-hat transform");
+  endif
+
+endfunction
+
+%!test
+%! I = [1 1 1; 1 1 1; 1 1 1;];
+%! se = [1 1; 0 1;];
+%! ## class of input should be the same as the output
+%! result = imtophat(logical(I), logical(se));
+%! expected = 0.5 < [0 0 1; 0 0 1; 1 1 1];
+%! assert(expected, result);
+%! result = imtophat((I), (se));
+%! expected = [0 0 1; 0 0 1; 1 1 1];
+%! assert(expected, result);
--- a/main/image/inst/rgbplot.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/rgbplot.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,48 +1,48 @@
-## Copyright (C) 2005 Berge-Gladel
-##
-## 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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn {Function File} {@var{h} =} rgbplot (@var{cmap})
-## Plot a given color map.
-##
-## The plot will display 3 lines, red, green and blue, showing the variation of
-## RGB values on @var{cmap}.  While input matrix must be a color map (see
-## @code{iscolormap}), it can also be used to see a colored line profile
-## (intensity values will have to be converted to class double with
-## @code{im2double}).
-##
-## If an output is requested, the graphics handle @var{h} to the plot is returned.
-##
-## @seealso{colormap, iscolormap}
-## @end deftypefn
-
-function h_out = rgbplot(map)
-
-  if (nargin != 1)
-    print_usage;
-  elseif (!iscolormap (map))
-    error("rgbplot: input must be a colormap");
-  endif
-
-  h = plot (map(:,1), "-r", map(:,2), "g-", map(:,3), "b-");
-  if (nargout > 0)
-    h_out = h;
-  endif
-endfunction
-
-%!demo
-%! ## look at the distribution of RGB values for the jet colormap
-%! cmap = jet (64);
-%! rgbplot (cmap);
+## Copyright (C) 2005 Berge-Gladel
+##
+## 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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{h} =} rgbplot (@var{cmap})
+## Plot a given color map.
+##
+## The plot will display 3 lines, red, green and blue, showing the variation of
+## RGB values on @var{cmap}.  While input matrix must be a color map (see
+## @code{iscolormap}), it can also be used to see a colored line profile
+## (intensity values will have to be converted to class double with
+## @code{im2double}).
+##
+## If an output is requested, the graphics handle @var{h} to the plot is returned.
+##
+## @seealso{colormap, iscolormap}
+## @end deftypefn
+
+function h_out = rgbplot(map)
+
+  if (nargin != 1)
+    print_usage;
+  elseif (!iscolormap (map))
+    error("rgbplot: input must be a colormap");
+  endif
+
+  h = plot (map(:,1), "-r", map(:,2), "g-", map(:,3), "b-");
+  if (nargout > 0)
+    h_out = h;
+  endif
+endfunction
+
+%!demo
+%! ## look at the distribution of RGB values for the jet colormap
+%! cmap = jet (64);
+%! rgbplot (cmap);
--- a/main/image/inst/wavelength2rgb.m	Thu Sep 27 12:51:44 2012 +0000
+++ b/main/image/inst/wavelength2rgb.m	Thu Sep 27 13:18:13 2012 +0000
@@ -1,118 +1,118 @@
-## Copyright (C) 2011 William Krekeler <WKrekeler@cleanearthtech.com>
-## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
-
-## -*- texinfo -*-
-## @deftypefn{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength})
-## @deftypefnx{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength}, @var{intensity_max})
-## @deftypefnx{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength}, @var{intensity_max}, @var{gamma})
-## Convert wavelength in nm into an RGB value set.
-##
-## Output:
-## @itemize @bullet
-## @item @var{rgb}: value set on scale of 1:@var{intensity_max}
-## @end itemize
-##
-## Input:
-## Output:
-## @itemize @bullet
-## @item @var{wavelength}: wavelength of input light value in nm. Must be a positive
-## numeric scalar.
-## @item @var{intensity_max}: max of integer scale to output values. Defaults to 255.
-## @item @var{gamma}: Controls luminance. Must be a value between 0 and 1. Defaults to 0.8.
-## @end itemize
-##
-## @example
-## X = 350:0.5:800;
-## Y = exp (log (X.^3));   # arbitrary
-## figure, plot(X, Y)
-## stepSize = 0.5 * max (diff (X));
-## for n = 1:numel(Y)
-##   RGB = wavelength2rgb (X(n), 1);
-##   if (sum (RGB) > 0 )   # ie don't fill black
-##     hold on, area( (X(n)-stepSize):(stepSize/1):(X(n)+stepSize), ...
-##                   repmat( Y(n), 1, numel((X(n)-stepSize):(stepSize/1):(X(n)+stepSize)) ), ...
-##                   'EdgeColor', RGB, 'FaceColor', RGB ); hold off
-##   endif
-## endfor
-## @end example
-##
-## Reference:
-## @itemize @bullet
-## @item @uref{http://stackoverflow.com/questions/2374959/algorithm-to-convert-any-positive-integer-to-an-rgb-value}
-## @item @uref{http://www.midnightkite.com/color.html} per Dan Bruton
-## @end itemize
-## @end deftypefn
-
-function rgb = wavelength2rgb (wavelength, intensity_max = 255, gamma = 0.8)
-
-  if (nargin < 1 || nargin > 3)
-    print_usage;
-  elseif (!isnumeric (wavelength) || !isscalar (wavelength) || wavelength <= 0)
-    error ("wavelength must a positive numeric scalar");
-  elseif (!isnumeric (intensity_max) || !isscalar (intensity_max) || intensity_max <= 0)
-    error ("intensity_max must a positive numeric scalar");
-  elseif (!isnumeric (gamma) || !isscalar (gamma) || gamma > 1 || gamma < 0)
-    error ("gamma must a numeric scalar between 1 and 0");
-  endif
-
-  rgb = zeros (3, numel (wavelength));  # initialize rgb, each rgb set stored by column
-
-  ## set the factor
-  if ( wavelength >= 380 && wavelength < 420 )
-     factor = 0.3 + 0.7*(wavelength - 380) / (420 - 380);
-  elseif ( wavelength >= 420 && wavelength < 701 )
-     factor = 1;
-  elseif ( wavelength >= 420 && wavelength < 701 )
-     factor = 0.3 + 0.7*(780 - wavelength) / (780 - 700);
-  else
-     factor = 0;
-  endif
-
-  ## initialize rgb
-  if ( wavelength >= 380 && wavelength < 440 )
-     rgb(1) = -(wavelength - 440) / (440 - 380);
-     rgb(2) = 0.0;
-     rgb(3) = 1.0;
-  elseif ( wavelength >= 440 && wavelength < 490 )
-     rgb(1) = 0.0;
-     rgb(2) = (wavelength - 440) / (490 - 440);
-     rgb(3) = 1.0;
-  elseif ( wavelength >= 490 && wavelength < 510 )
-     rgb(1) = 0.0;
-     rgb(2) = 1.0;
-     rgb(3) = -(wavelength - 510) / (510 - 490);
-  elseif ( wavelength >= 510 && wavelength < 580 )
-     rgb(1) = (wavelength - 510) / (580 - 510);
-     rgb(2) = 1.0;
-     rgb(3) = 0.0;
-  elseif ( wavelength >= 580 && wavelength < 645 )
-     rgb(1) = 1.0;
-     rgb(2) = -(wavelength - 645) / (645 - 580);
-     rgb(3) = 0.0;
-  elseif ( wavelength >= 645 && wavelength < 781 )
-     rgb(1) = 1.0;
-     rgb(2) = 0.0;
-     rgb(3) = 0.0;
-  else
-     rgb(1) = 0.0;
-     rgb(2) = 0.0;
-     rgb(3) = 0.0;
-  endif
-
-  ## correct rgb
-  rgb = intensity_max .* (rgb .* factor) .^gamma .* ( rgb > 0 );
-
-endfunction
+## Copyright (C) 2011 William Krekeler <WKrekeler@cleanearthtech.com>
+## Copyright (C) 2012 Carnë Draug <carandraug+dev@gmail.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 3 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, see <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength})
+## @deftypefnx{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength}, @var{intensity_max})
+## @deftypefnx{Function File} {@var{rgb} =} wavelength2rgb (@var{wavelength}, @var{intensity_max}, @var{gamma})
+## Convert wavelength in nm into an RGB value set.
+##
+## Output:
+## @itemize @bullet
+## @item @var{rgb}: value set on scale of 1:@var{intensity_max}
+## @end itemize
+##
+## Input:
+## Output:
+## @itemize @bullet
+## @item @var{wavelength}: wavelength of input light value in nm. Must be a positive
+## numeric scalar.
+## @item @var{intensity_max}: max of integer scale to output values. Defaults to 255.
+## @item @var{gamma}: Controls luminance. Must be a value between 0 and 1. Defaults to 0.8.
+## @end itemize
+##
+## @example
+## X = 350:0.5:800;
+## Y = exp (log (X.^3));   # arbitrary
+## figure, plot(X, Y)
+## stepSize = 0.5 * max (diff (X));
+## for n = 1:numel(Y)
+##   RGB = wavelength2rgb (X(n), 1);
+##   if (sum (RGB) > 0 )   # ie don't fill black
+##     hold on, area( (X(n)-stepSize):(stepSize/1):(X(n)+stepSize), ...
+##                   repmat( Y(n), 1, numel((X(n)-stepSize):(stepSize/1):(X(n)+stepSize)) ), ...
+##                   'EdgeColor', RGB, 'FaceColor', RGB ); hold off
+##   endif
+## endfor
+## @end example
+##
+## Reference:
+## @itemize @bullet
+## @item @uref{http://stackoverflow.com/questions/2374959/algorithm-to-convert-any-positive-integer-to-an-rgb-value}
+## @item @uref{http://www.midnightkite.com/color.html} per Dan Bruton
+## @end itemize
+## @end deftypefn
+
+function rgb = wavelength2rgb (wavelength, intensity_max = 255, gamma = 0.8)
+
+  if (nargin < 1 || nargin > 3)
+    print_usage;
+  elseif (!isnumeric (wavelength) || !isscalar (wavelength) || wavelength <= 0)
+    error ("wavelength must a positive numeric scalar");
+  elseif (!isnumeric (intensity_max) || !isscalar (intensity_max) || intensity_max <= 0)
+    error ("intensity_max must a positive numeric scalar");
+  elseif (!isnumeric (gamma) || !isscalar (gamma) || gamma > 1 || gamma < 0)
+    error ("gamma must a numeric scalar between 1 and 0");
+  endif
+
+  rgb = zeros (3, numel (wavelength));  # initialize rgb, each rgb set stored by column
+
+  ## set the factor
+  if ( wavelength >= 380 && wavelength < 420 )
+     factor = 0.3 + 0.7*(wavelength - 380) / (420 - 380);
+  elseif ( wavelength >= 420 && wavelength < 701 )
+     factor = 1;
+  elseif ( wavelength >= 420 && wavelength < 701 )
+     factor = 0.3 + 0.7*(780 - wavelength) / (780 - 700);
+  else
+     factor = 0;
+  endif
+
+  ## initialize rgb
+  if ( wavelength >= 380 && wavelength < 440 )
+     rgb(1) = -(wavelength - 440) / (440 - 380);
+     rgb(2) = 0.0;
+     rgb(3) = 1.0;
+  elseif ( wavelength >= 440 && wavelength < 490 )
+     rgb(1) = 0.0;
+     rgb(2) = (wavelength - 440) / (490 - 440);
+     rgb(3) = 1.0;
+  elseif ( wavelength >= 490 && wavelength < 510 )
+     rgb(1) = 0.0;
+     rgb(2) = 1.0;
+     rgb(3) = -(wavelength - 510) / (510 - 490);
+  elseif ( wavelength >= 510 && wavelength < 580 )
+     rgb(1) = (wavelength - 510) / (580 - 510);
+     rgb(2) = 1.0;
+     rgb(3) = 0.0;
+  elseif ( wavelength >= 580 && wavelength < 645 )
+     rgb(1) = 1.0;
+     rgb(2) = -(wavelength - 645) / (645 - 580);
+     rgb(3) = 0.0;
+  elseif ( wavelength >= 645 && wavelength < 781 )
+     rgb(1) = 1.0;
+     rgb(2) = 0.0;
+     rgb(3) = 0.0;
+  else
+     rgb(1) = 0.0;
+     rgb(2) = 0.0;
+     rgb(3) = 0.0;
+  endif
+
+  ## correct rgb
+  rgb = intensity_max .* (rgb .* factor) .^gamma .* ( rgb > 0 );
+
+endfunction