function varargout = bwselect(varargin)
%BWSELECT Select objects in binary image.
%   BW2 = BWSELECT(BW1,C,R,N) returns a binary image containing
%   the objects that overlap the pixel (R,C). R and C can be
%   scalars or equal-length vectors. If R and C are vectors, BW2
%   contains the set of objects overlapping with any of the
%   pixels (R(k),C(k)). N can have a value of either 4 or 8 (the
%   default), where 4 specifies 4-connected objects and 8
%   specifies 8-connected objects. Objects are connected sets of
%   "on" pixels (i.e., having value of 1).
%
%   BW2 = BWSELECT(BW1,N) displays the image BW1 on the screen
%   and lets you select the (R,C) coordinates using the mouse. If
%   you omit BW1, BWSELECT operates on the image in the current
%   axes. Use normal button clicks to add points. Pressing
%   <BACKSPACE> or <DELETE> removes the the previously selected
%   point. A shift-click, right-click, or double-click selects
%   the final point; pressing <RETURN> finishes the selection
%   without adding a point.
%
%   [BW2,IDX] = BWSELECT(...) returns the linear indices of the 
%   pixels belonging to the selected objects.
%
%   BW2 = BWSELECT(X,Y,BW1,Xi,Yi,N) uses the vectors X and Y to
%   establish a nondefault spatial coordinate system for BW1. Xi
%   and Yi are scalars or equal-length vectors that specify
%   locations in this coordinate system.
%
%   [X,Y,BW2,IDX,Xi,Yi] = BWSELECT(...) returns the XData and
%   YData in X and Y; the output image in BW2; linear indices of
%   the pixels belonging to the selected objects in IDX; and the 
%   specified spatial coordinates Xi and Yi.
%
%   If bwselect is called with no output arguments, the resulting
%   image is displayed in a new figure.
%
%   Class Support
%   -------------
%   The input image BW1 can be of class double or uint8. The
%   output image BW2 is of class uint8.
%
%   Example
%   -------
%       BW1 = imread('text.tif');
%       c = [16 90 144];
%       r = [85 197 247];
%       BW2 = bwselect(BW1,c,r,4);
%       imshow(BW1)
%       figure, imshow(BW2)
%
%   See also BWFILL, BWLABEL, ROIPOLY, ROIFILL.

%   Steven L. Eddins, October 1996
%   Copyright 1993-1998 The MathWorks, Inc.  All Rights Reserved.
%   $Revision: 1.8 $  $Date: 1997/11/24 15:34:12 $

[xdata,ydata,BW,xi,yi,r,c,n,newFig,msg] = ParseInputs(varargin{:});
if (~isempty(msg))
    error(msg);
end

% We're going to perform a fill operation on the complemented
% image, so we need to reverse the sense of the connectivity
% specifier.
if (n == 4)
    n = 8;
else
    n = 4;
end

[BW2, idx] = bwfill(~BW, c, r, n);
BW2(1:end) = 0;  % clears logical flag
BW2(idx) = 1;
BW2 = logical(BW2);

switch nargout
case 0
    % BWSELECT(...)
    
    if (newFig)
       figure;
    end
    imshow(xdata,ydata,BW2);
    
case 1
    % BW2 = BWSELECT(...)
    
    varargout{1} = BW2;
    
case 2
    % [BW2,IDX] = BWSELECT(...)
    
    varargout{1} = BW2;
    varargout{2} = idx;
    
otherwise
    % [X,Y,BW2,...] = BWSELECT(...)
    
    varargout{1} = xdata;
    varargout{2} = ydata;
    varargout{3} = BW2;
    
    if (nargout >= 4)
        % [X,Y,BW2,IDX,...] = BWSELECT(...)
        varargout{4} = idx;
    end
    
    if (nargout >= 5)
        % [X,Y,BW2,IDX,Xi,...] = BWSELECT(...)
        varargout{5} = xi;
    end
    
    if (nargout >= 6)
        % [X,Y,BW2,IDX,Xi,Yi] = BWSELECT(...)
        varargout{6} = yi;
    end
    
    if (nargout >= 7)
        warning('Too many output arguments');
    end
