function [a,map] = rgb2ind(r,g,b,cm,dith)
%RGB2IND Convert RGB image to indexed image.
%	[X,NEWMAP] = RGB2IND(R,G,B) converts the RGB image in the 
%	matrices R,G,B to an indexed image X with colormap MAP.  
%	The colormap will contain all the values in R,G,B and will
%	be of size PROD(SIZE(R))-by-3. To produce the indexed image
%	with the smallest colormap use CMUNIQUE.
%
%	[X,NEWMAP] = RGB2IND(R,G,B,TOL) converts the RGB image to an
%	indexed image X using uniform quantization in RGB space.
%	NEWMAP contains at most (FLOOR(1/TOL)+1)^3 colors.  TOL must
%	be between 0 and 1.0. 
%
%	[X,NEWMAP] = RGB2IND(R,G,B,N) converts the RGB image to a
%	indexed image X with N colors that best approximate R,G,B.
%	The N-by-3 matrix NEWMAP contains these colors.  
%
%	X = RGB2IND(R,G,B,MAP) converts the RGB image to an indexed
%	image X with colormap MAP.  RGB2IND matches colors in R,G,B
%	with the nearest color in the colormap MAP.
%
%	[...] = RGB2IND(...,'dither_flag') optionally controls
%	whether the returned image X is dithered or not. Dithering 
%	provides more pleasing looking images in general, with
%	better apparent color resolution, at the expense of spatial
%	resolution.  Possibilities are 'dither' or 'nodither'.
%	'dither' is the default.
%	
%	See also RGB2GRAY, IND2RGB, CMUNIQUE, IMAPPROX.

%	Clay M. Thompson 9-29-92
%	Copyright (c) 1992 by The MathWorks, Inc.
%	$Revision: 1.22 $  $Date: 1993/09/09 21:28:00 $

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

if nargin<5, dith = 'dither'; else dith = [lower(dith) ' ']; end
if (dith(1)~='d') & (dith(1)~='n')
  error('''dither_flag'' must be either ''dither'' or ''nodither''.');
end

if nargin==3,  % Directly convert R,G,B to indexed image.
  a = zeros(size(r));
  a(:) = 1:prod(size(r));
  map = [r(:),g(:),b(:)];

elseif prod(size(cm))==1, 
  if cm < 1.0, % Use uniform quantization

    %
    % Determine colors by uniform quantization
    %

    tol = cm;
    if (tol<0), error('Tolerance must be between 0.0 and 1.0'); end
    n = round(1/tol);

    % Create colormap
    [x,y,z] = meshgrid((0:n)/n,(0:n)/n,(0:n)/n);
    map = [x(:) y(:) z(:)];

    if dith(1) == 'n'; % 'nodither'
      % Determine indexed image (with no dithering)
      r = round(r*n);
      g = round(g*n);
      b = round(b*n);
      a = b*((n+1)^2) + r*(n+1) + g + 1;
      [a,map] = cmunique(a,map);
    else
      a = dither(r,g,b,map);
      [a,map] = cmunique(a,map);
    end

  else % Use variance minimization quantization
    [a,map] = vmquant(r,g,b,cm,[5 5 5],'n');
    % Use standalone dither if map is an approximation.
    if (dith(1)=='d') & (size(map,1) == cm)
       a = dither(r,g,b,map);
    end
  end

else 
  map = cm;
  if dith(1)=='n', % 'nodither'
    a = dither(r,g,b,map,5,4); % Use dither to do inverse colormap mapping.
  else
    a = dither(r,g,b,map);
  end
end