end

%%%
%%% Subfunction ParseInputs
%%%
function [xdata,ydata,I,xi,yi,r,c,style,newFig,msg] = ParseInputs(varargin)

msg = '';
style = 8;
xdata = [];
ydata = [];
I = [];
xi = [];
yi = [];
r = [];
c = [];
newFig = 0;

switch nargin
case 0
    % BWSELECT
    
    [xdata, ydata, I, flag] = getimage;
    if (flag == 0)
        msg = 'Current axes does not contain an image';
        return;
    end
    newFig = 1; 
    [xi,yi] = getpts;
    
    r = round(axes2pix(size(I,1), ydata, yi));
    c = round(axes2pix(size(I,2), xdata, xi));
    
case 1
    if ((prod(size(varargin{1})) == 1) & ...
                ((varargin{1} == 4) | (varargin{1} == 8)))
        % BWSELECT(N)
        
        style = varargin{1};
        [xdata,ydata,I,flag] = getimage;
        if (flag == 0)
            msg = 'Current axes does not contain an image';
            return;
        end
        
    else
        % BWSELECT(BW)
        
        I = varargin{1};
        xdata = [1 size(I,2)];
        ydata = [1 size(I,1)];
        imshow(xdata,ydata,I);
        
    end
    
    newFig = 1;
    [xi,yi] = getpts;
    
    r = round(axes2pix(size(I,1), ydata, yi));
    c = round(axes2pix(size(I,2), xdata, xi));
    
case 2
    % BWSELECT(BW, N)
    
    I = varargin{1};
    style = varargin{2};
    if ((style ~= 4) & (style ~= 8))
        msg = 'N must be 4 or 8';
        return;
    end
    
    xdata = [1 size(I,2)];
    ydata = [1 size(I,1)];
    
    imshow(xdata, ydata, I);
    newFig = 1;
    [xi,yi] = getpts;
    
    r = round(axes2pix(size(I,1), ydata, yi));
    c = round(axes2pix(size(I,2), xdata, xi));
    
case 3
    % BWSELECT(BW,Xi,Yi)

    I = varargin{1};
    xdata = [1 size(I,2)];
    ydata = [1 size(I,1)];
    xi = varargin{2};
    yi = varargin{3};
    r = round(yi);
    c = round(xi);
    
case 4
    % BWSELECT(BW,Xi,Yi,N)
    
    I = varargin{1};
    xdata = [1 size(I,2)];
    ydata = [1 size(I,1)];
    xi = varargin{2};
    yi = varargin{3};
    r = round(yi);
    c = round(xi);
    style = varargin{4};
    
case 5
    % BWSELECT(X,Y,BW,Xi,Yi)
    
    xdata = varargin{1};
    ydata = varargin{2};
    I = varargin{3};
    xi = varargin{4};
    yi = varargin{5};
    
    r = round(axes2pix(size(I,1), ydata, yi));
    c = round(axes2pix(size(I,2), xdata, xi));
    
case 6
    % BWSELECT(X,Y,BW,Xi,Yi,N)
    
    xdata = varargin{1};
    ydata = varargin{2};
    I = varargin{3};
    xi = varargin{4};
    yi = varargin{5};
    style = varargin{6};
    
    r = round(axes2pix(size(I,1), ydata, yi));
    c = round(axes2pix(size(I,2), xdata, xi));
    
otherwise
    msg = 'Too many input arguments';
    return;
end

% Force input input image to be binary.
I = uint8(I ~= 0);

badPix = find((r < 1) | (r > size(I,1)) | ...
        (c < 1) | (c > size(I,2)));
if (~isempty(badPix))
    warning('Ignoring out-of-range coordinates');
    r(badPix) = [];
    c(badPix) = [];
end 

